00001 #region --- License ---
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #endregion
00024
00025 using System;
00026 using System.Runtime.InteropServices;
00027
00028 namespace OpenTK
00029 {
00033 [Serializable]
00034 [StructLayout(LayoutKind.Sequential)]
00035 public struct Matrix4d : IEquatable<Matrix4d>
00036 {
00037 #region Fields
00038
00042 public Vector4d Row0;
00046 public Vector4d Row1;
00050 public Vector4d Row2;
00054 public Vector4d Row3;
00055
00059 public static Matrix4d Identity = new Matrix4d(Vector4d .UnitX, Vector4d .UnitY, Vector4d .UnitZ, Vector4d .UnitW);
00060
00061 #endregion
00062
00063 #region Constructors
00064
00072 public Matrix4d(Vector4d row0, Vector4d row1, Vector4d row2, Vector4d row3)
00073 {
00074 Row0 = row0;
00075 Row1 = row1;
00076 Row2 = row2;
00077 Row3 = row3;
00078 }
00079
00099 public Matrix4d(
00100 double m00, double m01, double m02, double m03,
00101 double m10, double m11, double m12, double m13,
00102 double m20, double m21, double m22, double m23,
00103 double m30, double m31, double m32, double m33)
00104 {
00105 Row0 = new Vector4d(m00, m01, m02, m03);
00106 Row1 = new Vector4d(m10, m11, m12, m13);
00107 Row2 = new Vector4d(m20, m21, m22, m23);
00108 Row3 = new Vector4d(m30, m31, m32, m33);
00109 }
00110
00111 #endregion
00112
00113 #region Public Members
00114
00115 #region Properties
00116
00120 public double Determinant
00121 {
00122 get
00123 {
00124 return
00125 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
00126 + 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
00127 - 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
00128 + 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
00129 + 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
00130 - 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;
00131 }
00132 }
00133
00137 public Vector4d Column0
00138 {
00139 get { return new Vector4d (Row0.X, Row1.X, Row2.X, Row3.X); }
00140 }
00141
00145 public Vector4d Column1
00146 {
00147 get { return new Vector4d (Row0.Y, Row1.Y, Row2.Y, Row3.Y); }
00148 }
00149
00153 public Vector4d Column2
00154 {
00155 get { return new Vector4d (Row0.Z, Row1.Z, Row2.Z, Row3.Z); }
00156 }
00157
00161 public Vector4d Column3
00162 {
00163 get { return new Vector4d (Row0.W, Row1.W, Row2.W, Row3.W); }
00164 }
00165
00169 public double M11 { get { return Row0.X; } set { Row0.X = value; } }
00170
00174 public double M12 { get { return Row0.Y; } set { Row0.Y = value; } }
00175
00179 public double M13 { get { return Row0.Z; } set { Row0.Z = value; } }
00180
00184 public double M14 { get { return Row0.W; } set { Row0.W = value; } }
00185
00189 public double M21 { get { return Row1.X; } set { Row1.X = value; } }
00190
00194 public double M22 { get { return Row1.Y; } set { Row1.Y = value; } }
00195
00199 public double M23 { get { return Row1.Z; } set { Row1.Z = value; } }
00200
00204 public double M24 { get { return Row1.W; } set { Row1.W = value; } }
00205
00209 public double M31 { get { return Row2.X; } set { Row2.X = value; } }
00210
00214 public double M32 { get { return Row2.Y; } set { Row2.Y = value; } }
00215
00219 public double M33 { get { return Row2.Z; } set { Row2.Z = value; } }
00220
00224 public double M34 { get { return Row2.W; } set { Row2.W = value; } }
00225
00229 public double M41 { get { return Row3.X; } set { Row3.X = value; } }
00230
00234 public double M42 { get { return Row3.Y; } set { Row3.Y = value; } }
00235
00239 public double M43 { get { return Row3.Z; } set { Row3.Z = value; } }
00240
00244 public double M44 { get { return Row3.W; } set { Row3.W = value; } }
00245
00246 #endregion
00247
00248 #region Instance
00249
00250 #region public void Invert()
00251
00255 public void Invert()
00256 {
00257 this = Matrix4d.Invert(this);
00258 }
00259
00260 #endregion
00261
00262 #region public void Transpose()
00263
00267 public void Transpose()
00268 {
00269 this = Matrix4d.Transpose(this);
00270 }
00271
00272 #endregion
00273
00274 #endregion
00275
00276 #region Static
00277
00278 #region CreateFromAxisAngle
00279
00286 public static void CreateFromAxisAngle(Vector3d axis, double angle, out Matrix4d result)
00287 {
00288 double cos = System.Math.Cos(-angle);
00289 double sin = System.Math.Sin(-angle);
00290 double t = 1.0 - cos;
00291
00292 axis.Normalize();
00293
00294 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,
00295 t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0,
00296 t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0,
00297 0, 0, 0, 1);
00298 }
00299
00306 public static Matrix4d CreateFromAxisAngle(Vector3d axis, double angle)
00307 {
00308 Matrix4d result;
00309 CreateFromAxisAngle(axis, angle, out result);
00310 return result;
00311 }
00312
00313 #endregion
00314
00315 #region CreateRotation[XYZ]
00316
00322 public static void CreateRotationX(double angle, out Matrix4d result)
00323 {
00324 double cos = System.Math.Cos(angle);
00325 double sin = System.Math.Sin(angle);
00326
00327 result.Row0 = Vector4d.UnitX;
00328 result.Row1 = new Vector4d(0, cos, sin, 0);
00329 result.Row2 = new Vector4d(0, -sin, cos, 0);
00330 result.Row3 = Vector4d.UnitW;
00331 }
00332
00338 public static Matrix4d CreateRotationX(double angle)
00339 {
00340 Matrix4d result;
00341 CreateRotationX(angle, out result);
00342 return result;
00343 }
00344
00350 public static void CreateRotationY(double angle, out Matrix4d result)
00351 {
00352 double cos = System.Math.Cos(angle);
00353 double sin = System.Math.Sin(angle);
00354
00355 result.Row0 = new Vector4d(cos, 0, -sin, 0);
00356 result.Row1 = Vector4d.UnitY;
00357 result.Row2 = new Vector4d(sin, 0, cos, 0);
00358 result.Row3 = Vector4d.UnitW;
00359 }
00360
00366 public static Matrix4d CreateRotationY(double angle)
00367 {
00368 Matrix4d result;
00369 CreateRotationY(angle, out result);
00370 return result;
00371 }
00372
00378 public static void CreateRotationZ(double angle, out Matrix4d result)
00379 {
00380 double cos = System.Math.Cos(angle);
00381 double sin = System.Math.Sin(angle);
00382
00383 result.Row0 = new Vector4d(cos, sin, 0, 0);
00384 result.Row1 = new Vector4d(-sin, cos, 0, 0);
00385 result.Row2 = Vector4d.UnitZ;
00386 result.Row3 = Vector4d.UnitW;
00387 }
00388
00394 public static Matrix4d CreateRotationZ(double angle)
00395 {
00396 Matrix4d result;
00397 CreateRotationZ(angle, out result);
00398 return result;
00399 }
00400
00401 #endregion
00402
00403 #region CreateTranslation
00404
00412 public static void CreateTranslation(double x, double y, double z, out Matrix4d result)
00413 {
00414 result = Identity;
00415 result.Row3 = new Vector4d(x, y, z, 1);
00416 }
00417
00423 public static void CreateTranslation(ref Vector3d vector, out Matrix4d result)
00424 {
00425 result = Identity;
00426 result.Row3 = new Vector4d(vector.X, vector.Y, vector.Z, 1);
00427 }
00428
00436 public static Matrix4d CreateTranslation(double x, double y, double z)
00437 {
00438 Matrix4d result;
00439 CreateTranslation(x, y, z, out result);
00440 return result;
00441 }
00442
00448 public static Matrix4d CreateTranslation(Vector3d vector)
00449 {
00450 Matrix4d result;
00451 CreateTranslation(vector.X, vector.Y, vector.Z, out result);
00452 return result;
00453 }
00454
00455 #endregion
00456
00457 #region CreateOrthographic
00458
00467 public static void CreateOrthographic(double width, double height, double zNear, double zFar, out Matrix4d result)
00468 {
00469 CreateOrthographicOffCenter(-width / 2, width / 2, -height / 2, height / 2, zNear, zFar, out result);
00470 }
00471
00480 public static Matrix4d CreateOrthographic(double width, double height, double zNear, double zFar)
00481 {
00482 Matrix4d result;
00483 CreateOrthographicOffCenter(-width / 2, width / 2, -height / 2, height / 2, zNear, zFar, out result);
00484 return result;
00485 }
00486
00487 #endregion
00488
00489 #region CreateOrthographicOffCenter
00490
00501 public static void CreateOrthographicOffCenter(double left, double right, double bottom, double top, double zNear, double zFar, out Matrix4d result)
00502 {
00503 result = new Matrix4d();
00504
00505 double invRL = 1 / (right - left);
00506 double invTB = 1 / (top - bottom);
00507 double invFN = 1 / (zFar - zNear);
00508
00509 result.M11 = 2 * invRL;
00510 result.M22 = 2 * invTB;
00511 result.M33 = -2 * invFN;
00512
00513 result.M41 = -(right + left) * invRL;
00514 result.M42 = -(top + bottom) * invTB;
00515 result.M43 = -(zFar + zNear) * invFN;
00516 result.M44 = 1;
00517 }
00518
00529 public static Matrix4d CreateOrthographicOffCenter(double left, double right, double bottom, double top, double zNear, double zFar)
00530 {
00531 Matrix4d result;
00532 CreateOrthographicOffCenter(left, right, bottom, top, zNear, zFar, out result);
00533 return result;
00534 }
00535
00536 #endregion
00537
00538 #region CreatePerspectiveFieldOfView
00539
00558 public static void CreatePerspectiveFieldOfView(double fovy, double aspect, double zNear, double zFar, out Matrix4d result)
00559 {
00560 if (fovy <= 0 || fovy > Math.PI)
00561 throw new ArgumentOutOfRangeException("fovy");
00562 if (aspect <= 0)
00563 throw new ArgumentOutOfRangeException("aspect");
00564 if (zNear <= 0)
00565 throw new ArgumentOutOfRangeException("zNear");
00566 if (zFar <= 0)
00567 throw new ArgumentOutOfRangeException("zFar");
00568 if (zNear >= zFar)
00569 throw new ArgumentOutOfRangeException("zNear");
00570
00571 double yMax = zNear * System.Math.Tan(0.5 * fovy);
00572 double yMin = -yMax;
00573 double xMin = yMin * aspect;
00574 double xMax = yMax * aspect;
00575
00576 CreatePerspectiveOffCenter(xMin, xMax, yMin, yMax, zNear, zFar, out result);
00577 }
00578
00597 public static Matrix4d CreatePerspectiveFieldOfView(double fovy, double aspect, double zNear, double zFar)
00598 {
00599 Matrix4d result;
00600 CreatePerspectiveFieldOfView(fovy, aspect, zNear, zFar, out result);
00601 return result;
00602 }
00603
00604 #endregion
00605
00606 #region CreatePerspectiveOffCenter
00607
00626 public static void CreatePerspectiveOffCenter(double left, double right, double bottom, double top, double zNear, double zFar, out Matrix4d result)
00627 {
00628 if (zNear <= 0)
00629 throw new ArgumentOutOfRangeException("zNear");
00630 if (zFar <= 0)
00631 throw new ArgumentOutOfRangeException("zFar");
00632 if (zNear >= zFar)
00633 throw new ArgumentOutOfRangeException("zNear");
00634
00635 double x = (2.0 * zNear) / (right - left);
00636 double y = (2.0 * zNear) / (top - bottom);
00637 double a = (right + left) / (right - left);
00638 double b = (top + bottom) / (top - bottom);
00639 double c = -(zFar + zNear) / (zFar - zNear);
00640 double d = -(2.0 * zFar * zNear) / (zFar - zNear);
00641
00642 result = new Matrix4d(x, 0, 0, 0,
00643 0, y, 0, 0,
00644 a, b, c, -1,
00645 0, 0, d, 0);
00646 }
00647
00666 public static Matrix4d CreatePerspectiveOffCenter(double left, double right, double bottom, double top, double zNear, double zFar)
00667 {
00668 Matrix4d result;
00669 CreatePerspectiveOffCenter(left, right, bottom, top, zNear, zFar, out result);
00670 return result;
00671 }
00672
00673 #endregion
00674
00675 #region Obsolete Functions
00676
00677 #region Translation Functions
00678
00684 [Obsolete("Use CreateTranslation instead.")]
00685 public static Matrix4d Translation(Vector3d trans)
00686 {
00687 return Translation(trans.X, trans.Y, trans.Z);
00688 }
00689
00697 [Obsolete("Use CreateTranslation instead.")]
00698 public static Matrix4d Translation(double x, double y, double z)
00699 {
00700 Matrix4d result = Identity;
00701 result.Row3 = new Vector4d(x, y, z, 1.0);
00702 return result;
00703 }
00704
00705 #endregion
00706
00707 #endregion
00708
00709 #region Scale Functions
00710
00716 public static Matrix4d Scale(double scale)
00717 {
00718 return Scale(scale, scale, scale);
00719 }
00720
00726 public static Matrix4d Scale(Vector3d scale)
00727 {
00728 return Scale(scale.X, scale.Y, scale.Z);
00729 }
00730
00738 public static Matrix4d Scale(double x, double y, double z)
00739 {
00740 Matrix4d result;
00741 result.Row0 = Vector4d .UnitX * x;
00742 result.Row1 = Vector4d .UnitY * y;
00743 result.Row2 = Vector4d .UnitZ * z;
00744 result.Row3 = Vector4d .UnitW;
00745 return result;
00746 }
00747
00748 #endregion
00749
00750 #region Rotation Functions
00751
00757 public static Matrix4d RotateX(double angle)
00758 {
00759 double cos = System.Math.Cos(angle);
00760 double sin = System.Math.Sin(angle);
00761
00762 Matrix4d result;
00763 result.Row0 = Vector4d .UnitX;
00764 result.Row1 = new Vector4d (0.0, cos, sin, 0.0);
00765 result.Row2 = new Vector4d (0.0, -sin, cos, 0.0);
00766 result.Row3 = Vector4d .UnitW;
00767 return result;
00768 }
00769
00775 public static Matrix4d RotateY(double angle)
00776 {
00777 double cos = System.Math.Cos(angle);
00778 double sin = System.Math.Sin(angle);
00779
00780 Matrix4d result;
00781 result.Row0 = new Vector4d (cos, 0.0, -sin, 0.0);
00782 result.Row1 = Vector4d .UnitY;
00783 result.Row2 = new Vector4d (sin, 0.0, cos, 0.0);
00784 result.Row3 = Vector4d .UnitW;
00785 return result;
00786 }
00787
00793 public static Matrix4d RotateZ(double angle)
00794 {
00795 double cos = System.Math.Cos(angle);
00796 double sin = System.Math.Sin(angle);
00797
00798 Matrix4d result;
00799 result.Row0 = new Vector4d (cos, sin, 0.0, 0.0);
00800 result.Row1 = new Vector4d (-sin, cos, 0.0, 0.0);
00801 result.Row2 = Vector4d .UnitZ;
00802 result.Row3 = Vector4d .UnitW;
00803 return result;
00804 }
00805
00812 public static Matrix4d Rotate(Vector3d axis, double angle)
00813 {
00814 double cos = System.Math.Cos(-angle);
00815 double sin = System.Math.Sin(-angle);
00816 double t = 1.0 - cos;
00817
00818 axis.Normalize();
00819
00820 Matrix4d result;
00821 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);
00822 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);
00823 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);
00824 result.Row3 = Vector4d .UnitW;
00825 return result;
00826 }
00827
00833 public static Matrix4d Rotate(Quaterniond q)
00834 {
00835 Vector3d axis;
00836 double angle;
00837 q.ToAxisAngle(out axis, out angle);
00838 return Rotate(axis, angle);
00839 }
00840
00841 #endregion
00842
00843 #region Camera Helper Functions
00844
00852 public static Matrix4d LookAt(Vector3d eye, Vector3d target, Vector3d up)
00853 {
00854 Vector3d z = Vector3d.Normalize(eye - target);
00855 Vector3d x = Vector3d.Normalize(Vector3d.Cross(up, z));
00856 Vector3d y = Vector3d.Normalize(Vector3d.Cross(z, x));
00857
00858 Matrix4d rot = new Matrix4d(new Vector4d (x.X, y.X, z.X, 0.0),
00859 new Vector4d (x.Y, y.Y, z.Y, 0.0),
00860 new Vector4d (x.Z, y.Z, z.Z, 0.0),
00861 Vector4d .UnitW);
00862
00863 Matrix4d trans = Matrix4d.CreateTranslation(-eye);
00864
00865 return trans * rot;
00866 }
00867
00881 public static Matrix4d LookAt(double eyeX, double eyeY, double eyeZ, double targetX, double targetY, double targetZ, double upX, double upY, double upZ)
00882 {
00883 return LookAt(new Vector3d(eyeX, eyeY, eyeZ), new Vector3d(targetX, targetY, targetZ), new Vector3d(upX, upY, upZ));
00884 }
00885
00896 public static Matrix4d Frustum(double left, double right, double bottom, double top, double near, double far)
00897 {
00898 double invRL = 1.0 / (right - left);
00899 double invTB = 1.0 / (top - bottom);
00900 double invFN = 1.0 / (far - near);
00901 return new Matrix4d(new Vector4d (2.0 * near * invRL, 0.0, 0.0, 0.0),
00902 new Vector4d (0.0, 2.0 * near * invTB, 0.0, 0.0),
00903 new Vector4d ((right + left) * invRL, (top + bottom) * invTB, -(far + near) * invFN, -1.0),
00904 new Vector4d (0.0, 0.0, -2.0 * far * near * invFN, 0.0));
00905 }
00906
00915 public static Matrix4d Perspective(double fovy, double aspect, double near, double far)
00916 {
00917 double yMax = near * System.Math.Tan(0.5f * fovy);
00918 double yMin = -yMax;
00919 double xMin = yMin * aspect;
00920 double xMax = yMax * aspect;
00921
00922 return Frustum(xMin, xMax, yMin, yMax, near, far);
00923 }
00924
00925 #endregion
00926
00927 #region Multiply Functions
00928
00935 public static Matrix4d Mult(Matrix4d left, Matrix4d right)
00936 {
00937 Matrix4d result;
00938 Mult(ref left, ref right, out result);
00939 return result;
00940 }
00941
00948 public static void Mult(ref Matrix4d left, ref Matrix4d right, out Matrix4d result)
00949 {
00950 result = new Matrix4d();
00951 result.M11 = left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41;
00952 result.M12 = left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42;
00953 result.M13 = left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43;
00954 result.M14 = left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44;
00955 result.M21 = left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41;
00956 result.M22 = left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42;
00957 result.M23 = left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43;
00958 result.M24 = left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44;
00959 result.M31 = left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41;
00960 result.M32 = left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42;
00961 result.M33 = left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43;
00962 result.M34 = left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44;
00963 result.M41 = left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41;
00964 result.M42 = left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42;
00965 result.M43 = left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43;
00966 result.M44 = left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44;
00967 }
00968
00969 #endregion
00970
00971 #region Invert Functions
00972
00979 public static Matrix4d Invert(Matrix4d mat)
00980 {
00981 int[] colIdx = { 0, 0, 0, 0 };
00982 int[] rowIdx = { 0, 0, 0, 0 };
00983 int[] pivotIdx = { -1, -1, -1, -1 };
00984
00985
00986 double[,] inverse = {{mat.Row0.X, mat.Row0.Y, mat.Row0.Z, mat.Row0.W},
00987 {mat.Row1.X, mat.Row1.Y, mat.Row1.Z, mat.Row1.W},
00988 {mat.Row2.X, mat.Row2.Y, mat.Row2.Z, mat.Row2.W},
00989 {mat.Row3.X, mat.Row3.Y, mat.Row3.Z, mat.Row3.W} };
00990 int icol = 0;
00991 int irow = 0;
00992 for (int i = 0; i < 4; i++)
00993 {
00994
00995 double maxPivot = 0.0;
00996 for (int j = 0; j < 4; j++)
00997 {
00998 if (pivotIdx[j] != 0)
00999 {
01000 for (int k = 0; k < 4; ++k)
01001 {
01002 if (pivotIdx[k] == -1)
01003 {
01004 double absVal = System.Math.Abs(inverse[j, k]);
01005 if (absVal > maxPivot)
01006 {
01007 maxPivot = absVal;
01008 irow = j;
01009 icol = k;
01010 }
01011 }
01012 else if (pivotIdx[k] > 0)
01013 {
01014 return mat;
01015 }
01016 }
01017 }
01018 }
01019
01020 ++(pivotIdx[icol]);
01021
01022
01023 if (irow != icol)
01024 {
01025 for (int k = 0; k < 4; ++k)
01026 {
01027 double f = inverse[irow, k];
01028 inverse[irow, k] = inverse[icol, k];
01029 inverse[icol, k] = f;
01030 }
01031 }
01032
01033 rowIdx[i] = irow;
01034 colIdx[i] = icol;
01035
01036 double pivot = inverse[icol, icol];
01037
01038 if (pivot == 0.0)
01039 {
01040 throw new InvalidOperationException("Matrix is singular and cannot be inverted.");
01041
01042 }
01043
01044
01045 double oneOverPivot = 1.0 / pivot;
01046 inverse[icol, icol] = 1.0;
01047 for (int k = 0; k < 4; ++k)
01048 inverse[icol, k] *= oneOverPivot;
01049
01050
01051 for (int j = 0; j < 4; ++j)
01052 {
01053
01054 if (icol != j)
01055 {
01056 double f = inverse[j, icol];
01057 inverse[j, icol] = 0.0;
01058 for (int k = 0; k < 4; ++k)
01059 inverse[j, k] -= inverse[icol, k] * f;
01060 }
01061 }
01062 }
01063
01064 for (int j = 3; j >= 0; --j)
01065 {
01066 int ir = rowIdx[j];
01067 int ic = colIdx[j];
01068 for (int k = 0; k < 4; ++k)
01069 {
01070 double f = inverse[k, ir];
01071 inverse[k, ir] = inverse[k, ic];
01072 inverse[k, ic] = f;
01073 }
01074 }
01075
01076 mat.Row0 = new Vector4d (inverse[0, 0], inverse[0, 1], inverse[0, 2], inverse[0, 3]);
01077 mat.Row1 = new Vector4d (inverse[1, 0], inverse[1, 1], inverse[1, 2], inverse[1, 3]);
01078 mat.Row2 = new Vector4d (inverse[2, 0], inverse[2, 1], inverse[2, 2], inverse[2, 3]);
01079 mat.Row3 = new Vector4d (inverse[3, 0], inverse[3, 1], inverse[3, 2], inverse[3, 3]);
01080 return mat;
01081 }
01082
01083 #endregion
01084
01085 #region Transpose
01086
01092 public static Matrix4d Transpose(Matrix4d mat)
01093 {
01094 return new Matrix4d(mat.Column0, mat.Column1, mat.Column2, mat.Column3);
01095 }
01096
01097
01103 public static void Transpose(ref Matrix4d mat, out Matrix4d result)
01104 {
01105 result.Row0 = mat.Column0;
01106 result.Row1 = mat.Column1;
01107 result.Row2 = mat.Column2;
01108 result.Row3 = mat.Column3;
01109 }
01110
01111 #endregion
01112
01113 #endregion
01114
01115 #region Operators
01116
01123 public static Matrix4d operator *(Matrix4d left, Matrix4d right)
01124 {
01125 return Matrix4d.Mult(left, right);
01126 }
01127
01134 public static bool operator ==(Matrix4d left, Matrix4d right)
01135 {
01136 return left.Equals(right);
01137 }
01138
01145 public static bool operator !=(Matrix4d left, Matrix4d right)
01146 {
01147 return !left.Equals(right);
01148 }
01149
01150 #endregion
01151
01152 #region Overrides
01153
01154 #region public override string ToString()
01155
01160 public override string ToString()
01161 {
01162 return String.Format("{0}\n{1}\n{2}\n{3}", Row0, Row1, Row2, Row3);
01163 }
01164
01165 #endregion
01166
01167 #region public override int GetHashCode()
01168
01173 public override int GetHashCode()
01174 {
01175 return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode() ^ Row3.GetHashCode();
01176 }
01177
01178 #endregion
01179
01180 #region public override bool Equals(object obj)
01181
01187 public override bool Equals(object obj)
01188 {
01189 if (!(obj is Matrix4d))
01190 return false;
01191
01192 return this.Equals((Matrix4d)obj);
01193 }
01194
01195 #endregion
01196
01197 #endregion
01198
01199 #endregion
01200
01201 #region IEquatable<Matrix4d> Members
01202
01206 public bool Equals(Matrix4d other)
01207 {
01208 return
01209 Row0 == other.Row0 &&
01210 Row1 == other.Row1 &&
01211 Row2 == other.Row2 &&
01212 Row3 == other.Row3;
01213 }
01214
01215 #endregion
01216 }
01217 }