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 with double-precision components.
32
    /// </summary>
33
    [Serializable]
34
    [StructLayout(LayoutKind.Sequential)]
35
    public struct Matrix4d : IEquatable<Matrix4d>
36
    {
37
        #region Fields
38
 
39
        /// <summary>
40
        /// Top row of the matrix
41
        /// </summary>
42
        public Vector4d  Row0;
43
        /// <summary>
44
        /// 2nd row of the matrix
45
        /// </summary>
46
        public Vector4d  Row1;
47
        /// <summary>
48
        /// 3rd row of the matrix
49
        /// </summary>
50
        public Vector4d  Row2;
51
        /// <summary>
52
        /// Bottom row of the matrix
53
        /// </summary>
54
        public Vector4d  Row3;
55
 
56
        /// <summary>
57
        /// The identity matrix
58
        /// </summary>
59
        public static Matrix4d Identity = new Matrix4d(Vector4d .UnitX, Vector4d .UnitY, Vector4d .UnitZ, Vector4d .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 Matrix4d(Vector4d row0, Vector4d row1, Vector4d row2, Vector4d 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.</param>
84
        /// <param name="m01">Second item of the first row.</param>
85
        /// <param name="m02">Third item of the first row.</param>
86
        /// <param name="m03">Fourth item of the first row.</param>
87
        /// <param name="m10">First item of the second row.</param>
88
        /// <param name="m11">Second item of the second row.</param>
89
        /// <param name="m12">Third item of the second row.</param>
90
        /// <param name="m13">Fourth item of the second row.</param>
91
        /// <param name="m20">First item of the third row.</param>
92
        /// <param name="m21">Second item of the third row.</param>
93
        /// <param name="m22">Third item of the third row.</param>
94
        /// <param name="m23">First item of the third row.</param>
95
        /// <param name="m30">Fourth item of the fourth row.</param>
96
        /// <param name="m31">Second item of the fourth row.</param>
97
        /// <param name="m32">Third item of the fourth row.</param>
98
        /// <param name="m33">Fourth item of the fourth row.</param>
99
        public Matrix4d(
100
            double m00, double m01, double m02, double m03,
101
            double m10, double m11, double m12, double m13,
102
            double m20, double m21, double m22, double m23,
103
            double m30, double m31, double m32, double m33)
104
        {
105
            Row0 = new Vector4d(m00, m01, m02, m03);
106
            Row1 = new Vector4d(m10, m11, m12, m13);
107
            Row2 = new Vector4d(m20, m21, m22, m23);
108
            Row3 = new Vector4d(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 double 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 Vector4d  Column0
138
        {
139
            get { return new Vector4d (Row0.X, Row1.X, Row2.X, Row3.X); }
140
        }
141
 
142
        /// <summary>
143
        /// The second column of this matrix
144
        /// </summary>
145
        public Vector4d  Column1
146
        {
147
            get { return new Vector4d (Row0.Y, Row1.Y, Row2.Y, Row3.Y); }
148
        }
149
 
150
        /// <summary>
151
        /// The third column of this matrix
152
        /// </summary>
153
        public Vector4d  Column2
154
        {
155
            get { return new Vector4d (Row0.Z, Row1.Z, Row2.Z, Row3.Z); }
156
        }
157
 
158
        /// <summary>
159
        /// The fourth column of this matrix
160
        /// </summary>
161
        public Vector4d  Column3
162
        {
163
            get { return new Vector4d (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 double 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 double 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 double 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 double 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 double 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 double 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 double 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 double 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 double 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 double 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 double 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 double 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 double 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 double 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 double 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 double 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 = Matrix4d.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 = Matrix4d.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(Vector3d axis, double angle, out Matrix4d result)
287
        {
288
            double cos = System.Math.Cos(-angle);
289
            double sin = System.Math.Sin(-angle);
290
            double t = 1.0 - cos;
291
 
292
            axis.Normalize();
293
 
294
            result = new Matrix4d(t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0,
295
                                 t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0,
296
                                 t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0,
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 Matrix4d CreateFromAxisAngle(Vector3d axis, double angle)
307
        {
308
            Matrix4d 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(double angle, out Matrix4d result)
323
        {
324
            double cos = System.Math.Cos(angle);
325
            double sin = System.Math.Sin(angle);
326
 
327
            result.Row0 = Vector4d.UnitX;
328
            result.Row1 = new Vector4d(0, cos, sin, 0);
329
            result.Row2 = new Vector4d(0, -sin, cos, 0);
330
            result.Row3 = Vector4d.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 Matrix4d CreateRotationX(double angle)
339
        {
340
            Matrix4d 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(double angle, out Matrix4d result)
351
        {
352
            double cos = System.Math.Cos(angle);
353
            double sin = System.Math.Sin(angle);
354
 
355
            result.Row0 = new Vector4d(cos, 0, -sin, 0);
356
            result.Row1 = Vector4d.UnitY;
357
            result.Row2 = new Vector4d(sin, 0, cos, 0);
358
            result.Row3 = Vector4d.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 Matrix4d CreateRotationY(double angle)
367
        {
368
            Matrix4d 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(double angle, out Matrix4d result)
379
        {
380
            double cos = System.Math.Cos(angle);
381
            double sin = System.Math.Sin(angle);
382
 
383
            result.Row0 = new Vector4d(cos, sin, 0, 0);
384
            result.Row1 = new Vector4d(-sin, cos, 0, 0);
385
            result.Row2 = Vector4d.UnitZ;
386
            result.Row3 = Vector4d.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 Matrix4d CreateRotationZ(double angle)
395
        {
396
            Matrix4d 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 Matrix4d instance.</param>
412
        public static void CreateTranslation(double x, double y, double z, out Matrix4d result)
413
        {
414
            result = Identity;
415
            result.Row3 = new Vector4d(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 Matrix4d instance.</param>
423
        public static void CreateTranslation(ref Vector3d vector, out Matrix4d result)
424
        {
425
            result = Identity;
426
            result.Row3 = new Vector4d(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 Matrix4d instance.</returns>
436
        public static Matrix4d CreateTranslation(double x, double y, double z)
437
        {
438
            Matrix4d 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 Matrix4d instance.</returns>
448
        public static Matrix4d CreateTranslation(Vector3d vector)
449
        {
450
            Matrix4d 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 Matrix4d instance.</param>
467
        public static void CreateOrthographic(double width, double height, double zNear, double zFar, out Matrix4d 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 Matrix4d instance.</rereturns>
480
        public static Matrix4d CreateOrthographic(double width, double height, double zNear, double zFar)
481
        {
482
            Matrix4d 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 Matrix4d instance.</param>
501
        public static void CreateOrthographicOffCenter(double left, double right, double bottom, double top, double zNear, double zFar, out Matrix4d result)
502
        {
503
            result = new Matrix4d();
504
 
505
            double invRL = 1 / (right - left);
506
            double invTB = 1 / (top - bottom);
507
            double 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 Matrix4d instance.</returns>
529
        public static Matrix4d CreateOrthographicOffCenter(double left, double right, double bottom, double top, double zNear, double zFar)
530
        {
531
            Matrix4d 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(double fovy, double aspect, double zNear, double zFar, out Matrix4d 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
            double yMax = zNear * System.Math.Tan(0.5 * fovy);
572
            double yMin = -yMax;
573
            double xMin = yMin * aspect;
574
            double 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 Matrix4d CreatePerspectiveFieldOfView(double fovy, double aspect, double zNear, double zFar)
598
        {
599
            Matrix4d 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(double left, double right, double bottom, double top, double zNear, double zFar, out Matrix4d 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
            double x = (2.0 * zNear) / (right - left);
636
            double y = (2.0 * zNear) / (top - bottom);
637
            double a = (right + left) / (right - left);
638
            double b = (top + bottom) / (top - bottom);
639
            double c = -(zFar + zNear) / (zFar - zNear);
640
            double d = -(2.0 * zFar * zNear) / (zFar - zNear);
641
 
642
            result = new Matrix4d(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 Matrix4d CreatePerspectiveOffCenter(double left, double right, double bottom, double top, double zNear, double zFar)
667
        {
668
            Matrix4d 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
        /// Build a translation matrix with the given translation
681
        /// </summary>
682
        /// <param name="trans">The vector to translate along</param>
683
        /// <returns>A Translation matrix</returns>
684
        [Obsolete("Use CreateTranslation instead.")]
685
        public static Matrix4d Translation(Vector3d 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 Matrix4d Translation(double x, double y, double z)
699
        {
700
            Matrix4d result = Identity;
701
            result.Row3 = new Vector4d(x, y, z, 1.0);
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 Matrix4d Scale(double 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 Matrix4d Scale(Vector3d 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 Matrix4d Scale(double x, double y, double z)
739
        {
740
            Matrix4d result;
741
            result.Row0 = Vector4d .UnitX * x;
742
            result.Row1 = Vector4d .UnitY * y;
743
            result.Row2 = Vector4d .UnitZ * z;
744
            result.Row3 = Vector4d .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
        public static Matrix4d RotateX(double angle)
758
        {
759
            double cos = System.Math.Cos(angle);
760
            double sin = System.Math.Sin(angle);
761
 
762
            Matrix4d result;
763
            result.Row0 = Vector4d .UnitX;
764
            result.Row1 = new Vector4d (0.0, cos, sin, 0.0);
765
            result.Row2 = new Vector4d (0.0, -sin, cos, 0.0);
766
            result.Row3 = Vector4d .UnitW;
767
            return result;
768
        }
769
 
770
        /// <summary>
771
        /// Build a rotation matrix that rotates about the y-axis
772
        /// </summary>
773
        /// <param name="angle">angle in radians to rotate counter-clockwise around the y-axis</param>
774
        /// <returns>A rotation matrix</returns>
775
        public static Matrix4d RotateY(double angle)
776
        {
777
            double cos = System.Math.Cos(angle);
778
            double sin = System.Math.Sin(angle);
779
 
780
            Matrix4d result;
781
            result.Row0 = new Vector4d (cos, 0.0, -sin, 0.0);
782
            result.Row1 = Vector4d .UnitY;
783
            result.Row2 = new Vector4d (sin, 0.0, cos, 0.0);
784
            result.Row3 = Vector4d .UnitW;
785
            return result;
786
        }
787
 
788
        /// <summary>
789
        /// Build a rotation matrix that rotates about the z-axis
790
        /// </summary>
791
        /// <param name="angle">angle in radians to rotate counter-clockwise around the z-axis</param>
792
        /// <returns>A rotation matrix</returns>
793
        public static Matrix4d RotateZ(double angle)
794
        {
795
            double cos = System.Math.Cos(angle);
796
            double sin = System.Math.Sin(angle);
797
 
798
            Matrix4d result;
799
            result.Row0 = new Vector4d (cos, sin, 0.0, 0.0);
800
            result.Row1 = new Vector4d (-sin, cos, 0.0, 0.0);
801
            result.Row2 = Vector4d .UnitZ;
802
            result.Row3 = Vector4d .UnitW;
803
            return result;
804
        }
805
 
806
        /// <summary>
807
        /// Build a rotation matrix to rotate about the given axis
808
        /// </summary>
809
        /// <param name="axis">the axis to rotate about</param>
810
        /// <param name="angle">angle in radians to rotate counter-clockwise (looking in the direction of the given axis)</param>
811
        /// <returns>A rotation matrix</returns>
812
        public static Matrix4d Rotate(Vector3d axis, double angle)
813
        {
814
            double cos = System.Math.Cos(-angle);
815
            double sin = System.Math.Sin(-angle);
816
            double t = 1.0 - cos;
817
 
818
            axis.Normalize();
819
 
820
            Matrix4d result;
821
            result.Row0 = new Vector4d (t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0);
822
            result.Row1 = new Vector4d (t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0);
823
            result.Row2 = new Vector4d (t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0);
824
            result.Row3 = Vector4d .UnitW;
825
            return result;
826
        }
827
 
828
        /// <summary>
829
        /// Build a rotation matrix from a quaternion
830
        /// </summary>
831
        /// <param name="q">the quaternion</param>
832
        /// <returns>A rotation matrix</returns>
833
        public static Matrix4d Rotate(Quaterniond q)
834
        {
835
            Vector3d axis;
836
            double angle;
837
            q.ToAxisAngle(out axis, out angle);
838
            return Rotate(axis, angle);
839
        }
840
 
841
        #endregion
842
 
843
        #region Camera Helper Functions
844
 
845
        /// <summary>
846
        /// Build a world space to camera space matrix
847
        /// </summary>
848
        /// <param name="eye">Eye (camera) position in world space</param>
849
        /// <param name="target">Target position in world space</param>
850
        /// <param name="up">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
851
        /// <returns>A Matrix that transforms world space to camera space</returns>
852
        public static Matrix4d LookAt(Vector3d eye, Vector3d target, Vector3d up)
853
        {
854
            Vector3d z = Vector3d.Normalize(eye - target);
855
            Vector3d x = Vector3d.Normalize(Vector3d.Cross(up, z));
856
            Vector3d y = Vector3d.Normalize(Vector3d.Cross(z, x));
857
 
858
            Matrix4d rot = new Matrix4d(new Vector4d (x.X, y.X, z.X, 0.0),
859
                                        new Vector4d (x.Y, y.Y, z.Y, 0.0),
860
                                        new Vector4d (x.Z, y.Z, z.Z, 0.0),
861
                                        Vector4d .UnitW);
862
 
863
            Matrix4d trans = Matrix4d.CreateTranslation(-eye);
864
 
865
            return trans * rot;
866
        }
867
 
868
        /// <summary>
869
        /// Build a world space to camera space matrix
870
        /// </summary>
871
        /// <param name="eyeX">Eye (camera) position in world space</param>
872
        /// <param name="eyeY">Eye (camera) position in world space</param>
873
        /// <param name="eyeZ">Eye (camera) position in world space</param>
874
        /// <param name="targetX">Target position in world space</param>
875
        /// <param name="targetY">Target position in world space</param>
876
        /// <param name="targetZ">Target position in world space</param>
877
        /// <param name="upX">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
878
        /// <param name="upY">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
879
        /// <param name="upZ">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
880
        /// <returns>A Matrix4 that transforms world space to camera space</returns>
881
        public static Matrix4d LookAt(double eyeX, double eyeY, double eyeZ, double targetX, double targetY, double targetZ, double upX, double upY, double upZ)
882
        {
883
            return LookAt(new Vector3d(eyeX, eyeY, eyeZ), new Vector3d(targetX, targetY, targetZ), new Vector3d(upX, upY, upZ));
884
        }
885
 
886
        /// <summary>
887
        /// Build a projection matrix
888
        /// </summary>
889
        /// <param name="left">Left edge of the view frustum</param>
890
        /// <param name="right">Right edge of the view frustum</param>
891
        /// <param name="bottom">Bottom edge of the view frustum</param>
892
        /// <param name="top">Top edge of the view frustum</param>
893
        /// <param name="near">Distance to the near clip plane</param>
894
        /// <param name="far">Distance to the far clip plane</param>
895
        /// <returns>A projection matrix that transforms camera space to raster space</returns>
896
        public static Matrix4d Frustum(double left, double right, double bottom, double top, double near, double far)
897
        {
898
            double invRL = 1.0 / (right - left);
899
            double invTB = 1.0 / (top - bottom);
900
            double invFN = 1.0 / (far - near);
901
            return new Matrix4d(new Vector4d (2.0 * near * invRL, 0.0, 0.0, 0.0),
902
                               new Vector4d (0.0, 2.0 * near * invTB, 0.0, 0.0),
903
                               new Vector4d ((right + left) * invRL, (top + bottom) * invTB, -(far + near) * invFN, -1.0),
904
                               new Vector4d (0.0, 0.0, -2.0 * far * near * invFN, 0.0));
905
        }
906
 
907
        /// <summary>
908
        /// Build a projection matrix
909
        /// </summary>
910
        /// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
911
        /// <param name="aspect">Aspect ratio of the view (width / height)</param>
912
        /// <param name="near">Distance to the near clip plane</param>
913
        /// <param name="far">Distance to the far clip plane</param>
914
        /// <returns>A projection matrix that transforms camera space to raster space</returns>
915
        public static Matrix4d Perspective(double fovy, double aspect, double near, double far)
916
        {
917
            double yMax = near * System.Math.Tan(0.5f * fovy);
918
            double yMin = -yMax;
919
            double xMin = yMin * aspect;
920
            double xMax = yMax * aspect;
921
 
922
            return Frustum(xMin, xMax, yMin, yMax, near, far);
923
        }
924
 
925
        #endregion
926
 
927
        #region Multiply Functions
928
 
929
        /// <summary>
930
        /// Multiplies two instances.
931
        /// </summary>
932
        /// <param name="left">The left operand of the multiplication.</param>
933
        /// <param name="right">The right operand of the multiplication.</param>
934
        /// <returns>A new instance that is the result of the multiplication</returns>
935
        public static Matrix4d Mult(Matrix4d left, Matrix4d right)
936
        {
937
            Matrix4d result;
938
            Mult(ref left, ref right, out result);
939
            return result;
940
        }
941
 
942
        /// <summary>
943
        /// Multiplies two instances.
944
        /// </summary>
945
        /// <param name="left">The left operand of the multiplication.</param>
946
        /// <param name="right">The right operand of the multiplication.</param>
947
        /// <param name="result">A new instance that is the result of the multiplication</param>
948
        public static void Mult(ref Matrix4d left, ref Matrix4d right, out Matrix4d result)
949
        {
950
            result = new Matrix4d();
951
            result.M11 = left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41;
952
            result.M12 = left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42;
953
            result.M13 = left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43;
954
            result.M14 = left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44;
955
            result.M21 = left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41;
956
            result.M22 = left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42;
957
            result.M23 = left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43;
958
            result.M24 = left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44;
959
            result.M31 = left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41;
960
            result.M32 = left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42;
961
            result.M33 = left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43;
962
            result.M34 = left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44;
963
            result.M41 = left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41;
964
            result.M42 = left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42;
965
            result.M43 = left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43;
966
            result.M44 = left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44;
967
        }
968
 
969
        #endregion
970
 
971
        #region Invert Functions
972
 
973
        /// <summary>
974
        /// Calculate the inverse of the given matrix
975
        /// </summary>
976
        /// <param name="mat">The matrix to invert</param>
977
        /// <returns>The inverse of the given matrix if it has one, or the input if it is singular</returns>
978
        /// <exception cref="InvalidOperationException">Thrown if the Matrix4d is singular.</exception>
979
        public static Matrix4d Invert(Matrix4d mat)
980
        {
981
            int[] colIdx = { 0, 0, 0, 0 };
982
            int[] rowIdx = { 0, 0, 0, 0 };
983
            int[] pivotIdx = { -1, -1, -1, -1 };
984
 
985
            // convert the matrix to an array for easy looping
986
            double[,] inverse = {{mat.Row0.X, mat.Row0.Y, mat.Row0.Z, mat.Row0.W},
987
                                {mat.Row1.X, mat.Row1.Y, mat.Row1.Z, mat.Row1.W},
988
                                {mat.Row2.X, mat.Row2.Y, mat.Row2.Z, mat.Row2.W},
989
                                {mat.Row3.X, mat.Row3.Y, mat.Row3.Z, mat.Row3.W} };
990
            int icol = 0;
991
            int irow = 0;
992
            for (int i = 0; i < 4; i++)
993
            {
994
                // Find the largest pivot value
995
                double maxPivot = 0.0;
996
                for (int j = 0; j < 4; j++)
997
                {
998
                    if (pivotIdx[j] != 0)
999
                    {
1000
                        for (int k = 0; k < 4; ++k)
1001
                        {
1002
                            if (pivotIdx[k] == -1)
1003
                            {
1004
                                double absVal = System.Math.Abs(inverse[j, k]);
1005
                                if (absVal > maxPivot)
1006
                                {
1007
                                    maxPivot = absVal;
1008
                                    irow = j;
1009
                                    icol = k;
1010
                                }
1011
                            }
1012
                            else if (pivotIdx[k] > 0)
1013
                            {
1014
                                return mat;
1015
                            }
1016
                        }
1017
                    }
1018
                }
1019
 
1020
                ++(pivotIdx[icol]);
1021
 
1022
                // Swap rows over so pivot is on diagonal
1023
                if (irow != icol)
1024
                {
1025
                    for (int k = 0; k < 4; ++k)
1026
                    {
1027
                        double f = inverse[irow, k];
1028
                        inverse[irow, k] = inverse[icol, k];
1029
                        inverse[icol, k] = f;
1030
                    }
1031
                }
1032
 
1033
                rowIdx[i] = irow;
1034
                colIdx[i] = icol;
1035
 
1036
                double pivot = inverse[icol, icol];
1037
                // check for singular matrix
1038
                if (pivot == 0.0)
1039
                {
1040
                    throw new InvalidOperationException("Matrix is singular and cannot be inverted.");
1041
                    //return mat;
1042
                }
1043
 
1044
                // Scale row so it has a unit diagonal
1045
                double oneOverPivot = 1.0 / pivot;
1046
                inverse[icol, icol] = 1.0;
1047
                for (int k = 0; k < 4; ++k)
1048
                    inverse[icol, k] *= oneOverPivot;
1049
 
1050
                // Do elimination of non-diagonal elements
1051
                for (int j = 0; j < 4; ++j)
1052
                {
1053
                    // check this isn't on the diagonal
1054
                    if (icol != j)
1055
                    {
1056
                        double f = inverse[j, icol];
1057
                        inverse[j, icol] = 0.0;
1058
                        for (int k = 0; k < 4; ++k)
1059
                            inverse[j, k] -= inverse[icol, k] * f;
1060
                    }
1061
                }
1062
            }
1063
 
1064
            for (int j = 3; j >= 0; --j)
1065
            {
1066
                int ir = rowIdx[j];
1067
                int ic = colIdx[j];
1068
                for (int k = 0; k < 4; ++k)
1069
                {
1070
                    double f = inverse[k, ir];
1071
                    inverse[k, ir] = inverse[k, ic];
1072
                    inverse[k, ic] = f;
1073
                }
1074
            }
1075
 
1076
            mat.Row0 = new Vector4d (inverse[0, 0], inverse[0, 1], inverse[0, 2], inverse[0, 3]);
1077
            mat.Row1 = new Vector4d (inverse[1, 0], inverse[1, 1], inverse[1, 2], inverse[1, 3]);
1078
            mat.Row2 = new Vector4d (inverse[2, 0], inverse[2, 1], inverse[2, 2], inverse[2, 3]);
1079
            mat.Row3 = new Vector4d (inverse[3, 0], inverse[3, 1], inverse[3, 2], inverse[3, 3]);
1080
            return mat;
1081
        }
1082
 
1083
        #endregion
1084
 
1085
        #region Transpose
1086
 
1087
        /// <summary>
1088
        /// Calculate the transpose of the given matrix
1089
        /// </summary>
1090
        /// <param name="mat">The matrix to transpose</param>
1091
        /// <returns>The transpose of the given matrix</returns>
1092
        public static Matrix4d Transpose(Matrix4d mat)
1093
        {
1094
            return new Matrix4d(mat.Column0, mat.Column1, mat.Column2, mat.Column3);
1095
        }
1096
 
1097
 
1098
        /// <summary>
1099
        /// Calculate the transpose of the given matrix
1100
        /// </summary>
1101
        /// <param name="mat">The matrix to transpose</param>
1102
        /// <param name="result">The result of the calculation</param>
1103
        public static void Transpose(ref Matrix4d mat, out Matrix4d result)
1104
        {
1105
            result.Row0 = mat.Column0;
1106
            result.Row1 = mat.Column1;
1107
            result.Row2 = mat.Column2;
1108
            result.Row3 = mat.Column3;
1109
        }
1110
 
1111
        #endregion
1112
 
1113
        #endregion
1114
 
1115
        #region Operators
1116
 
1117
        /// <summary>
1118
        /// Matrix multiplication
1119
        /// </summary>
1120
        /// <param name="left">left-hand operand</param>
1121
        /// <param name="right">right-hand operand</param>
1122
        /// <returns>A new Matrix44 which holds the result of the multiplication</returns>
1123
        public static Matrix4d operator *(Matrix4d left, Matrix4d right)
1124
        {
1125
            return Matrix4d.Mult(left, right);
1126
        }
1127
 
1128
        /// <summary>
1129
        /// Compares two instances for equality.
1130
        /// </summary>
1131
        /// <param name="left">The first instance.</param>
1132
        /// <param name="right">The second instance.</param>
1133
        /// <returns>True, if left equals right; false otherwise.</returns>
1134
        public static bool operator ==(Matrix4d left, Matrix4d right)
1135
        {
1136
            return left.Equals(right);
1137
        }
1138
 
1139
        /// <summary>
1140
        /// Compares two instances for inequality.
1141
        /// </summary>
1142
        /// <param name="left">The first instance.</param>
1143
        /// <param name="right">The second instance.</param>
1144
        /// <returns>True, if left does not equal right; false otherwise.</returns>
1145
        public static bool operator !=(Matrix4d left, Matrix4d right)
1146
        {
1147
            return !left.Equals(right);
1148
        }
1149
 
1150
        #endregion
1151
 
1152
        #region Overrides
1153
 
1154
        #region public override string ToString()
1155
 
1156
        /// <summary>
1157
        /// Returns a System.String that represents the current Matrix44.
1158
        /// </summary>
1159
        /// <returns></returns>
1160
        public override string ToString()
1161
        {
1162
            return String.Format("{0}\n{1}\n{2}\n{3}", Row0, Row1, Row2, Row3);
1163
        }
1164
 
1165
        #endregion
1166
 
1167
        #region public override int GetHashCode()
1168
 
1169
        /// <summary>
1170
        /// Returns the hashcode for this instance.
1171
        /// </summary>
1172
        /// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
1173
        public override int GetHashCode()
1174
        {
1175
            return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode() ^ Row3.GetHashCode();
1176
        }
1177
 
1178
        #endregion
1179
 
1180
        #region public override bool Equals(object obj)
1181
 
1182
        /// <summary>
1183
        /// Indicates whether this instance and a specified object are equal.
1184
        /// </summary>
1185
        /// <param name="obj">The object to compare to.</param>
1186
        /// <returns>True if the instances are equal; false otherwise.</returns>
1187
        public override bool Equals(object obj)
1188
        {
1189
            if (!(obj is Matrix4d))
1190
                return false;
1191
 
1192
            return this.Equals((Matrix4d)obj);
1193
        }
1194
 
1195
        #endregion
1196
 
1197
        #endregion
1198
 
1199
        #endregion
1200
 
1201
        #region IEquatable<Matrix4d> Members
1202
 
1203
        /// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
1204
        /// <param name="other">An matrix to compare with this matrix.</param>
1205
        /// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
1206
        public bool Equals(Matrix4d other)
1207
        {
1208
            return
1209
                Row0 == other.Row0 &&
1210
                Row1 == other.Row1 &&
1211
                Row2 == other.Row2 &&
1212
                Row3 == other.Row3;
1213
        }
1214
 
1215
        #endregion
1216
    }
1217
}