PVRTMatrixX.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. /******************************************************************************
  2. @File PVRTMatrixX.cpp
  3. @Title PVRTMatrixX
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform ANSI compatible
  7. @Description Set of mathematical functions involving matrices, vectors and
  8. quaternions.
  9. ******************************************************************************/
  10. #include "PVRTContext.h"
  11. #include <math.h>
  12. #include <string.h>
  13. #include "PVRTFixedPoint.h"
  14. #include "PVRTMatrix.h"
  15. /****************************************************************************
  16. ** Constants
  17. ****************************************************************************/
  18. static const PVRTMATRIXx c_mIdentity = {
  19. {
  20. PVRTF2X(1.0f), PVRTF2X(0.0f), PVRTF2X(0.0f), PVRTF2X(0.0f),
  21. PVRTF2X(0.0f), PVRTF2X(1.0f), PVRTF2X(0.0f), PVRTF2X(0.0f),
  22. PVRTF2X(0.0f), PVRTF2X(0.0f), PVRTF2X(1.0f), PVRTF2X(0.0f),
  23. PVRTF2X(0.0f), PVRTF2X(0.0f), PVRTF2X(0.0f), PVRTF2X(1.0f)
  24. }
  25. };
  26. /****************************************************************************
  27. ** Functions
  28. ****************************************************************************/
  29. /*!***************************************************************************
  30. @Function PVRTMatrixIdentityX
  31. @Output mOut Set to identity
  32. @Description Reset matrix to identity matrix.
  33. *****************************************************************************/
  34. void PVRTMatrixIdentityX(PVRTMATRIXx &mOut)
  35. {
  36. mOut.f[ 0]=PVRTF2X(1.0f); mOut.f[ 4]=PVRTF2X(0.0f); mOut.f[ 8]=PVRTF2X(0.0f); mOut.f[12]=PVRTF2X(0.0f);
  37. mOut.f[ 1]=PVRTF2X(0.0f); mOut.f[ 5]=PVRTF2X(1.0f); mOut.f[ 9]=PVRTF2X(0.0f); mOut.f[13]=PVRTF2X(0.0f);
  38. mOut.f[ 2]=PVRTF2X(0.0f); mOut.f[ 6]=PVRTF2X(0.0f); mOut.f[10]=PVRTF2X(1.0f); mOut.f[14]=PVRTF2X(0.0f);
  39. mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f);
  40. }
  41. /*!***************************************************************************
  42. @Function PVRTMatrixMultiplyX
  43. @Output mOut Result of mA x mB
  44. @Input mA First operand
  45. @Input mB Second operand
  46. @Description Multiply mA by mB and assign the result to mOut
  47. (mOut = p1 * p2). A copy of the result matrix is done in
  48. the function because mOut can be a parameter mA or mB.
  49. The fixed-point shift could be performed after adding
  50. all four intermediate results together however this might
  51. cause some overflow issues.
  52. ****************************************************************************/
  53. void PVRTMatrixMultiplyX(
  54. PVRTMATRIXx &mOut,
  55. const PVRTMATRIXx &mA,
  56. const PVRTMATRIXx &mB)
  57. {
  58. PVRTMATRIXx mRet;
  59. /* Perform calculation on a dummy matrix (mRet) */
  60. mRet.f[ 0] = PVRTXMUL(mA.f[ 0], mB.f[ 0]) + PVRTXMUL(mA.f[ 1], mB.f[ 4]) + PVRTXMUL(mA.f[ 2], mB.f[ 8]) + PVRTXMUL(mA.f[ 3], mB.f[12]);
  61. mRet.f[ 1] = PVRTXMUL(mA.f[ 0], mB.f[ 1]) + PVRTXMUL(mA.f[ 1], mB.f[ 5]) + PVRTXMUL(mA.f[ 2], mB.f[ 9]) + PVRTXMUL(mA.f[ 3], mB.f[13]);
  62. mRet.f[ 2] = PVRTXMUL(mA.f[ 0], mB.f[ 2]) + PVRTXMUL(mA.f[ 1], mB.f[ 6]) + PVRTXMUL(mA.f[ 2], mB.f[10]) + PVRTXMUL(mA.f[ 3], mB.f[14]);
  63. mRet.f[ 3] = PVRTXMUL(mA.f[ 0], mB.f[ 3]) + PVRTXMUL(mA.f[ 1], mB.f[ 7]) + PVRTXMUL(mA.f[ 2], mB.f[11]) + PVRTXMUL(mA.f[ 3], mB.f[15]);
  64. mRet.f[ 4] = PVRTXMUL(mA.f[ 4], mB.f[ 0]) + PVRTXMUL(mA.f[ 5], mB.f[ 4]) + PVRTXMUL(mA.f[ 6], mB.f[ 8]) + PVRTXMUL(mA.f[ 7], mB.f[12]);
  65. mRet.f[ 5] = PVRTXMUL(mA.f[ 4], mB.f[ 1]) + PVRTXMUL(mA.f[ 5], mB.f[ 5]) + PVRTXMUL(mA.f[ 6], mB.f[ 9]) + PVRTXMUL(mA.f[ 7], mB.f[13]);
  66. mRet.f[ 6] = PVRTXMUL(mA.f[ 4], mB.f[ 2]) + PVRTXMUL(mA.f[ 5], mB.f[ 6]) + PVRTXMUL(mA.f[ 6], mB.f[10]) + PVRTXMUL(mA.f[ 7], mB.f[14]);
  67. mRet.f[ 7] = PVRTXMUL(mA.f[ 4], mB.f[ 3]) + PVRTXMUL(mA.f[ 5], mB.f[ 7]) + PVRTXMUL(mA.f[ 6], mB.f[11]) + PVRTXMUL(mA.f[ 7], mB.f[15]);
  68. mRet.f[ 8] = PVRTXMUL(mA.f[ 8], mB.f[ 0]) + PVRTXMUL(mA.f[ 9], mB.f[ 4]) + PVRTXMUL(mA.f[10], mB.f[ 8]) + PVRTXMUL(mA.f[11], mB.f[12]);
  69. mRet.f[ 9] = PVRTXMUL(mA.f[ 8], mB.f[ 1]) + PVRTXMUL(mA.f[ 9], mB.f[ 5]) + PVRTXMUL(mA.f[10], mB.f[ 9]) + PVRTXMUL(mA.f[11], mB.f[13]);
  70. mRet.f[10] = PVRTXMUL(mA.f[ 8], mB.f[ 2]) + PVRTXMUL(mA.f[ 9], mB.f[ 6]) + PVRTXMUL(mA.f[10], mB.f[10]) + PVRTXMUL(mA.f[11], mB.f[14]);
  71. mRet.f[11] = PVRTXMUL(mA.f[ 8], mB.f[ 3]) + PVRTXMUL(mA.f[ 9], mB.f[ 7]) + PVRTXMUL(mA.f[10], mB.f[11]) + PVRTXMUL(mA.f[11], mB.f[15]);
  72. mRet.f[12] = PVRTXMUL(mA.f[12], mB.f[ 0]) + PVRTXMUL(mA.f[13], mB.f[ 4]) + PVRTXMUL(mA.f[14], mB.f[ 8]) + PVRTXMUL(mA.f[15], mB.f[12]);
  73. mRet.f[13] = PVRTXMUL(mA.f[12], mB.f[ 1]) + PVRTXMUL(mA.f[13], mB.f[ 5]) + PVRTXMUL(mA.f[14], mB.f[ 9]) + PVRTXMUL(mA.f[15], mB.f[13]);
  74. mRet.f[14] = PVRTXMUL(mA.f[12], mB.f[ 2]) + PVRTXMUL(mA.f[13], mB.f[ 6]) + PVRTXMUL(mA.f[14], mB.f[10]) + PVRTXMUL(mA.f[15], mB.f[14]);
  75. mRet.f[15] = PVRTXMUL(mA.f[12], mB.f[ 3]) + PVRTXMUL(mA.f[13], mB.f[ 7]) + PVRTXMUL(mA.f[14], mB.f[11]) + PVRTXMUL(mA.f[15], mB.f[15]);
  76. /* Copy result in pResultMatrix */
  77. mOut = mRet;
  78. }
  79. /*!***************************************************************************
  80. @Function Name PVRTMatrixTranslationX
  81. @Output mOut Translation matrix
  82. @Input fX X component of the translation
  83. @Input fY Y component of the translation
  84. @Input fZ Z component of the translation
  85. @Description Build a transaltion matrix mOut using fX, fY and fZ.
  86. *****************************************************************************/
  87. void PVRTMatrixTranslationX(
  88. PVRTMATRIXx &mOut,
  89. const int fX,
  90. const int fY,
  91. const int fZ)
  92. {
  93. mOut.f[ 0]=PVRTF2X(1.0f); mOut.f[ 4]=PVRTF2X(0.0f); mOut.f[ 8]=PVRTF2X(0.0f); mOut.f[12]=fX;
  94. mOut.f[ 1]=PVRTF2X(0.0f); mOut.f[ 5]=PVRTF2X(1.0f); mOut.f[ 9]=PVRTF2X(0.0f); mOut.f[13]=fY;
  95. mOut.f[ 2]=PVRTF2X(0.0f); mOut.f[ 6]=PVRTF2X(0.0f); mOut.f[10]=PVRTF2X(1.0f); mOut.f[14]=fZ;
  96. mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f);
  97. }
  98. /*!***************************************************************************
  99. @Function Name PVRTMatrixScalingX
  100. @Output mOut Scale matrix
  101. @Input fX X component of the scaling
  102. @Input fY Y component of the scaling
  103. @Input fZ Z component of the scaling
  104. @Description Build a scale matrix mOut using fX, fY and fZ.
  105. *****************************************************************************/
  106. void PVRTMatrixScalingX(
  107. PVRTMATRIXx &mOut,
  108. const int fX,
  109. const int fY,
  110. const int fZ)
  111. {
  112. mOut.f[ 0]=fX; mOut.f[ 4]=PVRTF2X(0.0f); mOut.f[ 8]=PVRTF2X(0.0f); mOut.f[12]=PVRTF2X(0.0f);
  113. mOut.f[ 1]=PVRTF2X(0.0f); mOut.f[ 5]=fY; mOut.f[ 9]=PVRTF2X(0.0f); mOut.f[13]=PVRTF2X(0.0f);
  114. mOut.f[ 2]=PVRTF2X(0.0f); mOut.f[ 6]=PVRTF2X(0.0f); mOut.f[10]=fZ; mOut.f[14]=PVRTF2X(0.0f);
  115. mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f);
  116. }
  117. /*!***************************************************************************
  118. @Function Name PVRTMatrixRotationXX
  119. @Output mOut Rotation matrix
  120. @Input fAngle Angle of the rotation
  121. @Description Create an X rotation matrix mOut.
  122. *****************************************************************************/
  123. void PVRTMatrixRotationXX(
  124. PVRTMATRIXx &mOut,
  125. const int fAngle)
  126. {
  127. int fCosine, fSine;
  128. /* Precompute cos and sin */
  129. #if defined(BUILD_DX9) || defined(BUILD_D3DM) || defined(BUILD_DX10)
  130. fCosine = PVRTXCOS(-fAngle);
  131. fSine = PVRTXSIN(-fAngle);
  132. #else
  133. fCosine = PVRTXCOS(fAngle);
  134. fSine = PVRTXSIN(fAngle);
  135. #endif
  136. /* Create the trigonometric matrix corresponding to X Rotation */
  137. mOut.f[ 0]=PVRTF2X(1.0f); mOut.f[ 4]=PVRTF2X(0.0f); mOut.f[ 8]=PVRTF2X(0.0f); mOut.f[12]=PVRTF2X(0.0f);
  138. mOut.f[ 1]=PVRTF2X(0.0f); mOut.f[ 5]=fCosine; mOut.f[ 9]=fSine; mOut.f[13]=PVRTF2X(0.0f);
  139. mOut.f[ 2]=PVRTF2X(0.0f); mOut.f[ 6]=-fSine; mOut.f[10]=fCosine; mOut.f[14]=PVRTF2X(0.0f);
  140. mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f);
  141. }
  142. /*!***************************************************************************
  143. @Function Name PVRTMatrixRotationYX
  144. @Output mOut Rotation matrix
  145. @Input fAngle Angle of the rotation
  146. @Description Create an Y rotation matrix mOut.
  147. *****************************************************************************/
  148. void PVRTMatrixRotationYX(
  149. PVRTMATRIXx &mOut,
  150. const int fAngle)
  151. {
  152. int fCosine, fSine;
  153. /* Precompute cos and sin */
  154. #if defined(BUILD_DX9) || defined(BUILD_D3DM) || defined(BUILD_DX10)
  155. fCosine = PVRTXCOS(-fAngle);
  156. fSine = PVRTXSIN(-fAngle);
  157. #else
  158. fCosine = PVRTXCOS(fAngle);
  159. fSine = PVRTXSIN(fAngle);
  160. #endif
  161. /* Create the trigonometric matrix corresponding to Y Rotation */
  162. mOut.f[ 0]=fCosine; mOut.f[ 4]=PVRTF2X(0.0f); mOut.f[ 8]=-fSine; mOut.f[12]=PVRTF2X(0.0f);
  163. mOut.f[ 1]=PVRTF2X(0.0f); mOut.f[ 5]=PVRTF2X(1.0f); mOut.f[ 9]=PVRTF2X(0.0f); mOut.f[13]=PVRTF2X(0.0f);
  164. mOut.f[ 2]=fSine; mOut.f[ 6]=PVRTF2X(0.0f); mOut.f[10]=fCosine; mOut.f[14]=PVRTF2X(0.0f);
  165. mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f);
  166. }
  167. /*!***************************************************************************
  168. @Function Name PVRTMatrixRotationZX
  169. @Output mOut Rotation matrix
  170. @Input fAngle Angle of the rotation
  171. @Description Create an Z rotation matrix mOut.
  172. *****************************************************************************/
  173. void PVRTMatrixRotationZX(
  174. PVRTMATRIXx &mOut,
  175. const int fAngle)
  176. {
  177. int fCosine, fSine;
  178. /* Precompute cos and sin */
  179. #if defined(BUILD_DX9) || defined(BUILD_D3DM) || defined(BUILD_DX10)
  180. fCosine = PVRTXCOS(-fAngle);
  181. fSine = PVRTXSIN(-fAngle);
  182. #else
  183. fCosine = PVRTXCOS(fAngle);
  184. fSine = PVRTXSIN(fAngle);
  185. #endif
  186. /* Create the trigonometric matrix corresponding to Z Rotation */
  187. mOut.f[ 0]=fCosine; mOut.f[ 4]=fSine; mOut.f[ 8]=PVRTF2X(0.0f); mOut.f[12]=PVRTF2X(0.0f);
  188. mOut.f[ 1]=-fSine; mOut.f[ 5]=fCosine; mOut.f[ 9]=PVRTF2X(0.0f); mOut.f[13]=PVRTF2X(0.0f);
  189. mOut.f[ 2]=PVRTF2X(0.0f); mOut.f[ 6]=PVRTF2X(0.0f); mOut.f[10]=PVRTF2X(1.0f); mOut.f[14]=PVRTF2X(0.0f);
  190. mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f);
  191. }
  192. /*!***************************************************************************
  193. @Function Name PVRTMatrixTransposeX
  194. @Output mOut Transposed matrix
  195. @Input mIn Original matrix
  196. @Description Compute the transpose matrix of mIn.
  197. *****************************************************************************/
  198. void PVRTMatrixTransposeX(
  199. PVRTMATRIXx &mOut,
  200. const PVRTMATRIXx &mIn)
  201. {
  202. PVRTMATRIXx mTmp;
  203. mTmp.f[ 0]=mIn.f[ 0]; mTmp.f[ 4]=mIn.f[ 1]; mTmp.f[ 8]=mIn.f[ 2]; mTmp.f[12]=mIn.f[ 3];
  204. mTmp.f[ 1]=mIn.f[ 4]; mTmp.f[ 5]=mIn.f[ 5]; mTmp.f[ 9]=mIn.f[ 6]; mTmp.f[13]=mIn.f[ 7];
  205. mTmp.f[ 2]=mIn.f[ 8]; mTmp.f[ 6]=mIn.f[ 9]; mTmp.f[10]=mIn.f[10]; mTmp.f[14]=mIn.f[11];
  206. mTmp.f[ 3]=mIn.f[12]; mTmp.f[ 7]=mIn.f[13]; mTmp.f[11]=mIn.f[14]; mTmp.f[15]=mIn.f[15];
  207. mOut = mTmp;
  208. }
  209. /*!***************************************************************************
  210. @Function PVRTMatrixInverseX
  211. @Output mOut Inversed matrix
  212. @Input mIn Original matrix
  213. @Description Compute the inverse matrix of mIn.
  214. The matrix must be of the form :
  215. A 0
  216. C 1
  217. Where A is a 3x3 matrix and C is a 1x3 matrix.
  218. *****************************************************************************/
  219. void PVRTMatrixInverseX(
  220. PVRTMATRIXx &mOut,
  221. const PVRTMATRIXx &mIn)
  222. {
  223. PVRTMATRIXx mDummyMatrix;
  224. int det_1;
  225. int pos, neg, temp;
  226. /* Calculate the determinant of submatrix A and determine if the
  227. the matrix is singular as limited by the double precision
  228. floating-point data representation. */
  229. pos = neg = 0;
  230. temp = PVRTXMUL(PVRTXMUL(mIn.f[ 0], mIn.f[ 5]), mIn.f[10]);
  231. if (temp >= 0) pos += temp; else neg += temp;
  232. temp = PVRTXMUL(PVRTXMUL(mIn.f[ 4], mIn.f[ 9]), mIn.f[ 2]);
  233. if (temp >= 0) pos += temp; else neg += temp;
  234. temp = PVRTXMUL(PVRTXMUL(mIn.f[ 8], mIn.f[ 1]), mIn.f[ 6]);
  235. if (temp >= 0) pos += temp; else neg += temp;
  236. temp = PVRTXMUL(PVRTXMUL(-mIn.f[ 8], mIn.f[ 5]), mIn.f[ 2]);
  237. if (temp >= 0) pos += temp; else neg += temp;
  238. temp = PVRTXMUL(PVRTXMUL(-mIn.f[ 4], mIn.f[ 1]), mIn.f[10]);
  239. if (temp >= 0) pos += temp; else neg += temp;
  240. temp = PVRTXMUL(PVRTXMUL(-mIn.f[ 0], mIn.f[ 9]), mIn.f[ 6]);
  241. if (temp >= 0) pos += temp; else neg += temp;
  242. det_1 = pos + neg;
  243. /* Is the submatrix A singular? */
  244. if (det_1 == 0)
  245. {
  246. /* Matrix M has no inverse */
  247. _RPT0(_CRT_WARN, "Matrix has no inverse : singular matrix\n");
  248. return;
  249. }
  250. else
  251. {
  252. /* Calculate inverse(A) = adj(A) / det(A) */
  253. //det_1 = 1.0 / det_1;
  254. det_1 = PVRTXDIV(PVRTF2X(1.0f), det_1);
  255. mDummyMatrix.f[ 0] = PVRTXMUL(( PVRTXMUL(mIn.f[ 5], mIn.f[10]) - PVRTXMUL(mIn.f[ 9], mIn.f[ 6]) ), det_1);
  256. mDummyMatrix.f[ 1] = - PVRTXMUL(( PVRTXMUL(mIn.f[ 1], mIn.f[10]) - PVRTXMUL(mIn.f[ 9], mIn.f[ 2]) ), det_1);
  257. mDummyMatrix.f[ 2] = PVRTXMUL(( PVRTXMUL(mIn.f[ 1], mIn.f[ 6]) - PVRTXMUL(mIn.f[ 5], mIn.f[ 2]) ), det_1);
  258. mDummyMatrix.f[ 4] = - PVRTXMUL(( PVRTXMUL(mIn.f[ 4], mIn.f[10]) - PVRTXMUL(mIn.f[ 8], mIn.f[ 6]) ), det_1);
  259. mDummyMatrix.f[ 5] = PVRTXMUL(( PVRTXMUL(mIn.f[ 0], mIn.f[10]) - PVRTXMUL(mIn.f[ 8], mIn.f[ 2]) ), det_1);
  260. mDummyMatrix.f[ 6] = - PVRTXMUL(( PVRTXMUL(mIn.f[ 0], mIn.f[ 6]) - PVRTXMUL(mIn.f[ 4], mIn.f[ 2]) ), det_1);
  261. mDummyMatrix.f[ 8] = PVRTXMUL(( PVRTXMUL(mIn.f[ 4], mIn.f[ 9]) - PVRTXMUL(mIn.f[ 8], mIn.f[ 5]) ), det_1);
  262. mDummyMatrix.f[ 9] = - PVRTXMUL(( PVRTXMUL(mIn.f[ 0], mIn.f[ 9]) - PVRTXMUL(mIn.f[ 8], mIn.f[ 1]) ), det_1);
  263. mDummyMatrix.f[10] = PVRTXMUL(( PVRTXMUL(mIn.f[ 0], mIn.f[ 5]) - PVRTXMUL(mIn.f[ 4], mIn.f[ 1]) ), det_1);
  264. /* Calculate -C * inverse(A) */
  265. mDummyMatrix.f[12] = - ( PVRTXMUL(mIn.f[12], mDummyMatrix.f[ 0]) + PVRTXMUL(mIn.f[13], mDummyMatrix.f[ 4]) + PVRTXMUL(mIn.f[14], mDummyMatrix.f[ 8]) );
  266. mDummyMatrix.f[13] = - ( PVRTXMUL(mIn.f[12], mDummyMatrix.f[ 1]) + PVRTXMUL(mIn.f[13], mDummyMatrix.f[ 5]) + PVRTXMUL(mIn.f[14], mDummyMatrix.f[ 9]) );
  267. mDummyMatrix.f[14] = - ( PVRTXMUL(mIn.f[12], mDummyMatrix.f[ 2]) + PVRTXMUL(mIn.f[13], mDummyMatrix.f[ 6]) + PVRTXMUL(mIn.f[14], mDummyMatrix.f[10]) );
  268. /* Fill in last row */
  269. mDummyMatrix.f[ 3] = PVRTF2X(0.0f);
  270. mDummyMatrix.f[ 7] = PVRTF2X(0.0f);
  271. mDummyMatrix.f[11] = PVRTF2X(0.0f);
  272. mDummyMatrix.f[15] = PVRTF2X(1.0f);
  273. }
  274. /* Copy contents of dummy matrix in pfMatrix */
  275. mOut = mDummyMatrix;
  276. }
  277. /*!***************************************************************************
  278. @Function PVRTMatrixInverseExX
  279. @Output mOut Inversed matrix
  280. @Input mIn Original matrix
  281. @Description Compute the inverse matrix of mIn.
  282. Uses a linear equation solver and the knowledge that M.M^-1=I.
  283. Use this fn to calculate the inverse of matrices that
  284. PVRTMatrixInverse() cannot.
  285. *****************************************************************************/
  286. void PVRTMatrixInverseExX(
  287. PVRTMATRIXx &mOut,
  288. const PVRTMATRIXx &mIn)
  289. {
  290. PVRTMATRIXx mTmp;
  291. int *ppfRows[4], pfRes[4], pfIn[20];
  292. int i, j;
  293. for (i = 0; i < 4; ++i)
  294. {
  295. ppfRows[i] = &pfIn[i * 5];
  296. }
  297. /* Solve 4 sets of 4 linear equations */
  298. for (i = 0; i < 4; ++i)
  299. {
  300. for (j = 0; j < 4; ++j)
  301. {
  302. ppfRows[j][0] = c_mIdentity.f[i + 4 * j];
  303. memcpy(&ppfRows[j][1], &mIn.f[j * 4], 4 * sizeof(float));
  304. }
  305. PVRTMatrixLinearEqSolveX(pfRes, (int**)ppfRows, 4);
  306. for(j = 0; j < 4; ++j)
  307. {
  308. mTmp.f[i + 4 * j] = pfRes[j];
  309. }
  310. }
  311. mOut = mTmp;
  312. }
  313. /*!***************************************************************************
  314. @Function PVRTMatrixLookAtLHX
  315. @Output mOut Look-at view matrix
  316. @Input vEye Position of the camera
  317. @Input vAt Point the camera is looking at
  318. @Input vUp Up direction for the camera
  319. @Description Create a look-at view matrix.
  320. *****************************************************************************/
  321. void PVRTMatrixLookAtLHX(
  322. PVRTMATRIXx &mOut,
  323. const PVRTVECTOR3x &vEye,
  324. const PVRTVECTOR3x &vAt,
  325. const PVRTVECTOR3x &vUp)
  326. {
  327. PVRTVECTOR3x f, vUpActual, s, u;
  328. PVRTMATRIXx t;
  329. f.x = vEye.x - vAt.x;
  330. f.y = vEye.y - vAt.y;
  331. f.z = vEye.z - vAt.z;
  332. PVRTMatrixVec3NormalizeX(f, f);
  333. PVRTMatrixVec3NormalizeX(vUpActual, vUp);
  334. PVRTMatrixVec3CrossProductX(s, f, vUpActual);
  335. PVRTMatrixVec3CrossProductX(u, s, f);
  336. mOut.f[ 0] = s.x;
  337. mOut.f[ 1] = u.x;
  338. mOut.f[ 2] = -f.x;
  339. mOut.f[ 3] = PVRTF2X(0.0f);
  340. mOut.f[ 4] = s.y;
  341. mOut.f[ 5] = u.y;
  342. mOut.f[ 6] = -f.y;
  343. mOut.f[ 7] = PVRTF2X(0.0f);
  344. mOut.f[ 8] = s.z;
  345. mOut.f[ 9] = u.z;
  346. mOut.f[10] = -f.z;
  347. mOut.f[11] = PVRTF2X(0.0f);
  348. mOut.f[12] = PVRTF2X(0.0f);
  349. mOut.f[13] = PVRTF2X(0.0f);
  350. mOut.f[14] = PVRTF2X(0.0f);
  351. mOut.f[15] = PVRTF2X(1.0f);
  352. PVRTMatrixTranslationX(t, -vEye.x, -vEye.y, -vEye.z);
  353. PVRTMatrixMultiplyX(mOut, t, mOut);
  354. }
  355. /*!***************************************************************************
  356. @Function PVRTMatrixLookAtRHX
  357. @Output mOut Look-at view matrix
  358. @Input vEye Position of the camera
  359. @Input vAt Point the camera is looking at
  360. @Input vUp Up direction for the camera
  361. @Description Create a look-at view matrix.
  362. *****************************************************************************/
  363. void PVRTMatrixLookAtRHX(
  364. PVRTMATRIXx &mOut,
  365. const PVRTVECTOR3x &vEye,
  366. const PVRTVECTOR3x &vAt,
  367. const PVRTVECTOR3x &vUp)
  368. {
  369. PVRTVECTOR3x f, vUpActual, s, u;
  370. PVRTMATRIXx t;
  371. f.x = vAt.x - vEye.x;
  372. f.y = vAt.y - vEye.y;
  373. f.z = vAt.z - vEye.z;
  374. PVRTMatrixVec3NormalizeX(f, f);
  375. PVRTMatrixVec3NormalizeX(vUpActual, vUp);
  376. PVRTMatrixVec3CrossProductX(s, f, vUpActual);
  377. PVRTMatrixVec3CrossProductX(u, s, f);
  378. mOut.f[ 0] = s.x;
  379. mOut.f[ 1] = u.x;
  380. mOut.f[ 2] = -f.x;
  381. mOut.f[ 3] = PVRTF2X(0.0f);
  382. mOut.f[ 4] = s.y;
  383. mOut.f[ 5] = u.y;
  384. mOut.f[ 6] = -f.y;
  385. mOut.f[ 7] = PVRTF2X(0.0f);
  386. mOut.f[ 8] = s.z;
  387. mOut.f[ 9] = u.z;
  388. mOut.f[10] = -f.z;
  389. mOut.f[11] = PVRTF2X(0.0f);
  390. mOut.f[12] = PVRTF2X(0.0f);
  391. mOut.f[13] = PVRTF2X(0.0f);
  392. mOut.f[14] = PVRTF2X(0.0f);
  393. mOut.f[15] = PVRTF2X(1.0f);
  394. PVRTMatrixTranslationX(t, -vEye.x, -vEye.y, -vEye.z);
  395. PVRTMatrixMultiplyX(mOut, t, mOut);
  396. }
  397. /*!***************************************************************************
  398. @Function PVRTMatrixPerspectiveFovLHX
  399. @Output mOut Perspective matrix
  400. @Input fFOVy Field of view
  401. @Input fAspect Aspect ratio
  402. @Input fNear Near clipping distance
  403. @Input fFar Far clipping distance
  404. @Input bRotate Should we rotate it ? (for upright screens)
  405. @Description Create a perspective matrix.
  406. *****************************************************************************/
  407. void PVRTMatrixPerspectiveFovLHX(
  408. PVRTMATRIXx &mOut,
  409. const int fFOVy,
  410. const int fAspect,
  411. const int fNear,
  412. const int fFar,
  413. const bool bRotate)
  414. {
  415. int f, fRealAspect;
  416. if (bRotate)
  417. fRealAspect = PVRTXDIV(PVRTF2X(1.0f), fAspect);
  418. else
  419. fRealAspect = fAspect;
  420. f = PVRTXDIV(PVRTF2X(1.0f), PVRTXTAN(PVRTXMUL(fFOVy, PVRTF2X(0.5f))));
  421. mOut.f[ 0] = PVRTXDIV(f, fRealAspect);
  422. mOut.f[ 1] = PVRTF2X(0.0f);
  423. mOut.f[ 2] = PVRTF2X(0.0f);
  424. mOut.f[ 3] = PVRTF2X(0.0f);
  425. mOut.f[ 4] = PVRTF2X(0.0f);
  426. mOut.f[ 5] = f;
  427. mOut.f[ 6] = PVRTF2X(0.0f);
  428. mOut.f[ 7] = PVRTF2X(0.0f);
  429. mOut.f[ 8] = PVRTF2X(0.0f);
  430. mOut.f[ 9] = PVRTF2X(0.0f);
  431. mOut.f[10] = PVRTXDIV(fFar, fFar - fNear);
  432. mOut.f[11] = PVRTF2X(1.0f);
  433. mOut.f[12] = PVRTF2X(0.0f);
  434. mOut.f[13] = PVRTF2X(0.0f);
  435. mOut.f[14] = -PVRTXMUL(PVRTXDIV(fFar, fFar - fNear), fNear);
  436. mOut.f[15] = PVRTF2X(0.0f);
  437. if (bRotate)
  438. {
  439. PVRTMATRIXx mRotation, mTemp = mOut;
  440. PVRTMatrixRotationZX(mRotation, PVRTF2X(90.0f*PVRT_PIf/180.0f));
  441. PVRTMatrixMultiplyX(mOut, mTemp, mRotation);
  442. }
  443. }
  444. /*!***************************************************************************
  445. @Function PVRTMatrixPerspectiveFovRHX
  446. @Output mOut Perspective matrix
  447. @Input fFOVy Field of view
  448. @Input fAspect Aspect ratio
  449. @Input fNear Near clipping distance
  450. @Input fFar Far clipping distance
  451. @Input bRotate Should we rotate it ? (for upright screens)
  452. @Description Create a perspective matrix.
  453. *****************************************************************************/
  454. void PVRTMatrixPerspectiveFovRHX(
  455. PVRTMATRIXx &mOut,
  456. const int fFOVy,
  457. const int fAspect,
  458. const int fNear,
  459. const int fFar,
  460. const bool bRotate)
  461. {
  462. int f;
  463. int fCorrectAspect = fAspect;
  464. if (bRotate)
  465. {
  466. fCorrectAspect = PVRTXDIV(PVRTF2X(1.0f), fAspect);
  467. }
  468. f = PVRTXDIV(PVRTF2X(1.0f), PVRTXTAN(PVRTXMUL(fFOVy, PVRTF2X(0.5f))));
  469. mOut.f[ 0] = PVRTXDIV(f, fCorrectAspect);
  470. mOut.f[ 1] = PVRTF2X(0.0f);
  471. mOut.f[ 2] = PVRTF2X(0.0f);
  472. mOut.f[ 3] = PVRTF2X(0.0f);
  473. mOut.f[ 4] = PVRTF2X(0.0f);
  474. mOut.f[ 5] = f;
  475. mOut.f[ 6] = PVRTF2X(0.0f);
  476. mOut.f[ 7] = PVRTF2X(0.0f);
  477. mOut.f[ 8] = PVRTF2X(0.0f);
  478. mOut.f[ 9] = PVRTF2X(0.0f);
  479. mOut.f[10] = PVRTXDIV(fFar + fNear, fNear - fFar);
  480. mOut.f[11] = PVRTF2X(-1.0f);
  481. mOut.f[12] = PVRTF2X(0.0f);
  482. mOut.f[13] = PVRTF2X(0.0f);
  483. mOut.f[14] = PVRTXMUL(PVRTXDIV(fFar, fNear - fFar), fNear) << 1; // Cheap 2x
  484. mOut.f[15] = PVRTF2X(0.0f);
  485. if (bRotate)
  486. {
  487. PVRTMATRIXx mRotation, mTemp = mOut;
  488. PVRTMatrixRotationZX(mRotation, PVRTF2X(-90.0f*PVRT_PIf/180.0f));
  489. PVRTMatrixMultiplyX(mOut, mTemp, mRotation);
  490. }
  491. }
  492. /*!***************************************************************************
  493. @Function PVRTMatrixOrthoLHX
  494. @Output mOut Orthographic matrix
  495. @Input w Width of the screen
  496. @Input h Height of the screen
  497. @Input zn Near clipping distance
  498. @Input zf Far clipping distance
  499. @Input bRotate Should we rotate it ? (for upright screens)
  500. @Description Create an orthographic matrix.
  501. *****************************************************************************/
  502. void PVRTMatrixOrthoLHX(
  503. PVRTMATRIXx &mOut,
  504. const int w,
  505. const int h,
  506. const int zn,
  507. const int zf,
  508. const bool bRotate)
  509. {
  510. int fCorrectW = w;
  511. int fCorrectH = h;
  512. if (bRotate)
  513. {
  514. fCorrectW = h;
  515. fCorrectH = w;
  516. }
  517. mOut.f[ 0] = PVRTXDIV(PVRTF2X(2.0f), fCorrectW);
  518. mOut.f[ 1] = PVRTF2X(0.0f);
  519. mOut.f[ 2] = PVRTF2X(0.0f);
  520. mOut.f[ 3] = PVRTF2X(0.0f);
  521. mOut.f[ 4] = PVRTF2X(0.0f);
  522. mOut.f[ 5] = PVRTXDIV(PVRTF2X(2.0f), fCorrectH);
  523. mOut.f[ 6] = PVRTF2X(0.0f);
  524. mOut.f[ 7] = PVRTF2X(0.0f);
  525. mOut.f[ 8] = PVRTF2X(0.0f);
  526. mOut.f[ 9] = PVRTF2X(0.0f);
  527. mOut.f[10] = PVRTXDIV(PVRTF2X(1.0f), zf - zn);
  528. mOut.f[11] = PVRTXDIV(zn, zn - zf);
  529. mOut.f[12] = PVRTF2X(0.0f);
  530. mOut.f[13] = PVRTF2X(0.0f);
  531. mOut.f[14] = PVRTF2X(0.0f);
  532. mOut.f[15] = PVRTF2X(1.0f);
  533. if (bRotate)
  534. {
  535. PVRTMATRIXx mRotation, mTemp = mOut;
  536. PVRTMatrixRotationZX(mRotation, PVRTF2X(-90.0f*PVRT_PIf/180.0f));
  537. PVRTMatrixMultiplyX(mOut, mRotation, mTemp);
  538. }
  539. }
  540. /*!***************************************************************************
  541. @Function PVRTMatrixOrthoRHX
  542. @Output mOut Orthographic matrix
  543. @Input w Width of the screen
  544. @Input h Height of the screen
  545. @Input zn Near clipping distance
  546. @Input zf Far clipping distance
  547. @Input bRotate Should we rotate it ? (for upright screens)
  548. @Description Create an orthographic matrix.
  549. *****************************************************************************/
  550. void PVRTMatrixOrthoRHX(
  551. PVRTMATRIXx &mOut,
  552. const int w,
  553. const int h,
  554. const int zn,
  555. const int zf,
  556. const bool bRotate)
  557. {
  558. int fCorrectW = w;
  559. int fCorrectH = h;
  560. if (bRotate)
  561. {
  562. fCorrectW = h;
  563. fCorrectH = w;
  564. }
  565. mOut.f[ 0] = PVRTXDIV(PVRTF2X(2.0f), fCorrectW);
  566. mOut.f[ 1] = PVRTF2X(0.0f);
  567. mOut.f[ 2] = PVRTF2X(0.0f);
  568. mOut.f[ 3] = PVRTF2X(0.0f);
  569. mOut.f[ 4] = PVRTF2X(0.0f);
  570. mOut.f[ 5] = PVRTXDIV(PVRTF2X(2.0f), fCorrectH);
  571. mOut.f[ 6] = PVRTF2X(0.0f);
  572. mOut.f[ 7] = PVRTF2X(0.0f);
  573. mOut.f[ 8] = PVRTF2X(0.0f);
  574. mOut.f[ 9] = PVRTF2X(0.0f);
  575. mOut.f[10] = PVRTXDIV(PVRTF2X(1.0f), zn - zf);
  576. mOut.f[11] = PVRTXDIV(zn, zn - zf);
  577. mOut.f[12] = PVRTF2X(0.0f);
  578. mOut.f[13] = PVRTF2X(0.0f);
  579. mOut.f[14] = PVRTF2X(0.0f);
  580. mOut.f[15] = PVRTF2X(1.0f);
  581. if (bRotate)
  582. {
  583. PVRTMATRIXx mRotation, mTemp = mOut;
  584. PVRTMatrixRotationZX(mRotation, PVRTF2X(-90.0f*PVRT_PIf/180.0f));
  585. PVRTMatrixMultiplyX(mOut, mRotation, mTemp);
  586. }
  587. }
  588. /*!***************************************************************************
  589. @Function PVRTMatrixVec3LerpX
  590. @Output vOut Result of the interpolation
  591. @Input v1 First vector to interpolate from
  592. @Input v2 Second vector to interpolate form
  593. @Input s Coefficient of interpolation
  594. @Description This function performs the linear interpolation based on
  595. the following formula: V1 + s(V2-V1).
  596. *****************************************************************************/
  597. void PVRTMatrixVec3LerpX(
  598. PVRTVECTOR3x &vOut,
  599. const PVRTVECTOR3x &v1,
  600. const PVRTVECTOR3x &v2,
  601. const int s)
  602. {
  603. vOut.x = v1.x + PVRTXMUL(s, v2.x - v1.x);
  604. vOut.y = v1.y + PVRTXMUL(s, v2.y - v1.y);
  605. vOut.z = v1.z + PVRTXMUL(s, v2.z - v1.z);
  606. }
  607. /*!***************************************************************************
  608. @Function PVRTMatrixVec3DotProductX
  609. @Input v1 First vector
  610. @Input v2 Second vector
  611. @Return Dot product of the two vectors.
  612. @Description This function performs the dot product of the two
  613. supplied vectors.
  614. A single >> 16 shift could be applied to the final accumulated
  615. result however this runs the risk of overflow between the
  616. results of the intermediate additions.
  617. *****************************************************************************/
  618. int PVRTMatrixVec3DotProductX(
  619. const PVRTVECTOR3x &v1,
  620. const PVRTVECTOR3x &v2)
  621. {
  622. return (PVRTXMUL(v1.x, v2.x) + PVRTXMUL(v1.y, v2.y) + PVRTXMUL(v1.z, v2.z));
  623. }
  624. /*!***************************************************************************
  625. @Function PVRTMatrixVec3CrossProductX
  626. @Output vOut Cross product of the two vectors
  627. @Input v1 First vector
  628. @Input v2 Second vector
  629. @Description This function performs the cross product of the two
  630. supplied vectors.
  631. *****************************************************************************/
  632. void PVRTMatrixVec3CrossProductX(
  633. PVRTVECTOR3x &vOut,
  634. const PVRTVECTOR3x &v1,
  635. const PVRTVECTOR3x &v2)
  636. {
  637. PVRTVECTOR3x result;
  638. /* Perform calculation on a dummy VECTOR (result) */
  639. result.x = PVRTXMUL(v1.y, v2.z) - PVRTXMUL(v1.z, v2.y);
  640. result.y = PVRTXMUL(v1.z, v2.x) - PVRTXMUL(v1.x, v2.z);
  641. result.z = PVRTXMUL(v1.x, v2.y) - PVRTXMUL(v1.y, v2.x);
  642. /* Copy result in pOut */
  643. vOut = result;
  644. }
  645. /*!***************************************************************************
  646. @Function PVRTMatrixVec3NormalizeX
  647. @Output vOut Normalized vector
  648. @Input vIn Vector to normalize
  649. @Description Normalizes the supplied vector.
  650. The square root function is currently still performed
  651. in floating-point.
  652. Original vector is scaled down prior to be normalized in
  653. order to avoid overflow issues.
  654. ****************************************************************************/
  655. void PVRTMatrixVec3NormalizeX(
  656. PVRTVECTOR3x &vOut,
  657. const PVRTVECTOR3x &vIn)
  658. {
  659. int f, n;
  660. PVRTVECTOR3x vTemp;
  661. /* Scale vector by uniform value */
  662. n = PVRTABS(vIn.x) + PVRTABS(vIn.y) + PVRTABS(vIn.z);
  663. vTemp.x = PVRTXDIV(vIn.x, n);
  664. vTemp.y = PVRTXDIV(vIn.y, n);
  665. vTemp.z = PVRTXDIV(vIn.z, n);
  666. /* Calculate x2+y2+z2/sqrt(x2+y2+z2) */
  667. f = PVRTMatrixVec3DotProductX(vTemp, vTemp);
  668. f = PVRTXDIV(PVRTF2X(1.0f), PVRTF2X(sqrt(PVRTX2F(f))));
  669. /* Multiply vector components by f */
  670. vOut.x = PVRTXMUL(vTemp.x, f);
  671. vOut.y = PVRTXMUL(vTemp.y, f);
  672. vOut.z = PVRTXMUL(vTemp.z, f);
  673. }
  674. /*!***************************************************************************
  675. @Function PVRTMatrixVec3LengthX
  676. @Input vIn Vector to get the length of
  677. @Return The length of the vector
  678. @Description Gets the length of the supplied vector
  679. *****************************************************************************/
  680. int PVRTMatrixVec3LengthX(
  681. const PVRTVECTOR3x &vIn)
  682. {
  683. int temp;
  684. temp = PVRTXMUL(vIn.x,vIn.x) + PVRTXMUL(vIn.y,vIn.y) + PVRTXMUL(vIn.z,vIn.z);
  685. return PVRTF2X(sqrt(PVRTX2F(temp)));
  686. }
  687. /*!***************************************************************************
  688. @Function PVRTMatrixLinearEqSolveX
  689. @Input pSrc 2D array of floats. 4 Eq linear problem is 5x4
  690. matrix, constants in first column
  691. @Input nCnt Number of equations to solve
  692. @Output pRes Result
  693. @Description Solves 'nCnt' simultaneous equations of 'nCnt' variables.
  694. pRes should be an array large enough to contain the
  695. results: the values of the 'nCnt' variables.
  696. This fn recursively uses Gaussian Elimination.
  697. *****************************************************************************/
  698. void PVRTMatrixLinearEqSolveX(
  699. int * const pRes,
  700. int ** const pSrc,
  701. const int nCnt)
  702. {
  703. int i, j, k;
  704. int f;
  705. if (nCnt == 1)
  706. {
  707. _ASSERT(pSrc[0][1] != 0);
  708. pRes[0] = PVRTXDIV(pSrc[0][0], pSrc[0][1]);
  709. return;
  710. }
  711. // Loop backwards in an attempt avoid the need to swap rows
  712. i = nCnt;
  713. while(i)
  714. {
  715. --i;
  716. if(pSrc[i][nCnt] != PVRTF2X(0.0f))
  717. {
  718. // Row i can be used to zero the other rows; let's move it to the bottom
  719. if(i != (nCnt-1))
  720. {
  721. for(j = 0; j <= nCnt; ++j)
  722. {
  723. // Swap the two values
  724. f = pSrc[nCnt-1][j];
  725. pSrc[nCnt-1][j] = pSrc[i][j];
  726. pSrc[i][j] = f;
  727. }
  728. }
  729. // Now zero the last columns of the top rows
  730. for(j = 0; j < (nCnt-1); ++j)
  731. {
  732. _ASSERT(pSrc[nCnt-1][nCnt] != PVRTF2X(0.0f));
  733. f = PVRTXDIV(pSrc[j][nCnt], pSrc[nCnt-1][nCnt]);
  734. // No need to actually calculate a zero for the final column
  735. for(k = 0; k < nCnt; ++k)
  736. {
  737. pSrc[j][k] -= PVRTXMUL(f, pSrc[nCnt-1][k]);
  738. }
  739. }
  740. break;
  741. }
  742. }
  743. // Solve the top-left sub matrix
  744. PVRTMatrixLinearEqSolveX(pRes, pSrc, nCnt - 1);
  745. // Now calc the solution for the bottom row
  746. f = pSrc[nCnt-1][0];
  747. for(k = 1; k < nCnt; ++k)
  748. {
  749. f -= PVRTXMUL(pSrc[nCnt-1][k], pRes[k-1]);
  750. }
  751. _ASSERT(pSrc[nCnt-1][nCnt] != PVRTF2X(0));
  752. f = PVRTXDIV(f, pSrc[nCnt-1][nCnt]);
  753. pRes[nCnt-1] = f;
  754. }
  755. /*****************************************************************************
  756. End of file (PVRTMatrixX.cpp)
  757. *****************************************************************************/