#ifndef D3DX_IMPL_H #define D3DX_IMPL_H #include "togl/dx_iunknown.h" #include "tier0/dynfunction.h" #include "tier0/vprof_telemetry.h" #include "tier0/dbg.h" #include "tier0/threadtools.h" #include "tier0/vprof.h" #include "tier1/strtools.h" #include "tier1/utlbuffer.h" #include "tier1/utlvector.h" #include "mathlib/vmatrix.h" // ------------------------------------------------------------------------------------------------------------------------------ // // D3DX // ------------------------------------------------------------------------------------------------------------------------------ // class D3DXMATRIX; D3DXMATRIX* D3DXMatrixMultiply( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 ); class D3DXMATRIX : public D3DMATRIX { public: D3DXMATRIX operator*( const D3DXMATRIX &o ) const { D3DXMATRIX result; D3DXMatrixMultiply( &result, this, &o ); // this = lhs o = rhs result = this * o return result; } operator FLOAT* () { return (float*)this; } float& operator()( int row, int column ) { return m[row][column]; } const float& operator()( int row, int column ) const { return m[row][column]; } bool operator != ( CONST D3DXMATRIX& src ) const { return V_memcmp( (void*)this, (void*)&src, sizeof(this) ) != 0; } }; typedef struct D3DXPLANE { float& operator[]( int i ) { return ((float*)this)[i]; } bool operator==( const D3DXPLANE &o ) { return a == o.a && b == o.b && c == o.c && d == o.d; } bool operator!=( const D3DXPLANE &o ) { return !( *this == o ); } operator float*() { return (float*)this; } operator const float*() const { return (const float*)this; } float a, b, c, d; } D3DXPLANE; class D3DXVECTOR2 { public: operator FLOAT* () { return (float*)this; } operator CONST FLOAT* () const { return (const float*)this; } float x, y; }; class D3DXVECTOR3 : public D3DVECTOR { public: D3DXVECTOR3() {} D3DXVECTOR3( float a, float b, float c ) { x = a; y = b; z = c; } operator FLOAT* () { return (float*)this; } operator CONST FLOAT* () const { return (const float*)this; } }; typedef enum _D3DXINCLUDE_TYPE { D3DXINC_LOCAL, // force 32-bit size enum D3DXINC_FORCE_DWORD = 0x7fffffff } D3DXINCLUDE_TYPE; class D3DXVECTOR4 { public: D3DXVECTOR4() {} D3DXVECTOR4( float a, float b, float c, float d ) { x = a; y = b; z = c; w = d; } float x,y,z,w; }; //---------------------------------------------------------------------------- // D3DXMACRO: // ---------- // Preprocessor macro definition. The application pass in a NULL-terminated // array of this structure to various D3DX APIs. This enables the application // to #define tokens at runtime, before the file is parsed. //---------------------------------------------------------------------------- typedef struct _D3DXMACRO { LPCSTR Name; LPCSTR Definition; } D3DXMACRO, *LPD3DXMACRO; #define D3DXINLINE inline #define D3DXSHADER_DEBUG (1 << 0) #define D3DXSHADER_AVOID_FLOW_CONTROL (1 << 9) typedef class CUtlMemory CD3DMATRIXAllocator; typedef class CUtlVector CD3DMATRIXStack; inline void D3DXMatrixIdentity(D3DXMATRIX* mat) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { mat->m[i][j] = (i == j) ? 1.0f : 0.0f; // 1's on the diagonal. } } } struct ID3DXMatrixStack //: public CUnknown { int m_refcount[2]; CD3DMATRIXStack m_stack; int m_stackTop; // top of stack is at the highest index, this is that index. push increases, pop decreases. ID3DXMatrixStack( void ) { m_refcount[0] = 1; m_refcount[1] = 0; }; inline void AddRef( int which = 0, char *comment = NULL ) { m_refcount[which]++; }; inline ULONG Release( int which = 0 , char *comment = NULL ) { bool deleting = false; m_refcount[which]--; if ( (!m_refcount[0]) && (!m_refcount[1]) ) { deleting = true; } if (deleting) { delete this; return 0; } else { return m_refcount[0]; } }; inline HRESULT Create() { m_stack.EnsureCapacity( 16 ); // 1KB ish m_stack.AddToTail(); m_stackTop = 0; // top of stack is at index 0 currently LoadIdentity(); return S_OK; } inline D3DXMATRIX* GetTop() { return (D3DXMATRIX*)&m_stack[ m_stackTop ]; } inline void Push() { D3DMATRIX temp = m_stack[ m_stackTop ]; m_stack.AddToTail( temp ); m_stackTop ++; } inline void Pop() { int elem = m_stackTop--; m_stack.Remove( elem ); } inline void LoadIdentity() { D3DXMATRIX *mat = GetTop(); D3DXMatrixIdentity( mat ); } inline void LoadMatrix( const D3DXMATRIX *pMat ) { *(GetTop()) = *pMat; } inline void MultMatrix( const D3DXMATRIX *pMat ) { // http://msdn.microsoft.com/en-us/library/bb174057(VS.85).aspx // This method right-multiplies the given matrix to the current matrix // (transformation is about the current world origin). // m_pstack[m_currentPos] = m_pstack[m_currentPos] * (*pMat); // This method does not add an item to the stack, it replaces the current // matrix with the product of the current matrix and the given matrix. DXABSTRACT_BREAK_ON_ERROR(); } inline void MultMatrixLocal( const D3DXMATRIX *pMat ) { // http://msdn.microsoft.com/en-us/library/bb174058(VS.85).aspx // This method left-multiplies the given matrix to the current matrix // (transformation is about the local origin of the object). // m_pstack[m_currentPos] = (*pMat) * m_pstack[m_currentPos]; // This method does not add an item to the stack, it replaces the current // matrix with the product of the given matrix and the current matrix. DXABSTRACT_BREAK_ON_ERROR(); } inline HRESULT ScaleLocal(FLOAT x, FLOAT y, FLOAT z) { // http://msdn.microsoft.com/en-us/library/bb174066(VS.85).aspx // Scale the current matrix about the object origin. // This method left-multiplies the current matrix with the computed // scale matrix. The transformation is about the local origin of the object. // // D3DXMATRIX tmp; // D3DXMatrixScaling(&tmp, x, y, z); // m_stack[m_currentPos] = tmp * m_stack[m_currentPos]; DXABSTRACT_BREAK_ON_ERROR(); return S_OK; } inline HRESULT RotateAxisLocal(CONST D3DXVECTOR3* pV, FLOAT Angle) { // http://msdn.microsoft.com/en-us/library/bb174062(VS.85).aspx // Left multiply the current matrix with the computed rotation // matrix, counterclockwise about the given axis with the given angle. // (rotation is about the local origin of the object) // D3DXMATRIX tmp; // D3DXMatrixRotationAxis( &tmp, pV, angle ); // m_stack[m_currentPos] = tmp * m_stack[m_currentPos]; // Because the rotation is left-multiplied to the matrix stack, the rotation // is relative to the object's local coordinate space. DXABSTRACT_BREAK_ON_ERROR(); return S_OK; } inline HRESULT TranslateLocal(FLOAT x, FLOAT y, FLOAT z) { // http://msdn.microsoft.com/en-us/library/bb174068(VS.85).aspx // Left multiply the current matrix with the computed translation // matrix. (transformation is about the local origin of the object) // D3DXMATRIX tmp; // D3DXMatrixTranslation( &tmp, x, y, z ); // m_stack[m_currentPos] = tmp * m_stack[m_currentPos]; DXABSTRACT_BREAK_ON_ERROR(); return S_OK; } }; typedef ID3DXMatrixStack* LPD3DXMATRIXSTACK; #if _WIN32 DECLARE_INTERFACE( ID3DXInclude ) { STDMETHOD( Open )( THIS_ D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID * ppData, UINT * pBytes ) PURE; STDMETHOD( Close )( THIS_ LPCVOID pData ) PURE; }; typedef ID3DXInclude* LPD3DXINCLUDE; DECLARE_INTERFACE_( ID3DXBuffer, IUnknown ) { // IUnknown STDMETHOD( QueryInterface )( THIS_ REFIID iid, LPVOID * ppv ) PURE; STDMETHOD_( ULONG, AddRef )( THIS ) PURE; STDMETHOD_( ULONG, Release )( THIS ) PURE; // ID3DXBuffer STDMETHOD_( LPVOID, GetBufferPointer )( THIS ) PURE; STDMETHOD_( DWORD, GetBufferSize )( THIS ) PURE; }; typedef ID3DXBuffer* LPD3DXBUFFER; #else struct ID3DXInclude { virtual HRESULT Open(D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes); virtual HRESULT Close(LPCVOID pData); }; typedef ID3DXInclude* LPD3DXINCLUDE; struct ID3DXBuffer : public CUnknown { inline void* GetBufferPointer() { DXABSTRACT_BREAK_ON_ERROR(); return NULL; } inline DWORD GetBufferSize() { DXABSTRACT_BREAK_ON_ERROR(); return 0; } }; typedef ID3DXBuffer* LPD3DXBUFFER; #endif class ID3DXConstantTable : public CUnknown { }; typedef ID3DXConstantTable* LPD3DXCONSTANTTABLE; inline const char* D3DXGetPixelShaderProfile(IDirect3DDevice9* pDevice) { DXABSTRACT_BREAK_ON_ERROR(); return ""; } inline D3DXMATRIX* D3DXMatrixMultiply( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 ) { D3DXMATRIX temp; for( int i=0; i<4; i++) { for( int j=0; j<4; j++) { temp.m[i][j] = (pM1->m[ i ][ 0 ] * pM2->m[ 0 ][ j ]) + (pM1->m[ i ][ 1 ] * pM2->m[ 1 ][ j ]) + (pM1->m[ i ][ 2 ] * pM2->m[ 2 ][ j ]) + (pM1->m[ i ][ 3 ] * pM2->m[ 3 ][ j ]); } } *pOut = temp; return pOut; } // Transform a 3D vector by a given matrix, projecting the result back into w = 1 // http://msdn.microsoft.com/en-us/library/ee417622(VS.85).aspx inline D3DXVECTOR3* D3DXVec3TransformCoord(D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM) { D3DXVECTOR3 vOut; vOut.x = vOut.y = vOut.z = 0.0f; float norm = (pM->m[0][3] * pV->x) + (pM->m[1][3] * pV->y) + (pM->m[2][3] *pV->z) + pM->m[3][3]; if ( norm ) { vOut.x = (pM->m[0][0] * pV->x + pM->m[1][0] * pV->y + pM->m[2][0] * pV->z + pM->m[3][0]) / norm; vOut.y = (pM->m[0][1] * pV->x + pM->m[1][1] * pV->y + pM->m[2][1] * pV->z + pM->m[3][1]) / norm; vOut.z = (pM->m[0][2] * pV->x + pM->m[1][2] * pV->y + pM->m[2][2] * pV->z + pM->m[3][2]) / norm; } *pOut = vOut; return pOut; } inline HRESULT D3DXCreateMatrixStack( DWORD Flags, LPD3DXMATRIXSTACK* ppStack) { *ppStack = new ID3DXMatrixStack; (*ppStack)->Create(); return S_OK; } inline D3DXVECTOR3* D3DXVec3Subtract( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) { pOut->x = pV1->x - pV2->x; pOut->y = pV1->y - pV2->y; pOut->z = pV1->z - pV2->z; return pOut; } inline D3DXVECTOR3* D3DXVec3Cross( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) { D3DXVECTOR3 v; v.x = pV1->y * pV2->z - pV1->z * pV2->y; v.y = pV1->z * pV2->x - pV1->x * pV2->z; v.z = pV1->x * pV2->y - pV1->y * pV2->x; *pOut = v; return pOut; } inline FLOAT D3DXVec3Dot( CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) { return pV1->x * pV2->x + pV1->y * pV2->y + pV1->z * pV2->z; } inline D3DXMATRIX* D3DXMatrixInverse( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM ) { Assert( sizeof( D3DXMATRIX ) == (16 * sizeof(float) ) ); Assert( sizeof( VMatrix ) == (16 * sizeof(float) ) ); Assert( pDeterminant == NULL ); // homey don't play that VMatrix *origM = (VMatrix*)pM; VMatrix *destM = (VMatrix*)pOut; bool success = MatrixInverseGeneral( *origM, *destM ); (void)success; Assert( success ); return pOut; } inline D3DXMATRIX* D3DXMatrixTranspose( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM ) { if (pOut != pM) { for( int i=0; i<4; i++) { for( int j=0; j<4; j++) { pOut->m[i][j] = pM->m[j][i]; } } } else { D3DXMATRIX temp = *pM; D3DXMatrixTranspose( pOut, &temp ); } return NULL; } inline D3DXPLANE* D3DXPlaneNormalize( D3DXPLANE *pOut, CONST D3DXPLANE *pP) { // not very different from normalizing a vector. // figure out the square root of the sum-of-squares of the x,y,z components // make sure that's non zero // then divide all four components by that value // or return some dummy plane like 0,0,1,0 if it fails float len = sqrt( (pP->a * pP->a) + (pP->b * pP->b) + (pP->c * pP->c) ); if (len > 1e-10) //FIXME need a real epsilon here ? { pOut->a = pP->a / len; pOut->b = pP->b / len; pOut->c = pP->c / len; pOut->d = pP->d / len; } else { pOut->a = 0.0f; pOut->b = 0.0f; pOut->c = 1.0f; pOut->d = 0.0f; } return pOut; } inline D3DXVECTOR4* D3DXVec4Transform( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, CONST D3DXMATRIX *pM ) { VMatrix *mat = (VMatrix*)pM; Vector4D *vIn = (Vector4D*)pV; Vector4D *vOut = (Vector4D*)pOut; Vector4DMultiplyTranspose( *mat, *vIn, *vOut ); return pOut; } inline D3DXVECTOR4* D3DXVec4Normalize( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV ) { Vector4D *vIn = (Vector4D*) pV; Vector4D *vOut = (Vector4D*) pOut; *vOut = *vIn; Vector4DNormalize( *vOut ); return pOut; } inline D3DXMATRIX* D3DXMatrixTranslation( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z ) { D3DXMatrixIdentity( pOut ); pOut->m[3][0] = x; pOut->m[3][1] = y; pOut->m[3][2] = z; return pOut; } // Build an ortho projection matrix. (right-handed) inline D3DXMATRIX* D3DXMatrixOrthoOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn,FLOAT zf ) { DXABSTRACT_BREAK_ON_ERROR(); return NULL; } inline D3DXMATRIX* D3DXMatrixPerspectiveRH( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ) { DXABSTRACT_BREAK_ON_ERROR(); return NULL; } inline D3DXMATRIX* D3DXMatrixPerspectiveOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf ) { DXABSTRACT_BREAK_ON_ERROR(); return NULL; } // Transform a plane by a matrix. The vector (a,b,c) must be normal. // M should be the inverse transpose of the transformation desired. inline D3DXPLANE* D3DXPlaneTransform( D3DXPLANE *pOut, CONST D3DXPLANE *pP, CONST D3DXMATRIX *pM ) { float *out = &pOut->a; // dot dot dot for( int x=0; x<4; x++ ) { out[x] = (pM->m[0][x] * pP->a) + (pM->m[1][x] * pP->b) + (pM->m[2][x] * pP->c) + (pM->m[3][x] * pP->d); } return pOut; } inline HRESULT D3DXCompileShader( LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable) { DXABSTRACT_BREAK_ON_ERROR(); // is anyone calling this ? return S_OK; } inline DWORD D3DXGetShaderVersion(const DWORD *byte_code) { return byte_code ? *byte_code : 0; } #endif