Matrix3x3.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace Ximmerse.XR.Internal.Mathmatics
  5. {
  6. /// <summary>
  7. /// A 3x3 matrix struct.
  8. /// Performative to represent quaternion.
  9. /// </summary>
  10. [System.Serializable]
  11. internal struct Matrix3x3
  12. {
  13. /// <summary>
  14. /// Gets a identity matrix.
  15. /// </summary>
  16. public static Matrix3x3 identity
  17. {
  18. get
  19. {
  20. return new Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
  21. }
  22. }
  23. /// <summary>
  24. /// Row 0
  25. /// </summary>
  26. [SerializeField]
  27. float m_m00, m_m01, m_m02;
  28. /// <summary>
  29. /// Row 1
  30. /// </summary>
  31. [SerializeField]
  32. float m_m10, m_m11, m_m12;
  33. /// <summary>
  34. /// Row 2
  35. /// </summary>
  36. [SerializeField]
  37. float m_m20, m_m21, m_m22;
  38. /// <summary>
  39. /// Row 0, Col 0
  40. /// </summary>
  41. public float m00
  42. {
  43. get => m_m00;
  44. }
  45. /// <summary>
  46. /// Row 0, Col 1
  47. /// </summary>
  48. public float m01
  49. {
  50. get => m_m01;
  51. }
  52. /// <summary>
  53. /// Row 0, Col 2
  54. /// </summary>
  55. public float m02
  56. {
  57. get => m_m02;
  58. }
  59. /// <summary>
  60. /// Row 1, Col 0
  61. /// </summary>
  62. public float m10
  63. {
  64. get => m_m10;
  65. }
  66. /// <summary>
  67. /// Row 1, Col 1
  68. /// </summary>
  69. public float m11
  70. {
  71. get => m_m11;
  72. }
  73. /// <summary>
  74. /// Row 1, Col 2
  75. /// </summary>
  76. public float m12
  77. {
  78. get => m_m12;
  79. }
  80. /// <summary>
  81. /// Row 2, Col 0
  82. /// </summary>
  83. public float m20
  84. {
  85. get => m_m20;
  86. }
  87. /// <summary>
  88. /// Row 2, Col 1
  89. /// </summary>
  90. public float m21
  91. {
  92. get => m_m21;
  93. }
  94. /// <summary>
  95. /// Row 2, Col 2
  96. /// </summary>
  97. public float m22
  98. {
  99. get => m_m22;
  100. }
  101. /// <summary>
  102. /// Gets element by row/col
  103. /// </summary>
  104. /// <param name="row"></param>
  105. /// <param name="col"></param>
  106. /// <returns></returns>
  107. public float this[int row, int col]
  108. {
  109. get
  110. {
  111. if (row == 0 && col == 0)
  112. {
  113. return m_m00;
  114. }
  115. if (row == 0 && col == 1)
  116. {
  117. return m_m01;
  118. }
  119. if (row == 0 && col == 2)
  120. {
  121. return m_m02;
  122. }
  123. if (row == 1 && col == 0)
  124. {
  125. return m_m10;
  126. }
  127. if (row == 1 && col == 1)
  128. {
  129. return m_m11;
  130. }
  131. if (row == 1 && col == 2)
  132. {
  133. return m_m12;
  134. }
  135. if (row == 2 && col == 0)
  136. {
  137. return m_m20;
  138. }
  139. if (row == 2 && col == 1)
  140. {
  141. return m_m21;
  142. }
  143. if (row == 2 && col == 2)
  144. {
  145. return m_m22;
  146. }
  147. throw new UnityException(string.Format("Invalid format : {0},{1}", row, col));
  148. }
  149. }
  150. /// <summary>
  151. /// Ctor of matrix 3x3
  152. /// </summary>
  153. /// <param name="m00"></param>
  154. /// <param name="m01"></param>
  155. /// <param name="m02"></param>
  156. /// <param name="m10"></param>
  157. /// <param name="m11"></param>
  158. /// <param name="m12"></param>
  159. /// <param name="m20"></param>
  160. /// <param name="m21"></param>
  161. /// <param name="m22"></param>
  162. public Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
  163. {
  164. m_m00 = m00;
  165. m_m01 = m01;
  166. m_m02 = m02;
  167. m_m10 = m10;
  168. m_m11 = m11;
  169. m_m12 = m12;
  170. m_m20 = m20;
  171. m_m21 = m21;
  172. m_m22 = m22;
  173. }
  174. /// <summary>
  175. /// Ctor a matrix3x3 by 2 vector3 of row and col.
  176. /// </summary>
  177. /// <param name="col">A vector3 of represents column.</param>
  178. /// <param name="row">A vector3 of represents row.</param>
  179. public Matrix3x3(Vector3 col, Vector3 row)
  180. {
  181. m_m00 = col.x * row.x;
  182. m_m01 = col.x * row.y;
  183. m_m02 = col.x * row.z;
  184. m_m10 = col.y * row.x;
  185. m_m11 = col.y * row.y;
  186. m_m12 = col.y * row.z;
  187. m_m20 = col.z * row.x;
  188. m_m21 = col.z * row.y;
  189. m_m22 = col.z * row.z;
  190. }
  191. /// <summary>
  192. /// Ctor of matrix 3x3 by quaternion.
  193. /// </summary>
  194. /// <param name="q"></param>
  195. public Matrix3x3(Quaternion q)
  196. {
  197. m_m00 = 1.0f - 2.0f * (q.y * q.y + q.z * q.z);
  198. m_m10 = (q.x * q.y + q.z * q.w) * 2.0f;
  199. m_m20 = (q.x * q.z - q.y * q.w) * 2.0f;
  200. m_m01 = (q.x * q.y - q.z * q.w) * 2.0f;
  201. m_m11 = 1.0f - 2.0f * (q.x * q.x + q.z * q.z);
  202. m_m21 = (q.y * q.z + q.x * q.w) * 2.0f;
  203. m_m02 = (q.x * q.z + q.y * q.w) * 2.0f;
  204. m_m12 = (q.y * q.z - q.x * q.w) * 2.0f;
  205. m_m22 = 1.0f - 2.0f * (q.x * q.x + q.y * q.y);
  206. }
  207. /// <summary>
  208. /// Sets this matrix3x3 by the quaternion.
  209. /// </summary>
  210. /// <param name="quaternion"></param>
  211. public void SetRotation(Quaternion q)
  212. {
  213. m_m00 = 1.0f - 2.0f * (q.y * q.y + q.z * q.z);
  214. m_m10 = (q.x * q.y + q.z * q.w) * 2.0f;
  215. m_m20 = (q.x * q.z - q.y * q.w) * 2.0f;
  216. m_m01 = (q.x * q.y - q.z * q.w) * 2.0f;
  217. m_m11 = 1.0f - 2.0f * (q.x * q.x + q.z * q.z);
  218. m_m21 = (q.y * q.z + q.x * q.w) * 2.0f;
  219. m_m02 = (q.x * q.z + q.y * q.w) * 2.0f;
  220. m_m12 = (q.y * q.z - q.x * q.w) * 2.0f;
  221. m_m22 = 1.0f - 2.0f * (q.x * q.x + q.y * q.y);
  222. }
  223. /// <summary>
  224. /// Transpose this 3x3 matrix.
  225. /// </summary>
  226. /// <returns></returns>
  227. public Matrix3x3 transpose
  228. {
  229. get => new Matrix3x3(m00, m10, m20, m01, m11, m21, m02, m12, m22);
  230. }
  231. /// <summary>
  232. /// Composite a rotation 3x3 matrix and a position to a matrix4x4 translation matrix.
  233. /// </summary>
  234. /// <param name="RotationMatrix"></param>
  235. /// <param name="position"></param>
  236. /// <returns></returns>
  237. public static Matrix4x4 ToTRS(Matrix3x3 RotationMatrix, Vector3 position)
  238. {
  239. Matrix4x4 trs = Matrix4x4.identity;
  240. trs.SetRow(0, new Vector4(RotationMatrix.m00, RotationMatrix.m01, RotationMatrix.m02, position.x));
  241. trs.SetRow(1, new Vector4(RotationMatrix.m10, RotationMatrix.m11, RotationMatrix.m12, position.y));
  242. trs.SetRow(2, new Vector4(RotationMatrix.m20, RotationMatrix.m21, RotationMatrix.m22, position.z));
  243. return trs;
  244. }
  245. /// <summary>
  246. /// Assumes the matrix3x3 represents a quaternion rotation.
  247. /// Thread safe function.
  248. /// </summary>
  249. /// <param name="m"></param>
  250. /// <returns></returns>
  251. public Quaternion GetRotation()
  252. {
  253. float fourXSquaredMinus1 = m_m00 - m_m11 - m_m22;
  254. float fourYSquaredMinus1 = m_m11 - m_m00 - m_m22;
  255. float fourZSquaredMinus1 = m_m22 - m_m00 - m_m11;
  256. float fourWSquaredMinus1 = m_m00 + m_m11 + m_m22;
  257. int biggestIndex = 0;
  258. float fourBiggestSquaredMinus1 = fourWSquaredMinus1;
  259. if (fourXSquaredMinus1 > fourBiggestSquaredMinus1)
  260. {
  261. fourBiggestSquaredMinus1 = fourXSquaredMinus1;
  262. biggestIndex = 1;
  263. }
  264. if (fourYSquaredMinus1 > fourBiggestSquaredMinus1)
  265. {
  266. fourBiggestSquaredMinus1 = fourYSquaredMinus1;
  267. biggestIndex = 2;
  268. }
  269. if (fourZSquaredMinus1 > fourBiggestSquaredMinus1)
  270. {
  271. fourBiggestSquaredMinus1 = fourZSquaredMinus1;
  272. biggestIndex = 3;
  273. }
  274. float biggestVal = Mathf.Sqrt(fourBiggestSquaredMinus1 + 1) * 0.5f;
  275. float mult = 0.25f / biggestVal;
  276. Quaternion q = Quaternion.identity;
  277. switch (biggestIndex)
  278. {
  279. case 0:
  280. q.w = biggestVal;
  281. q.x = (m_m12 - m_m21) * mult;
  282. q.y = (m_m20 - m_m02) * mult;
  283. q.z = (m_m01 - m_m10) * mult;
  284. break;
  285. case 1:
  286. q.w = (m_m12 - m_m21) * mult;
  287. q.x = biggestVal;
  288. q.y = (m_m01 + m_m10) * mult;
  289. q.z = (m_m20 + m_m02) * mult;
  290. break;
  291. case 2:
  292. q.w = (m_m20 - m_m02) * mult;
  293. q.x = (m_m01 + m_m10) * mult;
  294. q.y = biggestVal;
  295. q.z = (m_m12 + m_m21) * mult;
  296. break;
  297. case 3:
  298. q.w = (m_m01 - m_m10) * mult;
  299. q.x = (m_m20 + m_m02) * mult;
  300. q.y = (m_m12 + m_m21) * mult;
  301. q.z = biggestVal;
  302. break;
  303. default: // Silence a -Wswitch-default warning in GCC. Should never actually get here. Assert is just for sanity.
  304. break;
  305. }
  306. float e = 1 / (q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
  307. return new Quaternion(-q.x * e, -q.y * e, -q.z * e, q.w * e);
  308. }
  309. /// <summary>
  310. /// Gets row at the index of the matrix3x3
  311. /// </summary>
  312. /// <param name="RowIndex"></param>
  313. /// <returns></returns>
  314. public Vector3 GetRow(int RowIndex)
  315. {
  316. switch (RowIndex)
  317. {
  318. case 0:
  319. return new Vector3(m00, m01, m02);
  320. case 1:
  321. return new Vector3(m10, m11, m12);
  322. case 2:
  323. return new Vector3(m20, m21, m22);
  324. default:
  325. throw new UnityException(string.Format("Invalid index: {0}", RowIndex));
  326. }
  327. }
  328. /// <summary>
  329. /// Gets column at the index of the matrix3x3
  330. /// </summary>
  331. /// <param name="ColumnIndex"></param>
  332. /// <returns></returns>
  333. public Vector3 GetColumn(int ColumnIndex)
  334. {
  335. switch (ColumnIndex)
  336. {
  337. case 0:
  338. return new Vector3(m00, m10, m20);
  339. case 1:
  340. return new Vector3(m01, m11, m21);
  341. case 2:
  342. return new Vector3(m02, m12, m22);
  343. default:
  344. throw new UnityException(string.Format("Invalid index: {0}", ColumnIndex));
  345. }
  346. }
  347. public static Matrix3x3 operator *(float lhs, Matrix3x3 rhs)
  348. {
  349. return new Matrix3x3(lhs * rhs.m00, lhs * rhs.m01, lhs * rhs.m02,
  350. lhs * rhs.m10, lhs * rhs.m11, lhs * rhs.m12,
  351. lhs * rhs.m20, lhs * rhs.m21, lhs * rhs.m22);
  352. }
  353. public static Matrix3x3 operator *(Matrix3x3 lhs, float rhs)
  354. {
  355. return new Matrix3x3(rhs * lhs.m00, rhs * lhs.m01, rhs * lhs.m02,
  356. rhs * lhs.m10, rhs * lhs.m11, rhs * lhs.m12,
  357. rhs * lhs.m20, rhs * lhs.m21, rhs * lhs.m22);
  358. }
  359. /// <summary>
  360. /// Multiple two matrix3x3
  361. /// </summary>
  362. /// <param name="lhs"></param>
  363. /// <param name="rhs"></param>
  364. /// <returns></returns>
  365. public static Matrix3x3 operator *(Matrix3x3 lhs, Matrix3x3 rhs)
  366. {
  367. Vector3 lRow0 = lhs.GetRow(0);
  368. Vector3 lRow1 = lhs.GetRow(1);
  369. Vector3 lRow2 = lhs.GetRow(2);
  370. Vector3 rRow0 = rhs.GetRow(0);
  371. Vector3 rRow1 = rhs.GetRow(1);
  372. Vector3 rRow2 = rhs.GetRow(2);
  373. Matrix3x3 result = new Matrix3x3(
  374. m00: lRow0.x * rRow0.x + lRow0.y * rRow1.x + lRow0.z * rRow2.x,
  375. m01: lRow0.x * rRow0.y + lRow0.y * rRow1.y + lRow0.z * rRow2.y,
  376. m02: lRow0.x * rRow0.z + lRow0.y * rRow1.z + lRow0.z * rRow2.z,
  377. m10: lRow1.x * rRow0.x + lRow1.y * rRow1.x + lRow1.z * rRow2.x,
  378. m11: lRow1.x * rRow0.y + lRow1.y * rRow1.y + lRow1.z * rRow2.y,
  379. m12: lRow1.x * rRow0.z + lRow1.y * rRow1.z + lRow1.z * rRow2.z,
  380. m20: lRow2.x * rRow0.x + lRow2.y * rRow1.x + lRow2.z * rRow2.x,
  381. m21: lRow2.x * rRow0.y + lRow2.y * rRow1.y + lRow2.z * rRow2.y,
  382. m22: lRow2.x * rRow0.z + lRow2.y * rRow1.z + lRow2.z * rRow2.z
  383. );
  384. return result;
  385. }
  386. /// <summary>
  387. /// Plus lhs to rhs
  388. /// </summary>
  389. /// <param name="lhs"></param>
  390. /// <param name="rhs"></param>
  391. /// <returns></returns>
  392. public static Matrix3x3 operator +(Matrix3x3 lhs, Matrix3x3 rhs)
  393. {
  394. return new Matrix3x3(lhs.m00 + rhs.m00, lhs.m01 + rhs.m01, lhs.m02 + rhs.m02,
  395. lhs.m10 + rhs.m10, lhs.m11 + rhs.m11, lhs.m12 + rhs.m12,
  396. lhs.m20 + rhs.m20, lhs.m21 + rhs.m21, lhs.m22 + rhs.m22);
  397. }
  398. /// <summary>
  399. /// Minus lhs to rhs
  400. /// </summary>
  401. /// <param name="lhs"></param>
  402. /// <param name="rhs"></param>
  403. /// <returns></returns>
  404. public static Matrix3x3 operator -(Matrix3x3 lhs, Matrix3x3 rhs)
  405. {
  406. return new Matrix3x3(lhs.m00 - rhs.m00, lhs.m01 - rhs.m01, lhs.m02 - rhs.m02,
  407. lhs.m10 - rhs.m10, lhs.m11 - rhs.m11, lhs.m12 - rhs.m12,
  408. lhs.m20 - rhs.m20, lhs.m21 - rhs.m21, lhs.m22 - rhs.m22);
  409. }
  410. /// <summary>
  411. /// Multiple lhs by rhs Vector3
  412. /// </summary>
  413. /// <param name="lhs"></param>
  414. /// <param name="rhs"></param>
  415. /// <returns></returns>
  416. public static Vector3 operator *(Matrix3x3 lhs, Vector3 rhs)
  417. {
  418. Vector3 lCol0 = lhs.GetColumn(0);
  419. Vector3 lCol1 = lhs.GetColumn(1);
  420. Vector3 lCol2 = lhs.GetColumn(2);
  421. return lCol0 * rhs.x + lCol1 * rhs.y + lCol2 * rhs.z;
  422. }
  423. public override string ToString()
  424. {
  425. return string.Format("[{0}, {1}, {2}]\r\n[{3}, {4}, {5}]\r\n[{6}, {7}, {8}]", m00, m01, m02,
  426. m10, m11, m12,
  427. m20, m21, m22);
  428. }
  429. public string ToString(string format)
  430. {
  431. return string.Format("[{0}, {1}, {2}]\r\n[{3}, {4}, {5}]\r\n[{6}, {7}, {8}]", m00.ToString(format), m01.ToString(format), m02.ToString(format),
  432. m10.ToString(format), m11.ToString(format), m12.ToString(format),
  433. m20.ToString(format), m21.ToString(format), m22.ToString(format));
  434. }
  435. }
  436. }