d3dmath.cpp
上传用户:cydong117
上传日期:2009-11-10
资源大小:638k
文件大小:11k
源码类别:

模拟服务器

开发平台:

Visual C++

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