/PhysiXEngine/Helpers/Matrix3.cs

https://bitbucket.org/ideasstorm/physixlab · C# · 393 lines · 241 code · 43 blank · 109 comment · 3 complexity · 6e0c13e306734c9300873fb2fa32b9ab MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using Microsoft.Xna.Framework;
  4. using Microsoft.Xna.Framework.Graphics;
  5. namespace PhysiXEngine.Helpers
  6. {
  7. ///<summary>
  8. ///Holds an inertia tensor, consisting of a 3x3 row-major matrix.
  9. ///This matrix is not padding to produce an aligned structure, since
  10. ///it is most commonly used with a mass (single float) and two
  11. ///damping coefficients to make the 12-element characteristics array
  12. ///of a rigid body.
  13. ///</summary>
  14. public class Matrix3
  15. {
  16. ///<summary>
  17. ///Holds the tensor matrix data in array form.
  18. ///</summary>
  19. public float[] data = new float[9];
  20. ///<summary>
  21. ///Creates a new matrix.
  22. ///</summary>
  23. public Matrix3()
  24. {
  25. data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
  26. data[6] = data[7] = data[8] = 0;
  27. }
  28. /// <summary>
  29. /// Constructs a Matrix3x3 from a Matrix4x4
  30. /// </summary>
  31. /// <param name="m">Matrix to copy from</param>
  32. public Matrix3(Matrix mat)
  33. {
  34. Matrix m = Matrix.Transpose(mat);
  35. this.data[0] = m.M11;
  36. this.data[1] = m.M12;
  37. this.data[2] = m.M13;
  38. this.data[3] = m.M21;
  39. this.data[4] = m.M22;
  40. this.data[5] = m.M23;
  41. this.data[6] = m.M31;
  42. this.data[7] = m.M32;
  43. this.data[8] = m.M33;
  44. }
  45. public static implicit operator Matrix3 (Matrix instance)
  46. {
  47. return new Matrix3(instance);
  48. }
  49. public static explicit operator Matrix(Matrix3 instance)
  50. {
  51. Matrix m = new Matrix();
  52. m.M11 = instance.data[0];
  53. m.M12 = instance.data[1];
  54. m.M13 = instance.data[2];
  55. m.M21 = instance.data[3];
  56. m.M22 = instance.data[4];
  57. m.M23 = instance.data[5];
  58. m.M31 = instance.data[6];
  59. m.M32 = instance.data[7];
  60. m.M33 = instance.data[8];
  61. m.M44 = 1;
  62. //TODO be sure of this method (is it correct ?!)
  63. return m;
  64. }
  65. ///<summary>
  66. ///Creates a new matrix with the given three vectors making
  67. ///up its columns.
  68. ///</summary>
  69. public Matrix3(Vector3 compOne, Vector3 compTwo,
  70. Vector3 compThree)
  71. {
  72. setComponents(compOne, compTwo, compThree);
  73. }
  74. ///<summary>
  75. ///Creates a new matrix with explicit coefficients.
  76. ///</summary>
  77. public Matrix3(float c0, float c1, float c2, float c3, float c4, float c5,
  78. float c6, float c7, float c8)
  79. {
  80. data[0] = c0; data[1] = c1; data[2] = c2;
  81. data[3] = c3; data[4] = c4; data[5] = c5;
  82. data[6] = c6; data[7] = c7; data[8] = c8;
  83. }
  84. ///<summary>
  85. ///Sets the matrix to be a diagonal matrix with the given
  86. ///values along the leading diagonal.
  87. ///</summary>
  88. public void setDiagonal(float a, float b, float c)
  89. {
  90. setInertiaTensorCoeffs(a, b, c);
  91. }
  92. ///<summary>
  93. ///Sets the value of the matrix from inertia tensor values.
  94. ///</summary>
  95. public void setInertiaTensorCoeffs(float ix, float iy, float iz,
  96. float ixy = 0, float ixz = 0, float iyz = 0)
  97. {
  98. data[0] = ix;
  99. data[1] = data[3] = -ixy;
  100. data[2] = data[6] = -ixz;
  101. data[4] = iy;
  102. data[5] = data[7] = -iyz;
  103. data[8] = iz;
  104. }
  105. ///<summary>
  106. ///Sets the value of the matrix as an inertia tensor of
  107. ///a rectangular block aligned with the body's coordinate
  108. ///system with the given axis half-sizes and mass.
  109. ///</summary>
  110. public void setBlockInertiaTensor(Vector3 halfSizes, float mass)
  111. {
  112. Vector3 squares = new Vector3(halfSizes.X * halfSizes.X, halfSizes.Y * halfSizes.Y, halfSizes.Z * halfSizes.Z);
  113. setInertiaTensorCoeffs(0.3f * mass * (squares.Y + squares.Z),
  114. 0.3f * mass * (squares.X + squares.Z),
  115. 0.3f * mass * (squares.X + squares.Y));
  116. }
  117. ///<summary>
  118. ///Sets the matrix to be a skew symmetric matrix based on
  119. ///the given vector. The skew symmetric matrix is the equivalent
  120. ///of the vector product. So if a,b are vectors. a x b = A_s b
  121. ///where A_s is the skew symmetric form of a.
  122. ///</summary>
  123. public void setSkewSymmetric(Vector3 vector)
  124. {
  125. data[0] = data[4] = data[8] = 0;
  126. data[1] = -vector.Z;
  127. data[2] = vector.Y;
  128. data[3] = vector.Z;
  129. data[5] = -vector.X;
  130. data[6] = -vector.Y;
  131. data[7] = vector.X;
  132. }
  133. ///<summary>
  134. ///Sets the matrix values from the given three vector components.
  135. ///These are arranged as the three columns of the vector.
  136. ///</summary>
  137. public void setComponents(Vector3 compOne, Vector3 compTwo,
  138. Vector3 compThree)
  139. {
  140. data[0] = compOne.X;
  141. data[1] = compTwo.X;
  142. data[2] = compThree.X;
  143. data[3] = compOne.Y;
  144. data[4] = compTwo.Y;
  145. data[5] = compThree.Y;
  146. data[6] = compOne.Z;
  147. data[7] = compTwo.Z;
  148. data[8] = compThree.Z;
  149. }
  150. ///<summary>
  151. ///Transform the given vector by this matrix.
  152. ///
  153. ///@param vector The vector to transform.
  154. ///</summary>
  155. public static Vector3 operator *(Matrix3 m, Vector3 vector)
  156. {
  157. return new Vector3(
  158. vector.X * m.data[0] + vector.Y * m.data[1] + vector.Z * m.data[2],
  159. vector.X * m.data[3] + vector.Y * m.data[4] + vector.Z * m.data[5],
  160. vector.X * m.data[6] + vector.Y * m.data[7] + vector.Z * m.data[8]
  161. );
  162. }
  163. ///<summary>
  164. ///Transform the given vector by this matrix.
  165. ///
  166. ///@param vector The vector to transform.
  167. ///</summary>
  168. public Vector3 transform(Vector3 vector)
  169. {
  170. return (this) * vector;
  171. }
  172. ///<summary>
  173. ///Transform the given vector by the transpose of this matrix.
  174. ///
  175. ///@param vector The vector to transform.
  176. ///</summary>
  177. public Vector3 transformTranspose(Vector3 vector)
  178. {
  179. return new Vector3(
  180. vector.X * data[0] + vector.Y * data[3] + vector.Z * data[6],
  181. vector.X * data[1] + vector.Y * data[4] + vector.Z * data[7],
  182. vector.X * data[2] + vector.Y * data[5] + vector.Z * data[8]
  183. );
  184. }
  185. ///<summary>
  186. ///Gets a vector representing one row in the matrix.
  187. ///
  188. ///@param i The row to return.
  189. ///</summary>
  190. public Vector3 getRowVector(int i)
  191. {
  192. return new Vector3(data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
  193. }
  194. ///<summary>
  195. ///Gets a vector representing one axis (i.e. one column) in the matrix.
  196. ///
  197. ///@param i The row to return.
  198. ///
  199. ///@return The vector.
  200. ///</summary>
  201. public Vector3 getAxisVector(int i)
  202. {
  203. return new Vector3(data[i], data[i + 3], data[i + 6]);
  204. }
  205. ///<summary>
  206. ///Sets the matrix to be the inverse of the given matrix.
  207. ///
  208. ///@param m The matrix to invert and use to set this.
  209. ///</summary>
  210. public void setInverse(Matrix3 m)
  211. {
  212. float t4 = m.data[0] * m.data[4];
  213. float t6 = m.data[0] * m.data[5];
  214. float t8 = m.data[1] * m.data[3];
  215. float t10 = m.data[2] * m.data[3];
  216. float t12 = m.data[1] * m.data[6];
  217. float t14 = m.data[2] * m.data[6];
  218. /// Calculate the determinant
  219. float t16 = (t4 * m.data[8] - t6 * m.data[7] - t8 * m.data[8] +
  220. t10 * m.data[7] + t12 * m.data[5] - t14 * m.data[4]);
  221. /// Make sure the determinant is non-zero.
  222. if (t16 == (float)0.0f) return;
  223. float t17 = 1 / t16;
  224. data[0] = (m.data[4] * m.data[8] - m.data[5] * m.data[7]) * t17;
  225. data[1] = -(m.data[1] * m.data[8] - m.data[2] * m.data[7]) * t17;
  226. data[2] = (m.data[1] * m.data[5] - m.data[2] * m.data[4]) * t17;
  227. data[3] = -(m.data[3] * m.data[8] - m.data[5] * m.data[6]) * t17;
  228. data[4] = (m.data[0] * m.data[8] - t14) * t17;
  229. data[5] = -(t6 - t10) * t17;
  230. data[6] = (m.data[3] * m.data[7] - m.data[4] * m.data[6]) * t17;
  231. data[7] = -(m.data[0] * m.data[7] - t12) * t17;
  232. data[8] = (t4 - t8) * t17;
  233. }
  234. ///<summary> Returns a new matrix containing the inverse of this matrix. ///</summary>
  235. public Matrix3 inverse()
  236. {
  237. Matrix3 result = new Matrix3();
  238. result.setInverse(this);
  239. return result;
  240. }
  241. ///<summary>
  242. ///Inverts the matrix.
  243. ///</summary>
  244. public void invert()
  245. {
  246. setInverse(this);
  247. }
  248. ///<summary>
  249. ///Sets the matrix to be the transpose of the given matrix.
  250. ///
  251. ///@param m The matrix to transpose and use to set this.
  252. ///</summary>
  253. public void setTranspose(Matrix3 m)
  254. {
  255. data[0] = m.data[0];
  256. data[1] = m.data[3];
  257. data[2] = m.data[6];
  258. data[3] = m.data[1];
  259. data[4] = m.data[4];
  260. data[5] = m.data[7];
  261. data[6] = m.data[2];
  262. data[7] = m.data[5];
  263. data[8] = m.data[8];
  264. }
  265. ///<summary> Returns a new matrix containing the transpose of this matrix. ///</summary>
  266. public Matrix3 transpose()
  267. {
  268. Matrix3 result = new Matrix3();
  269. result.setTranspose(this);
  270. return result;
  271. }
  272. ///<summary>
  273. ///Returns a matrix which is this matrix multiplied by the given
  274. ///other matrix.
  275. ///</summary>
  276. public static Matrix3 operator *(Matrix3 m, Matrix3 o)
  277. {
  278. return new Matrix3(
  279. m.data[0] * o.data[0] + m.data[1] * o.data[3] + m.data[2] * o.data[6],
  280. m.data[0] * o.data[1] + m.data[1] * o.data[4] + m.data[2] * o.data[7],
  281. m.data[0] * o.data[2] + m.data[1] * o.data[5] + m.data[2] * o.data[8],
  282. m.data[3] * o.data[0] + m.data[4] * o.data[3] + m.data[5] * o.data[6],
  283. m.data[3] * o.data[1] + m.data[4] * o.data[4] + m.data[5] * o.data[7],
  284. m.data[3] * o.data[2] + m.data[4] * o.data[5] + m.data[5] * o.data[8],
  285. m.data[6] * o.data[0] + m.data[7] * o.data[3] + m.data[8] * o.data[6],
  286. m.data[6] * o.data[1] + m.data[7] * o.data[4] + m.data[8] * o.data[7],
  287. m.data[6] * o.data[2] + m.data[7] * o.data[5] + m.data[8] * o.data[8]
  288. );
  289. }
  290. ///<summary>
  291. ///Sets this matrix to be the rotation matrix corresponding to
  292. ///the given quaternion.
  293. ///</summary>
  294. void setOrientation(Quaternion q)
  295. {
  296. data[0] = 1 - (2 * q.Y * q.Y + 2 * q.Z * q.Z);
  297. data[1] = 2 * q.X * q.Y + 2 * q.Z * q.W;
  298. data[2] = 2 * q.X * q.Z - 2 * q.Y * q.W;
  299. data[3] = 2 * q.X * q.Y - 2 * q.Z * q.W;
  300. data[4] = 1 - (2 * q.X * q.X + 2 * q.Z * q.Z);
  301. data[5] = 2 * q.Y * q.Z + 2 * q.X * q.W;
  302. data[6] = 2 * q.X * q.Z + 2 * q.Y * q.W;
  303. data[7] = 2 * q.Y * q.Z - 2 * q.X * q.W;
  304. data[8] = 1 - (2 * q.X * q.X + 2 * q.Y * q.Y);
  305. }
  306. ///<summary>
  307. ///Multiplies this matrix in place by the given scalar.
  308. ///</summary>
  309. public static Matrix3 operator *(Matrix3 m, float scalar)
  310. {
  311. Matrix3 result = new Matrix3(
  312. m.data[0] * scalar, m.data[1] * scalar, m.data[2] * scalar,
  313. m.data[3] * scalar, m.data[4] * scalar, m.data[5] * scalar,
  314. m.data[6] * scalar, m.data[7] * scalar, m.data[8] * scalar
  315. );
  316. return result;
  317. }
  318. ///<summary>
  319. ///Does a component-wise addition of this matrix and the given
  320. ///matrix.
  321. ///</summary>
  322. public static Matrix3 operator +(Matrix3 m, Matrix3 o)
  323. {
  324. Matrix3 result = new Matrix3(
  325. m.data[0] + o.data[0],
  326. m.data[1] + o.data[1],
  327. m.data[2] + o.data[2],
  328. m.data[3] + o.data[3],
  329. m.data[4] + o.data[4],
  330. m.data[5] + o.data[5],
  331. m.data[6] + o.data[6],
  332. m.data[7] + o.data[7],
  333. m.data[8] + o.data[8]
  334. );
  335. return result;
  336. }
  337. ///<summary>
  338. ///Interpolates a couple of matrices.
  339. ///</summary>
  340. static Matrix3 linearInterpolate(Matrix3 a, Matrix3 b, float prop)
  341. {
  342. Matrix3 result = new Matrix3();
  343. for (uint i = 0; i < 9; i++)
  344. {
  345. result.data[i] = a.data[i] * (1 - prop) + b.data[i] * prop;
  346. }
  347. return result;
  348. }
  349. };
  350. }