PVRTVector.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /******************************************************************************
  2. @File PVRTVector.cpp
  3. @Title PVRTVector
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform ANSI compatible
  7. @Description Vector and matrix mathematics library
  8. ******************************************************************************/
  9. #include "PVRTVector.h"
  10. #include <math.h>
  11. /*!***************************************************************************
  12. ** PVRTVec2 2 component vector
  13. ****************************************************************************/
  14. /*!***************************************************************************
  15. @Function PVRTVec2
  16. @Input v3Vec a Vec3
  17. @Description Constructor from a Vec3
  18. *****************************************************************************/
  19. PVRTVec2::PVRTVec2(const PVRTVec3& vec3)
  20. {
  21. x = vec3.x; y = vec3.y;
  22. }
  23. /*!***************************************************************************
  24. ** PVRTVec3 3 component vector
  25. ****************************************************************************/
  26. /*!***************************************************************************
  27. @Function PVRTVec3
  28. @Input v4Vec a PVRTVec4
  29. @Description Constructor from a PVRTVec4
  30. *****************************************************************************/
  31. PVRTVec3::PVRTVec3(const PVRTVec4& vec4)
  32. {
  33. x = vec4.x; y = vec4.y; z = vec4.z;
  34. }
  35. /*!***************************************************************************
  36. @Function *
  37. @Input rhs a PVRTMat3
  38. @Returns result of multiplication
  39. @Description matrix multiplication operator PVRTVec3 and PVRTMat3
  40. ****************************************************************************/
  41. PVRTVec3 PVRTVec3::operator*(const PVRTMat3& rhs) const
  42. {
  43. PVRTVec3 out;
  44. out.x = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2]);
  45. out.y = VERTTYPEMUL(x,rhs.f[3])+VERTTYPEMUL(y,rhs.f[4])+VERTTYPEMUL(z,rhs.f[5]);
  46. out.z = VERTTYPEMUL(x,rhs.f[6])+VERTTYPEMUL(y,rhs.f[7])+VERTTYPEMUL(z,rhs.f[8]);
  47. return out;
  48. }
  49. /*!***************************************************************************
  50. @Function *=
  51. @Input rhs a PVRTMat3
  52. @Returns result of multiplication and assignment
  53. @Description matrix multiplication and assignment operator for PVRTVec3 and PVRTMat3
  54. ****************************************************************************/
  55. PVRTVec3& PVRTVec3::operator*=(const PVRTMat3& rhs)
  56. {
  57. VERTTYPE tx = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2]);
  58. VERTTYPE ty = VERTTYPEMUL(x,rhs.f[3])+VERTTYPEMUL(y,rhs.f[4])+VERTTYPEMUL(z,rhs.f[5]);
  59. z = VERTTYPEMUL(x,rhs.f[6])+VERTTYPEMUL(y,rhs.f[7])+VERTTYPEMUL(z,rhs.f[8]);
  60. x = tx;
  61. y = ty;
  62. return *this;
  63. }
  64. /*!***************************************************************************
  65. ** PVRTVec4 4 component vector
  66. ****************************************************************************/
  67. /*!***************************************************************************
  68. @Function *
  69. @Input rhs a PVRTMat4
  70. @Returns result of multiplication
  71. @Description matrix multiplication operator PVRTVec4 and PVRTMat4
  72. ****************************************************************************/
  73. PVRTVec4 PVRTVec4::operator*(const PVRTMat4& rhs) const
  74. {
  75. PVRTVec4 out;
  76. out.x = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2])+VERTTYPEMUL(w,rhs.f[3]);
  77. out.y = VERTTYPEMUL(x,rhs.f[4])+VERTTYPEMUL(y,rhs.f[5])+VERTTYPEMUL(z,rhs.f[6])+VERTTYPEMUL(w,rhs.f[7]);
  78. out.z = VERTTYPEMUL(x,rhs.f[8])+VERTTYPEMUL(y,rhs.f[9])+VERTTYPEMUL(z,rhs.f[10])+VERTTYPEMUL(w,rhs.f[11]);
  79. out.w = VERTTYPEMUL(x,rhs.f[12])+VERTTYPEMUL(y,rhs.f[13])+VERTTYPEMUL(z,rhs.f[14])+VERTTYPEMUL(w,rhs.f[15]);
  80. return out;
  81. }
  82. /*!***************************************************************************
  83. @Function *=
  84. @Input rhs a PVRTMat4
  85. @Returns result of multiplication and assignment
  86. @Description matrix multiplication and assignment operator for PVRTVec4 and PVRTMat4
  87. ****************************************************************************/
  88. PVRTVec4& PVRTVec4::operator*=(const PVRTMat4& rhs)
  89. {
  90. VERTTYPE tx = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2])+VERTTYPEMUL(w,rhs.f[3]);
  91. VERTTYPE ty = VERTTYPEMUL(x,rhs.f[4])+VERTTYPEMUL(y,rhs.f[5])+VERTTYPEMUL(z,rhs.f[6])+VERTTYPEMUL(w,rhs.f[7]);
  92. VERTTYPE tz = VERTTYPEMUL(x,rhs.f[8])+VERTTYPEMUL(y,rhs.f[9])+VERTTYPEMUL(z,rhs.f[10])+VERTTYPEMUL(w,rhs.f[11]);
  93. w = VERTTYPEMUL(x,rhs.f[12])+VERTTYPEMUL(y,rhs.f[13])+VERTTYPEMUL(z,rhs.f[14])+VERTTYPEMUL(w,rhs.f[15]);
  94. x = tx;
  95. y = ty;
  96. z = tz;
  97. return *this;
  98. }
  99. /*!***************************************************************************
  100. ** PVRTMat3 3x3 matrix
  101. ****************************************************************************/
  102. /*!***************************************************************************
  103. @Function PVRTMat3
  104. @Input mat a PVRTMat4
  105. @Description constructor to form a PVRTMat3 from a PVRTMat4
  106. ****************************************************************************/
  107. PVRTMat3::PVRTMat3(const PVRTMat4& mat)
  108. {
  109. VERTTYPE *dest = (VERTTYPE*)f, *src = (VERTTYPE*)mat.f;
  110. for(int i=0;i<3;i++)
  111. {
  112. for(int j=0;j<3;j++)
  113. {
  114. (*dest++) = (*src++);
  115. }
  116. src++;
  117. }
  118. }
  119. /*!***************************************************************************
  120. @Function RotationX
  121. @Input angle the angle of rotation
  122. @Returns rotation matrix
  123. @Description generates a 3x3 rotation matrix about the X axis
  124. ****************************************************************************/
  125. PVRTMat3 PVRTMat3::RotationX(VERTTYPE angle)
  126. {
  127. PVRTMat4 out;
  128. PVRTMatrixRotationX(out,angle);
  129. return PVRTMat3(out);
  130. }
  131. /*!***************************************************************************
  132. @Function RotationY
  133. @Input angle the angle of rotation
  134. @Returns rotation matrix
  135. @Description generates a 3x3 rotation matrix about the Y axis
  136. ****************************************************************************/
  137. PVRTMat3 PVRTMat3::RotationY(VERTTYPE angle)
  138. {
  139. PVRTMat4 out;
  140. PVRTMatrixRotationY(out,angle);
  141. return PVRTMat3(out);
  142. }
  143. /*!***************************************************************************
  144. @Function RotationZ
  145. @Input angle the angle of rotation
  146. @Returns rotation matrix
  147. @Description generates a 3x3 rotation matrix about the Z axis
  148. ****************************************************************************/
  149. PVRTMat3 PVRTMat3::RotationZ(VERTTYPE angle)
  150. {
  151. PVRTMat4 out;
  152. PVRTMatrixRotationZ(out,angle);
  153. return PVRTMat3(out);
  154. }
  155. /*!***************************************************************************
  156. ** PVRTMat4 4x4 matrix
  157. ****************************************************************************/
  158. /*!***************************************************************************
  159. @Function RotationX
  160. @Input angle the angle of rotation
  161. @Returns rotation matrix
  162. @Description generates a 4x4 rotation matrix about the X axis
  163. ****************************************************************************/
  164. PVRTMat4 PVRTMat4::RotationX(VERTTYPE angle)
  165. {
  166. PVRTMat4 out;
  167. PVRTMatrixRotationX(out,angle);
  168. return out;
  169. }
  170. /*!***************************************************************************
  171. @Function RotationY
  172. @Input angle the angle of rotation
  173. @Returns rotation matrix
  174. @Description generates a 4x4 rotation matrix about the Y axis
  175. ****************************************************************************/
  176. PVRTMat4 PVRTMat4::RotationY(VERTTYPE angle)
  177. {
  178. PVRTMat4 out;
  179. PVRTMatrixRotationY(out,angle);
  180. return out;
  181. }
  182. /*!***************************************************************************
  183. @Function RotationZ
  184. @Input angle the angle of rotation
  185. @Returns rotation matrix
  186. @Description generates a 4x4 rotation matrix about the Z axis
  187. ****************************************************************************/
  188. PVRTMat4 PVRTMat4::RotationZ(VERTTYPE angle)
  189. {
  190. PVRTMat4 out;
  191. PVRTMatrixRotationZ(out,angle);
  192. return out;
  193. }
  194. /*!***************************************************************************
  195. @Function *
  196. @Input rhs another PVRTMat4
  197. @Returns result of multiplication
  198. @Description Matrix multiplication of two 4x4 matrices.
  199. *****************************************************************************/
  200. PVRTMat4 PVRTMat4::operator*(const PVRTMat4& rhs) const
  201. {
  202. PVRTMat4 out;
  203. // col 1
  204. out.f[0] = VERTTYPEMUL(f[0],rhs.f[0])+VERTTYPEMUL(f[4],rhs.f[1])+VERTTYPEMUL(f[8],rhs.f[2])+VERTTYPEMUL(f[12],rhs.f[3]);
  205. out.f[1] = VERTTYPEMUL(f[1],rhs.f[0])+VERTTYPEMUL(f[5],rhs.f[1])+VERTTYPEMUL(f[9],rhs.f[2])+VERTTYPEMUL(f[13],rhs.f[3]);
  206. out.f[2] = VERTTYPEMUL(f[2],rhs.f[0])+VERTTYPEMUL(f[6],rhs.f[1])+VERTTYPEMUL(f[10],rhs.f[2])+VERTTYPEMUL(f[14],rhs.f[3]);
  207. out.f[3] = VERTTYPEMUL(f[3],rhs.f[0])+VERTTYPEMUL(f[7],rhs.f[1])+VERTTYPEMUL(f[11],rhs.f[2])+VERTTYPEMUL(f[15],rhs.f[3]);
  208. // col 2
  209. out.f[4] = VERTTYPEMUL(f[0],rhs.f[4])+VERTTYPEMUL(f[4],rhs.f[5])+VERTTYPEMUL(f[8],rhs.f[6])+VERTTYPEMUL(f[12],rhs.f[7]);
  210. out.f[5] = VERTTYPEMUL(f[1],rhs.f[4])+VERTTYPEMUL(f[5],rhs.f[5])+VERTTYPEMUL(f[9],rhs.f[6])+VERTTYPEMUL(f[13],rhs.f[7]);
  211. out.f[6] = VERTTYPEMUL(f[2],rhs.f[4])+VERTTYPEMUL(f[6],rhs.f[5])+VERTTYPEMUL(f[10],rhs.f[6])+VERTTYPEMUL(f[14],rhs.f[7]);
  212. out.f[7] = VERTTYPEMUL(f[3],rhs.f[4])+VERTTYPEMUL(f[7],rhs.f[5])+VERTTYPEMUL(f[11],rhs.f[6])+VERTTYPEMUL(f[15],rhs.f[7]);
  213. // col3
  214. out.f[8] = VERTTYPEMUL(f[0],rhs.f[8])+VERTTYPEMUL(f[4],rhs.f[9])+VERTTYPEMUL(f[8],rhs.f[10])+VERTTYPEMUL(f[12],rhs.f[11]);
  215. out.f[9] = VERTTYPEMUL(f[1],rhs.f[8])+VERTTYPEMUL(f[5],rhs.f[9])+VERTTYPEMUL(f[9],rhs.f[10])+VERTTYPEMUL(f[13],rhs.f[11]);
  216. out.f[10] = VERTTYPEMUL(f[2],rhs.f[8])+VERTTYPEMUL(f[6],rhs.f[9])+VERTTYPEMUL(f[10],rhs.f[10])+VERTTYPEMUL(f[14],rhs.f[11]);
  217. out.f[11] = VERTTYPEMUL(f[3],rhs.f[8])+VERTTYPEMUL(f[7],rhs.f[9])+VERTTYPEMUL(f[11],rhs.f[10])+VERTTYPEMUL(f[15],rhs.f[11]);
  218. // col3
  219. out.f[12] = VERTTYPEMUL(f[0],rhs.f[12])+VERTTYPEMUL(f[4],rhs.f[13])+VERTTYPEMUL(f[8],rhs.f[14])+VERTTYPEMUL(f[12],rhs.f[15]);
  220. out.f[13] = VERTTYPEMUL(f[1],rhs.f[12])+VERTTYPEMUL(f[5],rhs.f[13])+VERTTYPEMUL(f[9],rhs.f[14])+VERTTYPEMUL(f[13],rhs.f[15]);
  221. out.f[14] = VERTTYPEMUL(f[2],rhs.f[12])+VERTTYPEMUL(f[6],rhs.f[13])+VERTTYPEMUL(f[10],rhs.f[14])+VERTTYPEMUL(f[14],rhs.f[15]);
  222. out.f[15] = VERTTYPEMUL(f[3],rhs.f[12])+VERTTYPEMUL(f[7],rhs.f[13])+VERTTYPEMUL(f[11],rhs.f[14])+VERTTYPEMUL(f[15],rhs.f[15]);
  223. return out;
  224. }
  225. /*!***************************************************************************
  226. @Function inverse
  227. @Returns inverse mat4
  228. @Description Calculates multiplicative inverse of this matrix
  229. The matrix must be of the form :
  230. A 0
  231. C 1
  232. Where A is a 3x3 matrix and C is a 1x3 matrix.
  233. *****************************************************************************/
  234. PVRTMat4 PVRTMat4::inverse() const
  235. {
  236. PVRTMat4 out;
  237. VERTTYPE det_1;
  238. VERTTYPE pos, neg, temp;
  239. /* Calculate the determinant of submatrix A and determine if the
  240. the matrix is singular as limited by the double precision
  241. floating-point data representation. */
  242. pos = neg = f2vt(0.0);
  243. temp = VERTTYPEMUL(VERTTYPEMUL(f[ 0], f[ 5]), f[10]);
  244. if (temp >= 0) pos += temp; else neg += temp;
  245. temp = VERTTYPEMUL(VERTTYPEMUL(f[ 4], f[ 9]), f[ 2]);
  246. if (temp >= 0) pos += temp; else neg += temp;
  247. temp = VERTTYPEMUL(VERTTYPEMUL(f[ 8], f[ 1]), f[ 6]);
  248. if (temp >= 0) pos += temp; else neg += temp;
  249. temp = VERTTYPEMUL(VERTTYPEMUL(-f[ 8], f[ 5]), f[ 2]);
  250. if (temp >= 0) pos += temp; else neg += temp;
  251. temp = VERTTYPEMUL(VERTTYPEMUL(-f[ 4], f[ 1]), f[10]);
  252. if (temp >= 0) pos += temp; else neg += temp;
  253. temp = VERTTYPEMUL(VERTTYPEMUL(-f[ 0], f[ 9]), f[ 6]);
  254. if (temp >= 0) pos += temp; else neg += temp;
  255. det_1 = pos + neg;
  256. /* Is the submatrix A singular? */
  257. if (det_1 == f2vt(0.0)) //|| (VERTTYPEABS(det_1 / (pos - neg)) < 1.0e-15)
  258. {
  259. /* Matrix M has no inverse */
  260. _RPT0(_CRT_WARN, "Matrix has no inverse : singular matrix\n");
  261. }
  262. else
  263. {
  264. /* Calculate inverse(A) = adj(A) / det(A) */
  265. //det_1 = 1.0 / det_1;
  266. det_1 = VERTTYPEDIV(f2vt(1.0f), det_1);
  267. out.f[ 0] = VERTTYPEMUL(( VERTTYPEMUL(f[ 5], f[10]) - VERTTYPEMUL(f[ 9], f[ 6]) ), det_1);
  268. out.f[ 1] = - VERTTYPEMUL(( VERTTYPEMUL(f[ 1], f[10]) - VERTTYPEMUL(f[ 9], f[ 2]) ), det_1);
  269. out.f[ 2] = VERTTYPEMUL(( VERTTYPEMUL(f[ 1], f[ 6]) - VERTTYPEMUL(f[ 5], f[ 2]) ), det_1);
  270. out.f[ 4] = - VERTTYPEMUL(( VERTTYPEMUL(f[ 4], f[10]) - VERTTYPEMUL(f[ 8], f[ 6]) ), det_1);
  271. out.f[ 5] = VERTTYPEMUL(( VERTTYPEMUL(f[ 0], f[10]) - VERTTYPEMUL(f[ 8], f[ 2]) ), det_1);
  272. out.f[ 6] = - VERTTYPEMUL(( VERTTYPEMUL(f[ 0], f[ 6]) - VERTTYPEMUL(f[ 4], f[ 2]) ), det_1);
  273. out.f[ 8] = VERTTYPEMUL(( VERTTYPEMUL(f[ 4], f[ 9]) - VERTTYPEMUL(f[ 8], f[ 5]) ), det_1);
  274. out.f[ 9] = - VERTTYPEMUL(( VERTTYPEMUL(f[ 0], f[ 9]) - VERTTYPEMUL(f[ 8], f[ 1]) ), det_1);
  275. out.f[10] = VERTTYPEMUL(( VERTTYPEMUL(f[ 0], f[ 5]) - VERTTYPEMUL(f[ 4], f[ 1]) ), det_1);
  276. /* Calculate -C * inverse(A) */
  277. out.f[12] = - ( VERTTYPEMUL(f[12], out.f[ 0]) + VERTTYPEMUL(f[13], out.f[ 4]) + VERTTYPEMUL(f[14], out.f[ 8]) );
  278. out.f[13] = - ( VERTTYPEMUL(f[12], out.f[ 1]) + VERTTYPEMUL(f[13], out.f[ 5]) + VERTTYPEMUL(f[14], out.f[ 9]) );
  279. out.f[14] = - ( VERTTYPEMUL(f[12], out.f[ 2]) + VERTTYPEMUL(f[13], out.f[ 6]) + VERTTYPEMUL(f[14], out.f[10]) );
  280. /* Fill in last row */
  281. out.f[ 3] = f2vt(0.0f);
  282. out.f[ 7] = f2vt(0.0f);
  283. out.f[11] = f2vt(0.0f);
  284. out.f[15] = f2vt(1.0f);
  285. }
  286. return out;
  287. }
  288. /*!***************************************************************************
  289. @Function PVRTLinearEqSolve
  290. @Input pSrc 2D array of floats. 4 Eq linear problem is 5x4
  291. matrix, constants in first column
  292. @Input nCnt Number of equations to solve
  293. @Output pRes Result
  294. @Description Solves 'nCnt' simultaneous equations of 'nCnt' variables.
  295. pRes should be an array large enough to contain the
  296. results: the values of the 'nCnt' variables.
  297. This fn recursively uses Gaussian Elimination.
  298. *****************************************************************************/
  299. void PVRTLinearEqSolve(VERTTYPE * const pRes, VERTTYPE ** const pSrc, const int nCnt)
  300. {
  301. int i, j, k;
  302. VERTTYPE f;
  303. if (nCnt == 1)
  304. {
  305. _ASSERT(pSrc[0][1] != 0);
  306. pRes[0] = VERTTYPEDIV(pSrc[0][0], pSrc[0][1]);
  307. return;
  308. }
  309. // Loop backwards in an attempt avoid the need to swap rows
  310. i = nCnt;
  311. while(i)
  312. {
  313. --i;
  314. if(pSrc[i][nCnt] != f2vt(0.0f))
  315. {
  316. // Row i can be used to zero the other rows; let's move it to the bottom
  317. if(i != (nCnt-1))
  318. {
  319. for(j = 0; j <= nCnt; ++j)
  320. {
  321. // Swap the two values
  322. f = pSrc[nCnt-1][j];
  323. pSrc[nCnt-1][j] = pSrc[i][j];
  324. pSrc[i][j] = f;
  325. }
  326. }
  327. // Now zero the last columns of the top rows
  328. for(j = 0; j < (nCnt-1); ++j)
  329. {
  330. _ASSERT(pSrc[nCnt-1][nCnt] != f2vt(0.0f));
  331. f = VERTTYPEDIV(pSrc[j][nCnt], pSrc[nCnt-1][nCnt]);
  332. // No need to actually calculate a zero for the final column
  333. for(k = 0; k < nCnt; ++k)
  334. {
  335. pSrc[j][k] -= VERTTYPEMUL(f, pSrc[nCnt-1][k]);
  336. }
  337. }
  338. break;
  339. }
  340. }
  341. // Solve the top-left sub matrix
  342. PVRTLinearEqSolve(pRes, pSrc, nCnt - 1);
  343. // Now calc the solution for the bottom row
  344. f = pSrc[nCnt-1][0];
  345. for(k = 1; k < nCnt; ++k)
  346. {
  347. f -= VERTTYPEMUL(pSrc[nCnt-1][k], pRes[k-1]);
  348. }
  349. _ASSERT(pSrc[nCnt-1][nCnt] != f2vt(0));
  350. f = VERTTYPEDIV(f, pSrc[nCnt-1][nCnt]);
  351. pRes[nCnt-1] = f;
  352. }
  353. /*****************************************************************************
  354. End of file (PVRTVector.cpp)
  355. *****************************************************************************/