aboutsummaryrefslogtreecommitdiff
path: root/samples/DX_APIUsage/DXUT/Optional/SDKmesh.cpp
diff options
context:
space:
mode:
authorDave Clark <[email protected]>2018-02-28 17:22:22 -0500
committerDave Clark <[email protected]>2018-02-28 17:22:22 -0500
commit25528fd230f5f4298c35123a833cdb112675808e (patch)
treef5aca3f5ee5a7734df41e7b974a04c37ddff528e /samples/DX_APIUsage/DXUT/Optional/SDKmesh.cpp
parentPush GfeSDK #173 (diff)
downloadgfesdk-25528fd230f5f4298c35123a833cdb112675808e.tar.xz
gfesdk-25528fd230f5f4298c35123a833cdb112675808e.zip
Push SDK # 1.1.186
Documentation updates.
Diffstat (limited to 'samples/DX_APIUsage/DXUT/Optional/SDKmesh.cpp')
-rw-r--r--samples/DX_APIUsage/DXUT/Optional/SDKmesh.cpp2349
1 files changed, 2349 insertions, 0 deletions
diff --git a/samples/DX_APIUsage/DXUT/Optional/SDKmesh.cpp b/samples/DX_APIUsage/DXUT/Optional/SDKmesh.cpp
new file mode 100644
index 0000000..5002d74
--- /dev/null
+++ b/samples/DX_APIUsage/DXUT/Optional/SDKmesh.cpp
@@ -0,0 +1,2349 @@
+//--------------------------------------------------------------------------------------
+// File: SDKMesh.cpp
+//
+// The SDK Mesh format (.sdkmesh) is not a recommended file format for games.
+// It was designed to meet the specific needs of the SDK samples. Any real-world
+// applications should avoid this file format in favor of a destination format that
+// meets the specific needs of the application.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//--------------------------------------------------------------------------------------
+#include "DXUT.h"
+#include "SDKMesh.h"
+#include "SDKMisc.h"
+
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::LoadMaterials( ID3D11Device* pd3dDevice, SDKMESH_MATERIAL* pMaterials, UINT numMaterials,
+ SDKMESH_CALLBACKS11* pLoaderCallbacks )
+{
+ char strPath[MAX_PATH];
+
+ if( pLoaderCallbacks && pLoaderCallbacks->pCreateTextureFromFile )
+ {
+ for( UINT m = 0; m < numMaterials; m++ )
+ {
+ pMaterials[m].pDiffuseTexture11 = NULL;
+ pMaterials[m].pNormalTexture11 = NULL;
+ pMaterials[m].pSpecularTexture11 = NULL;
+ pMaterials[m].pDiffuseRV11 = NULL;
+ pMaterials[m].pNormalRV11 = NULL;
+ pMaterials[m].pSpecularRV11 = NULL;
+
+ // load textures
+ if( pMaterials[m].DiffuseTexture[0] != 0 )
+ {
+ pLoaderCallbacks->pCreateTextureFromFile( pd3dDevice,
+ pMaterials[m].DiffuseTexture, &pMaterials[m].pDiffuseRV11,
+ pLoaderCallbacks->pContext );
+ }
+ if( pMaterials[m].NormalTexture[0] != 0 )
+ {
+ pLoaderCallbacks->pCreateTextureFromFile( pd3dDevice,
+ pMaterials[m].NormalTexture, &pMaterials[m].pNormalRV11,
+ pLoaderCallbacks->pContext );
+ }
+ if( pMaterials[m].SpecularTexture[0] != 0 )
+ {
+ pLoaderCallbacks->pCreateTextureFromFile( pd3dDevice,
+ pMaterials[m].SpecularTexture, &pMaterials[m].pSpecularRV11,
+ pLoaderCallbacks->pContext );
+ }
+ }
+ }
+ else
+ {
+ for( UINT m = 0; m < numMaterials; m++ )
+ {
+ pMaterials[m].pDiffuseTexture11 = NULL;
+ pMaterials[m].pNormalTexture11 = NULL;
+ pMaterials[m].pSpecularTexture11 = NULL;
+ pMaterials[m].pDiffuseRV11 = NULL;
+ pMaterials[m].pNormalRV11 = NULL;
+ pMaterials[m].pSpecularRV11 = NULL;
+
+ // load textures
+ if( pMaterials[m].DiffuseTexture[0] != 0 )
+ {
+ sprintf_s( strPath, MAX_PATH, "%s%s", m_strPath, pMaterials[m].DiffuseTexture );
+ if( FAILED( DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice, DXUTGetD3D11DeviceContext(),
+ strPath, &pMaterials[m].pDiffuseRV11,
+ true ) ) )
+ pMaterials[m].pDiffuseRV11 = ( ID3D11ShaderResourceView* )ERROR_RESOURCE_VALUE;
+
+ }
+ if( pMaterials[m].NormalTexture[0] != 0 )
+ {
+ sprintf_s( strPath, MAX_PATH, "%s%s", m_strPath, pMaterials[m].NormalTexture );
+ if( FAILED( DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice, DXUTGetD3D11DeviceContext(),
+ strPath,
+ &pMaterials[m].pNormalRV11 ) ) )
+ pMaterials[m].pNormalRV11 = ( ID3D11ShaderResourceView* )ERROR_RESOURCE_VALUE;
+ }
+ if( pMaterials[m].SpecularTexture[0] != 0 )
+ {
+ sprintf_s( strPath, MAX_PATH, "%s%s", m_strPath, pMaterials[m].SpecularTexture );
+ if( FAILED( DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice, DXUTGetD3D11DeviceContext(),
+ strPath,
+ &pMaterials[m].pSpecularRV11 ) ) )
+ pMaterials[m].pSpecularRV11 = ( ID3D11ShaderResourceView* )ERROR_RESOURCE_VALUE;
+ }
+ }
+ }
+}
+
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::LoadMaterials( IDirect3DDevice9* pd3dDevice, SDKMESH_MATERIAL* pMaterials, UINT numMaterials,
+ SDKMESH_CALLBACKS9* pLoaderCallbacks )
+{
+ char strPath[MAX_PATH];
+
+ if( pLoaderCallbacks && pLoaderCallbacks->pCreateTextureFromFile )
+ {
+ for( UINT m = 0; m < numMaterials; m++ )
+ {
+ pMaterials[m].pDiffuseTexture9 = NULL;
+ pMaterials[m].pNormalTexture9 = NULL;
+ pMaterials[m].pSpecularTexture9 = NULL;
+
+ // load textures
+ if( pMaterials[m].DiffuseTexture[0] != 0 )
+ {
+ pLoaderCallbacks->pCreateTextureFromFile( pd3dDevice,
+ pMaterials[m].DiffuseTexture,
+ &pMaterials[m].pDiffuseTexture9,
+ pLoaderCallbacks->pContext );
+ }
+ if( pMaterials[m].NormalTexture[0] != 0 )
+ {
+ pLoaderCallbacks->pCreateTextureFromFile( pd3dDevice,
+ pMaterials[m].NormalTexture, &pMaterials[m].pNormalTexture9,
+ pLoaderCallbacks->pContext );
+ }
+ if( pMaterials[m].SpecularTexture[0] != 0 )
+ {
+ pLoaderCallbacks->pCreateTextureFromFile( pd3dDevice,
+ pMaterials[m].SpecularTexture,
+ &pMaterials[m].pSpecularTexture9,
+ pLoaderCallbacks->pContext );
+ }
+ }
+ }
+ else
+ {
+ for( UINT m = 0; m < numMaterials; m++ )
+ {
+ pMaterials[m].pDiffuseTexture9 = NULL;
+ pMaterials[m].pNormalTexture9 = NULL;
+ pMaterials[m].pSpecularTexture9 = NULL;
+ pMaterials[m].pDiffuseRV11 = NULL;
+ pMaterials[m].pNormalRV11 = NULL;
+ pMaterials[m].pSpecularRV11 = NULL;
+
+ // load textures
+ if( pMaterials[m].DiffuseTexture[0] != 0 )
+ {
+ sprintf_s( strPath, MAX_PATH, "%s%s", m_strPath, pMaterials[m].DiffuseTexture );
+ if( FAILED( DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice,
+ strPath,
+ &pMaterials[m].pDiffuseTexture9 ) ) )
+ pMaterials[m].pDiffuseTexture9 = ( IDirect3DTexture9* )ERROR_RESOURCE_VALUE;
+ }
+ if( pMaterials[m].NormalTexture[0] != 0 )
+ {
+ sprintf_s( strPath, MAX_PATH, "%s%s", m_strPath, pMaterials[m].NormalTexture );
+ if( FAILED( DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice,
+ strPath,
+ &pMaterials[m].pNormalTexture9 ) ) )
+ pMaterials[m].pNormalTexture9 = ( IDirect3DTexture9* )ERROR_RESOURCE_VALUE;
+ }
+ if( pMaterials[m].SpecularTexture[0] != 0 )
+ {
+ sprintf_s( strPath, MAX_PATH, "%s%s", m_strPath, pMaterials[m].SpecularTexture );
+ if( FAILED( DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice,
+ strPath,
+ &pMaterials[m].pSpecularTexture9 ) ) )
+ pMaterials[m].pSpecularTexture9 = ( IDirect3DTexture9* )ERROR_RESOURCE_VALUE;
+ }
+
+ }
+ }
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTSDKMesh::CreateVertexBuffer( ID3D11Device* pd3dDevice, SDKMESH_VERTEX_BUFFER_HEADER* pHeader,
+ void* pVertices, SDKMESH_CALLBACKS11* pLoaderCallbacks )
+{
+ HRESULT hr = S_OK;
+ pHeader->DataOffset = 0;
+ //Vertex Buffer
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = ( UINT )( pHeader->SizeBytes );
+ bufferDesc.Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+
+ if( pLoaderCallbacks && pLoaderCallbacks->pCreateVertexBuffer )
+ {
+ pLoaderCallbacks->pCreateVertexBuffer( pd3dDevice, &pHeader->pVB11, bufferDesc, pVertices,
+ pLoaderCallbacks->pContext );
+ }
+ else
+ {
+ D3D11_SUBRESOURCE_DATA InitData;
+ InitData.pSysMem = pVertices;
+ hr = pd3dDevice->CreateBuffer( &bufferDesc, &InitData, &pHeader->pVB11 );
+ DXUT_SetDebugName( pHeader->pVB11, "CDXUTSDKMesh" );
+ }
+
+ return hr;
+}
+
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTSDKMesh::CreateIndexBuffer( ID3D11Device* pd3dDevice, SDKMESH_INDEX_BUFFER_HEADER* pHeader,
+ void* pIndices, SDKMESH_CALLBACKS11* pLoaderCallbacks )
+{
+ HRESULT hr = S_OK;
+ pHeader->DataOffset = 0;
+ //Index Buffer
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = ( UINT )( pHeader->SizeBytes );
+ bufferDesc.Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+
+ if( pLoaderCallbacks && pLoaderCallbacks->pCreateIndexBuffer )
+ {
+ pLoaderCallbacks->pCreateIndexBuffer( pd3dDevice, &pHeader->pIB11, bufferDesc, pIndices,
+ pLoaderCallbacks->pContext );
+ }
+ else
+ {
+ D3D11_SUBRESOURCE_DATA InitData;
+ InitData.pSysMem = pIndices;
+ hr = pd3dDevice->CreateBuffer( &bufferDesc, &InitData, &pHeader->pIB11 );
+ DXUT_SetDebugName( pHeader->pIB11, "CDXUTSDKMesh" );
+ }
+
+ return hr;
+}
+
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTSDKMesh::CreateVertexBuffer( IDirect3DDevice9* pd3dDevice, SDKMESH_VERTEX_BUFFER_HEADER* pHeader,
+ void* pVertices, SDKMESH_CALLBACKS9* pLoaderCallbacks )
+{
+ HRESULT hr = S_OK;
+
+ pHeader->DataOffset = 0;
+ if( pLoaderCallbacks && pLoaderCallbacks->pCreateVertexBuffer )
+ {
+ pLoaderCallbacks->pCreateVertexBuffer( pd3dDevice, &pHeader->pVB9, ( UINT )pHeader->SizeBytes,
+ D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, pVertices,
+ pLoaderCallbacks->pContext );
+ }
+ else
+ {
+ hr = pd3dDevice->CreateVertexBuffer( ( UINT )pHeader->SizeBytes,
+ D3DUSAGE_WRITEONLY,
+ 0,
+ D3DPOOL_DEFAULT,
+ &pHeader->pVB9,
+ NULL );
+
+ //lock
+ if( SUCCEEDED( hr ) )
+ {
+ void* pLockedVerts = NULL;
+ V_RETURN( pHeader->pVB9->Lock( 0, 0, &pLockedVerts, 0 ) );
+ CopyMemory( pLockedVerts, pVertices, ( size_t )pHeader->SizeBytes );
+ pHeader->pVB9->Unlock();
+ }
+ }
+
+ return hr;
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTSDKMesh::CreateIndexBuffer( IDirect3DDevice9* pd3dDevice, SDKMESH_INDEX_BUFFER_HEADER* pHeader,
+ void* pIndices, SDKMESH_CALLBACKS9* pLoaderCallbacks )
+{
+ HRESULT hr = S_OK;
+
+ pHeader->DataOffset = 0;
+
+ D3DFORMAT ibFormat = D3DFMT_INDEX16;
+ switch( pHeader->IndexType )
+ {
+ case IT_16BIT:
+ ibFormat = D3DFMT_INDEX16;
+ break;
+ case IT_32BIT:
+ ibFormat = D3DFMT_INDEX32;
+ break;
+ };
+
+ if( pLoaderCallbacks && pLoaderCallbacks->pCreateIndexBuffer )
+ {
+ pLoaderCallbacks->pCreateIndexBuffer( pd3dDevice, &pHeader->pIB9, ( UINT )pHeader->SizeBytes,
+ D3DUSAGE_WRITEONLY, ibFormat, D3DPOOL_DEFAULT, pIndices,
+ pLoaderCallbacks->pContext );
+ }
+ else
+ {
+ hr = pd3dDevice->CreateIndexBuffer( ( UINT )( pHeader->SizeBytes ),
+ D3DUSAGE_WRITEONLY,
+ ibFormat,
+ D3DPOOL_DEFAULT,
+ &pHeader->pIB9,
+ NULL );
+
+ if( SUCCEEDED( hr ) )
+ {
+ void* pLockedIndices = NULL;
+ V_RETURN( pHeader->pIB9->Lock( 0, 0, &pLockedIndices, 0 ) );
+ CopyMemory( pLockedIndices, pIndices, ( size_t )( pHeader->SizeBytes ) );
+ pHeader->pIB9->Unlock();
+ }
+ }
+
+ return hr;
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTSDKMesh::CreateFromFile( ID3D11Device* pDev11,
+ IDirect3DDevice9* pDev9,
+ LPCTSTR szFileName,
+ bool bCreateAdjacencyIndices,
+ SDKMESH_CALLBACKS11* pLoaderCallbacks11,
+ SDKMESH_CALLBACKS9* pLoaderCallbacks9 )
+{
+ HRESULT hr = S_OK;
+
+ // Find the path for the file
+ V_RETURN( DXUTFindDXSDKMediaFileCch( m_strPathW, sizeof( m_strPathW ) / sizeof( WCHAR ), szFileName ) );
+
+ // Open the file
+ m_hFile = CreateFile( m_strPathW, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,
+ NULL );
+ if( INVALID_HANDLE_VALUE == m_hFile )
+ return DXUTERR_MEDIANOTFOUND;
+
+ // Change the path to just the directory
+ WCHAR* pLastBSlash = wcsrchr( m_strPathW, L'\\' );
+ if( pLastBSlash )
+ *( pLastBSlash + 1 ) = L'\0';
+ else
+ *m_strPathW = L'\0';
+
+ WideCharToMultiByte( CP_ACP, 0, m_strPathW, -1, m_strPath, MAX_PATH, NULL, FALSE );
+
+ // Get the file size
+ LARGE_INTEGER FileSize;
+ GetFileSizeEx( m_hFile, &FileSize );
+ UINT cBytes = FileSize.LowPart;
+
+ // Allocate memory
+ m_pStaticMeshData = new BYTE[ cBytes ];
+ if( !m_pStaticMeshData )
+ {
+ CloseHandle( m_hFile );
+ return E_OUTOFMEMORY;
+ }
+
+ // Read in the file
+ DWORD dwBytesRead;
+ if( !ReadFile( m_hFile, m_pStaticMeshData, cBytes, &dwBytesRead, NULL ) )
+ hr = E_FAIL;
+
+ CloseHandle( m_hFile );
+
+ if( SUCCEEDED( hr ) )
+ {
+ hr = CreateFromMemory( pDev11,
+ pDev9,
+ m_pStaticMeshData,
+ cBytes,
+ bCreateAdjacencyIndices,
+ false,
+ pLoaderCallbacks11,
+ pLoaderCallbacks9 );
+ if( FAILED( hr ) )
+ delete []m_pStaticMeshData;
+ }
+
+ return hr;
+}
+
+HRESULT CDXUTSDKMesh::CreateFromMemory( ID3D11Device* pDev11,
+ IDirect3DDevice9* pDev9,
+ BYTE* pData,
+ UINT DataBytes,
+ bool bCreateAdjacencyIndices,
+ bool bCopyStatic,
+ SDKMESH_CALLBACKS11* pLoaderCallbacks11,
+ SDKMESH_CALLBACKS9* pLoaderCallbacks9 )
+{
+ HRESULT hr = E_FAIL;
+ D3DXVECTOR3 lower;
+ D3DXVECTOR3 upper;
+
+ m_pDev9 = pDev9;
+ m_pDev11 = pDev11;
+
+ // Set outstanding resources to zero
+ m_NumOutstandingResources = 0;
+
+ if( bCopyStatic )
+ {
+ SDKMESH_HEADER* pHeader = ( SDKMESH_HEADER* )pData;
+
+ SIZE_T StaticSize = ( SIZE_T )( pHeader->HeaderSize + pHeader->NonBufferDataSize );
+ m_pHeapData = new BYTE[ StaticSize ];
+ if( !m_pHeapData )
+ return hr;
+
+ m_pStaticMeshData = m_pHeapData;
+
+ CopyMemory( m_pStaticMeshData, pData, StaticSize );
+ }
+ else
+ {
+ m_pHeapData = pData;
+ m_pStaticMeshData = pData;
+ }
+
+ // Pointer fixup
+ m_pMeshHeader = ( SDKMESH_HEADER* )m_pStaticMeshData;
+ m_pVertexBufferArray = ( SDKMESH_VERTEX_BUFFER_HEADER* )( m_pStaticMeshData +
+ m_pMeshHeader->VertexStreamHeadersOffset );
+ m_pIndexBufferArray = ( SDKMESH_INDEX_BUFFER_HEADER* )( m_pStaticMeshData +
+ m_pMeshHeader->IndexStreamHeadersOffset );
+ m_pMeshArray = ( SDKMESH_MESH* )( m_pStaticMeshData + m_pMeshHeader->MeshDataOffset );
+ m_pSubsetArray = ( SDKMESH_SUBSET* )( m_pStaticMeshData + m_pMeshHeader->SubsetDataOffset );
+ m_pFrameArray = ( SDKMESH_FRAME* )( m_pStaticMeshData + m_pMeshHeader->FrameDataOffset );
+ m_pMaterialArray = ( SDKMESH_MATERIAL* )( m_pStaticMeshData + m_pMeshHeader->MaterialDataOffset );
+
+ // Setup subsets
+ for( UINT i = 0; i < m_pMeshHeader->NumMeshes; i++ )
+ {
+ m_pMeshArray[i].pSubsets = ( UINT* )( m_pStaticMeshData + m_pMeshArray[i].SubsetOffset );
+ m_pMeshArray[i].pFrameInfluences = ( UINT* )( m_pStaticMeshData + m_pMeshArray[i].FrameInfluenceOffset );
+ }
+
+ // error condition
+ if( m_pMeshHeader->Version != SDKMESH_FILE_VERSION )
+ {
+ hr = E_NOINTERFACE;
+ goto Error;
+ }
+
+ // Setup buffer data pointer
+ BYTE* pBufferData = pData + m_pMeshHeader->HeaderSize + m_pMeshHeader->NonBufferDataSize;
+
+ // Get the start of the buffer data
+ UINT64 BufferDataStart = m_pMeshHeader->HeaderSize + m_pMeshHeader->NonBufferDataSize;
+
+ // Create VBs
+ m_ppVertices = new BYTE*[m_pMeshHeader->NumVertexBuffers];
+ for( UINT i = 0; i < m_pMeshHeader->NumVertexBuffers; i++ )
+ {
+ BYTE* pVertices = NULL;
+ pVertices = ( BYTE* )( pBufferData + ( m_pVertexBufferArray[i].DataOffset - BufferDataStart ) );
+
+ if( pDev11 )
+ CreateVertexBuffer( pDev11, &m_pVertexBufferArray[i], pVertices, pLoaderCallbacks11 );
+ else if( pDev9 )
+ CreateVertexBuffer( pDev9, &m_pVertexBufferArray[i], pVertices, pLoaderCallbacks9 );
+
+ m_ppVertices[i] = pVertices;
+ }
+
+ // Create IBs
+ m_ppIndices = new BYTE*[m_pMeshHeader->NumIndexBuffers];
+ for( UINT i = 0; i < m_pMeshHeader->NumIndexBuffers; i++ )
+ {
+ BYTE* pIndices = NULL;
+ pIndices = ( BYTE* )( pBufferData + ( m_pIndexBufferArray[i].DataOffset - BufferDataStart ) );
+
+ if( pDev11 )
+ CreateIndexBuffer( pDev11, &m_pIndexBufferArray[i], pIndices, pLoaderCallbacks11 );
+ else if( pDev9 )
+ CreateIndexBuffer( pDev9, &m_pIndexBufferArray[i], pIndices, pLoaderCallbacks9 );
+
+ m_ppIndices[i] = pIndices;
+ }
+
+ // Load Materials
+ if( pDev11 )
+ LoadMaterials( pDev11, m_pMaterialArray, m_pMeshHeader->NumMaterials, pLoaderCallbacks11 );
+ else if( pDev9 )
+ LoadMaterials( pDev9, m_pMaterialArray, m_pMeshHeader->NumMaterials, pLoaderCallbacks9 );
+
+ // Create a place to store our bind pose frame matrices
+ m_pBindPoseFrameMatrices = new D3DXMATRIX[ m_pMeshHeader->NumFrames ];
+ if( !m_pBindPoseFrameMatrices )
+ goto Error;
+
+ // Create a place to store our transformed frame matrices
+ m_pTransformedFrameMatrices = new D3DXMATRIX[ m_pMeshHeader->NumFrames ];
+ if( !m_pTransformedFrameMatrices )
+ goto Error;
+ m_pWorldPoseFrameMatrices = new D3DXMATRIX[ m_pMeshHeader->NumFrames ];
+ if( !m_pWorldPoseFrameMatrices )
+ goto Error;
+
+ SDKMESH_SUBSET* pSubset = NULL;
+ D3D11_PRIMITIVE_TOPOLOGY PrimType;
+
+ // update bounding volume
+ SDKMESH_MESH* currentMesh = &m_pMeshArray[0];
+ int tris = 0;
+ for (UINT meshi=0; meshi < m_pMeshHeader->NumMeshes; ++meshi) {
+ lower.x = FLT_MAX; lower.y = FLT_MAX; lower.z = FLT_MAX;
+ upper.x = -FLT_MAX; upper.y = -FLT_MAX; upper.z = -FLT_MAX;
+ currentMesh = GetMesh( meshi );
+ INT indsize;
+ if (m_pIndexBufferArray[currentMesh->IndexBuffer].IndexType == IT_16BIT ) {
+ indsize = 2;
+ }else {
+ indsize = 4;
+ }
+
+ for( UINT subset = 0; subset < currentMesh->NumSubsets; subset++ )
+ {
+ pSubset = GetSubset( meshi, subset ); //&m_pSubsetArray[ currentMesh->pSubsets[subset] ];
+
+ PrimType = GetPrimitiveType11( ( SDKMESH_PRIMITIVE_TYPE )pSubset->PrimitiveType );
+ assert( PrimType == D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );// only triangle lists are handled.
+
+ UINT IndexCount = ( UINT )pSubset->IndexCount;
+ UINT IndexStart = ( UINT )pSubset->IndexStart;
+
+ /*if( bAdjacent )
+ {
+ IndexCount *= 2;
+ IndexStart *= 2;
+ }*/
+
+ //BYTE* pIndices = NULL;
+ //m_ppIndices[i]
+ UINT *ind = ( UINT * )m_ppIndices[currentMesh->IndexBuffer];
+ FLOAT *verts = ( FLOAT* )m_ppVertices[currentMesh->VertexBuffers[0]];
+ UINT stride = (UINT)m_pVertexBufferArray[currentMesh->VertexBuffers[0]].StrideBytes;
+ assert (stride % 4 == 0);
+ stride /=4;
+ for (UINT vertind = IndexStart; vertind < IndexStart + IndexCount; ++vertind) {
+ UINT current_ind=0;
+ if (indsize == 2) {
+ UINT ind_div2 = vertind / 2;
+ current_ind = ind[ind_div2];
+ if (vertind %2 ==0) {
+ current_ind = current_ind << 16;
+ current_ind = current_ind >> 16;
+ }else {
+ current_ind = current_ind >> 16;
+ }
+ }else {
+ current_ind = ind[vertind];
+ }
+ tris++;
+ D3DXVECTOR3 *pt = (D3DXVECTOR3*)&(verts[stride * current_ind]);
+ if (pt->x < lower.x) {
+ lower.x = pt->x;
+ }
+ if (pt->y < lower.y) {
+ lower.y = pt->y;
+ }
+ if (pt->z < lower.z) {
+ lower.z = pt->z;
+ }
+ if (pt->x > upper.x) {
+ upper.x = pt->x;
+ }
+ if (pt->y > upper.y) {
+ upper.y = pt->y;
+ }
+ if (pt->z > upper.z) {
+ upper.z = pt->z;
+ }
+ //BYTE** m_ppVertices;
+ //BYTE** m_ppIndices;
+ }
+ //pd3dDeviceContext->DrawIndexed( IndexCount, IndexStart, VertexStart );
+ }
+
+ D3DXVECTOR3 half = upper - lower;
+ half *=0.5f;
+
+ currentMesh->BoundingBoxCenter = lower + half;
+ currentMesh->BoundingBoxExtents = half;
+
+ }
+ // Update
+
+
+
+ hr = S_OK;
+Error:
+
+ if( !pLoaderCallbacks9 )
+ {
+ CheckLoadDone();
+ }
+
+ return hr;
+}
+
+//--------------------------------------------------------------------------------------
+// transform bind pose frame using a recursive traversal
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::TransformBindPoseFrame( UINT iFrame, D3DXMATRIX* pParentWorld )
+{
+ if( !m_pBindPoseFrameMatrices )
+ return;
+
+ // Transform ourselves
+ D3DXMATRIX LocalWorld;
+ D3DXMatrixMultiply( &LocalWorld, &m_pFrameArray[iFrame].Matrix, pParentWorld );
+ m_pBindPoseFrameMatrices[iFrame] = LocalWorld;
+
+ // Transform our siblings
+ if( m_pFrameArray[iFrame].SiblingFrame != INVALID_FRAME )
+ TransformBindPoseFrame( m_pFrameArray[iFrame].SiblingFrame, pParentWorld );
+
+ // Transform our children
+ if( m_pFrameArray[iFrame].ChildFrame != INVALID_FRAME )
+ TransformBindPoseFrame( m_pFrameArray[iFrame].ChildFrame, &LocalWorld );
+}
+
+//--------------------------------------------------------------------------------------
+// transform frame using a recursive traversal
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::TransformFrame( UINT iFrame, D3DXMATRIX* pParentWorld, double fTime )
+{
+ // Get the tick data
+ D3DXMATRIX LocalTransform;
+ UINT iTick = GetAnimationKeyFromTime( fTime );
+
+ if( INVALID_ANIMATION_DATA != m_pFrameArray[iFrame].AnimationDataIndex )
+ {
+ SDKANIMATION_FRAME_DATA* pFrameData = &m_pAnimationFrameData[ m_pFrameArray[iFrame].AnimationDataIndex ];
+ SDKANIMATION_DATA* pData = &pFrameData->pAnimationData[ iTick ];
+
+ // turn it into a matrix (Ignore scaling for now)
+ D3DXVECTOR3 parentPos = pData->Translation;
+ D3DXMATRIX mTranslate;
+ D3DXMatrixTranslation( &mTranslate, parentPos.x, parentPos.y, parentPos.z );
+
+ D3DXQUATERNION quat;
+ D3DXMATRIX mQuat;
+ quat.w = pData->Orientation.w;
+ quat.x = pData->Orientation.x;
+ quat.y = pData->Orientation.y;
+ quat.z = pData->Orientation.z;
+ if( quat.w == 0 && quat.x == 0 && quat.y == 0 && quat.z == 0 )
+ D3DXQuaternionIdentity( &quat );
+ D3DXQuaternionNormalize( &quat, &quat );
+ D3DXMatrixRotationQuaternion( &mQuat, &quat );
+ LocalTransform = ( mQuat * mTranslate );
+ }
+ else
+ {
+ LocalTransform = m_pFrameArray[iFrame].Matrix;
+ }
+
+ // Transform ourselves
+ D3DXMATRIX LocalWorld;
+ D3DXMatrixMultiply( &LocalWorld, &LocalTransform, pParentWorld );
+ m_pTransformedFrameMatrices[iFrame] = LocalWorld;
+ m_pWorldPoseFrameMatrices[iFrame] = LocalWorld;
+
+ // Transform our siblings
+ if( m_pFrameArray[iFrame].SiblingFrame != INVALID_FRAME )
+ TransformFrame( m_pFrameArray[iFrame].SiblingFrame, pParentWorld, fTime );
+
+ // Transform our children
+ if( m_pFrameArray[iFrame].ChildFrame != INVALID_FRAME )
+ TransformFrame( m_pFrameArray[iFrame].ChildFrame, &LocalWorld, fTime );
+}
+
+//--------------------------------------------------------------------------------------
+// transform frame assuming that it is an absolute transformation
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::TransformFrameAbsolute( UINT iFrame, double fTime )
+{
+ D3DXMATRIX mTrans1;
+ D3DXMATRIX mTrans2;
+ D3DXMATRIX mRot1;
+ D3DXMATRIX mRot2;
+ D3DXQUATERNION quat1;
+ D3DXQUATERNION quat2;
+ D3DXMATRIX mTo;
+ D3DXMATRIX mInvTo;
+ D3DXMATRIX mFrom;
+
+ UINT iTick = GetAnimationKeyFromTime( fTime );
+
+ if( INVALID_ANIMATION_DATA != m_pFrameArray[iFrame].AnimationDataIndex )
+ {
+ SDKANIMATION_FRAME_DATA* pFrameData = &m_pAnimationFrameData[ m_pFrameArray[iFrame].AnimationDataIndex ];
+ SDKANIMATION_DATA* pData = &pFrameData->pAnimationData[ iTick ];
+ SDKANIMATION_DATA* pDataOrig = &pFrameData->pAnimationData[ 0 ];
+
+ D3DXMatrixTranslation( &mTrans1, -pDataOrig->Translation.x,
+ -pDataOrig->Translation.y,
+ -pDataOrig->Translation.z );
+ D3DXMatrixTranslation( &mTrans2, pData->Translation.x,
+ pData->Translation.y,
+ pData->Translation.z );
+
+ quat1.x = pDataOrig->Orientation.x;
+ quat1.y = pDataOrig->Orientation.y;
+ quat1.z = pDataOrig->Orientation.z;
+ quat1.w = pDataOrig->Orientation.w;
+ D3DXQuaternionInverse( &quat1, &quat1 );
+ D3DXMatrixRotationQuaternion( &mRot1, &quat1 );
+ mInvTo = mTrans1 * mRot1;
+
+ quat2.x = pData->Orientation.x;
+ quat2.y = pData->Orientation.y;
+ quat2.z = pData->Orientation.z;
+ quat2.w = pData->Orientation.w;
+ D3DXMatrixRotationQuaternion( &mRot2, &quat2 );
+ mFrom = mRot2 * mTrans2;
+
+ D3DXMATRIX mOutput = mInvTo * mFrom;
+ m_pTransformedFrameMatrices[iFrame] = mOutput;
+ }
+}
+
+#define MAX_D3D11_VERTEX_STREAMS D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::RenderMesh( UINT iMesh,
+ bool bAdjacent,
+ ID3D11DeviceContext* pd3dDeviceContext,
+ UINT iDiffuseSlot,
+ UINT iNormalSlot,
+ UINT iSpecularSlot )
+{
+ if( 0 < GetOutstandingBufferResources() )
+ return;
+
+ SDKMESH_MESH* pMesh = &m_pMeshArray[iMesh];
+
+ UINT Strides[MAX_D3D11_VERTEX_STREAMS];
+ UINT Offsets[MAX_D3D11_VERTEX_STREAMS];
+ ID3D11Buffer* pVB[MAX_D3D11_VERTEX_STREAMS];
+
+ if( pMesh->NumVertexBuffers > MAX_D3D11_VERTEX_STREAMS )
+ return;
+
+ for( UINT64 i = 0; i < pMesh->NumVertexBuffers; i++ )
+ {
+ pVB[i] = m_pVertexBufferArray[ pMesh->VertexBuffers[i] ].pVB11;
+ Strides[i] = ( UINT )m_pVertexBufferArray[ pMesh->VertexBuffers[i] ].StrideBytes;
+ Offsets[i] = 0;
+ }
+
+ SDKMESH_INDEX_BUFFER_HEADER* pIndexBufferArray;
+ if( bAdjacent )
+ pIndexBufferArray = m_pAdjacencyIndexBufferArray;
+ else
+ pIndexBufferArray = m_pIndexBufferArray;
+
+ ID3D11Buffer* pIB = pIndexBufferArray[ pMesh->IndexBuffer ].pIB11;
+ DXGI_FORMAT ibFormat = DXGI_FORMAT_R16_UINT;
+ switch( pIndexBufferArray[ pMesh->IndexBuffer ].IndexType )
+ {
+ case IT_16BIT:
+ ibFormat = DXGI_FORMAT_R16_UINT;
+ break;
+ case IT_32BIT:
+ ibFormat = DXGI_FORMAT_R32_UINT;
+ break;
+ };
+
+ pd3dDeviceContext->IASetVertexBuffers( 0, pMesh->NumVertexBuffers, pVB, Strides, Offsets );
+ pd3dDeviceContext->IASetIndexBuffer( pIB, ibFormat, 0 );
+
+ SDKMESH_SUBSET* pSubset = NULL;
+ SDKMESH_MATERIAL* pMat = NULL;
+ D3D11_PRIMITIVE_TOPOLOGY PrimType;
+
+ for( UINT subset = 0; subset < pMesh->NumSubsets; subset++ )
+ {
+ pSubset = &m_pSubsetArray[ pMesh->pSubsets[subset] ];
+
+ PrimType = GetPrimitiveType11( ( SDKMESH_PRIMITIVE_TYPE )pSubset->PrimitiveType );
+ if( bAdjacent )
+ {
+ switch( PrimType )
+ {
+ case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST:
+ PrimType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ;
+ break;
+ case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP:
+ PrimType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ;
+ break;
+ case D3D11_PRIMITIVE_TOPOLOGY_LINELIST:
+ PrimType = D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
+ break;
+ case D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP:
+ PrimType = D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ;
+ break;
+ }
+ }
+
+ pd3dDeviceContext->IASetPrimitiveTopology( PrimType );
+
+ pMat = &m_pMaterialArray[ pSubset->MaterialID ];
+ if( iDiffuseSlot != INVALID_SAMPLER_SLOT && !IsErrorResource( pMat->pDiffuseRV11 ) )
+ pd3dDeviceContext->PSSetShaderResources( iDiffuseSlot, 1, &pMat->pDiffuseRV11 );
+ if( iNormalSlot != INVALID_SAMPLER_SLOT && !IsErrorResource( pMat->pNormalRV11 ) )
+ pd3dDeviceContext->PSSetShaderResources( iNormalSlot, 1, &pMat->pNormalRV11 );
+ if( iSpecularSlot != INVALID_SAMPLER_SLOT && !IsErrorResource( pMat->pSpecularRV11 ) )
+ pd3dDeviceContext->PSSetShaderResources( iSpecularSlot, 1, &pMat->pSpecularRV11 );
+
+ UINT IndexCount = ( UINT )pSubset->IndexCount;
+ UINT IndexStart = ( UINT )pSubset->IndexStart;
+ UINT VertexStart = ( UINT )pSubset->VertexStart;
+ if( bAdjacent )
+ {
+ IndexCount *= 2;
+ IndexStart *= 2;
+ }
+
+ pd3dDeviceContext->DrawIndexed( IndexCount, IndexStart, VertexStart );
+ }
+}
+
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::RenderFrame( UINT iFrame,
+ bool bAdjacent,
+ ID3D11DeviceContext* pd3dDeviceContext,
+ UINT iDiffuseSlot,
+ UINT iNormalSlot,
+ UINT iSpecularSlot )
+{
+ if( !m_pStaticMeshData || !m_pFrameArray )
+ return;
+
+ if( m_pFrameArray[iFrame].Mesh != INVALID_MESH )
+ {
+ RenderMesh( m_pFrameArray[iFrame].Mesh,
+ bAdjacent,
+ pd3dDeviceContext,
+ iDiffuseSlot,
+ iNormalSlot,
+ iSpecularSlot );
+ }
+
+ // Render our children
+ if( m_pFrameArray[iFrame].ChildFrame != INVALID_FRAME )
+ RenderFrame( m_pFrameArray[iFrame].ChildFrame, bAdjacent, pd3dDeviceContext, iDiffuseSlot,
+ iNormalSlot, iSpecularSlot );
+
+ // Render our siblings
+ if( m_pFrameArray[iFrame].SiblingFrame != INVALID_FRAME )
+ RenderFrame( m_pFrameArray[iFrame].SiblingFrame, bAdjacent, pd3dDeviceContext, iDiffuseSlot,
+ iNormalSlot, iSpecularSlot );
+}
+
+//--------------------------------------------------------------------------------------
+
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::RenderMesh( UINT iMesh,
+ LPDIRECT3DDEVICE9 pd3dDevice,
+ LPD3DXEFFECT pEffect,
+ D3DXHANDLE hTechnique,
+ D3DXHANDLE htxDiffuse,
+ D3DXHANDLE htxNormal,
+ D3DXHANDLE htxSpecular )
+{
+ if( 0 < GetOutstandingBufferResources() )
+ return;
+
+ SDKMESH_MESH* pMesh = &m_pMeshArray[iMesh];
+
+ // set vb streams
+ for( UINT i = 0; i < ( UINT )pMesh->NumVertexBuffers; i++ )
+ {
+ pd3dDevice->SetStreamSource( i,
+ m_pVertexBufferArray[ pMesh->VertexBuffers[i] ].pVB9,
+ 0,
+ ( UINT )m_pVertexBufferArray[ pMesh->VertexBuffers[i] ].StrideBytes );
+ }
+
+ // Set our index buffer as well
+ pd3dDevice->SetIndices( m_pIndexBufferArray[ pMesh->IndexBuffer ].pIB9 );
+
+ // Render the scene with this technique
+ pEffect->SetTechnique( hTechnique );
+
+ SDKMESH_SUBSET* pSubset = NULL;
+ SDKMESH_MATERIAL* pMat = NULL;
+ D3DPRIMITIVETYPE PrimType;
+ UINT cPasses = 0;
+ pEffect->Begin( &cPasses, 0 );
+
+ for( UINT p = 0; p < cPasses; ++p )
+ {
+ pEffect->BeginPass( p );
+
+ for( UINT subset = 0; subset < pMesh->NumSubsets; subset++ )
+ {
+ pSubset = &m_pSubsetArray[ pMesh->pSubsets[subset] ];
+
+ PrimType = GetPrimitiveType9( ( SDKMESH_PRIMITIVE_TYPE )pSubset->PrimitiveType );
+
+ if( INVALID_MATERIAL != pSubset->MaterialID && m_pMeshHeader->NumMaterials > 0 )
+ {
+ pMat = &m_pMaterialArray[ pSubset->MaterialID ];
+ if( htxDiffuse && !IsErrorResource( pMat->pDiffuseTexture9 ) )
+ pEffect->SetTexture( htxDiffuse, pMat->pDiffuseTexture9 );
+ if( htxNormal && !IsErrorResource( pMat->pNormalTexture9 ) )
+ pEffect->SetTexture( htxNormal, pMat->pNormalTexture9 );
+ if( htxSpecular && !IsErrorResource( pMat->pSpecularTexture9 ) )
+ pEffect->SetTexture( htxSpecular, pMat->pSpecularTexture9 );
+ }
+
+ pEffect->CommitChanges();
+
+ UINT PrimCount = ( UINT )pSubset->IndexCount;
+ UINT IndexStart = ( UINT )pSubset->IndexStart;
+ UINT VertexStart = ( UINT )pSubset->VertexStart;
+ UINT VertexCount = ( UINT )pSubset->VertexCount;
+ if( D3DPT_TRIANGLELIST == PrimType )
+ PrimCount /= 3;
+ if( D3DPT_LINELIST == PrimType )
+ PrimCount /= 2;
+ if( D3DPT_TRIANGLESTRIP == PrimType )
+ PrimCount = ( PrimCount - 3 ) + 1;
+ if( D3DPT_LINESTRIP == PrimType )
+ PrimCount -= 1;
+
+ pd3dDevice->DrawIndexedPrimitive( PrimType, VertexStart, 0, VertexCount, IndexStart, PrimCount );
+ }
+
+ pEffect->EndPass();
+ }
+
+ pEffect->End();
+}
+
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::RenderFrame( UINT iFrame,
+ LPDIRECT3DDEVICE9 pd3dDevice,
+ LPD3DXEFFECT pEffect,
+ D3DXHANDLE hTechnique,
+ D3DXHANDLE htxDiffuse,
+ D3DXHANDLE htxNormal,
+ D3DXHANDLE htxSpecular )
+{
+ if( !m_pStaticMeshData || !m_pFrameArray )
+ return;
+
+ if( m_pFrameArray[iFrame].Mesh != INVALID_MESH )
+ {
+ RenderMesh( m_pFrameArray[iFrame].Mesh,
+ pd3dDevice,
+ pEffect,
+ hTechnique,
+ htxDiffuse,
+ htxNormal,
+ htxSpecular );
+ }
+
+ // Render our children
+ if( m_pFrameArray[iFrame].ChildFrame != INVALID_FRAME )
+ RenderFrame( m_pFrameArray[iFrame].ChildFrame, pd3dDevice, pEffect, hTechnique, htxDiffuse, htxNormal,
+ htxSpecular );
+
+ // Render our siblings
+ if( m_pFrameArray[iFrame].SiblingFrame != INVALID_FRAME )
+ RenderFrame( m_pFrameArray[iFrame].SiblingFrame, pd3dDevice, pEffect, hTechnique, htxDiffuse, htxNormal,
+ htxSpecular );
+}
+
+
+//--------------------------------------------------------------------------------------
+CDXUTSDKMesh::CDXUTSDKMesh() : m_NumOutstandingResources( 0 ),
+ m_bLoading( false ),
+ m_hFile( 0 ),
+ m_hFileMappingObject( 0 ),
+ m_pMeshHeader( NULL ),
+ m_pStaticMeshData( NULL ),
+ m_pHeapData( NULL ),
+ m_pAdjacencyIndexBufferArray( NULL ),
+ m_pAnimationData( NULL ),
+ m_pAnimationHeader( NULL ),
+ m_ppVertices( NULL ),
+ m_ppIndices( NULL ),
+ m_pBindPoseFrameMatrices( NULL ),
+ m_pTransformedFrameMatrices( NULL ),
+ m_pWorldPoseFrameMatrices( NULL ),
+ m_pDev9( NULL ),
+ m_pDev11( NULL )
+{
+}
+
+
+//--------------------------------------------------------------------------------------
+CDXUTSDKMesh::~CDXUTSDKMesh()
+{
+ Destroy();
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTSDKMesh::Create( ID3D11Device* pDev11, LPCTSTR szFileName, bool bCreateAdjacencyIndices,
+ SDKMESH_CALLBACKS11* pLoaderCallbacks )
+{
+ return CreateFromFile( pDev11, NULL, szFileName, bCreateAdjacencyIndices, pLoaderCallbacks, NULL );
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTSDKMesh::Create( IDirect3DDevice9* pDev9, LPCTSTR szFileName, bool bCreateAdjacencyIndices,
+ SDKMESH_CALLBACKS9* pLoaderCallbacks )
+{
+ return CreateFromFile( NULL, pDev9, szFileName, bCreateAdjacencyIndices, NULL, pLoaderCallbacks );
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTSDKMesh::Create( ID3D11Device* pDev11, BYTE* pData, UINT DataBytes, bool bCreateAdjacencyIndices,
+ bool bCopyStatic, SDKMESH_CALLBACKS11* pLoaderCallbacks )
+{
+ return CreateFromMemory( pDev11, NULL, pData, DataBytes, bCreateAdjacencyIndices, bCopyStatic,
+ pLoaderCallbacks, NULL );
+}
+
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTSDKMesh::Create( IDirect3DDevice9* pDev9, BYTE* pData, UINT DataBytes, bool bCreateAdjacencyIndices,
+ bool bCopyStatic, SDKMESH_CALLBACKS9* pLoaderCallbacks )
+{
+ return CreateFromMemory( NULL, pDev9, pData, DataBytes, bCreateAdjacencyIndices, bCopyStatic, NULL,
+ pLoaderCallbacks );
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTSDKMesh::LoadAnimation( WCHAR* szFileName )
+{
+ HRESULT hr = E_FAIL;
+ DWORD dwBytesRead = 0;
+ LARGE_INTEGER liMove;
+ WCHAR strPath[MAX_PATH];
+
+ // Find the path for the file
+ V_RETURN( DXUTFindDXSDKMediaFileCch( strPath, MAX_PATH, szFileName ) );
+
+ // Open the file
+ HANDLE hFile = CreateFile( strPath, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_FLAG_SEQUENTIAL_SCAN, NULL );
+ if( INVALID_HANDLE_VALUE == hFile )
+ return DXUTERR_MEDIANOTFOUND;
+
+ /////////////////////////
+ // Header
+ SDKANIMATION_FILE_HEADER fileheader;
+ if( !ReadFile( hFile, &fileheader, sizeof( SDKANIMATION_FILE_HEADER ), &dwBytesRead, NULL ) )
+ goto Error;
+
+ //allocate
+ m_pAnimationData = new BYTE[ ( size_t )( sizeof( SDKANIMATION_FILE_HEADER ) + fileheader.AnimationDataSize ) ];
+ if( !m_pAnimationData )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ }
+
+ // read it all in
+ liMove.QuadPart = 0;
+ if( !SetFilePointerEx( hFile, liMove, NULL, FILE_BEGIN ) )
+ goto Error;
+ if( !ReadFile( hFile, m_pAnimationData, ( DWORD )( sizeof( SDKANIMATION_FILE_HEADER ) +
+ fileheader.AnimationDataSize ), &dwBytesRead, NULL ) )
+ goto Error;
+
+ // pointer fixup
+ m_pAnimationHeader = ( SDKANIMATION_FILE_HEADER* )m_pAnimationData;
+ m_pAnimationFrameData = ( SDKANIMATION_FRAME_DATA* )( m_pAnimationData + m_pAnimationHeader->AnimationDataOffset );
+
+ UINT64 BaseOffset = sizeof( SDKANIMATION_FILE_HEADER );
+ for( UINT i = 0; i < m_pAnimationHeader->NumFrames; i++ )
+ {
+ m_pAnimationFrameData[i].pAnimationData = ( SDKANIMATION_DATA* )( m_pAnimationData +
+ m_pAnimationFrameData[i].DataOffset +
+ BaseOffset );
+ SDKMESH_FRAME* pFrame = FindFrame( m_pAnimationFrameData[i].FrameName );
+ if( pFrame )
+ {
+ pFrame->AnimationDataIndex = i;
+ }
+ }
+
+ hr = S_OK;
+Error:
+ CloseHandle( hFile );
+ return hr;
+}
+
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::Destroy()
+{
+ if( !CheckLoadDone() )
+ return;
+
+ if( m_pStaticMeshData )
+ {
+ if( m_pMaterialArray )
+ {
+ for( UINT64 m = 0; m < m_pMeshHeader->NumMaterials; m++ )
+ {
+ if( m_pDev9 )
+ {
+ if( !IsErrorResource( m_pMaterialArray[m].pDiffuseTexture9 ) )
+ SAFE_RELEASE( m_pMaterialArray[m].pDiffuseTexture9 );
+ if( !IsErrorResource( m_pMaterialArray[m].pNormalTexture9 ) )
+ SAFE_RELEASE( m_pMaterialArray[m].pNormalTexture9 );
+ if( !IsErrorResource( m_pMaterialArray[m].pSpecularTexture9 ) )
+ SAFE_RELEASE( m_pMaterialArray[m].pSpecularTexture9 );
+ }
+ else if( m_pDev11 )
+ {
+ //ID3D11Resource* pRes = NULL;
+ if( m_pMaterialArray[m].pDiffuseRV11 && !IsErrorResource( m_pMaterialArray[m].pDiffuseRV11 ) )
+ {
+ //m_pMaterialArray[m].pDiffuseRV11->GetResource( &pRes );
+ //SAFE_RELEASE( pRes );
+
+ SAFE_RELEASE( m_pMaterialArray[m].pDiffuseRV11 );
+ }
+ if( m_pMaterialArray[m].pNormalRV11 && !IsErrorResource( m_pMaterialArray[m].pNormalRV11 ) )
+ {
+ //m_pMaterialArray[m].pNormalRV11->GetResource( &pRes );
+ //SAFE_RELEASE( pRes );
+
+ SAFE_RELEASE( m_pMaterialArray[m].pNormalRV11 );
+ }
+ if( m_pMaterialArray[m].pSpecularRV11 && !IsErrorResource( m_pMaterialArray[m].pSpecularRV11 ) )
+ {
+ //m_pMaterialArray[m].pSpecularRV11->GetResource( &pRes );
+ //SAFE_RELEASE( pRes );
+
+ SAFE_RELEASE( m_pMaterialArray[m].pSpecularRV11 );
+ }
+ }
+ }
+ }
+
+ for( UINT64 i = 0; i < m_pMeshHeader->NumVertexBuffers; i++ )
+ {
+ if( !IsErrorResource( m_pVertexBufferArray[i].pVB9 ) )
+ SAFE_RELEASE( m_pVertexBufferArray[i].pVB9 );
+ }
+
+ for( UINT64 i = 0; i < m_pMeshHeader->NumIndexBuffers; i++ )
+ {
+ if( !IsErrorResource( m_pIndexBufferArray[i].pIB9 ) )
+ SAFE_RELEASE( m_pIndexBufferArray[i].pIB9 );
+ }
+ }
+
+ if( m_pAdjacencyIndexBufferArray )
+ {
+ for( UINT64 i = 0; i < m_pMeshHeader->NumIndexBuffers; i++ )
+ {
+ SAFE_RELEASE( m_pAdjacencyIndexBufferArray[i].pIB11 );
+ }
+ }
+ SAFE_DELETE_ARRAY( m_pAdjacencyIndexBufferArray );
+
+ SAFE_DELETE_ARRAY( m_pHeapData );
+ m_pStaticMeshData = NULL;
+ SAFE_DELETE_ARRAY( m_pAnimationData );
+ SAFE_DELETE_ARRAY( m_pBindPoseFrameMatrices );
+ SAFE_DELETE_ARRAY( m_pTransformedFrameMatrices );
+ SAFE_DELETE_ARRAY( m_pWorldPoseFrameMatrices );
+
+ SAFE_DELETE_ARRAY( m_ppVertices );
+ SAFE_DELETE_ARRAY( m_ppIndices );
+
+ m_pMeshHeader = NULL;
+ m_pVertexBufferArray = NULL;
+ m_pIndexBufferArray = NULL;
+ m_pMeshArray = NULL;
+ m_pSubsetArray = NULL;
+ m_pFrameArray = NULL;
+ m_pMaterialArray = NULL;
+
+ m_pAnimationHeader = NULL;
+ m_pAnimationFrameData = NULL;
+
+}
+
+//--------------------------------------------------------------------------------------
+// transform the bind pose
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::TransformBindPose( D3DXMATRIX* pWorld )
+{
+ TransformBindPoseFrame( 0, pWorld );
+}
+
+//--------------------------------------------------------------------------------------
+// transform the mesh frames according to the animation for time fTime
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::TransformMesh( D3DXMATRIX* pWorld, double fTime )
+{
+ if( m_pAnimationHeader == NULL || FTT_RELATIVE == m_pAnimationHeader->FrameTransformType )
+ {
+ TransformFrame( 0, pWorld, fTime );
+
+ // For each frame, move the transform to the bind pose, then
+ // move it to the final position
+ D3DXMATRIX mInvBindPose;
+ D3DXMATRIX mFinal;
+ for( UINT i = 0; i < m_pMeshHeader->NumFrames; i++ )
+ {
+ D3DXMatrixInverse( &mInvBindPose, NULL, &m_pBindPoseFrameMatrices[i] );
+ mFinal = mInvBindPose * m_pTransformedFrameMatrices[i];
+ m_pTransformedFrameMatrices[i] = mFinal;
+ }
+ }
+ else if( FTT_ABSOLUTE == m_pAnimationHeader->FrameTransformType )
+ {
+ for( UINT i = 0; i < m_pAnimationHeader->NumFrames; i++ )
+ TransformFrameAbsolute( i, fTime );
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::Render( ID3D11DeviceContext* pd3dDeviceContext,
+ UINT iDiffuseSlot,
+ UINT iNormalSlot,
+ UINT iSpecularSlot )
+{
+ RenderFrame( 0, false, pd3dDeviceContext, iDiffuseSlot, iNormalSlot, iSpecularSlot );
+}
+
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::RenderAdjacent( ID3D11DeviceContext* pd3dDeviceContext,
+ UINT iDiffuseSlot,
+ UINT iNormalSlot,
+ UINT iSpecularSlot )
+{
+ RenderFrame( 0, true, pd3dDeviceContext, iDiffuseSlot, iNormalSlot, iSpecularSlot );
+}
+
+
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::Render( LPDIRECT3DDEVICE9 pd3dDevice,
+ LPD3DXEFFECT pEffect,
+ D3DXHANDLE hTechnique,
+ D3DXHANDLE htxDiffuse,
+ D3DXHANDLE htxNormal,
+ D3DXHANDLE htxSpecular )
+{
+ RenderFrame( 0, pd3dDevice, pEffect, hTechnique, htxDiffuse, htxNormal, htxSpecular );
+}
+
+//--------------------------------------------------------------------------------------
+D3D11_PRIMITIVE_TOPOLOGY CDXUTSDKMesh::GetPrimitiveType11( SDKMESH_PRIMITIVE_TYPE PrimType )
+{
+ D3D11_PRIMITIVE_TOPOLOGY retType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+
+ switch( PrimType )
+ {
+ case PT_TRIANGLE_LIST:
+ retType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ break;
+ case PT_TRIANGLE_STRIP:
+ retType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
+ break;
+ case PT_LINE_LIST:
+ retType = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
+ break;
+ case PT_LINE_STRIP:
+ retType = D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
+ break;
+ case PT_POINT_LIST:
+ retType = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
+ break;
+ case PT_TRIANGLE_LIST_ADJ:
+ retType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ;
+ break;
+ case PT_TRIANGLE_STRIP_ADJ:
+ retType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ;
+ break;
+ case PT_LINE_LIST_ADJ:
+ retType = D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
+ break;
+ case PT_LINE_STRIP_ADJ:
+ retType = D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ;
+ break;
+ };
+
+ return retType;
+}
+
+//--------------------------------------------------------------------------------------
+DXGI_FORMAT CDXUTSDKMesh::GetIBFormat11( UINT iMesh )
+{
+ switch( m_pIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].IndexType )
+ {
+ case IT_16BIT:
+ return DXGI_FORMAT_R16_UINT;
+ case IT_32BIT:
+ return DXGI_FORMAT_R32_UINT;
+ };
+ return DXGI_FORMAT_R16_UINT;
+}
+
+//--------------------------------------------------------------------------------------
+ID3D11Buffer* CDXUTSDKMesh::GetVB11( UINT iMesh, UINT iVB )
+{
+ return m_pVertexBufferArray[ m_pMeshArray[ iMesh ].VertexBuffers[iVB] ].pVB11;
+}
+
+//--------------------------------------------------------------------------------------
+ID3D11Buffer* CDXUTSDKMesh::GetIB11( UINT iMesh )
+{
+ return m_pIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].pIB11;
+}
+SDKMESH_INDEX_TYPE CDXUTSDKMesh::GetIndexType( UINT iMesh )
+{
+ return ( SDKMESH_INDEX_TYPE ) m_pIndexBufferArray[m_pMeshArray[ iMesh ].IndexBuffer].IndexType;
+}
+//--------------------------------------------------------------------------------------
+ID3D11Buffer* CDXUTSDKMesh::GetAdjIB11( UINT iMesh )
+{
+ return m_pAdjacencyIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].pIB11;
+}
+
+//--------------------------------------------------------------------------------------
+D3DPRIMITIVETYPE CDXUTSDKMesh::GetPrimitiveType9( SDKMESH_PRIMITIVE_TYPE PrimType )
+{
+ D3DPRIMITIVETYPE retType = D3DPT_TRIANGLELIST;
+
+ switch( PrimType )
+ {
+ case PT_TRIANGLE_LIST:
+ retType = D3DPT_TRIANGLELIST;
+ break;
+ case PT_TRIANGLE_STRIP:
+ retType = D3DPT_TRIANGLESTRIP;
+ break;
+ case PT_LINE_LIST:
+ retType = D3DPT_LINELIST;
+ break;
+ case PT_LINE_STRIP:
+ retType = D3DPT_LINESTRIP;
+ break;
+ case PT_POINT_LIST:
+ retType = D3DPT_POINTLIST;
+ break;
+ };
+
+ return retType;
+}
+
+//--------------------------------------------------------------------------------------
+D3DFORMAT CDXUTSDKMesh::GetIBFormat9( UINT iMesh )
+{
+ switch( m_pIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].IndexType )
+ {
+ case IT_16BIT:
+ return D3DFMT_INDEX16;
+ case IT_32BIT:
+ return D3DFMT_INDEX32;
+ };
+ return D3DFMT_INDEX16;
+}
+
+//--------------------------------------------------------------------------------------
+IDirect3DVertexBuffer9* CDXUTSDKMesh::GetVB9( UINT iMesh, UINT iVB )
+{
+ return m_pVertexBufferArray[ m_pMeshArray[ iMesh ].VertexBuffers[iVB] ].pVB9;
+}
+
+//--------------------------------------------------------------------------------------
+IDirect3DIndexBuffer9* CDXUTSDKMesh::GetIB9( UINT iMesh )
+{
+ return m_pIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].pIB9;
+}
+
+//--------------------------------------------------------------------------------------
+char* CDXUTSDKMesh::GetMeshPathA()
+{
+ return m_strPath;
+}
+
+//--------------------------------------------------------------------------------------
+WCHAR* CDXUTSDKMesh::GetMeshPathW()
+{
+ return m_strPathW;
+}
+
+//--------------------------------------------------------------------------------------
+UINT CDXUTSDKMesh::GetNumMeshes()
+{
+ if( !m_pMeshHeader )
+ return 0;
+ return m_pMeshHeader->NumMeshes;
+}
+
+//--------------------------------------------------------------------------------------
+UINT CDXUTSDKMesh::GetNumMaterials()
+{
+ if( !m_pMeshHeader )
+ return 0;
+ return m_pMeshHeader->NumMaterials;
+}
+
+//--------------------------------------------------------------------------------------
+UINT CDXUTSDKMesh::GetNumVBs()
+{
+ if( !m_pMeshHeader )
+ return 0;
+ return m_pMeshHeader->NumVertexBuffers;
+}
+
+//--------------------------------------------------------------------------------------
+UINT CDXUTSDKMesh::GetNumIBs()
+{
+ if( !m_pMeshHeader )
+ return 0;
+ return m_pMeshHeader->NumIndexBuffers;
+}
+
+//--------------------------------------------------------------------------------------
+ID3D11Buffer* CDXUTSDKMesh::GetVB11At( UINT iVB )
+{
+ return m_pVertexBufferArray[ iVB ].pVB11;
+}
+
+//--------------------------------------------------------------------------------------
+ID3D11Buffer* CDXUTSDKMesh::GetIB11At( UINT iIB )
+{
+ return m_pIndexBufferArray[ iIB ].pIB11;
+}
+
+//--------------------------------------------------------------------------------------
+IDirect3DVertexBuffer9* CDXUTSDKMesh::GetVB9At( UINT iVB )
+{
+ return m_pVertexBufferArray[ iVB ].pVB9;
+}
+
+//--------------------------------------------------------------------------------------
+IDirect3DIndexBuffer9* CDXUTSDKMesh::GetIB9At( UINT iIB )
+{
+ return m_pIndexBufferArray[ iIB ].pIB9;
+}
+
+//--------------------------------------------------------------------------------------
+BYTE* CDXUTSDKMesh::GetRawVerticesAt( UINT iVB )
+{
+ return m_ppVertices[iVB];
+}
+
+//--------------------------------------------------------------------------------------
+BYTE* CDXUTSDKMesh::GetRawIndicesAt( UINT iIB )
+{
+ return m_ppIndices[iIB];
+}
+
+//--------------------------------------------------------------------------------------
+SDKMESH_MATERIAL* CDXUTSDKMesh::GetMaterial( UINT iMaterial )
+{
+ return &m_pMaterialArray[ iMaterial ];
+}
+
+//--------------------------------------------------------------------------------------
+SDKMESH_MESH* CDXUTSDKMesh::GetMesh( UINT iMesh )
+{
+ return &m_pMeshArray[ iMesh ];
+}
+
+//--------------------------------------------------------------------------------------
+UINT CDXUTSDKMesh::GetNumSubsets( UINT iMesh )
+{
+ return m_pMeshArray[ iMesh ].NumSubsets;
+}
+
+//--------------------------------------------------------------------------------------
+SDKMESH_SUBSET* CDXUTSDKMesh::GetSubset( UINT iMesh, UINT iSubset )
+{
+ return &m_pSubsetArray[ m_pMeshArray[ iMesh ].pSubsets[iSubset] ];
+}
+
+//--------------------------------------------------------------------------------------
+UINT CDXUTSDKMesh::GetVertexStride( UINT iMesh, UINT iVB )
+{
+ return ( UINT )m_pVertexBufferArray[ m_pMeshArray[ iMesh ].VertexBuffers[iVB] ].StrideBytes;
+}
+
+//--------------------------------------------------------------------------------------
+UINT CDXUTSDKMesh::GetNumFrames()
+{
+ return m_pMeshHeader->NumFrames;
+}
+
+//--------------------------------------------------------------------------------------
+SDKMESH_FRAME* CDXUTSDKMesh::GetFrame( UINT iFrame )
+{
+ assert( iFrame < m_pMeshHeader->NumFrames );
+ return &m_pFrameArray[ iFrame ];
+}
+
+//--------------------------------------------------------------------------------------
+SDKMESH_FRAME* CDXUTSDKMesh::FindFrame( char* pszName )
+{
+ for( UINT i = 0; i < m_pMeshHeader->NumFrames; i++ )
+ {
+ if( _stricmp( m_pFrameArray[i].Name, pszName ) == 0 )
+ {
+ return &m_pFrameArray[i];
+ }
+ }
+ return NULL;
+}
+
+//--------------------------------------------------------------------------------------
+UINT64 CDXUTSDKMesh::GetNumVertices( UINT iMesh, UINT iVB )
+{
+ return m_pVertexBufferArray[ m_pMeshArray[ iMesh ].VertexBuffers[iVB] ].NumVertices;
+}
+
+//--------------------------------------------------------------------------------------
+UINT64 CDXUTSDKMesh::GetNumIndices( UINT iMesh )
+{
+ return m_pIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].NumIndices;
+}
+
+//--------------------------------------------------------------------------------------
+D3DXVECTOR3 CDXUTSDKMesh::GetMeshBBoxCenter( UINT iMesh )
+{
+ return m_pMeshArray[iMesh].BoundingBoxCenter;
+}
+
+//--------------------------------------------------------------------------------------
+D3DXVECTOR3 CDXUTSDKMesh::GetMeshBBoxExtents( UINT iMesh )
+{
+ return m_pMeshArray[iMesh].BoundingBoxExtents;
+}
+
+//--------------------------------------------------------------------------------------
+UINT CDXUTSDKMesh::GetOutstandingResources()
+{
+ UINT outstandingResources = 0;
+ if( !m_pMeshHeader )
+ return 1;
+
+ outstandingResources += GetOutstandingBufferResources();
+
+ if( m_pDev11 )
+ {
+ for( UINT i = 0; i < m_pMeshHeader->NumMaterials; i++ )
+ {
+ if( m_pMaterialArray[i].DiffuseTexture[0] != 0 )
+ {
+ if( !m_pMaterialArray[i].pDiffuseRV11 && !IsErrorResource( m_pMaterialArray[i].pDiffuseRV11 ) )
+ outstandingResources ++;
+ }
+
+ if( m_pMaterialArray[i].NormalTexture[0] != 0 )
+ {
+ if( !m_pMaterialArray[i].pNormalRV11 && !IsErrorResource( m_pMaterialArray[i].pNormalRV11 ) )
+ outstandingResources ++;
+ }
+
+ if( m_pMaterialArray[i].SpecularTexture[0] != 0 )
+ {
+ if( !m_pMaterialArray[i].pSpecularRV11 && !IsErrorResource( m_pMaterialArray[i].pSpecularRV11 ) )
+ outstandingResources ++;
+ }
+ }
+ }
+ else
+ {
+ for( UINT i = 0; i < m_pMeshHeader->NumMaterials; i++ )
+ {
+ if( m_pMaterialArray[i].DiffuseTexture[0] != 0 )
+ {
+ if( !m_pMaterialArray[i].pDiffuseTexture9 && !IsErrorResource( m_pMaterialArray[i].pDiffuseTexture9 ) )
+ outstandingResources ++;
+ }
+
+ if( m_pMaterialArray[i].NormalTexture[0] != 0 )
+ {
+ if( !m_pMaterialArray[i].pNormalTexture9 && !IsErrorResource( m_pMaterialArray[i].pNormalTexture9 ) )
+ outstandingResources ++;
+ }
+
+ if( m_pMaterialArray[i].SpecularTexture[0] != 0 )
+ {
+ if( !m_pMaterialArray[i].pSpecularTexture9 &&
+ !IsErrorResource( m_pMaterialArray[i].pSpecularTexture9 ) )
+ outstandingResources ++;
+ }
+ }
+ }
+
+ return outstandingResources;
+}
+
+//--------------------------------------------------------------------------------------
+UINT CDXUTSDKMesh::GetOutstandingBufferResources()
+{
+ UINT outstandingResources = 0;
+ if( !m_pMeshHeader )
+ return 1;
+
+ for( UINT i = 0; i < m_pMeshHeader->NumVertexBuffers; i++ )
+ {
+ if( !m_pVertexBufferArray[i].pVB9 && !IsErrorResource( m_pVertexBufferArray[i].pVB9 ) )
+ outstandingResources ++;
+ }
+
+ for( UINT i = 0; i < m_pMeshHeader->NumIndexBuffers; i++ )
+ {
+ if( !m_pIndexBufferArray[i].pIB9 && !IsErrorResource( m_pIndexBufferArray[i].pIB9 ) )
+ outstandingResources ++;
+ }
+
+ return outstandingResources;
+}
+
+//--------------------------------------------------------------------------------------
+bool CDXUTSDKMesh::CheckLoadDone()
+{
+ if( 0 == GetOutstandingResources() )
+ {
+ m_bLoading = false;
+ return true;
+ }
+
+ return false;
+}
+
+//--------------------------------------------------------------------------------------
+bool CDXUTSDKMesh::IsLoaded()
+{
+ if( m_pStaticMeshData && !m_bLoading )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+//--------------------------------------------------------------------------------------
+bool CDXUTSDKMesh::IsLoading()
+{
+ return m_bLoading;
+}
+
+//--------------------------------------------------------------------------------------
+void CDXUTSDKMesh::SetLoading( bool bLoading )
+{
+ m_bLoading = bLoading;
+}
+
+//--------------------------------------------------------------------------------------
+BOOL CDXUTSDKMesh::HadLoadingError()
+{
+ if( m_pMeshHeader )
+ {
+ for( UINT i = 0; i < m_pMeshHeader->NumVertexBuffers; i++ )
+ {
+ if( IsErrorResource( m_pVertexBufferArray[i].pVB9 ) )
+ return TRUE;
+ }
+
+ for( UINT i = 0; i < m_pMeshHeader->NumIndexBuffers; i++ )
+ {
+ if( IsErrorResource( m_pIndexBufferArray[i].pIB9 ) )
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+//--------------------------------------------------------------------------------------
+UINT CDXUTSDKMesh::GetNumInfluences( UINT iMesh )
+{
+ return m_pMeshArray[iMesh].NumFrameInfluences;
+}
+
+//--------------------------------------------------------------------------------------
+const D3DXMATRIX* CDXUTSDKMesh::GetMeshInfluenceMatrix( UINT iMesh, UINT iInfluence )
+{
+ UINT iFrame = m_pMeshArray[iMesh].pFrameInfluences[ iInfluence ];
+ return &m_pTransformedFrameMatrices[iFrame];
+}
+
+const D3DXMATRIX* CDXUTSDKMesh::GetWorldMatrix( UINT iFrameIndex )
+{
+ return &m_pWorldPoseFrameMatrices[iFrameIndex];
+}
+
+const D3DXMATRIX* CDXUTSDKMesh::GetInfluenceMatrix( UINT iFrameIndex )
+{
+ return &m_pTransformedFrameMatrices[iFrameIndex];
+}
+
+//--------------------------------------------------------------------------------------
+UINT CDXUTSDKMesh::GetAnimationKeyFromTime( double fTime )
+{
+ if( m_pAnimationHeader == NULL )
+ {
+ return 0;
+ }
+
+ UINT iTick = ( UINT )( m_pAnimationHeader->AnimationFPS * fTime );
+
+ iTick = iTick % ( m_pAnimationHeader->NumAnimationKeys - 1 );
+ iTick ++;
+
+ return iTick;
+}
+
+bool CDXUTSDKMesh::GetAnimationProperties( UINT* pNumKeys, FLOAT* pFrameTime )
+{
+ if( m_pAnimationHeader == NULL )
+ {
+ return false;
+ }
+
+ *pNumKeys = m_pAnimationHeader->NumAnimationKeys;
+ *pFrameTime = 1.0f / (FLOAT)m_pAnimationHeader->AnimationFPS;
+
+ return true;
+}
+
+
+//-------------------------------------------------------------------------------------
+// CDXUTXFileMesh implementation.
+//-------------------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+CDXUTXFileMesh::CDXUTXFileMesh( LPCWSTR strName )
+{
+ wcscpy_s( m_strName, 512, strName );
+ m_pMesh = NULL;
+ m_pMaterials = NULL;
+ m_pTextures = NULL;
+ m_bUseMaterials = TRUE;
+ m_pVB = NULL;
+ m_pIB = NULL;
+ m_pDecl = NULL;
+ m_strMaterials = NULL;
+ m_dwNumMaterials = 0;
+ m_dwNumVertices = 0;
+ m_dwNumFaces = 0;
+ m_dwBytesPerVertex = 0;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+CDXUTXFileMesh::~CDXUTXFileMesh()
+{
+ Destroy();
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+HRESULT CDXUTXFileMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice, LPCWSTR strFilename )
+{
+ WCHAR strPath[MAX_PATH];
+ LPD3DXBUFFER pAdjacencyBuffer = NULL;
+ LPD3DXBUFFER pMtrlBuffer = NULL;
+ HRESULT hr;
+
+ // Cleanup previous mesh if any
+ Destroy();
+
+ // Find the path for the file, and convert it to ANSI (for the D3DX API)
+ DXUTFindDXSDKMediaFileCch( strPath, sizeof( strPath ) / sizeof( WCHAR ), strFilename );
+
+ // Load the mesh
+ if( FAILED( hr = D3DXLoadMeshFromX( strPath, D3DXMESH_MANAGED, pd3dDevice,
+ &pAdjacencyBuffer, &pMtrlBuffer, NULL,
+ &m_dwNumMaterials, &m_pMesh ) ) )
+ {
+ return hr;
+ }
+
+ // Optimize the mesh for performance
+ if( FAILED( hr = m_pMesh->OptimizeInplace(
+ D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
+ ( DWORD* )pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL ) ) )
+ {
+ SAFE_RELEASE( pAdjacencyBuffer );
+ SAFE_RELEASE( pMtrlBuffer );
+ return hr;
+ }
+
+ // Set strPath to the path of the mesh file
+ WCHAR* pLastBSlash = wcsrchr( strPath, L'\\' );
+ if( pLastBSlash )
+ *( pLastBSlash + 1 ) = L'\0';
+ else
+ *strPath = L'\0';
+
+ D3DXMATERIAL* d3dxMtrls = ( D3DXMATERIAL* )pMtrlBuffer->GetBufferPointer();
+ hr = CreateMaterials( strPath, pd3dDevice, d3dxMtrls, m_dwNumMaterials );
+
+ SAFE_RELEASE( pAdjacencyBuffer );
+ SAFE_RELEASE( pMtrlBuffer );
+
+ // Extract data from m_pMesh for easy access
+ D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
+ m_dwNumVertices = m_pMesh->GetNumVertices();
+ m_dwNumFaces = m_pMesh->GetNumFaces();
+ m_dwBytesPerVertex = m_pMesh->GetNumBytesPerVertex();
+ m_pMesh->GetIndexBuffer( &m_pIB );
+ m_pMesh->GetVertexBuffer( &m_pVB );
+ m_pMesh->GetDeclaration( decl );
+ pd3dDevice->CreateVertexDeclaration( decl, &m_pDecl );
+
+ return hr;
+}
+
+
+//-----------------------------------------------------------------------------
+HRESULT CDXUTXFileMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice,
+ LPD3DXFILEDATA pFileData )
+{
+ LPD3DXBUFFER pMtrlBuffer = NULL;
+ LPD3DXBUFFER pAdjacencyBuffer = NULL;
+ HRESULT hr;
+
+ // Cleanup previous mesh if any
+ Destroy();
+
+ // Load the mesh from the DXFILEDATA object
+ if( FAILED( hr = D3DXLoadMeshFromXof( pFileData, D3DXMESH_MANAGED, pd3dDevice,
+ &pAdjacencyBuffer, &pMtrlBuffer, NULL,
+ &m_dwNumMaterials, &m_pMesh ) ) )
+ {
+ return hr;
+ }
+
+ // Optimize the mesh for performance
+ if( FAILED( hr = m_pMesh->OptimizeInplace(
+ D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
+ ( DWORD* )pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL ) ) )
+ {
+ SAFE_RELEASE( pAdjacencyBuffer );
+ SAFE_RELEASE( pMtrlBuffer );
+ return hr;
+ }
+
+ D3DXMATERIAL* d3dxMtrls = ( D3DXMATERIAL* )pMtrlBuffer->GetBufferPointer();
+ hr = CreateMaterials( L"", pd3dDevice, d3dxMtrls, m_dwNumMaterials );
+
+ SAFE_RELEASE( pAdjacencyBuffer );
+ SAFE_RELEASE( pMtrlBuffer );
+
+ // Extract data from m_pMesh for easy access
+ D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
+ m_dwNumVertices = m_pMesh->GetNumVertices();
+ m_dwNumFaces = m_pMesh->GetNumFaces();
+ m_dwBytesPerVertex = m_pMesh->GetNumBytesPerVertex();
+ m_pMesh->GetIndexBuffer( &m_pIB );
+ m_pMesh->GetVertexBuffer( &m_pVB );
+ m_pMesh->GetDeclaration( decl );
+ pd3dDevice->CreateVertexDeclaration( decl, &m_pDecl );
+
+ return hr;
+}
+
+
+//-----------------------------------------------------------------------------
+HRESULT CDXUTXFileMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice, ID3DXMesh* pInMesh,
+ D3DXMATERIAL* pd3dxMaterials, DWORD dwMaterials )
+{
+ // Cleanup previous mesh if any
+ Destroy();
+
+ // Optimize the mesh for performance
+ DWORD* rgdwAdjacency = NULL;
+ rgdwAdjacency = new DWORD[pInMesh->GetNumFaces() * 3];
+ if( rgdwAdjacency == NULL )
+ return E_OUTOFMEMORY;
+ pInMesh->GenerateAdjacency( 1e-6f, rgdwAdjacency );
+
+ D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
+ pInMesh->GetDeclaration( decl );
+
+ DWORD dwOptions = pInMesh->GetOptions();
+ dwOptions &= ~( D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM | D3DXMESH_WRITEONLY );
+ dwOptions |= D3DXMESH_MANAGED;
+ dwOptions |= D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE;
+
+ ID3DXMesh* pTempMesh = NULL;
+ if( FAILED( pInMesh->Optimize( dwOptions, rgdwAdjacency, NULL, NULL, NULL, &pTempMesh ) ) )
+ {
+ SAFE_DELETE_ARRAY( rgdwAdjacency );
+ return E_FAIL;
+ }
+
+ SAFE_DELETE_ARRAY( rgdwAdjacency );
+ SAFE_RELEASE( m_pMesh );
+ m_pMesh = pTempMesh;
+
+ HRESULT hr;
+ hr = CreateMaterials( L"", pd3dDevice, pd3dxMaterials, dwMaterials );
+
+ // Extract data from m_pMesh for easy access
+ m_dwNumVertices = m_pMesh->GetNumVertices();
+ m_dwNumFaces = m_pMesh->GetNumFaces();
+ m_dwBytesPerVertex = m_pMesh->GetNumBytesPerVertex();
+ m_pMesh->GetIndexBuffer( &m_pIB );
+ m_pMesh->GetVertexBuffer( &m_pVB );
+ m_pMesh->GetDeclaration( decl );
+ pd3dDevice->CreateVertexDeclaration( decl, &m_pDecl );
+
+ return hr;
+}
+
+
+//-----------------------------------------------------------------------------
+HRESULT CDXUTXFileMesh::CreateMaterials( LPCWSTR strPath, IDirect3DDevice9* pd3dDevice, D3DXMATERIAL* d3dxMtrls,
+ DWORD dwNumMaterials )
+{
+ // Get material info for the mesh
+ // Get the array of materials out of the buffer
+ m_dwNumMaterials = dwNumMaterials;
+ if( d3dxMtrls && m_dwNumMaterials > 0 )
+ {
+ // Allocate memory for the materials and textures
+ m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials];
+ if( m_pMaterials == NULL )
+ return E_OUTOFMEMORY;
+ m_pTextures = new LPDIRECT3DBASETEXTURE9[m_dwNumMaterials];
+ if( m_pTextures == NULL )
+ return E_OUTOFMEMORY;
+ m_strMaterials = new CHAR[m_dwNumMaterials][MAX_PATH];
+ if( m_strMaterials == NULL )
+ return E_OUTOFMEMORY;
+
+ // Copy each material and create its texture
+ for( DWORD i = 0; i < m_dwNumMaterials; i++ )
+ {
+ // Copy the material
+ m_pMaterials[i] = d3dxMtrls[i].MatD3D;
+ m_pTextures[i] = NULL;
+
+ // Create a texture
+ if( d3dxMtrls[i].pTextureFilename )
+ {
+ strcpy_s( m_strMaterials[i], MAX_PATH, d3dxMtrls[i].pTextureFilename );
+
+ WCHAR strTexture[MAX_PATH];
+ WCHAR strTextureTemp[MAX_PATH];
+ D3DXIMAGE_INFO ImgInfo;
+
+ // First attempt to look for texture in the same folder as the input folder.
+ MultiByteToWideChar( CP_ACP, 0, d3dxMtrls[i].pTextureFilename, -1, strTextureTemp, MAX_PATH );
+ strTextureTemp[MAX_PATH - 1] = 0;
+
+ wcscpy_s( strTexture, MAX_PATH, strPath );
+ wcscat_s( strTexture, MAX_PATH, strTextureTemp );
+
+ // Inspect the texture file to determine the texture type.
+ if( FAILED( D3DXGetImageInfoFromFile( strTexture, &ImgInfo ) ) )
+ {
+ // Search the media folder
+ if( FAILED( DXUTFindDXSDKMediaFileCch( strTexture, MAX_PATH, strTextureTemp ) ) )
+ continue; // Can't find. Skip.
+
+ D3DXGetImageInfoFromFile( strTexture, &ImgInfo );
+ }
+
+ // Call the appropriate loader according to the texture type.
+ switch( ImgInfo.ResourceType )
+ {
+ case D3DRTYPE_TEXTURE:
+ {
+ IDirect3DTexture9* pTex;
+ if( SUCCEEDED( D3DXCreateTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
+ {
+ // Obtain the base texture interface
+ pTex->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&m_pTextures[i] );
+ // Release the specialized instance
+ pTex->Release();
+ }
+ break;
+ }
+ case D3DRTYPE_CUBETEXTURE:
+ {
+ IDirect3DCubeTexture9* pTex;
+ if( SUCCEEDED( D3DXCreateCubeTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
+ {
+ // Obtain the base texture interface
+ pTex->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&m_pTextures[i] );
+ // Release the specialized instance
+ pTex->Release();
+ }
+ break;
+ }
+ case D3DRTYPE_VOLUMETEXTURE:
+ {
+ IDirect3DVolumeTexture9* pTex;
+ if( SUCCEEDED( D3DXCreateVolumeTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
+ {
+ // Obtain the base texture interface
+ pTex->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&m_pTextures[i] );
+ // Release the specialized instance
+ pTex->Release();
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ return S_OK;
+}
+
+
+//-----------------------------------------------------------------------------
+HRESULT CDXUTXFileMesh::SetFVF( LPDIRECT3DDEVICE9 pd3dDevice, DWORD dwFVF )
+{
+ LPD3DXMESH pTempMesh = NULL;
+
+ if( m_pMesh )
+ {
+ if( FAILED( m_pMesh->CloneMeshFVF( m_pMesh->GetOptions(), dwFVF,
+ pd3dDevice, &pTempMesh ) ) )
+ {
+ SAFE_RELEASE( pTempMesh );
+ return E_FAIL;
+ }
+
+ DWORD dwOldFVF = 0;
+ dwOldFVF = m_pMesh->GetFVF();
+ SAFE_RELEASE( m_pMesh );
+ m_pMesh = pTempMesh;
+
+ // Compute normals if they are being requested and
+ // the old mesh does not have them.
+ if( !( dwOldFVF & D3DFVF_NORMAL ) && dwFVF & D3DFVF_NORMAL )
+ {
+ D3DXComputeNormals( m_pMesh, NULL );
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Convert the mesh to the format specified by the given vertex declarations.
+//-----------------------------------------------------------------------------
+HRESULT CDXUTXFileMesh::SetVertexDecl( LPDIRECT3DDEVICE9 pd3dDevice, const D3DVERTEXELEMENT9* pDecl,
+ bool bAutoComputeNormals, bool bAutoComputeTangents,
+ bool bSplitVertexForOptimalTangents )
+{
+ LPD3DXMESH pTempMesh = NULL;
+
+ if( m_pMesh )
+ {
+ if( FAILED( m_pMesh->CloneMesh( m_pMesh->GetOptions(), pDecl,
+ pd3dDevice, &pTempMesh ) ) )
+ {
+ SAFE_RELEASE( pTempMesh );
+ return E_FAIL;
+ }
+ }
+
+
+ // Check if the old declaration contains a normal.
+ bool bHadNormal = false;
+ bool bHadTangent = false;
+ D3DVERTEXELEMENT9 aOldDecl[MAX_FVF_DECL_SIZE];
+ if( m_pMesh && SUCCEEDED( m_pMesh->GetDeclaration( aOldDecl ) ) )
+ {
+ for( UINT index = 0; index < D3DXGetDeclLength( aOldDecl ); ++index )
+ {
+ if( aOldDecl[index].Usage == D3DDECLUSAGE_NORMAL )
+ {
+ bHadNormal = true;
+ }
+ if( aOldDecl[index].Usage == D3DDECLUSAGE_TANGENT )
+ {
+ bHadTangent = true;
+ }
+ }
+ }
+
+ // Check if the new declaration contains a normal.
+ bool bHaveNormalNow = false;
+ bool bHaveTangentNow = false;
+ D3DVERTEXELEMENT9 aNewDecl[MAX_FVF_DECL_SIZE];
+ if( pTempMesh && SUCCEEDED( pTempMesh->GetDeclaration( aNewDecl ) ) )
+ {
+ for( UINT index = 0; index < D3DXGetDeclLength( aNewDecl ); ++index )
+ {
+ if( aNewDecl[index].Usage == D3DDECLUSAGE_NORMAL )
+ {
+ bHaveNormalNow = true;
+ }
+ if( aNewDecl[index].Usage == D3DDECLUSAGE_TANGENT )
+ {
+ bHaveTangentNow = true;
+ }
+ }
+ }
+
+ SAFE_RELEASE( m_pMesh );
+
+ if( pTempMesh )
+ {
+ m_pMesh = pTempMesh;
+
+ if( !bHadNormal && bHaveNormalNow && bAutoComputeNormals )
+ {
+ // Compute normals in case the meshes have them
+ D3DXComputeNormals( m_pMesh, NULL );
+ }
+
+ if( bHaveNormalNow && !bHadTangent && bHaveTangentNow && bAutoComputeTangents )
+ {
+ ID3DXMesh* pNewMesh;
+ HRESULT hr;
+
+ DWORD* rgdwAdjacency = NULL;
+ rgdwAdjacency = new DWORD[m_pMesh->GetNumFaces() * 3];
+ if( rgdwAdjacency == NULL )
+ return E_OUTOFMEMORY;
+ V( m_pMesh->GenerateAdjacency( 1e-6f, rgdwAdjacency ) );
+
+ float fPartialEdgeThreshold;
+ float fSingularPointThreshold;
+ float fNormalEdgeThreshold;
+ if( bSplitVertexForOptimalTangents )
+ {
+ fPartialEdgeThreshold = 0.01f;
+ fSingularPointThreshold = 0.25f;
+ fNormalEdgeThreshold = 0.01f;
+ }
+ else
+ {
+ fPartialEdgeThreshold = -1.01f;
+ fSingularPointThreshold = 0.01f;
+ fNormalEdgeThreshold = -1.01f;
+ }
+
+ // Compute tangents, which are required for normal mapping
+ hr = D3DXComputeTangentFrameEx( m_pMesh,
+ D3DDECLUSAGE_TEXCOORD, 0,
+ D3DDECLUSAGE_TANGENT, 0,
+ D3DX_DEFAULT, 0,
+ D3DDECLUSAGE_NORMAL, 0,
+ 0, rgdwAdjacency,
+ fPartialEdgeThreshold, fSingularPointThreshold, fNormalEdgeThreshold,
+ &pNewMesh, NULL );
+
+ SAFE_DELETE_ARRAY( rgdwAdjacency );
+ if( FAILED( hr ) )
+ return hr;
+
+ SAFE_RELEASE( m_pMesh );
+ m_pMesh = pNewMesh;
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+HRESULT CDXUTXFileMesh::RestoreDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice )
+{
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+HRESULT CDXUTXFileMesh::InvalidateDeviceObjects()
+{
+ SAFE_RELEASE( m_pIB );
+ SAFE_RELEASE( m_pVB );
+ SAFE_RELEASE( m_pDecl );
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+HRESULT CDXUTXFileMesh::Destroy()
+{
+ InvalidateDeviceObjects();
+ for( UINT i = 0; i < m_dwNumMaterials; i++ )
+ SAFE_RELEASE( m_pTextures[i] );
+ SAFE_DELETE_ARRAY( m_pTextures );
+ SAFE_DELETE_ARRAY( m_pMaterials );
+ SAFE_DELETE_ARRAY( m_strMaterials );
+
+ SAFE_RELEASE( m_pMesh );
+
+ m_dwNumMaterials = 0L;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+HRESULT CDXUTXFileMesh::Render( LPDIRECT3DDEVICE9 pd3dDevice, bool bDrawOpaqueSubsets,
+ bool bDrawAlphaSubsets )
+{
+ if( NULL == m_pMesh )
+ return E_FAIL;
+
+ // Frist, draw the subsets without alpha
+ if( bDrawOpaqueSubsets )
+ {
+ for( DWORD i = 0; i < m_dwNumMaterials; i++ )
+ {
+ if( m_bUseMaterials )
+ {
+ if( m_pMaterials[i].Diffuse.a < 1.0f )
+ continue;
+ pd3dDevice->SetMaterial( &m_pMaterials[i] );
+ pd3dDevice->SetTexture( 0, m_pTextures[i] );
+ }
+ m_pMesh->DrawSubset( i );
+ }
+ }
+
+ // Then, draw the subsets with alpha
+ if( bDrawAlphaSubsets && m_bUseMaterials )
+ {
+ for( DWORD i = 0; i < m_dwNumMaterials; i++ )
+ {
+ if( m_pMaterials[i].Diffuse.a == 1.0f )
+ continue;
+
+ // Set the material and texture
+ pd3dDevice->SetMaterial( &m_pMaterials[i] );
+ pd3dDevice->SetTexture( 0, m_pTextures[i] );
+ m_pMesh->DrawSubset( i );
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+HRESULT CDXUTXFileMesh::Render( ID3DXEffect* pEffect,
+ D3DXHANDLE hTexture,
+ D3DXHANDLE hDiffuse,
+ D3DXHANDLE hAmbient,
+ D3DXHANDLE hSpecular,
+ D3DXHANDLE hEmissive,
+ D3DXHANDLE hPower,
+ bool bDrawOpaqueSubsets,
+ bool bDrawAlphaSubsets )
+{
+ if( NULL == m_pMesh )
+ return E_FAIL;
+
+ UINT cPasses;
+ // Frist, draw the subsets without alpha
+ if( bDrawOpaqueSubsets )
+ {
+ pEffect->Begin( &cPasses, 0 );
+ for( UINT p = 0; p < cPasses; ++p )
+ {
+ pEffect->BeginPass( p );
+ for( DWORD i = 0; i < m_dwNumMaterials; i++ )
+ {
+ if( m_bUseMaterials )
+ {
+ if( m_pMaterials[i].Diffuse.a < 1.0f )
+ continue;
+ if( hTexture )
+ pEffect->SetTexture( hTexture, m_pTextures[i] );
+ // D3DCOLORVALUE and D3DXVECTOR4 are data-wise identical.
+ // No conversion is needed.
+ if( hDiffuse )
+ pEffect->SetVector( hDiffuse, ( D3DXVECTOR4* )&m_pMaterials[i].Diffuse );
+ if( hAmbient )
+ pEffect->SetVector( hAmbient, ( D3DXVECTOR4* )&m_pMaterials[i].Ambient );
+ if( hSpecular )
+ pEffect->SetVector( hSpecular, ( D3DXVECTOR4* )&m_pMaterials[i].Specular );
+ if( hEmissive )
+ pEffect->SetVector( hEmissive, ( D3DXVECTOR4* )&m_pMaterials[i].Emissive );
+ if( hPower )
+ pEffect->SetFloat( hPower, m_pMaterials[i].Power );
+ pEffect->CommitChanges();
+ }
+ m_pMesh->DrawSubset( i );
+ }
+ pEffect->EndPass();
+ }
+ pEffect->End();
+ }
+
+ // Then, draw the subsets with alpha
+ if( bDrawAlphaSubsets && m_bUseMaterials )
+ {
+ pEffect->Begin( &cPasses, 0 );
+ for( UINT p = 0; p < cPasses; ++p )
+ {
+ pEffect->BeginPass( p );
+ for( DWORD i = 0; i < m_dwNumMaterials; i++ )
+ {
+ if( m_bUseMaterials )
+ {
+ if( m_pMaterials[i].Diffuse.a == 1.0f )
+ continue;
+ if( hTexture )
+ pEffect->SetTexture( hTexture, m_pTextures[i] );
+ // D3DCOLORVALUE and D3DXVECTOR4 are data-wise identical.
+ // No conversion is needed.
+ if( hDiffuse )
+ pEffect->SetVector( hDiffuse, ( D3DXVECTOR4* )&m_pMaterials[i].Diffuse );
+ if( hAmbient )
+ pEffect->SetVector( hAmbient, ( D3DXVECTOR4* )&m_pMaterials[i].Ambient );
+ if( hSpecular )
+ pEffect->SetVector( hSpecular, ( D3DXVECTOR4* )&m_pMaterials[i].Specular );
+ if( hEmissive )
+ pEffect->SetVector( hEmissive, ( D3DXVECTOR4* )&m_pMaterials[i].Emissive );
+ if( hPower )
+ pEffect->SetFloat( hPower, m_pMaterials[i].Power );
+ pEffect->CommitChanges();
+ }
+ m_pMesh->DrawSubset( i );
+ }
+ pEffect->EndPass();
+ }
+ pEffect->End();
+ }
+
+ return S_OK;
+}