Matrix.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. #include "Base.h"
  2. #include "Matrix.h"
  3. namespace gameplay
  4. {
  5. Matrix::Matrix(void)
  6. {
  7. setIdentity(m);
  8. }
  9. Matrix::Matrix(float m0, float m1, float m2, float m3,
  10. float m4, float m5, float m6, float m7,
  11. float m8, float m9, float m10, float m11,
  12. float m12, float m13, float m14, float m15)
  13. {
  14. m[0] = m0;
  15. m[1] = m1;
  16. m[2] = m2;
  17. m[3] = m3;
  18. m[4] = m4;
  19. m[5] = m5;
  20. m[6] = m6;
  21. m[7] = m7;
  22. m[8] = m8;
  23. m[9] = m9;
  24. m[10] = m10;
  25. m[11] = m11;
  26. m[12] = m12;
  27. m[13] = m13;
  28. m[14] = m14;
  29. m[15] = m15;
  30. }
  31. Matrix::~Matrix(void)
  32. {
  33. }
  34. void Matrix::setIdentity(float* matrix)
  35. {
  36. memcpy(matrix, MATRIX4F_IDENTITY, MATRIX4F_SIZE);
  37. }
  38. void Matrix::createRotation(const Quaternion& q, float* dst)
  39. {
  40. assert(dst);
  41. float x2 = q.x + q.x;
  42. float y2 = q.y + q.y;
  43. float z2 = q.z + q.z;
  44. float xx2 = q.x * x2;
  45. float yy2 = q.y * y2;
  46. float zz2 = q.z * z2;
  47. float xy2 = q.x * y2;
  48. float xz2 = q.x * z2;
  49. float yz2 = q.y * z2;
  50. float wx2 = q.w * x2;
  51. float wy2 = q.w * y2;
  52. float wz2 = q.w * z2;
  53. dst[0] = 1.0f - yy2 - zz2;
  54. dst[1] = xy2 + wz2;
  55. dst[2] = xz2 - wy2;
  56. dst[3] = 0.0f;
  57. dst[4] = xy2 - wz2;
  58. dst[5] = 1.0f - xx2 - zz2;
  59. dst[6] = yz2 + wx2;
  60. dst[7] = 0.0f;
  61. dst[8] = xz2 + wy2;
  62. dst[9] = yz2 - wx2;
  63. dst[10] = 1.0f - xx2 - yy2;
  64. dst[11] = 0.0f;
  65. dst[12] = 0.0f;
  66. dst[13] = 0.0f;
  67. dst[14] = 0.0f;
  68. dst[15] = 1.0f;
  69. }
  70. void Matrix::createRotation(float x, float y, float z, float angle, float* dst)
  71. {
  72. // Make sure the input axis is normalized
  73. float n = x*x + y*y + z*z;
  74. if (n != 1.0f)
  75. {
  76. // Not normalized
  77. n = sqrt(n);
  78. if (n > 0.000001f) // prevent divide too close to zero
  79. {
  80. n = 1.0f / n;
  81. x *= n;
  82. y *= n;
  83. z *= n;
  84. }
  85. }
  86. float c = cos(angle);
  87. float s = sin(angle);
  88. float t = 1.0f - c;
  89. float tx = t * x;
  90. float ty = t * y;
  91. float tz = t * z;
  92. float txy = tx * y;
  93. float txz = tx * z;
  94. float tyz = ty * z;
  95. float sx = s * x;
  96. float sy = s * y;
  97. float sz = s * z;
  98. dst[0] = c + tx*x;
  99. dst[1] = txy + sz;
  100. dst[2] = txz - sy;
  101. dst[3] = 0.0f;
  102. dst[4] = txy - sz;
  103. dst[5] = c + ty*y;
  104. dst[6] = tyz + sx;
  105. dst[7] = 0.0f;
  106. dst[8] = txz + sy;
  107. dst[9] = tyz - sx;
  108. dst[10] = c + tz*z;
  109. dst[11] = 0.0f;
  110. dst[12] = 0.0f;
  111. dst[13] = 0.0f;
  112. dst[14] = 0.0f;
  113. dst[15] = 1.0f;
  114. }
  115. void Matrix::createRotationX(float angle, float* dst)
  116. {
  117. setIdentity(dst);
  118. float c = cos(angle);
  119. float s = sin(angle);
  120. dst[5] = c;
  121. dst[6] = s;
  122. dst[9] = -s;
  123. dst[10] = c;
  124. }
  125. void Matrix::createRotationY(float angle, float* dst)
  126. {
  127. setIdentity(dst);
  128. float c = cos(angle);
  129. float s = sin(angle);
  130. dst[0] = c;
  131. dst[2] = -s;
  132. dst[8] = s;
  133. dst[10] = c;
  134. }
  135. void Matrix::createRotationZ(float angle, float* dst)
  136. {
  137. setIdentity(dst);
  138. float c = cos(angle);
  139. float s = sin(angle);
  140. dst[0] = c;
  141. dst[1] = s;
  142. dst[4] = -s;
  143. dst[5] = c;
  144. }
  145. void Matrix::createTranslation(float x, float y, float z, float* dst)
  146. {
  147. setIdentity(dst);
  148. dst[12] = x;
  149. dst[13] = y;
  150. dst[14] = z;
  151. }
  152. void Matrix::createScale(float x, float y, float z, float* dst)
  153. {
  154. setIdentity(dst);
  155. dst[0] = x;
  156. dst[5] = y;
  157. dst[10] = z;
  158. }
  159. float* Matrix::getArray()
  160. {
  161. return m;
  162. }
  163. void Matrix::translate(float x, float y, float z)
  164. {
  165. float t[16];
  166. createTranslation(x, y, z, t);
  167. multiply(m, t, m);
  168. }
  169. void Matrix::scale(float x, float y, float z)
  170. {
  171. float s[16];
  172. createScale(x, y, z, s);
  173. multiply(m, s, m);
  174. }
  175. void Matrix::rotate(const Quaternion& q)
  176. {
  177. float r[16];
  178. createRotation(q, r);
  179. multiply(m, r, m);
  180. }
  181. void Matrix::rotate(float x, float y, float z, float angle)
  182. {
  183. float r[16];
  184. createRotation(x, y, z, angle, r);
  185. multiply(m, r, m);
  186. }
  187. void Matrix::rotateX(float angle)
  188. {
  189. float r[16];
  190. createRotationX(angle, r);
  191. multiply(m, r, m);
  192. }
  193. void Matrix::rotateY(float angle)
  194. {
  195. float r[16];
  196. createRotationY(angle, r);
  197. multiply(m, r, m);
  198. }
  199. void Matrix::rotateZ(float angle)
  200. {
  201. float r[16];
  202. createRotationZ(angle, r);
  203. multiply(m, r, m);
  204. }
  205. void Matrix::multiply(const float* m1, const float* m2, float* dst)
  206. {
  207. // Support the case where m1 or m2 is the same array as dst.
  208. float product[16];
  209. product[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];
  210. product[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];
  211. product[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];
  212. product[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];
  213. product[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];
  214. product[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];
  215. product[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];
  216. product[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];
  217. product[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];
  218. product[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];
  219. product[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];
  220. product[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];
  221. product[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];
  222. product[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];
  223. product[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
  224. product[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
  225. memcpy(dst, product, MATRIX4F_SIZE);
  226. }
  227. bool Matrix::decompose(Vector3* scale, Quaternion* rotation, Vector3* translation) const
  228. {
  229. if (translation)
  230. {
  231. // Extract the translation
  232. translation->x = m[12];
  233. translation->y = m[13];
  234. translation->z = m[14];
  235. }
  236. // nothing left to do
  237. if (scale == NULL && rotation == NULL)
  238. {
  239. return true;
  240. }
  241. // Extract the scale.
  242. // This is simply the length of each axis (row/column) in the matrix.
  243. Vector3 xaxis(m[0], m[1], m[2]);
  244. float scaleX = xaxis.length();
  245. Vector3 yaxis(m[4], m[5], m[6]);
  246. float scaleY = yaxis.length();
  247. Vector3 zaxis(m[8], m[9], m[10]);
  248. float scaleZ = zaxis.length();
  249. // Determine if we have a negative scale (true if determinant is less than zero).
  250. // In this case, we simply negate a single axis of the scale.
  251. float det = determinant();
  252. if (det < 0)
  253. {
  254. scaleZ = -scaleZ;
  255. }
  256. if (scale)
  257. {
  258. scale->x = scaleX;
  259. scale->y = scaleY;
  260. scale->z = scaleZ;
  261. }
  262. // nothing left to do
  263. if (rotation == NULL)
  264. return true;
  265. // scale too close to zero, can't decompose rotation
  266. if (scaleX < MATH_TOLERANCE || scaleY < MATH_TOLERANCE || fabs(scaleZ) < MATH_TOLERANCE)
  267. return false;
  268. float rn;
  269. // Factor the scale out of the matrix axes
  270. rn = 1.0f / scaleX;
  271. xaxis.x *= rn;
  272. xaxis.y *= rn;
  273. xaxis.z *= rn;
  274. rn = 1.0f / scaleY;
  275. yaxis.x *= rn;
  276. yaxis.y *= rn;
  277. yaxis.z *= rn;
  278. rn = 1.0f / scaleZ;
  279. zaxis.x *= rn;
  280. zaxis.y *= rn;
  281. zaxis.z *= rn;
  282. // Now calculate the rotation from the resulting matrix (axes)
  283. float trace = xaxis.x + yaxis.y + zaxis.z + 1.0f;
  284. if (trace > MATH_TOLERANCE)
  285. {
  286. float s = 0.5f / sqrt(trace);
  287. rotation->w = 0.25f / s;
  288. rotation->x = ( yaxis.z - zaxis.y ) * s;
  289. rotation->y = ( zaxis.x - xaxis.z ) * s;
  290. rotation->z = ( xaxis.y - yaxis.x ) * s;
  291. }
  292. else
  293. {
  294. if (xaxis.x > yaxis.y && xaxis.x > zaxis.z)
  295. {
  296. float s = 2.0f * sqrt(1.0f + xaxis.x - yaxis.y - zaxis.z);
  297. rotation->w = (yaxis.z - zaxis.y ) / s;
  298. rotation->x = 0.25f * s;
  299. rotation->y = (yaxis.x + xaxis.y ) / s;
  300. rotation->z = (zaxis.x + xaxis.z ) / s;
  301. }
  302. else if (yaxis.y > zaxis.z)
  303. {
  304. float s = 2.0f * sqrt(1.0f + yaxis.y - xaxis.x - zaxis.z);
  305. rotation->w = (zaxis.x - xaxis.z ) / s;
  306. rotation->x = (yaxis.x + xaxis.y ) / s;
  307. rotation->y = 0.25f * s;
  308. rotation->z = (zaxis.y + yaxis.z ) / s;
  309. }
  310. else
  311. {
  312. float s = 2.0f * sqrt(1.0f + zaxis.z - xaxis.x - yaxis.y );
  313. rotation->w = (xaxis.y - yaxis.x ) / s;
  314. rotation->x = (zaxis.x + xaxis.z ) / s;
  315. rotation->y = (zaxis.y + yaxis.z ) / s;
  316. rotation->z = 0.25f * s;
  317. }
  318. }
  319. return true;
  320. }
  321. float Matrix::determinant() const
  322. {
  323. float a0 = m[0] * m[5] - m[1] * m[4];
  324. float a1 = m[0] * m[6] - m[2] * m[4];
  325. float a2 = m[0] * m[7] - m[3] * m[4];
  326. float a3 = m[1] * m[6] - m[2] * m[5];
  327. float a4 = m[1] * m[7] - m[3] * m[5];
  328. float a5 = m[2] * m[7] - m[3] * m[6];
  329. float b0 = m[8] * m[13] - m[9] * m[12];
  330. float b1 = m[8] * m[14] - m[10] * m[12];
  331. float b2 = m[8] * m[15] - m[11] * m[12];
  332. float b3 = m[9] * m[14] - m[10] * m[13];
  333. float b4 = m[9] * m[15] - m[11] * m[13];
  334. float b5 = m[10] * m[15] - m[11] * m[14];
  335. // Calculate the determinant
  336. return (a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0);
  337. }
  338. void Matrix::transformPoint(const Vector3& p, Vector3* dst) const
  339. {
  340. dst->set(
  341. p.x * m[0] + p.y * m[4] + p.z * m[8] + m[12],
  342. p.x * m[1] + p.y * m[5] + p.z * m[9] + m[13],
  343. p.x * m[2] + p.y * m[6] + p.z * m[10] + m[14] );
  344. }
  345. }