Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

329 lines
11 KiB

  1. //-----------------------------------------------------------------------------
  2. // File: D3DMath.cpp
  3. //
  4. // Desc: Shortcut macros and functions for using DX objects
  5. //
  6. // Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
  7. //-----------------------------------------------------------------------------
  8. #define D3D_OVERLOADS
  9. #define STRICT
  10. #include "StdAfx.h"
  11. #include <math.h>
  12. #include "D3DMath.h"
  13. //-----------------------------------------------------------------------------
  14. // Name: D3DMath_MatrixMultiply()
  15. // Desc: Does the matrix operation: [Q] = [A] * [B]. Note that the order of
  16. // this operation was changed from the previous version of the DXSDK.
  17. //-----------------------------------------------------------------------------
  18. VOID D3DMath_MatrixMultiply(D3DMATRIX& q, D3DMATRIX& a, D3DMATRIX& b)
  19. {
  20. FLOAT* pA = (FLOAT*)&a;
  21. FLOAT* pB = (FLOAT*)&b;
  22. FLOAT pM[16];
  23. ZeroMemory(pM, sizeof(D3DMATRIX));
  24. for(WORD i=0; i<4; i++)
  25. for(WORD j=0; j<4; j++)
  26. for(WORD k=0; k<4; k++)
  27. pM[4*i+j] += pA[4*i+k] * pB[4*k+j];
  28. memcpy(&q, pM, sizeof(D3DMATRIX));
  29. }
  30. //-----------------------------------------------------------------------------
  31. // Name: D3DMath_MatrixInvert()
  32. // Desc: Does the matrix operation: [Q] = inv[A]. Note: this function only
  33. // works for matrices with [0 0 0 1] for the 4th column.
  34. //-----------------------------------------------------------------------------
  35. HRESULT D3DMath_MatrixInvert(D3DMATRIX& q, D3DMATRIX& a)
  36. {
  37. if (fabs(a._44 - 1.0f) > .001f)
  38. return E_INVALIDARG;
  39. if (fabs(a._14) > .001f || fabs(a._24) > .001f || fabs(a._34) > .001f)
  40. return E_INVALIDARG;
  41. FLOAT fDetInv = 1.0f / (a._11 * (a._22 * a._33 - a._23 * a._32) -
  42. a._12 * (a._21 * a._33 - a._23 * a._31) +
  43. a._13 * (a._21 * a._32 - a._22 * a._31));
  44. q._11 = fDetInv * (a._22 * a._33 - a._23 * a._32);
  45. q._12 = -fDetInv * (a._12 * a._33 - a._13 * a._32);
  46. q._13 = fDetInv * (a._12 * a._23 - a._13 * a._22);
  47. q._14 = 0.0f;
  48. q._21 = -fDetInv * (a._21 * a._33 - a._23 * a._31);
  49. q._22 = fDetInv * (a._11 * a._33 - a._13 * a._31);
  50. q._23 = -fDetInv * (a._11 * a._23 - a._13 * a._21);
  51. q._24 = 0.0f;
  52. q._31 = fDetInv * (a._21 * a._32 - a._22 * a._31);
  53. q._32 = -fDetInv * (a._11 * a._32 - a._12 * a._31);
  54. q._33 = fDetInv * (a._11 * a._22 - a._12 * a._21);
  55. q._34 = 0.0f;
  56. q._41 = -(a._41 * q._11 + a._42 * q._21 + a._43 * q._31);
  57. q._42 = -(a._41 * q._12 + a._42 * q._22 + a._43 * q._32);
  58. q._43 = -(a._41 * q._13 + a._42 * q._23 + a._43 * q._33);
  59. q._44 = 1.0f;
  60. return S_OK;
  61. }
  62. //-----------------------------------------------------------------------------
  63. // Name: D3DMath_VectorMatrixMultiply()
  64. // Desc: Multiplies a vector by a matrix
  65. //-----------------------------------------------------------------------------
  66. HRESULT D3DMath_VectorMatrixMultiply(D3DVECTOR& vDest, D3DVECTOR& vSrc,
  67. D3DMATRIX& mat)
  68. {
  69. FLOAT x = vSrc.x*mat._11 + vSrc.y*mat._21 + vSrc.z* mat._31 + mat._41;
  70. FLOAT y = vSrc.x*mat._12 + vSrc.y*mat._22 + vSrc.z* mat._32 + mat._42;
  71. FLOAT z = vSrc.x*mat._13 + vSrc.y*mat._23 + vSrc.z* mat._33 + mat._43;
  72. FLOAT w = vSrc.x*mat._14 + vSrc.y*mat._24 + vSrc.z* mat._34 + mat._44;
  73. if (fabs(w) < g_EPSILON)
  74. return E_INVALIDARG;
  75. vDest.x = x/w;
  76. vDest.y = y/w;
  77. vDest.z = z/w;
  78. return S_OK;
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Name: D3DMath_VertexMatrixMultiply()
  82. // Desc: Multiplies a vertex by a matrix
  83. //-----------------------------------------------------------------------------
  84. HRESULT D3DMath_VertexMatrixMultiply(D3DVERTEX& vDest, D3DVERTEX& vSrc,
  85. D3DMATRIX& mat)
  86. {
  87. HRESULT hr;
  88. D3DVECTOR* pSrcVec = (D3DVECTOR*)&vSrc.x;
  89. D3DVECTOR* pDestVec = (D3DVECTOR*)&vDest.x;
  90. if (SUCCEEDED(hr = D3DMath_VectorMatrixMultiply(*pDestVec, *pSrcVec,
  91. mat)))
  92. {
  93. pSrcVec = (D3DVECTOR*)&vSrc.nx;
  94. pDestVec = (D3DVECTOR*)&vDest.nx;
  95. hr = D3DMath_VectorMatrixMultiply(*pDestVec, *pSrcVec, mat);
  96. }
  97. return hr;
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Name: D3DMath_QuaternionFromRotation()
  101. // Desc: Converts a normalized axis and angle to a unit quaternion.
  102. //-----------------------------------------------------------------------------
  103. VOID D3DMath_QuaternionFromRotation(FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
  104. D3DVECTOR& v, FLOAT fTheta)
  105. {
  106. x = sinf(fTheta/2.0f) * v.x;
  107. y = sinf(fTheta/2.0f) * v.y;
  108. z = sinf(fTheta/2.0f) * v.z;
  109. w = cosf(fTheta/2.0f);
  110. }
  111. //-----------------------------------------------------------------------------
  112. // Name: D3DMath_RotationFromQuaternion()
  113. // Desc: Converts a normalized axis and angle to a unit quaternion.
  114. //-----------------------------------------------------------------------------
  115. VOID D3DMath_RotationFromQuaternion(D3DVECTOR& v, FLOAT& fTheta,
  116. FLOAT x, FLOAT y, FLOAT z, FLOAT w)
  117. {
  118. fTheta = acosf(w) * 2.0f;
  119. v.x = x / sinf(fTheta/2.0f);
  120. v.y = y / sinf(fTheta/2.0f);
  121. v.z = z / sinf(fTheta/2.0f);
  122. }
  123. //-----------------------------------------------------------------------------
  124. // Name: D3DMath_QuaternionFromAngles()
  125. // Desc: Converts euler angles to a unit quaternion.
  126. //-----------------------------------------------------------------------------
  127. VOID D3DMath_QuaternionFromAngles(FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
  128. FLOAT fYaw, FLOAT fPitch, FLOAT fRoll)
  129. {
  130. FLOAT fSinYaw = sinf(fYaw/2.0f);
  131. FLOAT fSinPitch = sinf(fPitch/2.0f);
  132. FLOAT fSinRoll = sinf(fRoll/2.0f);
  133. FLOAT fCosYaw = cosf(fYaw/2.0f);
  134. FLOAT fCosPitch = cosf(fPitch/2.0f);
  135. FLOAT fCosRoll = cosf(fRoll/2.0f);
  136. x = fSinRoll * fCosPitch * fCosYaw - fCosRoll * fSinPitch * fSinYaw;
  137. y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
  138. z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
  139. w = fCosRoll * fCosPitch * fCosYaw + fSinRoll * fSinPitch * fSinYaw;
  140. }
  141. //-----------------------------------------------------------------------------
  142. // Name: D3DMath_MatrixFromQuaternion()
  143. // Desc: Converts a unit quaternion into a rotation matrix.
  144. //-----------------------------------------------------------------------------
  145. VOID D3DMath_MatrixFromQuaternion(D3DMATRIX& mat, FLOAT x, FLOAT y, FLOAT z,
  146. FLOAT w)
  147. {
  148. FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z;
  149. FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z;
  150. FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z;
  151. mat._11 = 1 - 2 * (yy + zz);
  152. mat._12 = 2 * (xy - wz);
  153. mat._13 = 2 * (xz + wy);
  154. mat._21 = 2 * (xy + wz);
  155. mat._22 = 1 - 2 * (xx + zz);
  156. mat._23 = 2 * (yz - wx);
  157. mat._31 = 2 * (xz - wy);
  158. mat._32 = 2 * (yz + wx);
  159. mat._33 = 1 - 2 * (xx + yy);
  160. mat._14 = mat._24 = mat._34 = 0.0f;
  161. mat._41 = mat._42 = mat._43 = 0.0f;
  162. mat._44 = 1.0f;
  163. }
  164. //-----------------------------------------------------------------------------
  165. // Name: D3DMath_QuaternionFromMatrix()
  166. // Desc: Converts a rotation matrix into a unit quaternion.
  167. //-----------------------------------------------------------------------------
  168. VOID D3DMath_QuaternionFromMatrix(FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
  169. D3DMATRIX& mat)
  170. {
  171. if (mat._11 + mat._22 + mat._33 > 0.0f)
  172. {
  173. FLOAT s = sqrtf(mat._11 + mat._22 + mat._33 + mat._44);
  174. x = (mat._23-mat._32) / (2*s);
  175. y = (mat._31-mat._13) / (2*s);
  176. z = (mat._12-mat._21) / (2*s);
  177. w = 0.5f * s;
  178. }
  179. else
  180. {
  181. }
  182. FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z;
  183. FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z;
  184. FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z;
  185. mat._11 = 1 - 2 * (yy + zz);
  186. mat._12 = 2 * (xy - wz);
  187. mat._13 = 2 * (xz + wy);
  188. mat._21 = 2 * (xy + wz);
  189. mat._22 = 1 - 2 * (xx + zz);
  190. mat._23 = 2 * (yz - wx);
  191. mat._31 = 2 * (xz - wy);
  192. mat._32 = 2 * (yz + wx);
  193. mat._33 = 1 - 2 * (xx + yy);
  194. mat._14 = mat._24 = mat._34 = 0.0f;
  195. mat._41 = mat._42 = mat._43 = 0.0f;
  196. mat._44 = 1.0f;
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Name: D3DMath_QuaternionMultiply()
  200. // Desc: Mulitples two quaternions together as in {Q} = {A} * {B}.
  201. //-----------------------------------------------------------------------------
  202. VOID D3DMath_QuaternionMultiply(FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
  203. FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
  204. FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw)
  205. {
  206. FLOAT Dx = Ax*Bw + Ay*Bz - Az*By + Aw*Bx;
  207. FLOAT Dy = -Ax*Bz + Ay*Bw + Az*Bx + Aw*By;
  208. FLOAT Dz = Ax*By - Ay*Bx + Az*Bw + Aw*Bz;
  209. FLOAT Dw = -Ax*Bx - Ay*By - Az*Bz + Aw*Bw;
  210. Qx = Dx; Qy = Dy; Qz = Dz; Qw = Dw;
  211. }
  212. //-----------------------------------------------------------------------------
  213. // Name: D3DMath_SlerpQuaternions()
  214. // Desc: Compute a quaternion which is the spherical linear interpolation
  215. // between two other quaternions by dvFraction.
  216. //-----------------------------------------------------------------------------
  217. VOID D3DMath_QuaternionSlerp(FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
  218. FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
  219. FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw,
  220. FLOAT fAlpha)
  221. {
  222. // Compute dot product (equal to cosine of the angle between quaternions)
  223. FLOAT fCosTheta = Ax*Bx + Ay*By + Az*Bz + Aw*Bw;
  224. // Check angle to see if quaternions are in opposite hemispheres
  225. if (fCosTheta < 0.0f)
  226. {
  227. // If so, flip one of the quaterions
  228. fCosTheta = -fCosTheta;
  229. Bx = -Bx; By = -By; Bz = -Bz; Bw = -Bw;
  230. }
  231. // Set factors to do linear interpolation, as a special case where the
  232. // quaternions are close together.
  233. FLOAT fBeta = 1.0f - fAlpha;
  234. // If the quaternions aren't close, proceed with spherical interpolation
  235. if (1.0f - fCosTheta > 0.001f)
  236. {
  237. FLOAT fTheta = acosf(fCosTheta);
  238. fBeta = sinf(fTheta*fBeta) / sinf(fTheta);
  239. fAlpha = sinf(fTheta*fAlpha) / sinf(fTheta);
  240. }
  241. // Do the interpolation
  242. Qx = fBeta*Ax + fAlpha*Bx;
  243. Qy = fBeta*Ay + fAlpha*By;
  244. Qz = fBeta*Az + fAlpha*Bz;
  245. Qw = fBeta*Aw + fAlpha*Bw;
  246. }