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 Matrix4 : IEquatable<Matrix4>
00036 {
00037 #region Fields
00038
00042 public Vector4 Row0;
00046 public Vector4 Row1;
00050 public Vector4 Row2;
00054 public Vector4 Row3;
00055
00059 public static Matrix4 Identity = new Matrix4(Vector4.UnitX, Vector4.UnitY, Vector4.UnitZ, Vector4.UnitW);
00060
00061 #endregion
00062
00063 #region Constructors
00064
00072 public Matrix4(Vector4 row0, Vector4 row1, Vector4 row2, Vector4 row3)
00073 {
00074 Row0 = row0;
00075 Row1 = row1;
00076 Row2 = row2;
00077 Row3 = row3;
00078 }
00079
00099 public Matrix4(
00100 float m00, float m01, float m02, float m03,
00101 float m10, float m11, float m12, float m13,
00102 float m20, float m21, float m22, float m23,
00103 float m30, float m31, float m32, float m33)
00104 {
00105 Row0 = new Vector4(m00, m01, m02, m03);
00106 Row1 = new Vector4(m10, m11, m12, m13);
00107 Row2 = new Vector4(m20, m21, m22, m23);
00108 Row3 = new Vector4(m30, m31, m32, m33);
00109 }
00110
00111 #endregion
00112
00113 #region Public Members
00114
00115 #region Properties
00116
00120 public float 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 Vector4 Column0
00138 {
00139 get { return new Vector4(Row0.X, Row1.X, Row2.X, Row3.X); }
00140 }
00141
00145 public Vector4 Column1
00146 {
00147 get { return new Vector4(Row0.Y, Row1.Y, Row2.Y, Row3.Y); }
00148 }
00149
00153 public Vector4 Column2
00154 {
00155 get { return new Vector4(Row0.Z, Row1.Z, Row2.Z, Row3.Z); }
00156 }
00157
00161 public Vector4 Column3
00162 {
00163 get { return new Vector4(Row0.W, Row1.W, Row2.W, Row3.W); }
00164 }
00165
00169 public float M11 { get { return Row0.X; } set { Row0.X = value; } }
00170
00174 public float M12 { get { return Row0.Y; } set { Row0.Y = value; } }
00175
00179 public float M13 { get { return Row0.Z; } set { Row0.Z = value; } }
00180
00184 public float M14 { get { return Row0.W; } set { Row0.W = value; } }
00185
00189 public float M21 { get { return Row1.X; } set { Row1.X = value; } }
00190
00194 public float M22 { get { return Row1.Y; } set { Row1.Y = value; } }
00195
00199 public float M23 { get { return Row1.Z; } set { Row1.Z = value; } }
00200
00204 public float M24 { get { return Row1.W; } set { Row1.W = value; } }
00205
00209 public float M31 { get { return Row2.X; } set { Row2.X = value; } }
00210
00214 public float M32 { get { return Row2.Y; } set { Row2.Y = value; } }
00215
00219 public float M33 { get { return Row2.Z; } set { Row2.Z = value; } }
00220
00224 public float M34 { get { return Row2.W; } set { Row2.W = value; } }
00225
00229 public float M41 { get { return Row3.X; } set { Row3.X = value; } }
00230
00234 public float M42 { get { return Row3.Y; } set { Row3.Y = value; } }
00235
00239 public float M43 { get { return Row3.Z; } set { Row3.Z = value; } }
00240
00244 public float 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 = Matrix4.Invert(this);
00258 }
00259
00260 #endregion
00261
00262 #region public void Transpose()
00263
00267 public void Transpose()
00268 {
00269 this = Matrix4.Transpose(this);
00270 }
00271
00272 #endregion
00273
00274 #endregion
00275
00276 #region Static
00277
00278 #region CreateFromAxisAngle
00279
00286 public static void CreateFromAxisAngle(Vector3 axis, float angle, out Matrix4 result)
00287 {
00288 float cos = (float)System.Math.Cos(-angle);
00289 float sin = (float)System.Math.Sin(-angle);
00290 float t = 1.0f - cos;
00291
00292 axis.Normalize();
00293
00294 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,
00295 t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f,
00296 t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f,
00297 0, 0, 0, 1);
00298 }
00299
00306 public static Matrix4 CreateFromAxisAngle(Vector3 axis, float angle)
00307 {
00308 Matrix4 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(float angle, out Matrix4 result)
00323 {
00324 float cos = (float)System.Math.Cos(angle);
00325 float sin = (float)System.Math.Sin(angle);
00326
00327 result.Row0 = Vector4.UnitX;
00328 result.Row1 = new Vector4(0.0f, cos, sin, 0.0f);
00329 result.Row2 = new Vector4(0.0f, -sin, cos, 0.0f);
00330 result.Row3 = Vector4.UnitW;
00331 }
00332
00338 public static Matrix4 CreateRotationX(float angle)
00339 {
00340 Matrix4 result;
00341 CreateRotationX(angle, out result);
00342 return result;
00343 }
00344
00350 public static void CreateRotationY(float angle, out Matrix4 result)
00351 {
00352 float cos = (float)System.Math.Cos(angle);
00353 float sin = (float)System.Math.Sin(angle);
00354
00355 result.Row0 = new Vector4(cos, 0.0f, -sin, 0.0f);
00356 result.Row1 = Vector4.UnitY;
00357 result.Row2 = new Vector4(sin, 0.0f, cos, 0.0f);
00358 result.Row3 = Vector4.UnitW;
00359 }
00360
00366 public static Matrix4 CreateRotationY(float angle)
00367 {
00368 Matrix4 result;
00369 CreateRotationY(angle, out result);
00370 return result;
00371 }
00372
00378 public static void CreateRotationZ(float angle, out Matrix4 result)
00379 {
00380 float cos = (float)System.Math.Cos(angle);
00381 float sin = (float)System.Math.Sin(angle);
00382
00383 result.Row0 = new Vector4(cos, sin, 0.0f, 0.0f);
00384 result.Row1 = new Vector4(-sin, cos, 0.0f, 0.0f);
00385 result.Row2 = Vector4.UnitZ;
00386 result.Row3 = Vector4.UnitW;
00387 }
00388
00394 public static Matrix4 CreateRotationZ(float angle)
00395 {
00396 Matrix4 result;
00397 CreateRotationZ(angle, out result);
00398 return result;
00399 }
00400
00401 #endregion
00402
00403 #region CreateTranslation
00404
00412 public static void CreateTranslation(float x, float y, float z, out Matrix4 result)
00413 {
00414 result = Identity;
00415 result.Row3 = new Vector4(x, y, z, 1);
00416 }
00417
00423 public static void CreateTranslation(ref Vector3 vector, out Matrix4 result)
00424 {
00425 result = Identity;
00426 result.Row3 = new Vector4(vector.X, vector.Y, vector.Z, 1);
00427 }
00428
00436 public static Matrix4 CreateTranslation(float x, float y, float z)
00437 {
00438 Matrix4 result;
00439 CreateTranslation(x, y, z, out result);
00440 return result;
00441 }
00442
00448 public static Matrix4 CreateTranslation(Vector3 vector)
00449 {
00450 Matrix4 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(float width, float height, float zNear, float zFar, out Matrix4 result)
00468 {
00469 CreateOrthographicOffCenter(-width / 2, width / 2, -height / 2, height / 2, zNear, zFar, out result);
00470 }
00471
00480 public static Matrix4 CreateOrthographic(float width, float height, float zNear, float zFar)
00481 {
00482 Matrix4 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(float left, float right, float bottom, float top, float zNear, float zFar, out Matrix4 result)
00502 {
00503 result = new Matrix4();
00504
00505 float invRL = 1 / (right - left);
00506 float invTB = 1 / (top - bottom);
00507 float 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 Matrix4 CreateOrthographicOffCenter(float left, float right, float bottom, float top, float zNear, float zFar)
00530 {
00531 Matrix4 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(float fovy, float aspect, float zNear, float zFar, out Matrix4 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 float yMax = zNear * (float)System.Math.Tan(0.5f * fovy);
00572 float yMin = -yMax;
00573 float xMin = yMin * aspect;
00574 float xMax = yMax * aspect;
00575
00576 CreatePerspectiveOffCenter(xMin, xMax, yMin, yMax, zNear, zFar, out result);
00577 }
00578
00597 public static Matrix4 CreatePerspectiveFieldOfView(float fovy, float aspect, float zNear, float zFar)
00598 {
00599 Matrix4 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(float left, float right, float bottom, float top, float zNear, float zFar, out Matrix4 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 float x = (2.0f * zNear) / (right - left);
00636 float y = (2.0f * zNear) / (top - bottom);
00637 float a = (right + left) / (right - left);
00638 float b = (top + bottom) / (top - bottom);
00639 float c = -(zFar + zNear) / (zFar - zNear);
00640 float d = -(2.0f * zFar * zNear) / (zFar - zNear);
00641
00642 result = new Matrix4(x, 0, 0, 0,
00643 0, y, 0, 0,
00644 a, b, c, -1,
00645 0, 0, d, 0);
00646 }
00647
00666 public static Matrix4 CreatePerspectiveOffCenter(float left, float right, float bottom, float top, float zNear, float zFar)
00667 {
00668 Matrix4 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 Matrix4 Translation(Vector3 trans)
00686 {
00687 return Translation(trans.X, trans.Y, trans.Z);
00688 }
00689
00697 [Obsolete("Use CreateTranslation instead.")]
00698 public static Matrix4 Translation(float x, float y, float z)
00699 {
00700 Matrix4 result = Identity;
00701 result.Row3 = new Vector4(x, y, z, 1.0f);
00702 return result;
00703 }
00704
00705 #endregion
00706
00707 #endregion
00708
00709 #region Scale Functions
00710
00716 public static Matrix4 Scale(float scale)
00717 {
00718 return Scale(scale, scale, scale);
00719 }
00720
00726 public static Matrix4 Scale(Vector3 scale)
00727 {
00728 return Scale(scale.X, scale.Y, scale.Z);
00729 }
00730
00738 public static Matrix4 Scale(float x, float y, float z)
00739 {
00740 Matrix4 result;
00741 result.Row0 = Vector4.UnitX * x;
00742 result.Row1 = Vector4.UnitY * y;
00743 result.Row2 = Vector4.UnitZ * z;
00744 result.Row3 = Vector4.UnitW;
00745 return result;
00746 }
00747
00748 #endregion
00749
00750 #region Rotation Functions
00751
00757 [Obsolete("Use CreateRotationX instead.")]
00758 public static Matrix4 RotateX(float angle)
00759 {
00760 float cos = (float)System.Math.Cos(angle);
00761 float sin = (float)System.Math.Sin(angle);
00762
00763 Matrix4 result;
00764 result.Row0 = Vector4.UnitX;
00765 result.Row1 = new Vector4(0.0f, cos, sin, 0.0f);
00766 result.Row2 = new Vector4(0.0f, -sin, cos, 0.0f);
00767 result.Row3 = Vector4.UnitW;
00768 return result;
00769 }
00770
00776 [Obsolete("Use CreateRotationY instead.")]
00777 public static Matrix4 RotateY(float angle)
00778 {
00779 float cos = (float)System.Math.Cos(angle);
00780 float sin = (float)System.Math.Sin(angle);
00781
00782 Matrix4 result;
00783 result.Row0 = new Vector4(cos, 0.0f, -sin, 0.0f);
00784 result.Row1 = Vector4.UnitY;
00785 result.Row2 = new Vector4(sin, 0.0f, cos, 0.0f);
00786 result.Row3 = Vector4.UnitW;
00787 return result;
00788 }
00789
00795 [Obsolete("Use CreateRotationZ instead.")]
00796 public static Matrix4 RotateZ(float angle)
00797 {
00798 float cos = (float)System.Math.Cos(angle);
00799 float sin = (float)System.Math.Sin(angle);
00800
00801 Matrix4 result;
00802 result.Row0 = new Vector4(cos, sin, 0.0f, 0.0f);
00803 result.Row1 = new Vector4(-sin, cos, 0.0f, 0.0f);
00804 result.Row2 = Vector4.UnitZ;
00805 result.Row3 = Vector4.UnitW;
00806 return result;
00807 }
00808
00815 [Obsolete("Use CreateFromAxisAngle instead.")]
00816 public static Matrix4 Rotate(Vector3 axis, float angle)
00817 {
00818 float cos = (float)System.Math.Cos(-angle);
00819 float sin = (float)System.Math.Sin(-angle);
00820 float t = 1.0f - cos;
00821
00822 axis.Normalize();
00823
00824 Matrix4 result;
00825 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);
00826 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);
00827 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);
00828 result.Row3 = Vector4.UnitW;
00829 return result;
00830 }
00831
00837 public static Matrix4 Rotate(Quaternion q)
00838 {
00839 Vector3 axis;
00840 float angle;
00841 q.ToAxisAngle(out axis, out angle);
00842 return CreateFromAxisAngle(axis, angle);
00843 }
00844
00845 #endregion
00846
00847 #region Camera Helper Functions
00848
00856 public static Matrix4 LookAt(Vector3 eye, Vector3 target, Vector3 up)
00857 {
00858 Vector3 z = Vector3.Normalize(eye - target);
00859 Vector3 x = Vector3.Normalize(Vector3.Cross(up, z));
00860 Vector3 y = Vector3.Normalize(Vector3.Cross(z, x));
00861
00862 Matrix4 rot = new Matrix4(new Vector4(x.X, y.X, z.X, 0.0f),
00863 new Vector4(x.Y, y.Y, z.Y, 0.0f),
00864 new Vector4(x.Z, y.Z, z.Z, 0.0f),
00865 Vector4.UnitW);
00866
00867 Matrix4 trans = Matrix4.CreateTranslation(-eye);
00868
00869 return trans * rot;
00870 }
00871
00885 public static Matrix4 LookAt(float eyeX, float eyeY, float eyeZ, float targetX, float targetY, float targetZ, float upX, float upY, float upZ)
00886 {
00887 return LookAt(new Vector3(eyeX, eyeY, eyeZ), new Vector3(targetX, targetY, targetZ), new Vector3(upX, upY, upZ));
00888 }
00889
00900 [Obsolete("Use CreatePerspectiveOffCenter instead.")]
00901 public static Matrix4 Frustum(float left, float right, float bottom, float top, float near, float far)
00902 {
00903 float invRL = 1.0f / (right - left);
00904 float invTB = 1.0f / (top - bottom);
00905 float invFN = 1.0f / (far - near);
00906 return new Matrix4(new Vector4(2.0f * near * invRL, 0.0f, 0.0f, 0.0f),
00907 new Vector4(0.0f, 2.0f * near * invTB, 0.0f, 0.0f),
00908 new Vector4((right + left) * invRL, (top + bottom) * invTB, -(far + near) * invFN, -1.0f),
00909 new Vector4(0.0f, 0.0f, -2.0f * far * near * invFN, 0.0f));
00910 }
00911
00920 [Obsolete("Use CreatePerspectiveFieldOfView instead.")]
00921 public static Matrix4 Perspective(float fovy, float aspect, float near, float far)
00922 {
00923 float yMax = near * (float)System.Math.Tan(0.5f * fovy);
00924 float yMin = -yMax;
00925 float xMin = yMin * aspect;
00926 float xMax = yMax * aspect;
00927
00928 return Frustum(xMin, xMax, yMin, yMax, near, far);
00929 }
00930
00931 #endregion
00932
00933 #region Multiply Functions
00934
00941 public static Matrix4 Mult(Matrix4 left, Matrix4 right)
00942 {
00943 Matrix4 result;
00944 Mult(ref left, ref right, out result);
00945 return result;
00946 }
00947
00954 public static void Mult(ref Matrix4 left, ref Matrix4 right, out Matrix4 result)
00955 {
00956 result = new Matrix4(
00957 left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41,
00958 left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42,
00959 left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43,
00960 left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44,
00961 left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41,
00962 left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42,
00963 left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43,
00964 left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44,
00965 left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41,
00966 left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42,
00967 left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43,
00968 left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44,
00969 left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41,
00970 left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42,
00971 left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43,
00972 left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44);
00973 }
00974
00975 #endregion
00976
00977 #region Invert Functions
00978
00985 public static Matrix4 Invert(Matrix4 mat)
00986 {
00987 int[] colIdx = { 0, 0, 0, 0 };
00988 int[] rowIdx = { 0, 0, 0, 0 };
00989 int[] pivotIdx = { -1, -1, -1, -1 };
00990
00991
00992 float[,] inverse = {{mat.Row0.X, mat.Row0.Y, mat.Row0.Z, mat.Row0.W},
00993 {mat.Row1.X, mat.Row1.Y, mat.Row1.Z, mat.Row1.W},
00994 {mat.Row2.X, mat.Row2.Y, mat.Row2.Z, mat.Row2.W},
00995 {mat.Row3.X, mat.Row3.Y, mat.Row3.Z, mat.Row3.W} };
00996 int icol = 0;
00997 int irow = 0;
00998 for (int i = 0; i < 4; i++)
00999 {
01000
01001 float maxPivot = 0.0f;
01002 for (int j = 0; j < 4; j++)
01003 {
01004 if (pivotIdx[j] != 0)
01005 {
01006 for (int k = 0; k < 4; ++k)
01007 {
01008 if (pivotIdx[k] == -1)
01009 {
01010 float absVal = System.Math.Abs(inverse[j, k]);
01011 if (absVal > maxPivot)
01012 {
01013 maxPivot = absVal;
01014 irow = j;
01015 icol = k;
01016 }
01017 }
01018 else if (pivotIdx[k] > 0)
01019 {
01020 return mat;
01021 }
01022 }
01023 }
01024 }
01025
01026 ++(pivotIdx[icol]);
01027
01028
01029 if (irow != icol)
01030 {
01031 for (int k = 0; k < 4; ++k)
01032 {
01033 float f = inverse[irow, k];
01034 inverse[irow, k] = inverse[icol, k];
01035 inverse[icol, k] = f;
01036 }
01037 }
01038
01039 rowIdx[i] = irow;
01040 colIdx[i] = icol;
01041
01042 float pivot = inverse[icol, icol];
01043
01044 if (pivot == 0.0f)
01045 {
01046 throw new InvalidOperationException("Matrix is singular and cannot be inverted.");
01047
01048 }
01049
01050
01051 float oneOverPivot = 1.0f / pivot;
01052 inverse[icol, icol] = 1.0f;
01053 for (int k = 0; k < 4; ++k)
01054 inverse[icol, k] *= oneOverPivot;
01055
01056
01057 for (int j = 0; j < 4; ++j)
01058 {
01059
01060 if (icol != j)
01061 {
01062 float f = inverse[j, icol];
01063 inverse[j, icol] = 0.0f;
01064 for (int k = 0; k < 4; ++k)
01065 inverse[j, k] -= inverse[icol, k] * f;
01066 }
01067 }
01068 }
01069
01070 for (int j = 3; j >= 0; --j)
01071 {
01072 int ir = rowIdx[j];
01073 int ic = colIdx[j];
01074 for (int k = 0; k < 4; ++k)
01075 {
01076 float f = inverse[k, ir];
01077 inverse[k, ir] = inverse[k, ic];
01078 inverse[k, ic] = f;
01079 }
01080 }
01081
01082 mat.Row0 = new Vector4(inverse[0, 0], inverse[0, 1], inverse[0, 2], inverse[0, 3]);
01083 mat.Row1 = new Vector4(inverse[1, 0], inverse[1, 1], inverse[1, 2], inverse[1, 3]);
01084 mat.Row2 = new Vector4(inverse[2, 0], inverse[2, 1], inverse[2, 2], inverse[2, 3]);
01085 mat.Row3 = new Vector4(inverse[3, 0], inverse[3, 1], inverse[3, 2], inverse[3, 3]);
01086 return mat;
01087 }
01088
01089 #endregion
01090
01091 #region Transpose
01092
01098 public static Matrix4 Transpose(Matrix4 mat)
01099 {
01100 return new Matrix4(mat.Column0, mat.Column1, mat.Column2, mat.Column3);
01101 }
01102
01103
01109 public static void Transpose(ref Matrix4 mat, out Matrix4 result)
01110 {
01111 result.Row0 = mat.Column0;
01112 result.Row1 = mat.Column1;
01113 result.Row2 = mat.Column2;
01114 result.Row3 = mat.Column3;
01115 }
01116
01117 #endregion
01118
01119 #endregion
01120
01121 #region Operators
01122
01129 public static Matrix4 operator *(Matrix4 left, Matrix4 right)
01130 {
01131 return Matrix4.Mult(left, right);
01132 }
01133
01140 public static bool operator ==(Matrix4 left, Matrix4 right)
01141 {
01142 return left.Equals(right);
01143 }
01144
01151 public static bool operator !=(Matrix4 left, Matrix4 right)
01152 {
01153 return !left.Equals(right);
01154 }
01155
01156 #endregion
01157
01158 #region Overrides
01159
01160 #region public override string ToString()
01161
01166 public override string ToString()
01167 {
01168 return String.Format("{0}\n{1}\n{2}\n{3}", Row0, Row1, Row2, Row3);
01169 }
01170
01171 #endregion
01172
01173 #region public override int GetHashCode()
01174
01179 public override int GetHashCode()
01180 {
01181 return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode() ^ Row3.GetHashCode();
01182 }
01183
01184 #endregion
01185
01186 #region public override bool Equals(object obj)
01187
01193 public override bool Equals(object obj)
01194 {
01195 if (!(obj is Matrix4))
01196 return false;
01197
01198 return this.Equals((Matrix4)obj);
01199 }
01200
01201 #endregion
01202
01203 #endregion
01204
01205 #endregion
01206
01207 #region IEquatable<Matrix4> Members
01208
01212 public bool Equals(Matrix4 other)
01213 {
01214 return
01215 Row0 == other.Row0 &&
01216 Row1 == other.Row1 &&
01217 Row2 == other.Row2 &&
01218 Row3 == other.Row3;
01219 }
01220
01221 #endregion
01222 }
01223 }