Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1452 chris 1
#region --- License ---
2
/*
3
Copyright (c) 2006 - 2008 The Open Toolkit library.
4
 
5
Permission is hereby granted, free of charge, to any person obtaining a copy of
6
this software and associated documentation files (the "Software"), to deal in
7
the Software without restriction, including without limitation the rights to
8
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
of the Software, and to permit persons to whom the Software is furnished to do
10
so, subject to the following conditions:
11
 
12
The above copyright notice and this permission notice shall be included in all
13
copies or substantial portions of the Software.
14
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
SOFTWARE.
22
 */
23
#endregion
24
 
25
using System;
26
using System.Runtime.InteropServices;
27
 
28
namespace OpenTK
29
{
30
    /// <summary>
31
    /// Represents a 4x4 Matrix
32
    /// </summary>
33
    [Serializable]
34
    [StructLayout(LayoutKind.Sequential)]
35
    public struct Matrix4 : IEquatable<Matrix4>
36
    {
37
        #region Fields
38
 
39
        /// <summary>
40
        /// Top row of the matrix
41
        /// </summary>
42
        public Vector4 Row0;
43
        /// <summary>
44
        /// 2nd row of the matrix
45
        /// </summary>
46
        public Vector4 Row1;
47
        /// <summary>
48
        /// 3rd row of the matrix
49
        /// </summary>
50
        public Vector4 Row2;
51
        /// <summary>
52
        /// Bottom row of the matrix
53
        /// </summary>
54
        public Vector4 Row3;
55
 
56
        /// <summary>
57
        /// The identity matrix
58
        /// </summary>
59
        public static Matrix4 Identity = new Matrix4(Vector4.UnitX, Vector4.UnitY, Vector4.UnitZ, Vector4.UnitW);
60
 
61
        #endregion
62
 
63
        #region Constructors
64
 
65
        /// <summary>
66
        /// Constructs a new instance.
67
        /// </summary>
68
        /// <param name="row0">Top row of the matrix</param>
69
        /// <param name="row1">Second row of the matrix</param>
70
        /// <param name="row2">Third row of the matrix</param>
71
        /// <param name="row3">Bottom row of the matrix</param>
72
        public Matrix4(Vector4 row0, Vector4 row1, Vector4 row2, Vector4 row3)
73
        {
74
            Row0 = row0;
75
            Row1 = row1;
76
            Row2 = row2;
77
            Row3 = row3;
78
        }
79
 
80
        /// <summary>
81
        /// Constructs a new instance.
82
        /// </summary>
83
        /// <param name="m00">First item of the first row of the matrix.</param>
84
        /// <param name="m01">Second item of the first row of the matrix.</param>
85
        /// <param name="m02">Third item of the first row of the matrix.</param>
86
        /// <param name="m03">Fourth item of the first row of the matrix.</param>
87
        /// <param name="m10">First item of the second row of the matrix.</param>
88
        /// <param name="m11">Second item of the second row of the matrix.</param>
89
        /// <param name="m12">Third item of the second row of the matrix.</param>
90
        /// <param name="m13">Fourth item of the second row of the matrix.</param>
91
        /// <param name="m20">First item of the third row of the matrix.</param>
92
        /// <param name="m21">Second item of the third row of the matrix.</param>
93
        /// <param name="m22">Third item of the third row of the matrix.</param>
94
        /// <param name="m23">First item of the third row of the matrix.</param>
95
        /// <param name="m30">Fourth item of the fourth row of the matrix.</param>
96
        /// <param name="m31">Second item of the fourth row of the matrix.</param>
97
        /// <param name="m32">Third item of the fourth row of the matrix.</param>
98
        /// <param name="m33">Fourth item of the fourth row of the matrix.</param>
99
        public Matrix4(
100
            float m00, float m01, float m02, float m03,
101
            float m10, float m11, float m12, float m13,
102
            float m20, float m21, float m22, float m23,
103
            float m30, float m31, float m32, float m33)
104
        {
105
            Row0 = new Vector4(m00, m01, m02, m03);
106
            Row1 = new Vector4(m10, m11, m12, m13);
107
            Row2 = new Vector4(m20, m21, m22, m23);
108
            Row3 = new Vector4(m30, m31, m32, m33);
109
        }
110
 
111
        #endregion
112
 
113
        #region Public Members
114
 
115
        #region Properties
116
 
117
        /// <summary>
118
        /// The determinant of this matrix
119
        /// </summary>
120
        public float Determinant
121
        {
122
            get
123
            {
124
                return
125
                    Row0.X * Row1.Y * Row2.Z * Row3.W - Row0.X * Row1.Y * Row2.W * Row3.Z + Row0.X * Row1.Z * Row2.W * Row3.Y - Row0.X * Row1.Z * Row2.Y * Row3.W
126
                  + Row0.X * Row1.W * Row2.Y * Row3.Z - Row0.X * Row1.W * Row2.Z * Row3.Y - Row0.Y * Row1.Z * Row2.W * Row3.X + Row0.Y * Row1.Z * Row2.X * Row3.W
127
                  - Row0.Y * Row1.W * Row2.X * Row3.Z + Row0.Y * Row1.W * Row2.Z * Row3.X - Row0.Y * Row1.X * Row2.Z * Row3.W + Row0.Y * Row1.X * Row2.W * Row3.Z
128
                  + Row0.Z * Row1.W * Row2.X * Row3.Y - Row0.Z * Row1.W * Row2.Y * Row3.X + Row0.Z * Row1.X * Row2.Y * Row3.W - Row0.Z * Row1.X * Row2.W * Row3.Y
129
                  + Row0.Z * Row1.Y * Row2.W * Row3.X - Row0.Z * Row1.Y * Row2.X * Row3.W - Row0.W * Row1.X * Row2.Y * Row3.Z + Row0.W * Row1.X * Row2.Z * Row3.Y
130
                  - Row0.W * Row1.Y * Row2.Z * Row3.X + Row0.W * Row1.Y * Row2.X * Row3.Z - Row0.W * Row1.Z * Row2.X * Row3.Y + Row0.W * Row1.Z * Row2.Y * Row3.X;
131
            }
132
        }
133
 
134
        /// <summary>
135
        /// The first column of this matrix
136
        /// </summary>
137
        public Vector4 Column0
138
        {
139
            get { return new Vector4(Row0.X, Row1.X, Row2.X, Row3.X); }
140
        }
141
 
142
        /// <summary>
143
        /// The second column of this matrix
144
        /// </summary>
145
        public Vector4 Column1
146
        {
147
            get { return new Vector4(Row0.Y, Row1.Y, Row2.Y, Row3.Y); }
148
        }
149
 
150
        /// <summary>
151
        /// The third column of this matrix
152
        /// </summary>
153
        public Vector4 Column2
154
        {
155
            get { return new Vector4(Row0.Z, Row1.Z, Row2.Z, Row3.Z); }
156
        }
157
 
158
        /// <summary>
159
        /// The fourth column of this matrix
160
        /// </summary>
161
        public Vector4 Column3
162
        {
163
            get { return new Vector4(Row0.W, Row1.W, Row2.W, Row3.W); }
164
        }
165
 
166
        /// <summary>
167
        /// Gets or sets the value at row 1, column 1 of this instance.
168
        /// </summary>
169
        public float M11 { get { return Row0.X; } set { Row0.X = value; } }
170
 
171
        /// <summary>
172
        /// Gets or sets the value at row 1, column 2 of this instance.
173
        /// </summary>
174
        public float M12 { get { return Row0.Y; } set { Row0.Y = value; } }
175
 
176
        /// <summary>
177
        /// Gets or sets the value at row 1, column 3 of this instance.
178
        /// </summary>
179
        public float M13 { get { return Row0.Z; } set { Row0.Z = value; } }
180
 
181
        /// <summary>
182
        /// Gets or sets the value at row 1, column 4 of this instance.
183
        /// </summary>
184
        public float M14 { get { return Row0.W; } set { Row0.W = value; } }
185
 
186
        /// <summary>
187
        /// Gets or sets the value at row 2, column 1 of this instance.
188
        /// </summary>
189
        public float M21 { get { return Row1.X; } set { Row1.X = value; } }
190
 
191
        /// <summary>
192
        /// Gets or sets the value at row 2, column 2 of this instance.
193
        /// </summary>
194
        public float M22 { get { return Row1.Y; } set { Row1.Y = value; } }
195
 
196
        /// <summary>
197
        /// Gets or sets the value at row 2, column 3 of this instance.
198
        /// </summary>
199
        public float M23 { get { return Row1.Z; } set { Row1.Z = value; } }
200
 
201
        /// <summary>
202
        /// Gets or sets the value at row 2, column 4 of this instance.
203
        /// </summary>
204
        public float M24 { get { return Row1.W; } set { Row1.W = value; } }
205
 
206
        /// <summary>
207
        /// Gets or sets the value at row 3, column 1 of this instance.
208
        /// </summary>
209
        public float M31 { get { return Row2.X; } set { Row2.X = value; } }
210
 
211
        /// <summary>
212
        /// Gets or sets the value at row 3, column 2 of this instance.
213
        /// </summary>
214
        public float M32 { get { return Row2.Y; } set { Row2.Y = value; } }
215
 
216
        /// <summary>
217
        /// Gets or sets the value at row 3, column 3 of this instance.
218
        /// </summary>
219
        public float M33 { get { return Row2.Z; } set { Row2.Z = value; } }
220
 
221
        /// <summary>
222
        /// Gets or sets the value at row 3, column 4 of this instance.
223
        /// </summary>
224
        public float M34 { get { return Row2.W; } set { Row2.W = value; } }
225
 
226
        /// <summary>
227
        /// Gets or sets the value at row 4, column 1 of this instance.
228
        /// </summary>
229
        public float M41 { get { return Row3.X; } set { Row3.X = value; } }
230
 
231
        /// <summary>
232
        /// Gets or sets the value at row 4, column 2 of this instance.
233
        /// </summary>
234
        public float M42 { get { return Row3.Y; } set { Row3.Y = value; } }
235
 
236
        /// <summary>
237
        /// Gets or sets the value at row 4, column 3 of this instance.
238
        /// </summary>
239
        public float M43 { get { return Row3.Z; } set { Row3.Z = value; } }
240
 
241
        /// <summary>
242
        /// Gets or sets the value at row 4, column 4 of this instance.
243
        /// </summary>
244
        public float M44 { get { return Row3.W; } set { Row3.W = value; } }
245
 
246
        #endregion
247
 
248
        #region Instance
249
 
250
        #region public void Invert()
251
 
252
        /// <summary>
253
        /// Converts this instance into its inverse.
254
        /// </summary>
255
        public void Invert()
256
        {
257
            this = Matrix4.Invert(this);
258
        }
259
 
260
        #endregion
261
 
262
        #region public void Transpose()
263
 
264
        /// <summary>
265
        /// Converts this instance into its transpose.
266
        /// </summary>
267
        public void Transpose()
268
        {
269
            this = Matrix4.Transpose(this);
270
        }
271
 
272
        #endregion
273
 
274
        #endregion
275
 
276
        #region Static
277
 
278
        #region CreateFromAxisAngle
279
 
280
        /// <summary>
281
        /// Build a rotation matrix from the specified axis/angle rotation.
282
        /// </summary>
283
        /// <param name="axis">The axis to rotate about.</param>
284
        /// <param name="angle">Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).</param>
285
        /// <param name="result">A matrix instance.</param>
286
        public static void CreateFromAxisAngle(Vector3 axis, float angle, out Matrix4 result)
287
        {
288
            float cos = (float)System.Math.Cos(-angle);
289
            float sin = (float)System.Math.Sin(-angle);
290
            float t = 1.0f - cos;
291
 
292
            axis.Normalize();
293
 
294
            result = new Matrix4(t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0f,
295
                                 t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f,
296
                                 t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f,
297
                                 0, 0, 0, 1);
298
        }
299
 
300
        /// <summary>
301
        /// Build a rotation matrix from the specified axis/angle rotation.
302
        /// </summary>
303
        /// <param name="axis">The axis to rotate about.</param>
304
        /// <param name="angle">Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).</param>
305
        /// <returns>A matrix instance.</returns>
306
        public static Matrix4 CreateFromAxisAngle(Vector3 axis, float angle)
307
        {
308
            Matrix4 result;
309
            CreateFromAxisAngle(axis, angle, out result);
310
            return result;
311
        }
312
 
313
        #endregion
314
 
315
        #region CreateRotation[XYZ]
316
 
317
        /// <summary>
318
        /// Builds a rotation matrix for a rotation around the x-axis.
319
        /// </summary>
320
        /// <param name="angle">The counter-clockwise angle in radians.</param>
321
        /// <param name="result">The resulting Matrix4 instance.</param>
322
        public static void CreateRotationX(float angle, out Matrix4 result)
323
        {
324
            float cos = (float)System.Math.Cos(angle);
325
            float sin = (float)System.Math.Sin(angle);
326
 
327
            result.Row0 = Vector4.UnitX;
328
            result.Row1 = new Vector4(0.0f, cos, sin, 0.0f);
329
            result.Row2 = new Vector4(0.0f, -sin, cos, 0.0f);
330
            result.Row3 = Vector4.UnitW;
331
        }
332
 
333
        /// <summary>
334
        /// Builds a rotation matrix for a rotation around the x-axis.
335
        /// </summary>
336
        /// <param name="angle">The counter-clockwise angle in radians.</param>
337
        /// <returns>The resulting Matrix4 instance.</returns>
338
        public static Matrix4 CreateRotationX(float angle)
339
        {
340
            Matrix4 result;
341
            CreateRotationX(angle, out result);
342
            return result;
343
        }
344
 
345
        /// <summary>
346
        /// Builds a rotation matrix for a rotation around the y-axis.
347
        /// </summary>
348
        /// <param name="angle">The counter-clockwise angle in radians.</param>
349
        /// <param name="result">The resulting Matrix4 instance.</param>
350
        public static void CreateRotationY(float angle, out Matrix4 result)
351
        {
352
            float cos = (float)System.Math.Cos(angle);
353
            float sin = (float)System.Math.Sin(angle);
354
 
355
            result.Row0 = new Vector4(cos, 0.0f, -sin, 0.0f);
356
            result.Row1 = Vector4.UnitY;
357
            result.Row2 = new Vector4(sin, 0.0f, cos, 0.0f);
358
            result.Row3 = Vector4.UnitW;
359
        }
360
 
361
        /// <summary>
362
        /// Builds a rotation matrix for a rotation around the y-axis.
363
        /// </summary>
364
        /// <param name="angle">The counter-clockwise angle in radians.</param>
365
        /// <returns>The resulting Matrix4 instance.</returns>
366
        public static Matrix4 CreateRotationY(float angle)
367
        {
368
            Matrix4 result;
369
            CreateRotationY(angle, out result);
370
            return result;
371
        }
372
 
373
        /// <summary>
374
        /// Builds a rotation matrix for a rotation around the z-axis.
375
        /// </summary>
376
        /// <param name="angle">The counter-clockwise angle in radians.</param>
377
        /// <param name="result">The resulting Matrix4 instance.</param>
378
        public static void CreateRotationZ(float angle, out Matrix4 result)
379
        {
380
            float cos = (float)System.Math.Cos(angle);
381
            float sin = (float)System.Math.Sin(angle);
382
 
383
            result.Row0 = new Vector4(cos, sin, 0.0f, 0.0f);
384
            result.Row1 = new Vector4(-sin, cos, 0.0f, 0.0f);
385
            result.Row2 = Vector4.UnitZ;
386
            result.Row3 = Vector4.UnitW;
387
        }
388
 
389
        /// <summary>
390
        /// Builds a rotation matrix for a rotation around the z-axis.
391
        /// </summary>
392
        /// <param name="angle">The counter-clockwise angle in radians.</param>
393
        /// <returns>The resulting Matrix4 instance.</returns>
394
        public static Matrix4 CreateRotationZ(float angle)
395
        {
396
            Matrix4 result;
397
            CreateRotationZ(angle, out result);
398
            return result;
399
        }
400
 
401
        #endregion
402
 
403
        #region CreateTranslation
404
 
405
        /// <summary>
406
        /// Creates a translation matrix.
407
        /// </summary>
408
        /// <param name="x">X translation.</param>
409
        /// <param name="y">Y translation.</param>
410
        /// <param name="z">Z translation.</param>
411
        /// <param name="result">The resulting Matrix4 instance.</param>
412
        public static void CreateTranslation(float x, float y, float z, out Matrix4 result)
413
        {
414
            result = Identity;
415
            result.Row3 = new Vector4(x, y, z, 1);
416
        }
417
 
418
        /// <summary>
419
        /// Creates a translation matrix.
420
        /// </summary>
421
        /// <param name="vector">The translation vector.</param>
422
        /// <param name="result">The resulting Matrix4 instance.</param>
423
        public static void CreateTranslation(ref Vector3 vector, out Matrix4 result)
424
        {
425
            result = Identity;
426
            result.Row3 = new Vector4(vector.X, vector.Y, vector.Z, 1);
427
        }
428
 
429
        /// <summary>
430
        /// Creates a translation matrix.
431
        /// </summary>
432
        /// <param name="x">X translation.</param>
433
        /// <param name="y">Y translation.</param>
434
        /// <param name="z">Z translation.</param>
435
        /// <returns>The resulting Matrix4 instance.</returns>
436
        public static Matrix4 CreateTranslation(float x, float y, float z)
437
        {
438
            Matrix4 result;
439
            CreateTranslation(x, y, z, out result);
440
            return result;
441
        }
442
 
443
        /// <summary>
444
        /// Creates a translation matrix.
445
        /// </summary>
446
        /// <param name="vector">The translation vector.</param>
447
        /// <returns>The resulting Matrix4 instance.</returns>
448
        public static Matrix4 CreateTranslation(Vector3 vector)
449
        {
450
            Matrix4 result;
451
            CreateTranslation(vector.X, vector.Y, vector.Z, out result);
452
            return result;
453
        }
454
 
455
        #endregion
456
 
457
        #region CreateOrthographic
458
 
459
        /// <summary>
460
        /// Creates an orthographic projection matrix.
461
        /// </summary>
462
        /// <param name="width">The width of the projection volume.</param>
463
        /// <param name="height">The height of the projection volume.</param>
464
        /// <param name="zNear">The near edge of the projection volume.</param>
465
        /// <param name="zFar">The far edge of the projection volume.</param>
466
        /// <param name="result">The resulting Matrix4 instance.</param>
467
        public static void CreateOrthographic(float width, float height, float zNear, float zFar, out Matrix4 result)
468
        {
469
            CreateOrthographicOffCenter(-width / 2, width / 2, -height / 2, height / 2, zNear, zFar, out result);
470
        }
471
 
472
        /// <summary>
473
        /// Creates an orthographic projection matrix.
474
        /// </summary>
475
        /// <param name="width">The width of the projection volume.</param>
476
        /// <param name="height">The height of the projection volume.</param>
477
        /// <param name="zNear">The near edge of the projection volume.</param>
478
        /// <param name="zFar">The far edge of the projection volume.</param>
479
        /// <rereturns>The resulting Matrix4 instance.</rereturns>
480
        public static Matrix4 CreateOrthographic(float width, float height, float zNear, float zFar)
481
        {
482
            Matrix4 result;
483
            CreateOrthographicOffCenter(-width / 2, width / 2, -height / 2, height / 2, zNear, zFar, out result);
484
            return result;
485
        }
486
 
487
        #endregion
488
 
489
        #region CreateOrthographicOffCenter
490
 
491
        /// <summary>
492
        /// Creates an orthographic projection matrix.
493
        /// </summary>
494
        /// <param name="left">The left edge of the projection volume.</param>
495
        /// <param name="right">The right edge of the projection volume.</param>
496
        /// <param name="bottom">The bottom edge of the projection volume.</param>
497
        /// <param name="top">The top edge of the projection volume.</param>
498
        /// <param name="zNear">The near edge of the projection volume.</param>
499
        /// <param name="zFar">The far edge of the projection volume.</param>
500
        /// <param name="result">The resulting Matrix4 instance.</param>
501
        public static void CreateOrthographicOffCenter(float left, float right, float bottom, float top, float zNear, float zFar, out Matrix4 result)
502
        {
503
            result = new Matrix4();
504
 
505
            float invRL = 1 / (right - left);
506
            float invTB = 1 / (top - bottom);
507
            float invFN = 1 / (zFar - zNear);
508
 
509
            result.M11 = 2 * invRL;
510
            result.M22 = 2 * invTB;
511
            result.M33 = -2 * invFN;
512
 
513
            result.M41 = -(right + left) * invRL;
514
            result.M42 = -(top + bottom) * invTB;
515
            result.M43 = -(zFar + zNear) * invFN;
516
            result.M44 = 1;
517
        }
518
 
519
        /// <summary>
520
        /// Creates an orthographic projection matrix.
521
        /// </summary>
522
        /// <param name="left">The left edge of the projection volume.</param>
523
        /// <param name="right">The right edge of the projection volume.</param>
524
        /// <param name="bottom">The bottom edge of the projection volume.</param>
525
        /// <param name="top">The top edge of the projection volume.</param>
526
        /// <param name="zNear">The near edge of the projection volume.</param>
527
        /// <param name="zFar">The far edge of the projection volume.</param>
528
        /// <returns>The resulting Matrix4 instance.</returns>
529
        public static Matrix4 CreateOrthographicOffCenter(float left, float right, float bottom, float top, float zNear, float zFar)
530
        {
531
            Matrix4 result;
532
            CreateOrthographicOffCenter(left, right, bottom, top, zNear, zFar, out result);
533
            return result;
534
        }
535
 
536
        #endregion
537
 
538
        #region CreatePerspectiveFieldOfView
539
 
540
        /// <summary>
541
        /// Creates a perspective projection matrix.
542
        /// </summary>
543
        /// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
544
        /// <param name="aspect">Aspect ratio of the view (width / height)</param>
545
        /// <param name="zNear">Distance to the near clip plane</param>
546
        /// <param name="zFar">Distance to the far clip plane</param>
547
        /// <param name="result">A projection matrix that transforms camera space to raster space</param>
548
        /// <exception cref="System.ArgumentOutOfRangeException">
549
        /// Thrown under the following conditions:
550
        /// <list type="bullet">
551
        /// <item>fovy is zero, less than zero or larger than Math.PI</item>
552
        /// <item>aspect is negative or zero</item>
553
        /// <item>zNear is negative or zero</item>
554
        /// <item>zFar is negative or zero</item>
555
        /// <item>zNear is larger than zFar</item>
556
        /// </list>
557
        /// </exception>
558
        public static void CreatePerspectiveFieldOfView(float fovy, float aspect, float zNear, float zFar, out Matrix4 result)
559
        {
560
            if (fovy <= 0 || fovy > Math.PI)
561
                throw new ArgumentOutOfRangeException("fovy");
562
            if (aspect <= 0)
563
                throw new ArgumentOutOfRangeException("aspect");
564
            if (zNear <= 0)
565
                throw new ArgumentOutOfRangeException("zNear");
566
            if (zFar <= 0)
567
                throw new ArgumentOutOfRangeException("zFar");
568
            if (zNear >= zFar)
569
                throw new ArgumentOutOfRangeException("zNear");
570
 
571
            float yMax = zNear * (float)System.Math.Tan(0.5f * fovy);
572
            float yMin = -yMax;
573
            float xMin = yMin * aspect;
574
            float xMax = yMax * aspect;
575
 
576
            CreatePerspectiveOffCenter(xMin, xMax, yMin, yMax, zNear, zFar, out result);
577
        }
578
 
579
        /// <summary>
580
        /// Creates a perspective projection matrix.
581
        /// </summary>
582
        /// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
583
        /// <param name="aspect">Aspect ratio of the view (width / height)</param>
584
        /// <param name="zNear">Distance to the near clip plane</param>
585
        /// <param name="zFar">Distance to the far clip plane</param>
586
        /// <returns>A projection matrix that transforms camera space to raster space</returns>
587
        /// <exception cref="System.ArgumentOutOfRangeException">
588
        /// Thrown under the following conditions:
589
        /// <list type="bullet">
590
        /// <item>fovy is zero, less than zero or larger than Math.PI</item>
591
        /// <item>aspect is negative or zero</item>
592
        /// <item>zNear is negative or zero</item>
593
        /// <item>zFar is negative or zero</item>
594
        /// <item>zNear is larger than zFar</item>
595
        /// </list>
596
        /// </exception>
597
        public static Matrix4 CreatePerspectiveFieldOfView(float fovy, float aspect, float zNear, float zFar)
598
        {
599
            Matrix4 result;
600
            CreatePerspectiveFieldOfView(fovy, aspect, zNear, zFar, out result);
601
            return result;
602
        }
603
 
604
        #endregion
605
 
606
        #region CreatePerspectiveOffCenter
607
 
608
        /// <summary>
609
        /// Creates an perspective projection matrix.
610
        /// </summary>
611
        /// <param name="left">Left edge of the view frustum</param>
612
        /// <param name="right">Right edge of the view frustum</param>
613
        /// <param name="bottom">Bottom edge of the view frustum</param>
614
        /// <param name="top">Top edge of the view frustum</param>
615
        /// <param name="zNear">Distance to the near clip plane</param>
616
        /// <param name="zFar">Distance to the far clip plane</param>
617
        /// <param name="result">A projection matrix that transforms camera space to raster space</param>
618
        /// <exception cref="System.ArgumentOutOfRangeException">
619
        /// Thrown under the following conditions:
620
        /// <list type="bullet">
621
        /// <item>zNear is negative or zero</item>
622
        /// <item>zFar is negative or zero</item>
623
        /// <item>zNear is larger than zFar</item>
624
        /// </list>
625
        /// </exception>
626
        public static void CreatePerspectiveOffCenter(float left, float right, float bottom, float top, float zNear, float zFar, out Matrix4 result)
627
        {
628
            if (zNear <= 0)
629
                throw new ArgumentOutOfRangeException("zNear");
630
            if (zFar <= 0)
631
                throw new ArgumentOutOfRangeException("zFar");
632
            if (zNear >= zFar)
633
                throw new ArgumentOutOfRangeException("zNear");
634
 
635
            float x = (2.0f * zNear) / (right - left);
636
            float y = (2.0f * zNear) / (top - bottom);
637
            float a = (right + left) / (right - left);
638
            float b = (top + bottom) / (top - bottom);
639
            float c = -(zFar + zNear) / (zFar - zNear);
640
            float d = -(2.0f * zFar * zNear) / (zFar - zNear);
641
 
642
            result = new Matrix4(x, 0, 0,  0,
643
                                 0, y, 0,  0,
644
                                 a, b, c, -1,
645
                                 0, 0, d,  0);
646
        }
647
 
648
        /// <summary>
649
        /// Creates an perspective projection matrix.
650
        /// </summary>
651
        /// <param name="left">Left edge of the view frustum</param>
652
        /// <param name="right">Right edge of the view frustum</param>
653
        /// <param name="bottom">Bottom edge of the view frustum</param>
654
        /// <param name="top">Top edge of the view frustum</param>
655
        /// <param name="zNear">Distance to the near clip plane</param>
656
        /// <param name="zFar">Distance to the far clip plane</param>
657
        /// <returns>A projection matrix that transforms camera space to raster space</returns>
658
        /// <exception cref="System.ArgumentOutOfRangeException">
659
        /// Thrown under the following conditions:
660
        /// <list type="bullet">
661
        /// <item>zNear is negative or zero</item>
662
        /// <item>zFar is negative or zero</item>
663
        /// <item>zNear is larger than zFar</item>
664
        /// </list>
665
        /// </exception>
666
        public static Matrix4 CreatePerspectiveOffCenter(float left, float right, float bottom, float top, float zNear, float zFar)
667
        {
668
            Matrix4 result;
669
            CreatePerspectiveOffCenter(left, right, bottom, top, zNear, zFar, out result);
670
            return result;
671
        }
672
 
673
        #endregion
674
 
675
        #region Obsolete Functions
676
 
677
        #region Translation Functions
678
 
679
        /// <summary>
680
        /// Builds a translation matrix.
681
        /// </summary>
682
        /// <param name="trans">The translation vector.</param>
683
        /// <returns>A new Matrix4 instance.</returns>
684
        [Obsolete("Use CreateTranslation instead.")]
685
        public static Matrix4 Translation(Vector3 trans)
686
        {
687
            return Translation(trans.X, trans.Y, trans.Z);
688
        }
689
 
690
        /// <summary>
691
        /// Build a translation matrix with the given translation
692
        /// </summary>
693
        /// <param name="x">X translation</param>
694
        /// <param name="y">Y translation</param>
695
        /// <param name="z">Z translation</param>
696
        /// <returns>A Translation matrix</returns>
697
        [Obsolete("Use CreateTranslation instead.")]
698
        public static Matrix4 Translation(float x, float y, float z)
699
        {
700
            Matrix4 result = Identity;
701
            result.Row3 = new Vector4(x, y, z, 1.0f);
702
            return result;
703
        }
704
 
705
        #endregion
706
 
707
        #endregion
708
 
709
        #region Scale Functions
710
 
711
        /// <summary>
712
        /// Build a scaling matrix
713
        /// </summary>
714
        /// <param name="scale">Single scale factor for x,y and z axes</param>
715
        /// <returns>A scaling matrix</returns>
716
        public static Matrix4 Scale(float scale)
717
        {
718
            return Scale(scale, scale, scale);
719
        }
720
 
721
        /// <summary>
722
        /// Build a scaling matrix
723
        /// </summary>
724
        /// <param name="scale">Scale factors for x,y and z axes</param>
725
        /// <returns>A scaling matrix</returns>
726
        public static Matrix4 Scale(Vector3 scale)
727
        {
728
            return Scale(scale.X, scale.Y, scale.Z);
729
        }
730
 
731
        /// <summary>
732
        /// Build a scaling matrix
733
        /// </summary>
734
        /// <param name="x">Scale factor for x-axis</param>
735
        /// <param name="y">Scale factor for y-axis</param>
736
        /// <param name="z">Scale factor for z-axis</param>
737
        /// <returns>A scaling matrix</returns>
738
        public static Matrix4 Scale(float x, float y, float z)
739
        {
740
            Matrix4 result;
741
            result.Row0 = Vector4.UnitX * x;
742
            result.Row1 = Vector4.UnitY * y;
743
            result.Row2 = Vector4.UnitZ * z;
744
            result.Row3 = Vector4.UnitW;
745
            return result;
746
        }
747
 
748
        #endregion
749
 
750
        #region Rotation Functions
751
 
752
        /// <summary>
753
        /// Build a rotation matrix that rotates about the x-axis
754
        /// </summary>
755
        /// <param name="angle">angle in radians to rotate counter-clockwise around the x-axis</param>
756
        /// <returns>A rotation matrix</returns>
757
        [Obsolete("Use CreateRotationX instead.")]
758
        public static Matrix4 RotateX(float angle)
759
        {
760
            float cos = (float)System.Math.Cos(angle);
761
            float sin = (float)System.Math.Sin(angle);
762
 
763
            Matrix4 result;
764
            result.Row0 = Vector4.UnitX;
765
            result.Row1 = new Vector4(0.0f, cos, sin, 0.0f);
766
            result.Row2 = new Vector4(0.0f, -sin, cos, 0.0f);
767
            result.Row3 = Vector4.UnitW;
768
            return result;
769
        }
770
 
771
        /// <summary>
772
        /// Build a rotation matrix that rotates about the y-axis
773
        /// </summary>
774
        /// <param name="angle">angle in radians to rotate counter-clockwise around the y-axis</param>
775
        /// <returns>A rotation matrix</returns>
776
        [Obsolete("Use CreateRotationY instead.")]
777
        public static Matrix4 RotateY(float angle)
778
        {
779
            float cos = (float)System.Math.Cos(angle);
780
            float sin = (float)System.Math.Sin(angle);
781
 
782
            Matrix4 result;
783
            result.Row0 = new Vector4(cos, 0.0f, -sin, 0.0f);
784
            result.Row1 = Vector4.UnitY;
785
            result.Row2 = new Vector4(sin, 0.0f, cos, 0.0f);
786
            result.Row3 = Vector4.UnitW;
787
            return result;
788
        }
789
 
790
        /// <summary>
791
        /// Build a rotation matrix that rotates about the z-axis
792
        /// </summary>
793
        /// <param name="angle">angle in radians to rotate counter-clockwise around the z-axis</param>
794
        /// <returns>A rotation matrix</returns>
795
        [Obsolete("Use CreateRotationZ instead.")]
796
        public static Matrix4 RotateZ(float angle)
797
        {
798
            float cos = (float)System.Math.Cos(angle);
799
            float sin = (float)System.Math.Sin(angle);
800
 
801
            Matrix4 result;
802
            result.Row0 = new Vector4(cos, sin, 0.0f, 0.0f);
803
            result.Row1 = new Vector4(-sin, cos, 0.0f, 0.0f);
804
            result.Row2 = Vector4.UnitZ;
805
            result.Row3 = Vector4.UnitW;
806
            return result;
807
        }
808
 
809
        /// <summary>
810
        /// Build a rotation matrix to rotate about the given axis
811
        /// </summary>
812
        /// <param name="axis">the axis to rotate about</param>
813
        /// <param name="angle">angle in radians to rotate counter-clockwise (looking in the direction of the given axis)</param>
814
        /// <returns>A rotation matrix</returns>
815
        [Obsolete("Use CreateFromAxisAngle instead.")]
816
        public static Matrix4 Rotate(Vector3 axis, float angle)
817
        {
818
            float cos = (float)System.Math.Cos(-angle);
819
            float sin = (float)System.Math.Sin(-angle);
820
            float t = 1.0f - cos;
821
 
822
            axis.Normalize();
823
 
824
            Matrix4 result;
825
            result.Row0 = new Vector4(t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0f);
826
            result.Row1 = new Vector4(t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f);
827
            result.Row2 = new Vector4(t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f);
828
            result.Row3 = Vector4.UnitW;
829
            return result;
830
        }
831
 
832
        /// <summary>
833
        /// Build a rotation matrix from a quaternion
834
        /// </summary>
835
        /// <param name="q">the quaternion</param>
836
        /// <returns>A rotation matrix</returns>
837
        public static Matrix4 Rotate(Quaternion q)
838
        {
839
            Vector3 axis;
840
            float angle;
841
            q.ToAxisAngle(out axis, out angle);
842
            return CreateFromAxisAngle(axis, angle);
843
        }
844
 
845
        #endregion
846
 
847
        #region Camera Helper Functions
848
 
849
        /// <summary>
850
        /// Build a world space to camera space matrix
851
        /// </summary>
852
        /// <param name="eye">Eye (camera) position in world space</param>
853
        /// <param name="target">Target position in world space</param>
854
        /// <param name="up">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
855
        /// <returns>A Matrix4 that transforms world space to camera space</returns>
856
        public static Matrix4 LookAt(Vector3 eye, Vector3 target, Vector3 up)
857
        {
858
            Vector3 z = Vector3.Normalize(eye - target);
859
            Vector3 x = Vector3.Normalize(Vector3.Cross(up, z));
860
            Vector3 y = Vector3.Normalize(Vector3.Cross(z, x));
861
 
862
            Matrix4 rot = new Matrix4(new Vector4(x.X, y.X, z.X, 0.0f),
863
                                        new Vector4(x.Y, y.Y, z.Y, 0.0f),
864
                                        new Vector4(x.Z, y.Z, z.Z, 0.0f),
865
                                        Vector4.UnitW);
866
 
867
            Matrix4 trans = Matrix4.CreateTranslation(-eye);
868
 
869
            return trans * rot;
870
        }
871
 
872
        /// <summary>
873
        /// Build a world space to camera space matrix
874
        /// </summary>
875
        /// <param name="eyeX">Eye (camera) position in world space</param>
876
        /// <param name="eyeY">Eye (camera) position in world space</param>
877
        /// <param name="eyeZ">Eye (camera) position in world space</param>
878
        /// <param name="targetX">Target position in world space</param>
879
        /// <param name="targetY">Target position in world space</param>
880
        /// <param name="targetZ">Target position in world space</param>
881
        /// <param name="upX">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
882
        /// <param name="upY">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
883
        /// <param name="upZ">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
884
        /// <returns>A Matrix4 that transforms world space to camera space</returns>
885
        public static Matrix4 LookAt(float eyeX, float eyeY, float eyeZ, float targetX, float targetY, float targetZ, float upX, float upY, float upZ)
886
        {
887
            return LookAt(new Vector3(eyeX, eyeY, eyeZ), new Vector3(targetX, targetY, targetZ), new Vector3(upX, upY, upZ));
888
        }
889
 
890
        /// <summary>
891
        /// Build a projection matrix
892
        /// </summary>
893
        /// <param name="left">Left edge of the view frustum</param>
894
        /// <param name="right">Right edge of the view frustum</param>
895
        /// <param name="bottom">Bottom edge of the view frustum</param>
896
        /// <param name="top">Top edge of the view frustum</param>
897
        /// <param name="near">Distance to the near clip plane</param>
898
        /// <param name="far">Distance to the far clip plane</param>
899
        /// <returns>A projection matrix that transforms camera space to raster space</returns>
900
        [Obsolete("Use CreatePerspectiveOffCenter instead.")]
901
        public static Matrix4 Frustum(float left, float right, float bottom, float top, float near, float far)
902
        {
903
            float invRL = 1.0f / (right - left);
904
            float invTB = 1.0f / (top - bottom);
905
            float invFN = 1.0f / (far - near);
906
            return new Matrix4(new Vector4(2.0f * near * invRL, 0.0f, 0.0f, 0.0f),
907
                               new Vector4(0.0f, 2.0f * near * invTB, 0.0f, 0.0f),
908
                               new Vector4((right + left) * invRL, (top + bottom) * invTB, -(far + near) * invFN, -1.0f),
909
                               new Vector4(0.0f, 0.0f, -2.0f * far * near * invFN, 0.0f));
910
        }
911
 
912
        /// <summary>
913
        /// Build a projection matrix
914
        /// </summary>
915
        /// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
916
        /// <param name="aspect">Aspect ratio of the view (width / height)</param>
917
        /// <param name="near">Distance to the near clip plane</param>
918
        /// <param name="far">Distance to the far clip plane</param>
919
        /// <returns>A projection matrix that transforms camera space to raster space</returns>
920
        [Obsolete("Use CreatePerspectiveFieldOfView instead.")]
921
        public static Matrix4 Perspective(float fovy, float aspect, float near, float far)
922
        {
923
            float yMax = near * (float)System.Math.Tan(0.5f * fovy);
924
            float yMin = -yMax;
925
            float xMin = yMin * aspect;
926
            float xMax = yMax * aspect;
927
 
928
            return Frustum(xMin, xMax, yMin, yMax, near, far);
929
        }
930
 
931
        #endregion
932
 
933
        #region Multiply Functions
934
 
935
        /// <summary>
936
        /// Multiplies two instances.
937
        /// </summary>
938
        /// <param name="left">The left operand of the multiplication.</param>
939
        /// <param name="right">The right operand of the multiplication.</param>
940
        /// <returns>A new instance that is the result of the multiplication</returns>
941
        public static Matrix4 Mult(Matrix4 left, Matrix4 right)
942
        {
943
            Matrix4 result;
944
            Mult(ref left, ref right, out result);
945
            return result;
946
        }
947
 
948
        /// <summary>
949
        /// Multiplies two instances.
950
        /// </summary>
951
        /// <param name="left">The left operand of the multiplication.</param>
952
        /// <param name="right">The right operand of the multiplication.</param>
953
        /// <param name="result">A new instance that is the result of the multiplication</param>
954
        public static void Mult(ref Matrix4 left, ref Matrix4 right, out Matrix4 result)
955
        {
956
            result = new Matrix4(
957
                left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41,
958
                left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42,
959
                left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43,
960
                left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44,
961
                left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41,
962
                left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42,
963
                left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43,
964
                left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44,
965
                left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41,
966
                left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42,
967
                left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43,
968
                left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44,
969
                left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41,
970
                left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42,
971
                left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43,
972
                left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44);
973
        }
974
 
975
        #endregion
976
 
977
        #region Invert Functions
978
 
979
        /// <summary>
980
        /// Calculate the inverse of the given matrix
981
        /// </summary>
982
        /// <param name="mat">The matrix to invert</param>
983
        /// <returns>The inverse of the given matrix if it has one, or the input if it is singular</returns>
984
        /// <exception cref="InvalidOperationException">Thrown if the Matrix4 is singular.</exception>
985
        public static Matrix4 Invert(Matrix4 mat)
986
        {
987
            int[] colIdx = { 0, 0, 0, 0 };
988
            int[] rowIdx = { 0, 0, 0, 0 };
989
            int[] pivotIdx = { -1, -1, -1, -1 };
990
 
991
            // convert the matrix to an array for easy looping
992
            float[,] inverse = {{mat.Row0.X, mat.Row0.Y, mat.Row0.Z, mat.Row0.W},
993
                                {mat.Row1.X, mat.Row1.Y, mat.Row1.Z, mat.Row1.W},
994
                                {mat.Row2.X, mat.Row2.Y, mat.Row2.Z, mat.Row2.W},
995
                                {mat.Row3.X, mat.Row3.Y, mat.Row3.Z, mat.Row3.W} };
996
            int icol = 0;
997
            int irow = 0;
998
            for (int i = 0; i < 4; i++)
999
            {
1000
                // Find the largest pivot value
1001
                float maxPivot = 0.0f;
1002
                for (int j = 0; j < 4; j++)
1003
                {
1004
                    if (pivotIdx[j] != 0)
1005
                    {
1006
                        for (int k = 0; k < 4; ++k)
1007
                        {
1008
                            if (pivotIdx[k] == -1)
1009
                            {
1010
                                float absVal = System.Math.Abs(inverse[j, k]);
1011
                                if (absVal > maxPivot)
1012
                                {
1013
                                    maxPivot = absVal;
1014
                                    irow = j;
1015
                                    icol = k;
1016
                                }
1017
                            }
1018
                            else if (pivotIdx[k] > 0)
1019
                            {
1020
                                return mat;
1021
                            }
1022
                        }
1023
                    }
1024
                }
1025
 
1026
                ++(pivotIdx[icol]);
1027
 
1028
                // Swap rows over so pivot is on diagonal
1029
                if (irow != icol)
1030
                {
1031
                    for (int k = 0; k < 4; ++k)
1032
                    {
1033
                        float f = inverse[irow, k];
1034
                        inverse[irow, k] = inverse[icol, k];
1035
                        inverse[icol, k] = f;
1036
                    }
1037
                }
1038
 
1039
                rowIdx[i] = irow;
1040
                colIdx[i] = icol;
1041
 
1042
                float pivot = inverse[icol, icol];
1043
                // check for singular matrix
1044
                if (pivot == 0.0f)
1045
                {
1046
                    throw new InvalidOperationException("Matrix is singular and cannot be inverted.");
1047
                    //return mat;
1048
                }
1049
 
1050
                // Scale row so it has a unit diagonal
1051
                float oneOverPivot = 1.0f / pivot;
1052
                inverse[icol, icol] = 1.0f;
1053
                for (int k = 0; k < 4; ++k)
1054
                    inverse[icol, k] *= oneOverPivot;
1055
 
1056
                // Do elimination of non-diagonal elements
1057
                for (int j = 0; j < 4; ++j)
1058
                {
1059
                    // check this isn't on the diagonal
1060
                    if (icol != j)
1061
                    {
1062
                        float f = inverse[j, icol];
1063
                        inverse[j, icol] = 0.0f;
1064
                        for (int k = 0; k < 4; ++k)
1065
                            inverse[j, k] -= inverse[icol, k] * f;
1066
                    }
1067
                }
1068
            }
1069
 
1070
            for (int j = 3; j >= 0; --j)
1071
            {
1072
                int ir = rowIdx[j];
1073
                int ic = colIdx[j];
1074
                for (int k = 0; k < 4; ++k)
1075
                {
1076
                    float f = inverse[k, ir];
1077
                    inverse[k, ir] = inverse[k, ic];
1078
                    inverse[k, ic] = f;
1079
                }
1080
            }
1081
 
1082
            mat.Row0 = new Vector4(inverse[0, 0], inverse[0, 1], inverse[0, 2], inverse[0, 3]);
1083
            mat.Row1 = new Vector4(inverse[1, 0], inverse[1, 1], inverse[1, 2], inverse[1, 3]);
1084
            mat.Row2 = new Vector4(inverse[2, 0], inverse[2, 1], inverse[2, 2], inverse[2, 3]);
1085
            mat.Row3 = new Vector4(inverse[3, 0], inverse[3, 1], inverse[3, 2], inverse[3, 3]);
1086
            return mat;
1087
        }
1088
 
1089
        #endregion
1090
 
1091
        #region Transpose
1092
 
1093
        /// <summary>
1094
        /// Calculate the transpose of the given matrix
1095
        /// </summary>
1096
        /// <param name="mat">The matrix to transpose</param>
1097
        /// <returns>The transpose of the given matrix</returns>
1098
        public static Matrix4 Transpose(Matrix4 mat)
1099
        {
1100
            return new Matrix4(mat.Column0, mat.Column1, mat.Column2, mat.Column3);
1101
        }
1102
 
1103
 
1104
        /// <summary>
1105
        /// Calculate the transpose of the given matrix
1106
        /// </summary>
1107
        /// <param name="mat">The matrix to transpose</param>
1108
        /// <param name="result">The result of the calculation</param>
1109
        public static void Transpose(ref Matrix4 mat, out Matrix4 result)
1110
        {
1111
            result.Row0 = mat.Column0;
1112
            result.Row1 = mat.Column1;
1113
            result.Row2 = mat.Column2;
1114
            result.Row3 = mat.Column3;
1115
        }
1116
 
1117
        #endregion
1118
 
1119
        #endregion
1120
 
1121
        #region Operators
1122
 
1123
        /// <summary>
1124
        /// Matrix multiplication
1125
        /// </summary>
1126
        /// <param name="left">left-hand operand</param>
1127
        /// <param name="right">right-hand operand</param>
1128
        /// <returns>A new Matrix44 which holds the result of the multiplication</returns>
1129
        public static Matrix4 operator *(Matrix4 left, Matrix4 right)
1130
        {
1131
            return Matrix4.Mult(left, right);
1132
        }
1133
 
1134
        /// <summary>
1135
        /// Compares two instances for equality.
1136
        /// </summary>
1137
        /// <param name="left">The first instance.</param>
1138
        /// <param name="right">The second instance.</param>
1139
        /// <returns>True, if left equals right; false otherwise.</returns>
1140
        public static bool operator ==(Matrix4 left, Matrix4 right)
1141
        {
1142
            return left.Equals(right);
1143
        }
1144
 
1145
        /// <summary>
1146
        /// Compares two instances for inequality.
1147
        /// </summary>
1148
        /// <param name="left">The first instance.</param>
1149
        /// <param name="right">The second instance.</param>
1150
        /// <returns>True, if left does not equal right; false otherwise.</returns>
1151
        public static bool operator !=(Matrix4 left, Matrix4 right)
1152
        {
1153
            return !left.Equals(right);
1154
        }
1155
 
1156
        #endregion
1157
 
1158
        #region Overrides
1159
 
1160
        #region public override string ToString()
1161
 
1162
        /// <summary>
1163
        /// Returns a System.String that represents the current Matrix44.
1164
        /// </summary>
1165
        /// <returns></returns>
1166
        public override string ToString()
1167
        {
1168
            return String.Format("{0}\n{1}\n{2}\n{3}", Row0, Row1, Row2, Row3);
1169
        }
1170
 
1171
        #endregion
1172
 
1173
        #region public override int GetHashCode()
1174
 
1175
        /// <summary>
1176
        /// Returns the hashcode for this instance.
1177
        /// </summary>
1178
        /// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
1179
        public override int GetHashCode()
1180
        {
1181
            return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode() ^ Row3.GetHashCode();
1182
        }
1183
 
1184
        #endregion
1185
 
1186
        #region public override bool Equals(object obj)
1187
 
1188
        /// <summary>
1189
        /// Indicates whether this instance and a specified object are equal.
1190
        /// </summary>
1191
        /// <param name="obj">The object to compare tresult.</param>
1192
        /// <returns>True if the instances are equal; false otherwise.</returns>
1193
        public override bool Equals(object obj)
1194
        {
1195
            if (!(obj is Matrix4))
1196
                return false;
1197
 
1198
            return this.Equals((Matrix4)obj);
1199
        }
1200
 
1201
        #endregion
1202
 
1203
        #endregion
1204
 
1205
        #endregion
1206
 
1207
        #region IEquatable<Matrix4> Members
1208
 
1209
        /// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
1210
        /// <param name="other">An matrix to compare with this matrix.</param>
1211
        /// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
1212
        public bool Equals(Matrix4 other)
1213
        {
1214
            return
1215
                Row0 == other.Row0 &&
1216
                Row1 == other.Row1 &&
1217
                Row2 == other.Row2 &&
1218
                Row3 == other.Row3;
1219
        }
1220
 
1221
        #endregion
1222
    }
1223
}