Matrix.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206
  1. #include "Base.h"
  2. #include "Matrix.h"
  3. #include "Quaternion.h"
  4. #define MATRIX_SIZE ( sizeof(float) * 16 )
  5. namespace gameplay
  6. {
  7. static const float MATRIX_IDENTITY[16] =
  8. {
  9. 1.0f, 0.0f, 0.0f, 0.0f,
  10. 0.0f, 1.0f, 0.0f, 0.0f,
  11. 0.0f, 0.0f, 1.0f, 0.0f,
  12. 0.0f, 0.0f, 0.0f, 1.0f
  13. };
  14. Matrix::Matrix()
  15. {
  16. *this = Matrix::identity();
  17. }
  18. Matrix::Matrix(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44)
  19. {
  20. set(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
  21. }
  22. Matrix::Matrix(const float* m)
  23. {
  24. set(m);
  25. }
  26. Matrix::Matrix(const Matrix& copy)
  27. {
  28. memcpy(m, copy.m, MATRIX_SIZE);
  29. }
  30. Matrix::~Matrix()
  31. {
  32. }
  33. const Matrix& Matrix::identity()
  34. {
  35. static Matrix m(
  36. 1, 0, 0, 0,
  37. 0, 1, 0, 0,
  38. 0, 0, 1, 0,
  39. 0, 0, 0, 1 );
  40. return m;
  41. }
  42. const Matrix& Matrix::zero()
  43. {
  44. static Matrix m(
  45. 0, 0, 0, 0,
  46. 0, 0, 0, 0,
  47. 0, 0, 0, 0,
  48. 0, 0, 0, 0 );
  49. return m;
  50. }
  51. void Matrix::createLookAt(const Vector3& eyePosition, const Vector3& targetPosition, const Vector3& up, Matrix* dst)
  52. {
  53. createLookAt(eyePosition.x, eyePosition.y, eyePosition.z, targetPosition.x, targetPosition.y, targetPosition.z, up.x, up.y, up.z, dst);
  54. }
  55. void Matrix::createLookAt(float eyePositionX, float eyePositionY, float eyePositionZ,
  56. float targetPositionX, float targetPositionY, float targetPositionZ,
  57. float upX, float upY, float upZ, Matrix* dst)
  58. {
  59. GP_ASSERT(dst);
  60. Vector3 eye(eyePositionX, eyePositionY, eyePositionZ);
  61. Vector3 target(targetPositionX, targetPositionY, targetPositionZ);
  62. Vector3 up(upX, upY, upZ);
  63. up.normalize();
  64. Vector3 zaxis;
  65. Vector3::subtract(eye, target, &zaxis);
  66. zaxis.normalize();
  67. Vector3 xaxis;
  68. Vector3::cross(up, zaxis, &xaxis);
  69. xaxis.normalize();
  70. Vector3 yaxis;
  71. Vector3::cross(zaxis, xaxis, &yaxis);
  72. yaxis.normalize();
  73. dst->m[0] = xaxis.x;
  74. dst->m[1] = yaxis.x;
  75. dst->m[2] = zaxis.x;
  76. dst->m[3] = 0.0f;
  77. dst->m[4] = xaxis.y;
  78. dst->m[5] = yaxis.y;
  79. dst->m[6] = zaxis.y;
  80. dst->m[7] = 0.0f;
  81. dst->m[8] = xaxis.z;
  82. dst->m[9] = yaxis.z;
  83. dst->m[10] = zaxis.z;
  84. dst->m[11] = 0.0f;
  85. dst->m[12] = -Vector3::dot(xaxis, eye);
  86. dst->m[13] = -Vector3::dot(yaxis, eye);
  87. dst->m[14] = -Vector3::dot(zaxis, eye);
  88. dst->m[15] = 1.0f;
  89. }
  90. void Matrix::createPerspective(float fieldOfView, float aspectRatio,
  91. float zNearPlane, float zFarPlane, Matrix* dst)
  92. {
  93. GP_ASSERT(dst);
  94. GP_ASSERT(zFarPlane != zNearPlane);
  95. float f_n = 1.0f / (zFarPlane - zNearPlane);
  96. float theta = MATH_DEG_TO_RAD(fieldOfView) * 0.5f;
  97. if (fabs(fmod(theta, MATH_PIOVER2)) < MATH_EPSILON)
  98. {
  99. GP_ERROR("Invalid field of view value (%d) causes attempted calculation tan(%d), which is undefined.", fieldOfView, theta);
  100. return;
  101. }
  102. float divisor = tan(theta);
  103. GP_ASSERT(divisor);
  104. float factor = 1.0f / divisor;
  105. memset(dst, 0, MATRIX_SIZE);
  106. GP_ASSERT(aspectRatio);
  107. dst->m[0] = (1.0f / aspectRatio) * factor;
  108. dst->m[5] = factor;
  109. dst->m[10] = (-(zFarPlane + zNearPlane)) * f_n;
  110. dst->m[11] = -1.0f;
  111. dst->m[14] = -2.0f * zFarPlane * zNearPlane * f_n;
  112. }
  113. void Matrix::createOrthographic(float width, float height, float zNearPlane, float zFarPlane, Matrix* dst)
  114. {
  115. float halfWidth = width / 2.0f;
  116. float halfHeight = height / 2.0f;
  117. createOrthographicOffCenter(-halfWidth, halfWidth, -halfHeight, halfHeight, zNearPlane, zFarPlane, dst);
  118. }
  119. void Matrix::createOrthographicOffCenter(float left, float right, float bottom, float top,
  120. float zNearPlane, float zFarPlane, Matrix* dst)
  121. {
  122. GP_ASSERT(dst);
  123. GP_ASSERT(right != left);
  124. GP_ASSERT(top != bottom);
  125. GP_ASSERT(zFarPlane != zNearPlane);
  126. float r_l = 1.0f / (right - left);
  127. float t_b = 1.0f / (top - bottom);
  128. float f_n = 1.0f / (zFarPlane - zNearPlane);
  129. memset(dst, 0, MATRIX_SIZE);
  130. dst->m[0] = 2.0f * r_l;
  131. dst->m[5] = 2.0f * t_b;
  132. dst->m[10] = -2.0f * f_n;
  133. dst->m[12] = (-(right + left)) * r_l;
  134. dst->m[13] = (-(top + bottom)) * t_b;
  135. dst->m[14] = (-(zFarPlane + zNearPlane)) * f_n;
  136. dst->m[15] = 1.0f;
  137. }
  138. void Matrix::createScale(const Vector3& scale, Matrix* dst)
  139. {
  140. GP_ASSERT(dst);
  141. memcpy(dst, MATRIX_IDENTITY, MATRIX_SIZE);
  142. dst->m[0] = scale.x;
  143. dst->m[5] = scale.y;
  144. dst->m[10] = scale.z;
  145. }
  146. void Matrix::createScale(float xScale, float yScale, float zScale, Matrix* dst)
  147. {
  148. GP_ASSERT(dst);
  149. memcpy(dst, MATRIX_IDENTITY, MATRIX_SIZE);
  150. dst->m[0] = xScale;
  151. dst->m[5] = yScale;
  152. dst->m[10] = zScale;
  153. }
  154. void Matrix::createRotation(const Quaternion& q, Matrix* dst)
  155. {
  156. GP_ASSERT(dst);
  157. float x2 = q.x + q.x;
  158. float y2 = q.y + q.y;
  159. float z2 = q.z + q.z;
  160. float xx2 = q.x * x2;
  161. float yy2 = q.y * y2;
  162. float zz2 = q.z * z2;
  163. float xy2 = q.x * y2;
  164. float xz2 = q.x * z2;
  165. float yz2 = q.y * z2;
  166. float wx2 = q.w * x2;
  167. float wy2 = q.w * y2;
  168. float wz2 = q.w * z2;
  169. dst->m[0] = 1.0f - yy2 - zz2;
  170. dst->m[1] = xy2 + wz2;
  171. dst->m[2] = xz2 - wy2;
  172. dst->m[3] = 0.0f;
  173. dst->m[4] = xy2 - wz2;
  174. dst->m[5] = 1.0f - xx2 - zz2;
  175. dst->m[6] = yz2 + wx2;
  176. dst->m[7] = 0.0f;
  177. dst->m[8] = xz2 + wy2;
  178. dst->m[9] = yz2 - wx2;
  179. dst->m[10] = 1.0f - xx2 - yy2;
  180. dst->m[11] = 0.0f;
  181. dst->m[12] = 0.0f;
  182. dst->m[13] = 0.0f;
  183. dst->m[14] = 0.0f;
  184. dst->m[15] = 1.0f;
  185. }
  186. void Matrix::createRotation(const Vector3& axis, float angle, Matrix* dst)
  187. {
  188. GP_ASSERT(dst);
  189. float x = axis.x;
  190. float y = axis.y;
  191. float z = axis.z;
  192. // Make sure the input axis is normalized.
  193. float n = x*x + y*y + z*z;
  194. if (n != 1.0f)
  195. {
  196. // Not normalized.
  197. n = sqrt(n);
  198. // Prevent divide too close to zero.
  199. if (n > 0.000001f)
  200. {
  201. n = 1.0f / n;
  202. x *= n;
  203. y *= n;
  204. z *= n;
  205. }
  206. }
  207. float c = cos(angle);
  208. float s = sin(angle);
  209. float t = 1.0f - c;
  210. float tx = t * x;
  211. float ty = t * y;
  212. float tz = t * z;
  213. float txy = tx * y;
  214. float txz = tx * z;
  215. float tyz = ty * z;
  216. float sx = s * x;
  217. float sy = s * y;
  218. float sz = s * z;
  219. dst->m[0] = c + tx*x;
  220. dst->m[1] = txy + sz;
  221. dst->m[2] = txz - sy;
  222. dst->m[3] = 0.0f;
  223. dst->m[4] = txy - sz;
  224. dst->m[5] = c + ty*y;
  225. dst->m[6] = tyz + sx;
  226. dst->m[7] = 0.0f;
  227. dst->m[8] = txz + sy;
  228. dst->m[9] = tyz - sx;
  229. dst->m[10] = c + tz*z;
  230. dst->m[11] = 0.0f;
  231. dst->m[12] = 0.0f;
  232. dst->m[13] = 0.0f;
  233. dst->m[14] = 0.0f;
  234. dst->m[15] = 1.0f;
  235. }
  236. void Matrix::createRotationX(float angle, Matrix* dst)
  237. {
  238. GP_ASSERT(dst);
  239. memcpy(dst, MATRIX_IDENTITY, MATRIX_SIZE);
  240. float c = cos(angle);
  241. float s = sin(angle);
  242. dst->m[5] = c;
  243. dst->m[6] = s;
  244. dst->m[9] = -s;
  245. dst->m[10] = c;
  246. }
  247. void Matrix::createRotationY(float angle, Matrix* dst)
  248. {
  249. GP_ASSERT(dst);
  250. memcpy(dst, MATRIX_IDENTITY, MATRIX_SIZE);
  251. float c = cos(angle);
  252. float s = sin(angle);
  253. dst->m[0] = c;
  254. dst->m[2] = -s;
  255. dst->m[8] = s;
  256. dst->m[10] = c;
  257. }
  258. void Matrix::createRotationZ(float angle, Matrix* dst)
  259. {
  260. GP_ASSERT(dst);
  261. memcpy(dst, MATRIX_IDENTITY, MATRIX_SIZE);
  262. float c = cos(angle);
  263. float s = sin(angle);
  264. dst->m[0] = c;
  265. dst->m[1] = s;
  266. dst->m[4] = -s;
  267. dst->m[5] = c;
  268. }
  269. void Matrix::createTranslation(const Vector3& translation, Matrix* dst)
  270. {
  271. GP_ASSERT(dst);
  272. memcpy(dst, MATRIX_IDENTITY, MATRIX_SIZE);
  273. dst->m[12] = translation.x;
  274. dst->m[13] = translation.y;
  275. dst->m[14] = translation.z;
  276. }
  277. void Matrix::createTranslation(float xTranslation, float yTranslation, float zTranslation, Matrix* dst)
  278. {
  279. GP_ASSERT(dst);
  280. memcpy(dst, MATRIX_IDENTITY, MATRIX_SIZE);
  281. dst->m[12] = xTranslation;
  282. dst->m[13] = yTranslation;
  283. dst->m[14] = zTranslation;
  284. }
  285. void Matrix::add(float scalar)
  286. {
  287. add(scalar, this);
  288. }
  289. void Matrix::add(float scalar, Matrix* dst)
  290. {
  291. GP_ASSERT(dst);
  292. dst->m[0] = m[0] + scalar;
  293. dst->m[1] = m[1] + scalar;
  294. dst->m[2] = m[2] + scalar;
  295. dst->m[3] = m[3] + scalar;
  296. dst->m[4] = m[4] + scalar;
  297. dst->m[5] = m[5] + scalar;
  298. dst->m[6] = m[6] + scalar;
  299. dst->m[7] = m[7] + scalar;
  300. dst->m[8] = m[8] + scalar;
  301. dst->m[9] = m[9] + scalar;
  302. dst->m[10] = m[10] + scalar;
  303. dst->m[11] = m[11] + scalar;
  304. dst->m[12] = m[12] + scalar;
  305. dst->m[13] = m[13] + scalar;
  306. dst->m[14] = m[14] + scalar;
  307. dst->m[15] = m[15] + scalar;
  308. }
  309. void Matrix::add(const Matrix& m)
  310. {
  311. add(*this, m, this);
  312. }
  313. void Matrix::add(const Matrix& m1, const Matrix& m2, Matrix* dst)
  314. {
  315. GP_ASSERT(dst);
  316. #ifdef USE_NEON
  317. asm volatile(
  318. "vld1.32 {q0, q1}, [%1]! \n\t"
  319. "vld1.32 {q2, q3}, [%1]! \n\t"
  320. "vld1.32 {q8, q9}, [%2]! \n\t"
  321. "vld1.32 {q10, q11}, [%2]! \n\t"
  322. "vadd.f32 q12, q0, q8 \n\t"
  323. "vadd.f32 q13, q1, q9 \n\t"
  324. "vadd.f32 q14, q2, q10 \n\t"
  325. "vadd.f32 q15, q3, q11 \n\t"
  326. "vst1.32 {q12, q13}, [%0]! \n\t"
  327. "vst1.32 {q14, q15}, [%0]! \n\t"
  328. :
  329. : "r"(dst->m), "r"(m1.m), "r"(m2.m)
  330. : "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory"
  331. );
  332. #else
  333. dst->m[0] = m1.m[0] + m2.m[0];
  334. dst->m[1] = m1.m[1] + m2.m[1];
  335. dst->m[2] = m1.m[2] + m2.m[2];
  336. dst->m[3] = m1.m[3] + m2.m[3];
  337. dst->m[4] = m1.m[4] + m2.m[4];
  338. dst->m[5] = m1.m[5] + m2.m[5];
  339. dst->m[6] = m1.m[6] + m2.m[6];
  340. dst->m[7] = m1.m[7] + m2.m[7];
  341. dst->m[8] = m1.m[8] + m2.m[8];
  342. dst->m[9] = m1.m[9] + m2.m[9];
  343. dst->m[10] = m1.m[10] + m2.m[10];
  344. dst->m[11] = m1.m[11] + m2.m[11];
  345. dst->m[12] = m1.m[12] + m2.m[12];
  346. dst->m[13] = m1.m[13] + m2.m[13];
  347. dst->m[14] = m1.m[14] + m2.m[14];
  348. dst->m[15] = m1.m[15] + m2.m[15];
  349. #endif
  350. }
  351. bool Matrix::decompose(Vector3* scale, Quaternion* rotation, Vector3* translation) const
  352. {
  353. if (translation)
  354. {
  355. // Extract the translation.
  356. translation->x = m[12];
  357. translation->y = m[13];
  358. translation->z = m[14];
  359. }
  360. // Nothing left to do.
  361. if (scale == NULL && rotation == NULL)
  362. return true;
  363. // Extract the scale.
  364. // This is simply the length of each axis (row/column) in the matrix.
  365. Vector3 xaxis(m[0], m[1], m[2]);
  366. float scaleX = xaxis.length();
  367. Vector3 yaxis(m[4], m[5], m[6]);
  368. float scaleY = yaxis.length();
  369. Vector3 zaxis(m[8], m[9], m[10]);
  370. float scaleZ = zaxis.length();
  371. // Determine if we have a negative scale (true if determinant is less than zero).
  372. // In this case, we simply negate a single axis of the scale.
  373. float det = determinant();
  374. if (det < 0)
  375. scaleZ = -scaleZ;
  376. if (scale)
  377. {
  378. scale->x = scaleX;
  379. scale->y = scaleY;
  380. scale->z = scaleZ;
  381. }
  382. // Nothing left to do.
  383. if (rotation == NULL)
  384. return true;
  385. // Scale too close to zero, can't decompose rotation.
  386. if (scaleX < MATH_TOLERANCE || scaleY < MATH_TOLERANCE || fabs(scaleZ) < MATH_TOLERANCE)
  387. return false;
  388. float rn;
  389. // Factor the scale out of the matrix axes.
  390. rn = 1.0f / scaleX;
  391. xaxis.x *= rn;
  392. xaxis.y *= rn;
  393. xaxis.z *= rn;
  394. rn = 1.0f / scaleY;
  395. yaxis.x *= rn;
  396. yaxis.y *= rn;
  397. yaxis.z *= rn;
  398. rn = 1.0f / scaleZ;
  399. zaxis.x *= rn;
  400. zaxis.y *= rn;
  401. zaxis.z *= rn;
  402. // Now calculate the rotation from the resulting matrix (axes).
  403. float trace = xaxis.x + yaxis.y + zaxis.z + 1.0f;
  404. if (trace > MATH_EPSILON)
  405. {
  406. float s = 0.5f / sqrt(trace);
  407. rotation->w = 0.25f / s;
  408. rotation->x = (yaxis.z - zaxis.y) * s;
  409. rotation->y = (zaxis.x - xaxis.z) * s;
  410. rotation->z = (xaxis.y - yaxis.x) * s;
  411. }
  412. else
  413. {
  414. // Note: since xaxis, yaxis, and zaxis are normalized,
  415. // we will never divide by zero in the code below.
  416. if (xaxis.x > yaxis.y && xaxis.x > zaxis.z)
  417. {
  418. float s = 0.5f / sqrt(1.0f + xaxis.x - yaxis.y - zaxis.z);
  419. rotation->w = (yaxis.z - zaxis.y) * s;
  420. rotation->x = 0.25f / s;
  421. rotation->y = (yaxis.x + xaxis.y) * s;
  422. rotation->z = (zaxis.x + xaxis.z) * s;
  423. }
  424. else if (yaxis.y > zaxis.z)
  425. {
  426. float s = 0.5f / sqrt(1.0f + yaxis.y - xaxis.x - zaxis.z);
  427. rotation->w = (zaxis.x - xaxis.z) * s;
  428. rotation->x = (yaxis.x + xaxis.y) * s;
  429. rotation->y = 0.25f / s;
  430. rotation->z = (zaxis.y + yaxis.z) * s;
  431. }
  432. else
  433. {
  434. float s = 0.5f / sqrt(1.0f + zaxis.z - xaxis.x - yaxis.y );
  435. rotation->w = (xaxis.y - yaxis.x ) * s;
  436. rotation->x = (zaxis.x + xaxis.z ) * s;
  437. rotation->y = (zaxis.y + yaxis.z ) * s;
  438. rotation->z = 0.25f / s;
  439. }
  440. }
  441. return true;
  442. }
  443. float Matrix::determinant() const
  444. {
  445. float a0 = m[0] * m[5] - m[1] * m[4];
  446. float a1 = m[0] * m[6] - m[2] * m[4];
  447. float a2 = m[0] * m[7] - m[3] * m[4];
  448. float a3 = m[1] * m[6] - m[2] * m[5];
  449. float a4 = m[1] * m[7] - m[3] * m[5];
  450. float a5 = m[2] * m[7] - m[3] * m[6];
  451. float b0 = m[8] * m[13] - m[9] * m[12];
  452. float b1 = m[8] * m[14] - m[10] * m[12];
  453. float b2 = m[8] * m[15] - m[11] * m[12];
  454. float b3 = m[9] * m[14] - m[10] * m[13];
  455. float b4 = m[9] * m[15] - m[11] * m[13];
  456. float b5 = m[10] * m[15] - m[11] * m[14];
  457. // Calculate the determinant.
  458. return (a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0);
  459. }
  460. void Matrix::getScale(Vector3* scale) const
  461. {
  462. decompose(scale, NULL, NULL);
  463. }
  464. bool Matrix::getRotation(Quaternion* rotation) const
  465. {
  466. return decompose(NULL, rotation, NULL);
  467. }
  468. void Matrix::getTranslation(Vector3* translation) const
  469. {
  470. decompose(NULL, NULL, translation);
  471. }
  472. void Matrix::getUpVector(Vector3* dst) const
  473. {
  474. GP_ASSERT(dst);
  475. dst->x = m[4];
  476. dst->y = m[5];
  477. dst->z = m[6];
  478. }
  479. void Matrix::getDownVector(Vector3* dst) const
  480. {
  481. GP_ASSERT(dst);
  482. dst->x = -m[4];
  483. dst->y = -m[5];
  484. dst->z = -m[6];
  485. }
  486. void Matrix::getLeftVector(Vector3* dst) const
  487. {
  488. GP_ASSERT(dst);
  489. dst->x = -m[0];
  490. dst->y = -m[1];
  491. dst->z = -m[2];
  492. }
  493. void Matrix::getRightVector(Vector3* dst) const
  494. {
  495. GP_ASSERT(dst);
  496. dst->x = m[0];
  497. dst->y = m[1];
  498. dst->z = m[2];
  499. }
  500. void Matrix::getForwardVector(Vector3* dst) const
  501. {
  502. GP_ASSERT(dst);
  503. dst->x = -m[8];
  504. dst->y = -m[9];
  505. dst->z = -m[10];
  506. }
  507. void Matrix::getBackVector(Vector3* dst) const
  508. {
  509. GP_ASSERT(dst);
  510. dst->x = m[8];
  511. dst->y = m[9];
  512. dst->z = m[10];
  513. }
  514. bool Matrix::invert()
  515. {
  516. return invert(this);
  517. }
  518. bool Matrix::invert(Matrix* dst) const
  519. {
  520. float a0 = m[0] * m[5] - m[1] * m[4];
  521. float a1 = m[0] * m[6] - m[2] * m[4];
  522. float a2 = m[0] * m[7] - m[3] * m[4];
  523. float a3 = m[1] * m[6] - m[2] * m[5];
  524. float a4 = m[1] * m[7] - m[3] * m[5];
  525. float a5 = m[2] * m[7] - m[3] * m[6];
  526. float b0 = m[8] * m[13] - m[9] * m[12];
  527. float b1 = m[8] * m[14] - m[10] * m[12];
  528. float b2 = m[8] * m[15] - m[11] * m[12];
  529. float b3 = m[9] * m[14] - m[10] * m[13];
  530. float b4 = m[9] * m[15] - m[11] * m[13];
  531. float b5 = m[10] * m[15] - m[11] * m[14];
  532. // Calculate the determinant.
  533. float det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
  534. // Close to zero, can't invert.
  535. if (fabs(det) <= MATH_TOLERANCE)
  536. return false;
  537. // Support the case where m == dst.
  538. Matrix inverse;
  539. inverse.m[0] = m[5] * b5 - m[6] * b4 + m[7] * b3;
  540. inverse.m[1] = -m[1] * b5 + m[2] * b4 - m[3] * b3;
  541. inverse.m[2] = m[13] * a5 - m[14] * a4 + m[15] * a3;
  542. inverse.m[3] = -m[9] * a5 + m[10] * a4 - m[11] * a3;
  543. inverse.m[4] = -m[4] * b5 + m[6] * b2 - m[7] * b1;
  544. inverse.m[5] = m[0] * b5 - m[2] * b2 + m[3] * b1;
  545. inverse.m[6] = -m[12] * a5 + m[14] * a2 - m[15] * a1;
  546. inverse.m[7] = m[8] * a5 - m[10] * a2 + m[11] * a1;
  547. inverse.m[8] = m[4] * b4 - m[5] * b2 + m[7] * b0;
  548. inverse.m[9] = -m[0] * b4 + m[1] * b2 - m[3] * b0;
  549. inverse.m[10] = m[12] * a4 - m[13] * a2 + m[15] * a0;
  550. inverse.m[11] = -m[8] * a4 + m[9] * a2 - m[11] * a0;
  551. inverse.m[12] = -m[4] * b3 + m[5] * b1 - m[6] * b0;
  552. inverse.m[13] = m[0] * b3 - m[1] * b1 + m[2] * b0;
  553. inverse.m[14] = -m[12] * a3 + m[13] * a1 - m[14] * a0;
  554. inverse.m[15] = m[8] * a3 - m[9] * a1 + m[10] * a0;
  555. multiply(inverse, 1.0f / det, dst);
  556. return true;
  557. }
  558. bool Matrix::isIdentity() const
  559. {
  560. return (memcmp(m, MATRIX_IDENTITY, MATRIX_SIZE) == 0);
  561. }
  562. void Matrix::multiply(float scalar)
  563. {
  564. multiply(scalar, this);
  565. }
  566. void Matrix::multiply(float scalar, Matrix* dst) const
  567. {
  568. multiply(*this, scalar, dst);
  569. }
  570. void Matrix::multiply(const Matrix& m, float scalar, Matrix* dst)
  571. {
  572. GP_ASSERT(dst);
  573. #ifdef USE_NEON
  574. asm volatile(
  575. "vld1.32 {d0[0]}, [%0] \n\t"
  576. "vld1.32 {q4-q5}, [%1]! \n\t"
  577. "vld1.32 {q6-q7}, [%1]! \n\t"
  578. "vmul.f32 q8, q4, d0[0] \n\t"
  579. "vmul.f32 q9, q5, d0[0] \n\t"
  580. "vmul.f32 q10, q6, d0[0] \n\t"
  581. "vmul.f32 q11, q7, d0[0] \n\t"
  582. "vst1.32 {q8-q9}, [%2]! \n\t"
  583. "vst1.32 {q10-q11}, [%2]! \n\t"
  584. :
  585. : "r"(&scalar), "r"(m.m), "r"(dst->m)
  586. : "q0", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "memory"
  587. );
  588. #else
  589. dst->m[0] = m.m[0] * scalar;
  590. dst->m[1] = m.m[1] * scalar;
  591. dst->m[2] = m.m[2] * scalar;
  592. dst->m[3] = m.m[3] * scalar;
  593. dst->m[4] = m.m[4] * scalar;
  594. dst->m[5] = m.m[5] * scalar;
  595. dst->m[6] = m.m[6] * scalar;
  596. dst->m[7] = m.m[7] * scalar;
  597. dst->m[8] = m.m[8] * scalar;
  598. dst->m[9] = m.m[9] * scalar;
  599. dst->m[10] = m.m[10] * scalar;
  600. dst->m[11] = m.m[11] * scalar;
  601. dst->m[12] = m.m[12] * scalar;
  602. dst->m[13] = m.m[13] * scalar;
  603. dst->m[14] = m.m[14] * scalar;
  604. dst->m[15] = m.m[15] * scalar;
  605. #endif
  606. }
  607. void Matrix::multiply(const Matrix& m)
  608. {
  609. multiply(*this, m, this);
  610. }
  611. void Matrix::multiply(const Matrix& m1, const Matrix& m2, Matrix* dst)
  612. {
  613. GP_ASSERT(dst);
  614. #ifdef USE_NEON // if set, neon unit is present.
  615. asm volatile
  616. (
  617. "vld1.32 {d16 - d19}, [%1]! \n\t" // load first eight elements of matrix 0
  618. "vld1.32 {d20 - d23}, [%1]! \n\t" // load second eight elements of matrix 0
  619. "vld1.32 {d0 - d3}, [%2]! \n\t" // load first eight elements of matrix 1
  620. "vld1.32 {d4 - d7}, [%2]! \n\t" // load second eight elements of matrix 1
  621. "vmul.f32 q12, q8, d0[0] \n\t" // rslt col0 = (mat0 col0) * (mat1 col0 elt0)
  622. "vmul.f32 q13, q8, d2[0] \n\t" // rslt col1 = (mat0 col0) * (mat1 col1 elt0)
  623. "vmul.f32 q14, q8, d4[0] \n\t" // rslt col2 = (mat0 col0) * (mat1 col2 elt0)
  624. "vmul.f32 q15, q8, d6[0] \n\t" // rslt col3 = (mat0 col0) * (mat1 col3 elt0)
  625. "vmla.f32 q12, q9, d0[1] \n\t" // rslt col0 += (mat0 col1) * (mat1 col0 elt1)
  626. "vmla.f32 q13, q9, d2[1] \n\t" // rslt col1 += (mat0 col1) * (mat1 col1 elt1)
  627. "vmla.f32 q14, q9, d4[1] \n\t" // rslt col2 += (mat0 col1) * (mat1 col2 elt1)
  628. "vmla.f32 q15, q9, d6[1] \n\t" // rslt col3 += (mat0 col1) * (mat1 col3 elt1)
  629. "vmla.f32 q12, q10, d1[0] \n\t" // rslt col0 += (mat0 col2) * (mat1 col0 elt2)
  630. "vmla.f32 q13, q10, d3[0] \n\t" // rslt col1 += (mat0 col2) * (mat1 col1 elt2)
  631. "vmla.f32 q14, q10, d5[0] \n\t" // rslt col2 += (mat0 col2) * (mat1 col2 elt2)
  632. "vmla.f32 q15, q10, d7[0] \n\t" // rslt col3 += (mat0 col2) * (mat1 col2 elt2)
  633. "vmla.f32 q12, q11, d1[1] \n\t" // rslt col0 += (mat0 col3) * (mat1 col0 elt3)
  634. "vmla.f32 q13, q11, d3[1] \n\t" // rslt col1 += (mat0 col3) * (mat1 col1 elt3)
  635. "vmla.f32 q14, q11, d5[1] \n\t" // rslt col2 += (mat0 col3) * (mat1 col2 elt3)
  636. "vmla.f32 q15, q11, d7[1] \n\t" // rslt col3 += (mat0 col3) * (mat1 col3 elt3)
  637. "vst1.32 {d24 - d27}, [%0]! \n\t" // store first eight elements of result
  638. "vst1.32 {d28 - d31}, [%0]! \n\t" // store second eight elements of result
  639. : // output
  640. : "r"(dst->m), "r"(m1.m), "r"(m2.m) // input - note *value* of pointer doesn't change.
  641. : "memory", "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
  642. );
  643. #else
  644. // Support the case where m1 or m2 is the same array as dst.
  645. float product[16];
  646. product[0] = m1.m[0] * m2.m[0] + m1.m[4] * m2.m[1] + m1.m[8] * m2.m[2] + m1.m[12] * m2.m[3];
  647. product[1] = m1.m[1] * m2.m[0] + m1.m[5] * m2.m[1] + m1.m[9] * m2.m[2] + m1.m[13] * m2.m[3];
  648. product[2] = m1.m[2] * m2.m[0] + m1.m[6] * m2.m[1] + m1.m[10] * m2.m[2] + m1.m[14] * m2.m[3];
  649. product[3] = m1.m[3] * m2.m[0] + m1.m[7] * m2.m[1] + m1.m[11] * m2.m[2] + m1.m[15] * m2.m[3];
  650. product[4] = m1.m[0] * m2.m[4] + m1.m[4] * m2.m[5] + m1.m[8] * m2.m[6] + m1.m[12] * m2.m[7];
  651. product[5] = m1.m[1] * m2.m[4] + m1.m[5] * m2.m[5] + m1.m[9] * m2.m[6] + m1.m[13] * m2.m[7];
  652. product[6] = m1.m[2] * m2.m[4] + m1.m[6] * m2.m[5] + m1.m[10] * m2.m[6] + m1.m[14] * m2.m[7];
  653. product[7] = m1.m[3] * m2.m[4] + m1.m[7] * m2.m[5] + m1.m[11] * m2.m[6] + m1.m[15] * m2.m[7];
  654. product[8] = m1.m[0] * m2.m[8] + m1.m[4] * m2.m[9] + m1.m[8] * m2.m[10] + m1.m[12] * m2.m[11];
  655. product[9] = m1.m[1] * m2.m[8] + m1.m[5] * m2.m[9] + m1.m[9] * m2.m[10] + m1.m[13] * m2.m[11];
  656. product[10] = m1.m[2] * m2.m[8] + m1.m[6] * m2.m[9] + m1.m[10] * m2.m[10] + m1.m[14] * m2.m[11];
  657. product[11] = m1.m[3] * m2.m[8] + m1.m[7] * m2.m[9] + m1.m[11] * m2.m[10] + m1.m[15] * m2.m[11];
  658. product[12] = m1.m[0] * m2.m[12] + m1.m[4] * m2.m[13] + m1.m[8] * m2.m[14] + m1.m[12] * m2.m[15];
  659. product[13] = m1.m[1] * m2.m[12] + m1.m[5] * m2.m[13] + m1.m[9] * m2.m[14] + m1.m[13] * m2.m[15];
  660. product[14] = m1.m[2] * m2.m[12] + m1.m[6] * m2.m[13] + m1.m[10] * m2.m[14] + m1.m[14] * m2.m[15];
  661. product[15] = m1.m[3] * m2.m[12] + m1.m[7] * m2.m[13] + m1.m[11] * m2.m[14] + m1.m[15] * m2.m[15];
  662. memcpy(dst->m, product, MATRIX_SIZE);
  663. #endif
  664. }
  665. void Matrix::negate()
  666. {
  667. negate(this);
  668. }
  669. void Matrix::negate(Matrix* dst) const
  670. {
  671. GP_ASSERT(dst);
  672. #ifdef USE_NEON
  673. asm volatile(
  674. "vld1.32 {q0-q1}, [%1]! \n\t" // load m0-m7
  675. "vld1.32 {q2-q3}, [%1]! \n\t" // load m8-m15
  676. "vneg.f32 q4, q0 \n\t" // negate m0-m3
  677. "vneg.f32 q5, q1 \n\t" // negate m4-m7
  678. "vneg.f32 q6, q2 \n\t" // negate m8-m15
  679. "vneg.f32 q7, q3 \n\t" // negate m8-m15
  680. "vst1.32 {q4-q5}, [%0]! \n\t" // store m0-m7
  681. "vst1.32 {q6-q7}, [%0]! \n\t" // store m8-m15
  682. :
  683. : "r"(dst->m), "r"(m)
  684. : "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "memory"
  685. );
  686. #else
  687. dst->m[0] = -m[0];
  688. dst->m[1] = -m[1];
  689. dst->m[2] = -m[2];
  690. dst->m[3] = -m[3];
  691. dst->m[4] = -m[4];
  692. dst->m[5] = -m[5];
  693. dst->m[6] = -m[6];
  694. dst->m[7] = -m[7];
  695. dst->m[8] = -m[8];
  696. dst->m[9] = -m[9];
  697. dst->m[10] = -m[10];
  698. dst->m[11] = -m[11];
  699. dst->m[12] = -m[12];
  700. dst->m[13] = -m[13];
  701. dst->m[14] = -m[14];
  702. dst->m[15] = -m[15];
  703. #endif
  704. }
  705. void Matrix::rotate(const Quaternion& q)
  706. {
  707. rotate(q, this);
  708. }
  709. void Matrix::rotate(const Quaternion& q, Matrix* dst) const
  710. {
  711. Matrix r;
  712. createRotation(q, &r);
  713. multiply(*this, r, dst);
  714. }
  715. void Matrix::rotate(const Vector3& axis, float angle)
  716. {
  717. rotate(axis, angle, this);
  718. }
  719. void Matrix::rotate(const Vector3& axis, float angle, Matrix* dst) const
  720. {
  721. Matrix r;
  722. createRotation(axis, angle, &r);
  723. multiply(*this, r, dst);
  724. }
  725. void Matrix::rotateX(float angle)
  726. {
  727. rotateX(angle, this);
  728. }
  729. void Matrix::rotateX(float angle, Matrix* dst) const
  730. {
  731. Matrix r;
  732. createRotationX(angle, &r);
  733. multiply(*this, r, dst);
  734. }
  735. void Matrix::rotateY(float angle)
  736. {
  737. rotateY(angle, this);
  738. }
  739. void Matrix::rotateY(float angle, Matrix* dst) const
  740. {
  741. Matrix r;
  742. createRotationY(angle, &r);
  743. multiply(*this, r, dst);
  744. }
  745. void Matrix::rotateZ(float angle)
  746. {
  747. rotateZ(angle, this);
  748. }
  749. void Matrix::rotateZ(float angle, Matrix* dst) const
  750. {
  751. Matrix r;
  752. createRotationZ(angle, &r);
  753. multiply(*this, r, dst);
  754. }
  755. void Matrix::scale(float value)
  756. {
  757. scale(value, this);
  758. }
  759. void Matrix::scale(float value, Matrix* dst) const
  760. {
  761. scale(value, value, value, dst);
  762. }
  763. void Matrix::scale(float xScale, float yScale, float zScale)
  764. {
  765. scale(xScale, yScale, zScale, this);
  766. }
  767. void Matrix::scale(float xScale, float yScale, float zScale, Matrix* dst) const
  768. {
  769. Matrix s;
  770. createScale(xScale, yScale, zScale, &s);
  771. multiply(*this, s, dst);
  772. }
  773. void Matrix::scale(const Vector3& s)
  774. {
  775. scale(s.x, s.y, s.z, this);
  776. }
  777. void Matrix::scale(const Vector3& s, Matrix* dst) const
  778. {
  779. scale(s.x, s.y, s.z, dst);
  780. }
  781. void Matrix::set(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44)
  782. {
  783. m[0] = m11;
  784. m[1] = m21;
  785. m[2] = m31;
  786. m[3] = m41;
  787. m[4] = m12;
  788. m[5] = m22;
  789. m[6] = m32;
  790. m[7] = m42;
  791. m[8] = m13;
  792. m[9] = m23;
  793. m[10] = m33;
  794. m[11] = m43;
  795. m[12] = m14;
  796. m[13] = m24;
  797. m[14] = m34;
  798. m[15] = m44;
  799. }
  800. void Matrix::set(const float* m)
  801. {
  802. GP_ASSERT(m);
  803. memcpy(this->m, m, MATRIX_SIZE);
  804. }
  805. void Matrix::set(const Matrix& m)
  806. {
  807. memcpy(this->m, m.m, MATRIX_SIZE);
  808. }
  809. void Matrix::setIdentity()
  810. {
  811. memcpy(m, MATRIX_IDENTITY, MATRIX_SIZE);
  812. }
  813. void Matrix::setZero()
  814. {
  815. memset(m, 0, MATRIX_SIZE);
  816. }
  817. void Matrix::subtract(const Matrix& m)
  818. {
  819. subtract(*this, m, this);
  820. }
  821. void Matrix::subtract(const Matrix& m1, const Matrix& m2, Matrix* dst)
  822. {
  823. GP_ASSERT(dst);
  824. #ifdef USE_NEON
  825. asm volatile(
  826. "vld1.32 {q0, q1}, [%1]! \n\t"
  827. "vld1.32 {q2, q3}, [%1]! \n\t"
  828. "vld1.32 {q8, q9}, [%2]! \n\t"
  829. "vld1.32 {q10, q11}, [%2]! \n\t"
  830. "vsub.f32 q12, q0, q8 \n\t"
  831. "vsub.f32 q13, q1, q9 \n\t"
  832. "vsub.f32 q14, q2, q10 \n\t"
  833. "vsub.f32 q15, q3, q11 \n\t"
  834. "vst1.32 {q12, q13}, [%0]! \n\t"
  835. "vst1.32 {q14, q15}, [%0]! \n\t"
  836. :
  837. : "r"(dst->m), "r"(m1.m), "r"(m2.m)
  838. : "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory"
  839. );
  840. #else
  841. dst->m[0] = m1.m[0] - m2.m[0];
  842. dst->m[1] = m1.m[1] - m2.m[1];
  843. dst->m[2] = m1.m[2] - m2.m[2];
  844. dst->m[3] = m1.m[3] - m2.m[3];
  845. dst->m[4] = m1.m[4] - m2.m[4];
  846. dst->m[5] = m1.m[5] - m2.m[5];
  847. dst->m[6] = m1.m[6] - m2.m[6];
  848. dst->m[7] = m1.m[7] - m2.m[7];
  849. dst->m[8] = m1.m[8] - m2.m[8];
  850. dst->m[9] = m1.m[9] - m2.m[9];
  851. dst->m[10] = m1.m[10] - m2.m[10];
  852. dst->m[11] = m1.m[11] - m2.m[11];
  853. dst->m[12] = m1.m[12] - m2.m[12];
  854. dst->m[13] = m1.m[13] - m2.m[13];
  855. dst->m[14] = m1.m[14] - m2.m[14];
  856. dst->m[15] = m1.m[15] - m2.m[15];
  857. #endif
  858. }
  859. void Matrix::transformPoint(Vector3* point) const
  860. {
  861. GP_ASSERT(point);
  862. transformVector(point->x, point->y, point->z, 1.0f, point);
  863. }
  864. void Matrix::transformPoint(const Vector3& point, Vector3* dst) const
  865. {
  866. transformVector(point.x, point.y, point.z, 1.0f, dst);
  867. }
  868. void Matrix::transformVector(Vector3* vector) const
  869. {
  870. GP_ASSERT(vector);
  871. transformVector(vector->x, vector->y, vector->z, 0.0f, vector);
  872. }
  873. void Matrix::transformVector(const Vector3& vector, Vector3* dst) const
  874. {
  875. transformVector(vector.x, vector.y, vector.z, 0.0f, dst);
  876. }
  877. void Matrix::transformVector(float x, float y, float z, float w, Vector3* dst) const
  878. {
  879. GP_ASSERT(dst);
  880. #ifdef USE_NEON
  881. asm volatile(
  882. "vld1.32 {d0[0]}, [%0] \n\t" // load x
  883. "vld1.32 {d0[1]}, [%1] \n\t" // load y
  884. "vld1.32 {d1[0]}, [%2] \n\t" // load z
  885. "vld1.32 {d1[1]}, [%3] \n\t" // load w
  886. "vld1.32 {d18 - d21}, [%4]! \n\t" // load first 8 elements of matrix m0-m7
  887. "vld1.32 {d22 - d25}, [%4]! \n\t" // load second 8 elements of matrix m8-m15
  888. "vmul.f32 q13, q9, d0[0] \n\t" // Q5 = (m0-m3)*x
  889. "vmla.f32 q13, q10, d0[1] \n\t" // Q5 += (m4-m7)*y
  890. "vmla.f32 q13, q11, d1[0] \n\t" // Q5 += (m8-m11)*z
  891. "vmla.f32 q13, q12, d1[1] \n\t" // Q5 += (m12-m15)*w
  892. "vst1.32 {d26[0]}, [%5]! \n\t" // store dst->x
  893. "vst1.32 {d26[1]}, [%5]! \n\t" // store dst->y
  894. "vst1.32 {d27[0]}, [%5]! \n\t" // store dst->z
  895. :
  896. : "r"(&x), "r"(&y), "r"(&z), "r"(&w), "r"(m), "r"(dst)
  897. : "q0", "q9", "q10","q11", "q12", "q13", "memory"
  898. );
  899. #else
  900. dst->set(
  901. x * m[0] + y * m[4] + z * m[8] + w * m[12],
  902. x * m[1] + y * m[5] + z * m[9] + w * m[13],
  903. x * m[2] + y * m[6] + z * m[10] + w * m[14]);
  904. #endif
  905. }
  906. void Matrix::transformVector(Vector4* vector) const
  907. {
  908. GP_ASSERT(vector);
  909. transformVector(*vector, vector);
  910. }
  911. void Matrix::transformVector(const Vector4& vector, Vector4* dst) const
  912. {
  913. GP_ASSERT(dst);
  914. #ifdef USE_NEON
  915. asm volatile
  916. (
  917. "vld1.32 {d0, d1}, [%1] \n\t" //Q0 = v (x, y, z, w)
  918. "vld1.32 {d18 - d21}, [%0]! \n\t" //Q1 = M (m0-m7)
  919. "vld1.32 {d22 - d25}, [%0]! \n\t" //Q2 = M (m8-m15)
  920. "vmul.f32 q13, q9, d0[0] \n\t" //Q5 = Q0*Q0[0]
  921. "vmla.f32 q13, q10, d0[1] \n\t" //Q5 += Q1*Q0[1]
  922. "vmla.f32 q13, q11, d1[0] \n\t" //Q5 += Q2*Q0[2]
  923. "vmla.f32 q13, q12, d1[1] \n\t" //Q5 += Q3*Q0[3]
  924. "vst1.32 {d26, d27}, [%2] \n\t" //Q4 = m+12
  925. :
  926. : "r"(m), "r"(&vector), "r"(dst)
  927. : "q0", "q9", "q10","q11", "q12", "q13", "memory"
  928. );
  929. #else
  930. dst->set(
  931. vector.x * m[0] + vector.y * m[4] + vector.z * m[8] + vector.w * m[12],
  932. vector.x * m[1] + vector.y * m[5] + vector.z * m[9] + vector.w * m[13],
  933. vector.x * m[2] + vector.y * m[6] + vector.z * m[10] + vector.w * m[14],
  934. vector.x * m[3] + vector.y * m[7] + vector.z * m[11] + vector.w * m[15]);
  935. #endif
  936. }
  937. void Matrix::translate(float x, float y, float z)
  938. {
  939. translate(x, y, z, this);
  940. }
  941. void Matrix::translate(float x, float y, float z, Matrix* dst) const
  942. {
  943. Matrix t;
  944. createTranslation(x, y, z, &t);
  945. multiply(*this, t, dst);
  946. }
  947. void Matrix::translate(const Vector3& t)
  948. {
  949. translate(t.x, t.y, t.z, this);
  950. }
  951. void Matrix::translate(const Vector3& t, Matrix* dst) const
  952. {
  953. translate(t.x, t.y, t.z, dst);
  954. }
  955. void Matrix::transpose()
  956. {
  957. transpose(this);
  958. }
  959. void Matrix::transpose(Matrix* dst) const
  960. {
  961. GP_ASSERT(dst);
  962. #ifdef USE_NEON
  963. asm volatile(
  964. "vld4.32 {d0[0], d2[0], d4[0], d6[0]}, [%0]! \n\t"
  965. "vld4.32 {d0[1], d2[1], d4[1], d6[1]}, [%0]! \n\t"
  966. "vld4.32 {d1[0], d3[0], d5[0], d7[0]}, [%0]! \n\t"
  967. "vld4.32 {d1[1], d3[1], d5[1], d7[1]}, [%0]! \n\t"
  968. "vst1.32 {q0-q1}, [%1]! \n\t"
  969. "vst1.32 {q2-q3}, [%1]! \n\t"
  970. :
  971. : "r"(this->m), "r"(dst->m)
  972. : "q0", "q1", "q2", "q3", "memory"
  973. );
  974. #else
  975. float t[16] = {
  976. m[0], m[4], m[8], m[12],
  977. m[1], m[5], m[9], m[13],
  978. m[2], m[6], m[10], m[14],
  979. m[3], m[7], m[11], m[15]
  980. };
  981. memcpy(dst->m, t, MATRIX_SIZE);
  982. #endif
  983. }
  984. }