1312 lines
46 KiB
C++
1312 lines
46 KiB
C++
//--------------------------------------------------------------------------------------
|
|
// 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.
|
|
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// http://go.microsoft.com/fwlink/?LinkId=320437
|
|
//--------------------------------------------------------------------------------------
|
|
#include "DXUT.h"
|
|
#include "SDKMesh.h"
|
|
#include "SDKMisc.h"
|
|
|
|
using namespace DirectX;
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
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 = nullptr;
|
|
pMaterials[m].pNormalTexture11 = nullptr;
|
|
pMaterials[m].pSpecularTexture11 = nullptr;
|
|
pMaterials[m].pDiffuseRV11 = nullptr;
|
|
pMaterials[m].pNormalRV11 = nullptr;
|
|
pMaterials[m].pSpecularRV11 = nullptr;
|
|
|
|
// 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 = nullptr;
|
|
pMaterials[m].pNormalTexture11 = nullptr;
|
|
pMaterials[m].pSpecularTexture11 = nullptr;
|
|
pMaterials[m].pDiffuseRV11 = nullptr;
|
|
pMaterials[m].pNormalRV11 = nullptr;
|
|
pMaterials[m].pSpecularRV11 = nullptr;
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
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 );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
DXUT_SetDebugName(pHeader->pVB11, "CDXUTSDKMesh");
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
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 );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
DXUT_SetDebugName(pHeader->pIB11, "CDXUTSDKMesh");
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
HRESULT CDXUTSDKMesh::CreateFromFile( ID3D11Device* pDev11,
|
|
LPCWSTR szFileName,
|
|
SDKMESH_CALLBACKS11* pLoaderCallbacks11 )
|
|
{
|
|
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, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,
|
|
nullptr );
|
|
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, nullptr, FALSE );
|
|
|
|
// Get the file size
|
|
LARGE_INTEGER FileSize;
|
|
GetFileSizeEx( m_hFile, &FileSize );
|
|
UINT cBytes = FileSize.LowPart;
|
|
|
|
// Allocate memory
|
|
m_pStaticMeshData = new (std::nothrow) 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, nullptr ) )
|
|
hr = E_FAIL;
|
|
|
|
CloseHandle( m_hFile );
|
|
|
|
if( SUCCEEDED( hr ) )
|
|
{
|
|
hr = CreateFromMemory( pDev11,
|
|
m_pStaticMeshData,
|
|
cBytes,
|
|
false,
|
|
pLoaderCallbacks11 );
|
|
if( FAILED( hr ) )
|
|
delete []m_pStaticMeshData;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
_Use_decl_annotations_
|
|
HRESULT CDXUTSDKMesh::CreateFromMemory( ID3D11Device* pDev11,
|
|
BYTE* pData,
|
|
size_t DataBytes,
|
|
bool bCopyStatic,
|
|
SDKMESH_CALLBACKS11* pLoaderCallbacks11 )
|
|
{
|
|
XMFLOAT3 lower;
|
|
XMFLOAT3 upper;
|
|
|
|
m_pDev11 = pDev11;
|
|
|
|
if ( DataBytes < sizeof(SDKMESH_HEADER) )
|
|
return E_FAIL;
|
|
|
|
// Set outstanding resources to zero
|
|
m_NumOutstandingResources = 0;
|
|
|
|
if( bCopyStatic )
|
|
{
|
|
auto pHeader = reinterpret_cast<SDKMESH_HEADER*>( pData );
|
|
|
|
SIZE_T StaticSize = ( SIZE_T )( pHeader->HeaderSize + pHeader->NonBufferDataSize );
|
|
if ( DataBytes < StaticSize )
|
|
return E_FAIL;
|
|
|
|
m_pHeapData = new (std::nothrow) BYTE[ StaticSize ];
|
|
if( !m_pHeapData )
|
|
return E_OUTOFMEMORY;
|
|
|
|
m_pStaticMeshData = m_pHeapData;
|
|
|
|
memcpy( m_pStaticMeshData, pData, StaticSize );
|
|
}
|
|
else
|
|
{
|
|
m_pHeapData = pData;
|
|
m_pStaticMeshData = pData;
|
|
}
|
|
|
|
// Pointer fixup
|
|
m_pMeshHeader = reinterpret_cast<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 )
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
// 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 (std::nothrow) BYTE*[m_pMeshHeader->NumVertexBuffers];
|
|
if ( !m_ppVertices )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
for( UINT i = 0; i < m_pMeshHeader->NumVertexBuffers; i++ )
|
|
{
|
|
BYTE* pVertices = nullptr;
|
|
pVertices = ( BYTE* )( pBufferData + ( m_pVertexBufferArray[i].DataOffset - BufferDataStart ) );
|
|
|
|
if( pDev11 )
|
|
CreateVertexBuffer( pDev11, &m_pVertexBufferArray[i], pVertices, pLoaderCallbacks11 );
|
|
|
|
m_ppVertices[i] = pVertices;
|
|
}
|
|
|
|
// Create IBs
|
|
m_ppIndices = new (std::nothrow) BYTE*[m_pMeshHeader->NumIndexBuffers];
|
|
if ( !m_ppIndices )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
for( UINT i = 0; i < m_pMeshHeader->NumIndexBuffers; i++ )
|
|
{
|
|
BYTE* pIndices = nullptr;
|
|
pIndices = ( BYTE* )( pBufferData + ( m_pIndexBufferArray[i].DataOffset - BufferDataStart ) );
|
|
|
|
if( pDev11 )
|
|
CreateIndexBuffer( pDev11, &m_pIndexBufferArray[i], pIndices, pLoaderCallbacks11 );
|
|
|
|
m_ppIndices[i] = pIndices;
|
|
}
|
|
|
|
// Load Materials
|
|
if( pDev11 )
|
|
LoadMaterials( pDev11, m_pMaterialArray, m_pMeshHeader->NumMaterials, pLoaderCallbacks11 );
|
|
|
|
// Create a place to store our bind pose frame matrices
|
|
m_pBindPoseFrameMatrices = new (std::nothrow) XMFLOAT4X4[ m_pMeshHeader->NumFrames ];
|
|
if( !m_pBindPoseFrameMatrices )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Create a place to store our transformed frame matrices
|
|
m_pTransformedFrameMatrices = new (std::nothrow) XMFLOAT4X4[ m_pMeshHeader->NumFrames ];
|
|
if( !m_pTransformedFrameMatrices )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
m_pWorldPoseFrameMatrices = new (std::nothrow) XMFLOAT4X4[ m_pMeshHeader->NumFrames ];
|
|
if( !m_pWorldPoseFrameMatrices )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
SDKMESH_SUBSET* pSubset = nullptr;
|
|
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 = nullptr;
|
|
//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++;
|
|
XMFLOAT3 *pt = (XMFLOAT3*)&(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 );
|
|
}
|
|
|
|
XMFLOAT3 half( ( upper.x - lower.x ) * 0.5f,
|
|
( upper.y - lower.y ) * 0.5f,
|
|
( upper.z - lower.z ) * 0.5f );
|
|
|
|
currentMesh->BoundingBoxCenter.x = lower.x + half.x;
|
|
currentMesh->BoundingBoxCenter.y = lower.y + half.y;
|
|
currentMesh->BoundingBoxCenter.z = lower.z + half.z;
|
|
|
|
currentMesh->BoundingBoxExtents = half;
|
|
|
|
}
|
|
// Update
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// transform bind pose frame using a recursive traversal
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
void CDXUTSDKMesh::TransformBindPoseFrame( UINT iFrame, CXMMATRIX parentWorld )
|
|
{
|
|
if( !m_pBindPoseFrameMatrices )
|
|
return;
|
|
|
|
// Transform ourselves
|
|
XMMATRIX m = XMLoadFloat4x4( &m_pFrameArray[iFrame].Matrix );
|
|
XMMATRIX mLocalWorld = XMMatrixMultiply( m, parentWorld );
|
|
XMStoreFloat4x4( &m_pBindPoseFrameMatrices[iFrame], mLocalWorld );
|
|
|
|
// Transform our siblings
|
|
if( m_pFrameArray[iFrame].SiblingFrame != INVALID_FRAME )
|
|
{
|
|
TransformBindPoseFrame( m_pFrameArray[iFrame].SiblingFrame, parentWorld );
|
|
}
|
|
|
|
// Transform our children
|
|
if( m_pFrameArray[iFrame].ChildFrame != INVALID_FRAME )
|
|
{
|
|
TransformBindPoseFrame( m_pFrameArray[iFrame].ChildFrame, mLocalWorld );
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// transform frame using a recursive traversal
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
void CDXUTSDKMesh::TransformFrame( UINT iFrame, CXMMATRIX parentWorld, double fTime )
|
|
{
|
|
// Get the tick data
|
|
XMMATRIX mLocalTransform;
|
|
|
|
UINT iTick = GetAnimationKeyFromTime( fTime );
|
|
|
|
if( INVALID_ANIMATION_DATA != m_pFrameArray[iFrame].AnimationDataIndex )
|
|
{
|
|
auto pFrameData = &m_pAnimationFrameData[ m_pFrameArray[iFrame].AnimationDataIndex ];
|
|
auto pData = &pFrameData->pAnimationData[ iTick ];
|
|
|
|
// turn it into a matrix (Ignore scaling for now)
|
|
XMFLOAT3 parentPos = pData->Translation;
|
|
XMMATRIX mTranslate = XMMatrixTranslation( parentPos.x, parentPos.y, parentPos.z );
|
|
|
|
XMVECTOR quat = XMVectorSet( pData->Orientation.x, pData->Orientation.y, pData->Orientation.z, pData->Orientation.w );
|
|
if ( XMVector4Equal( quat, g_XMZero ) )
|
|
quat = XMQuaternionIdentity();
|
|
quat = XMQuaternionNormalize( quat );
|
|
XMMATRIX mQuat = XMMatrixRotationQuaternion( quat );
|
|
mLocalTransform = ( mQuat * mTranslate );
|
|
}
|
|
else
|
|
{
|
|
mLocalTransform = XMLoadFloat4x4( &m_pFrameArray[iFrame].Matrix );
|
|
}
|
|
|
|
// Transform ourselves
|
|
XMMATRIX mLocalWorld = XMMatrixMultiply( mLocalTransform, parentWorld );
|
|
XMStoreFloat4x4( &m_pTransformedFrameMatrices[iFrame], mLocalWorld );
|
|
XMStoreFloat4x4( &m_pWorldPoseFrameMatrices[iFrame], mLocalWorld );
|
|
|
|
// Transform our siblings
|
|
if( m_pFrameArray[iFrame].SiblingFrame != INVALID_FRAME )
|
|
{
|
|
TransformFrame( m_pFrameArray[iFrame].SiblingFrame, parentWorld, fTime );
|
|
}
|
|
|
|
// Transform our children
|
|
if( m_pFrameArray[iFrame].ChildFrame != INVALID_FRAME )
|
|
{
|
|
TransformFrame( m_pFrameArray[iFrame].ChildFrame, mLocalWorld, fTime );
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// transform frame assuming that it is an absolute transformation
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
void CDXUTSDKMesh::TransformFrameAbsolute( UINT iFrame, double fTime )
|
|
{
|
|
UINT iTick = GetAnimationKeyFromTime( fTime );
|
|
|
|
if( INVALID_ANIMATION_DATA != m_pFrameArray[iFrame].AnimationDataIndex )
|
|
{
|
|
auto pFrameData = &m_pAnimationFrameData[ m_pFrameArray[iFrame].AnimationDataIndex ];
|
|
auto pData = &pFrameData->pAnimationData[ iTick ];
|
|
auto pDataOrig = &pFrameData->pAnimationData[ 0 ];
|
|
|
|
XMMATRIX mTrans1 = XMMatrixTranslation( -pDataOrig->Translation.x, -pDataOrig->Translation.y, -pDataOrig->Translation.z );
|
|
XMMATRIX mTrans2 = XMMatrixTranslation( pData->Translation.x, pData->Translation.y, pData->Translation.z );
|
|
|
|
XMVECTOR quat1 = XMVectorSet( pDataOrig->Orientation.x, pDataOrig->Orientation.y, pDataOrig->Orientation.z, pDataOrig->Orientation.w );
|
|
quat1 = XMQuaternionInverse( quat1 );
|
|
XMMATRIX mRot1 = XMMatrixRotationQuaternion( quat1 );
|
|
XMMATRIX mInvTo = mTrans1 * mRot1;
|
|
|
|
XMVECTOR quat2 = XMVectorSet( pData->Orientation.x, pData->Orientation.y, pData->Orientation.z, pData->Orientation.w );
|
|
XMMATRIX mRot2 = XMMatrixRotationQuaternion( quat2 );
|
|
XMMATRIX mFrom = mRot2 * mTrans2;
|
|
|
|
XMMATRIX mOutput = mInvTo * mFrom;
|
|
XMStoreFloat4x4( &m_pTransformedFrameMatrices[iFrame], mOutput );
|
|
}
|
|
}
|
|
|
|
#define MAX_D3D11_VERTEX_STREAMS D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
void CDXUTSDKMesh::RenderMesh( UINT iMesh,
|
|
bool bAdjacent,
|
|
ID3D11DeviceContext* pd3dDeviceContext,
|
|
UINT iDiffuseSlot,
|
|
UINT iNormalSlot,
|
|
UINT iSpecularSlot )
|
|
{
|
|
if( 0 < GetOutstandingBufferResources() )
|
|
return;
|
|
|
|
auto 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;
|
|
|
|
auto 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 = nullptr;
|
|
SDKMESH_MATERIAL* pMat = nullptr;
|
|
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 );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
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 );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
CDXUTSDKMesh::CDXUTSDKMesh() : m_NumOutstandingResources( 0 ),
|
|
m_bLoading( false ),
|
|
m_hFile( 0 ),
|
|
m_hFileMappingObject( 0 ),
|
|
m_pMeshHeader( nullptr ),
|
|
m_pStaticMeshData( nullptr ),
|
|
m_pHeapData( nullptr ),
|
|
m_pAdjacencyIndexBufferArray( nullptr ),
|
|
m_pAnimationData( nullptr ),
|
|
m_pAnimationHeader( nullptr ),
|
|
m_ppVertices( nullptr ),
|
|
m_ppIndices( nullptr ),
|
|
m_pBindPoseFrameMatrices( nullptr ),
|
|
m_pTransformedFrameMatrices( nullptr ),
|
|
m_pWorldPoseFrameMatrices( nullptr ),
|
|
m_pDev11( nullptr )
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
CDXUTSDKMesh::~CDXUTSDKMesh()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
HRESULT CDXUTSDKMesh::Create( ID3D11Device* pDev11, LPCWSTR szFileName, SDKMESH_CALLBACKS11* pLoaderCallbacks )
|
|
{
|
|
return CreateFromFile( pDev11, szFileName, pLoaderCallbacks );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
HRESULT CDXUTSDKMesh::Create( ID3D11Device* pDev11, BYTE* pData, size_t DataBytes, bool bCopyStatic, SDKMESH_CALLBACKS11* pLoaderCallbacks )
|
|
{
|
|
return CreateFromMemory( pDev11, pData, DataBytes, bCopyStatic, pLoaderCallbacks );
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
HRESULT CDXUTSDKMesh::LoadAnimation( _In_z_ const 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, nullptr, OPEN_EXISTING,
|
|
FILE_FLAG_SEQUENTIAL_SCAN, nullptr );
|
|
if( INVALID_HANDLE_VALUE == hFile )
|
|
return DXUTERR_MEDIANOTFOUND;
|
|
|
|
/////////////////////////
|
|
// Header
|
|
SDKANIMATION_FILE_HEADER fileheader;
|
|
if( !ReadFile( hFile, &fileheader, sizeof( SDKANIMATION_FILE_HEADER ), &dwBytesRead, nullptr ) )
|
|
{
|
|
CloseHandle(hFile);
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
//allocate
|
|
m_pAnimationData = new (std::nothrow) BYTE[ ( size_t )( sizeof( SDKANIMATION_FILE_HEADER ) + fileheader.AnimationDataSize ) ];
|
|
if( !m_pAnimationData )
|
|
{
|
|
CloseHandle(hFile);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// read it all in
|
|
liMove.QuadPart = 0;
|
|
if( !SetFilePointerEx( hFile, liMove, nullptr, FILE_BEGIN ) )
|
|
{
|
|
CloseHandle(hFile);
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
if( !ReadFile( hFile, m_pAnimationData, ( DWORD )( sizeof( SDKANIMATION_FILE_HEADER ) +
|
|
fileheader.AnimationDataSize ), &dwBytesRead, nullptr ) )
|
|
{
|
|
CloseHandle(hFile);
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
// 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 );
|
|
auto pFrame = FindFrame( m_pAnimationFrameData[i].FrameName );
|
|
if( pFrame )
|
|
{
|
|
pFrame->AnimationDataIndex = i;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
void CDXUTSDKMesh::Destroy()
|
|
{
|
|
if( !CheckLoadDone() )
|
|
return;
|
|
|
|
if( m_pStaticMeshData )
|
|
{
|
|
if( m_pMaterialArray )
|
|
{
|
|
for( UINT64 m = 0; m < m_pMeshHeader->NumMaterials; m++ )
|
|
{
|
|
if( m_pDev11 )
|
|
{
|
|
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++ )
|
|
{
|
|
SAFE_RELEASE( m_pVertexBufferArray[i].pVB11 );
|
|
}
|
|
|
|
for( UINT64 i = 0; i < m_pMeshHeader->NumIndexBuffers; i++ )
|
|
{
|
|
SAFE_RELEASE( m_pIndexBufferArray[i].pIB11 );
|
|
}
|
|
}
|
|
|
|
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 = nullptr;
|
|
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 = nullptr;
|
|
m_pVertexBufferArray = nullptr;
|
|
m_pIndexBufferArray = nullptr;
|
|
m_pMeshArray = nullptr;
|
|
m_pSubsetArray = nullptr;
|
|
m_pFrameArray = nullptr;
|
|
m_pMaterialArray = nullptr;
|
|
|
|
m_pAnimationHeader = nullptr;
|
|
m_pAnimationFrameData = nullptr;
|
|
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// transform the mesh frames according to the animation for time fTime
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
void CDXUTSDKMesh::TransformMesh( CXMMATRIX world, double fTime )
|
|
{
|
|
if( !m_pAnimationHeader || FTT_RELATIVE == m_pAnimationHeader->FrameTransformType )
|
|
{
|
|
TransformFrame( 0, world, fTime );
|
|
|
|
// For each frame, move the transform to the bind pose, then
|
|
// move it to the final position
|
|
for( UINT i = 0; i < m_pMeshHeader->NumFrames; i++ )
|
|
{
|
|
XMMATRIX m = XMLoadFloat4x4( &m_pBindPoseFrameMatrices[i] );
|
|
XMMATRIX mInvBindPose = XMMatrixInverse( nullptr, m );
|
|
m = XMLoadFloat4x4( &m_pTransformedFrameMatrices[i] );
|
|
XMMATRIX mFinal = mInvBindPose * m;
|
|
XMStoreFloat4x4( &m_pTransformedFrameMatrices[i], mFinal );
|
|
}
|
|
}
|
|
else if( FTT_ABSOLUTE == m_pAnimationHeader->FrameTransformType )
|
|
{
|
|
for( UINT i = 0; i < m_pAnimationHeader->NumFrames; i++ )
|
|
TransformFrameAbsolute( i, fTime );
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
void CDXUTSDKMesh::Render( ID3D11DeviceContext* pd3dDeviceContext,
|
|
UINT iDiffuseSlot,
|
|
UINT iNormalSlot,
|
|
UINT iSpecularSlot )
|
|
{
|
|
RenderFrame( 0, false, pd3dDeviceContext, iDiffuseSlot, iNormalSlot, iSpecularSlot );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
void CDXUTSDKMesh::RenderAdjacent( ID3D11DeviceContext* pd3dDeviceContext,
|
|
UINT iDiffuseSlot,
|
|
UINT iNormalSlot,
|
|
UINT iSpecularSlot )
|
|
{
|
|
RenderFrame( 0, true, pd3dDeviceContext, iDiffuseSlot, iNormalSlot, iSpecularSlot );
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
D3D11_PRIMITIVE_TOPOLOGY CDXUTSDKMesh::GetPrimitiveType11( _In_ 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( _In_ UINT iMesh ) const
|
|
{
|
|
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( _In_ UINT iMesh, _In_ UINT iVB ) const
|
|
{
|
|
return m_pVertexBufferArray[ m_pMeshArray[ iMesh ].VertexBuffers[iVB] ].pVB11;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
ID3D11Buffer* CDXUTSDKMesh::GetIB11( _In_ UINT iMesh ) const
|
|
{
|
|
return m_pIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].pIB11;
|
|
}
|
|
SDKMESH_INDEX_TYPE CDXUTSDKMesh::GetIndexType( _In_ UINT iMesh ) const
|
|
{
|
|
return ( SDKMESH_INDEX_TYPE ) m_pIndexBufferArray[m_pMeshArray[ iMesh ].IndexBuffer].IndexType;
|
|
}
|
|
//--------------------------------------------------------------------------------------
|
|
ID3D11Buffer* CDXUTSDKMesh::GetAdjIB11( _In_ UINT iMesh ) const
|
|
{
|
|
return m_pAdjacencyIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].pIB11;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
const char* CDXUTSDKMesh::GetMeshPathA() const
|
|
{
|
|
return m_strPath;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
const WCHAR* CDXUTSDKMesh::GetMeshPathW() const
|
|
{
|
|
return m_strPathW;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT CDXUTSDKMesh::GetNumMeshes() const
|
|
{
|
|
if( !m_pMeshHeader )
|
|
return 0;
|
|
return m_pMeshHeader->NumMeshes;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT CDXUTSDKMesh::GetNumMaterials() const
|
|
{
|
|
if( !m_pMeshHeader )
|
|
return 0;
|
|
return m_pMeshHeader->NumMaterials;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT CDXUTSDKMesh::GetNumVBs() const
|
|
{
|
|
if( !m_pMeshHeader )
|
|
return 0;
|
|
return m_pMeshHeader->NumVertexBuffers;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT CDXUTSDKMesh::GetNumIBs() const
|
|
{
|
|
if( !m_pMeshHeader )
|
|
return 0;
|
|
return m_pMeshHeader->NumIndexBuffers;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
ID3D11Buffer* CDXUTSDKMesh::GetVB11At( _In_ UINT iVB ) const
|
|
{
|
|
return m_pVertexBufferArray[ iVB ].pVB11;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
ID3D11Buffer* CDXUTSDKMesh::GetIB11At( _In_ UINT iIB ) const
|
|
{
|
|
return m_pIndexBufferArray[ iIB ].pIB11;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
BYTE* CDXUTSDKMesh::GetRawVerticesAt( _In_ UINT iVB ) const
|
|
{
|
|
return m_ppVertices[iVB];
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
BYTE* CDXUTSDKMesh::GetRawIndicesAt( _In_ UINT iIB ) const
|
|
{
|
|
return m_ppIndices[iIB];
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
SDKMESH_MATERIAL* CDXUTSDKMesh::GetMaterial( _In_ UINT iMaterial ) const
|
|
{
|
|
return &m_pMaterialArray[ iMaterial ];
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
SDKMESH_MESH* CDXUTSDKMesh::GetMesh( _In_ UINT iMesh ) const
|
|
{
|
|
return &m_pMeshArray[ iMesh ];
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT CDXUTSDKMesh::GetNumSubsets( _In_ UINT iMesh ) const
|
|
{
|
|
return m_pMeshArray[ iMesh ].NumSubsets;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
SDKMESH_SUBSET* CDXUTSDKMesh::GetSubset( _In_ UINT iMesh, _In_ UINT iSubset ) const
|
|
{
|
|
return &m_pSubsetArray[ m_pMeshArray[ iMesh ].pSubsets[iSubset] ];
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT CDXUTSDKMesh::GetVertexStride( _In_ UINT iMesh, _In_ UINT iVB ) const
|
|
{
|
|
return ( UINT )m_pVertexBufferArray[ m_pMeshArray[ iMesh ].VertexBuffers[iVB] ].StrideBytes;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT CDXUTSDKMesh::GetNumFrames() const
|
|
{
|
|
return m_pMeshHeader->NumFrames;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
SDKMESH_FRAME* CDXUTSDKMesh::GetFrame( _In_ UINT iFrame ) const
|
|
{
|
|
assert( iFrame < m_pMeshHeader->NumFrames );
|
|
return &m_pFrameArray[ iFrame ];
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
SDKMESH_FRAME* CDXUTSDKMesh::FindFrame( _In_z_ const char* pszName ) const
|
|
{
|
|
for( UINT i = 0; i < m_pMeshHeader->NumFrames; i++ )
|
|
{
|
|
if( _stricmp( m_pFrameArray[i].Name, pszName ) == 0 )
|
|
{
|
|
return &m_pFrameArray[i];
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT64 CDXUTSDKMesh::GetNumVertices( _In_ UINT iMesh, _In_ UINT iVB ) const
|
|
{
|
|
return m_pVertexBufferArray[ m_pMeshArray[ iMesh ].VertexBuffers[iVB] ].NumVertices;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT64 CDXUTSDKMesh::GetNumIndices( _In_ UINT iMesh ) const
|
|
{
|
|
return m_pIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].NumIndices;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
XMVECTOR CDXUTSDKMesh::GetMeshBBoxCenter( _In_ UINT iMesh ) const
|
|
{
|
|
return XMLoadFloat3( &m_pMeshArray[iMesh].BoundingBoxCenter );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
XMVECTOR CDXUTSDKMesh::GetMeshBBoxExtents( _In_ UINT iMesh ) const
|
|
{
|
|
return XMLoadFloat3( &m_pMeshArray[iMesh].BoundingBoxExtents );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT CDXUTSDKMesh::GetOutstandingResources() const
|
|
{
|
|
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 ++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return outstandingResources;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT CDXUTSDKMesh::GetOutstandingBufferResources() const
|
|
{
|
|
UINT outstandingResources = 0;
|
|
if( !m_pMeshHeader )
|
|
return 1;
|
|
|
|
return outstandingResources;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
bool CDXUTSDKMesh::CheckLoadDone()
|
|
{
|
|
if( 0 == GetOutstandingResources() )
|
|
{
|
|
m_bLoading = false;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
bool CDXUTSDKMesh::IsLoaded() const
|
|
{
|
|
if( m_pStaticMeshData && !m_bLoading )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
bool CDXUTSDKMesh::IsLoading() const
|
|
{
|
|
return m_bLoading;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
void CDXUTSDKMesh::SetLoading( _In_ bool bLoading )
|
|
{
|
|
m_bLoading = bLoading;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
BOOL CDXUTSDKMesh::HadLoadingError() const
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT CDXUTSDKMesh::GetNumInfluences( _In_ UINT iMesh ) const
|
|
{
|
|
return m_pMeshArray[iMesh].NumFrameInfluences;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
XMMATRIX CDXUTSDKMesh::GetMeshInfluenceMatrix( _In_ UINT iMesh, _In_ UINT iInfluence ) const
|
|
{
|
|
UINT iFrame = m_pMeshArray[iMesh].pFrameInfluences[ iInfluence ];
|
|
return XMLoadFloat4x4( &m_pTransformedFrameMatrices[iFrame] );
|
|
}
|
|
|
|
XMMATRIX CDXUTSDKMesh::GetWorldMatrix( _In_ UINT iFrameIndex ) const
|
|
{
|
|
return XMLoadFloat4x4( &m_pWorldPoseFrameMatrices[iFrameIndex] );
|
|
}
|
|
|
|
XMMATRIX CDXUTSDKMesh::GetInfluenceMatrix( _In_ UINT iFrameIndex ) const
|
|
{
|
|
return XMLoadFloat4x4( &m_pTransformedFrameMatrices[iFrameIndex] );
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
UINT CDXUTSDKMesh::GetAnimationKeyFromTime( _In_ double fTime ) const
|
|
{
|
|
if( !m_pAnimationHeader )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
UINT iTick = ( UINT )( m_pAnimationHeader->AnimationFPS * fTime );
|
|
|
|
iTick = iTick % ( m_pAnimationHeader->NumAnimationKeys - 1 );
|
|
iTick ++;
|
|
|
|
return iTick;
|
|
}
|
|
|
|
_Use_decl_annotations_
|
|
bool CDXUTSDKMesh::GetAnimationProperties( UINT* pNumKeys, float* pFrameTime ) const
|
|
{
|
|
if( !m_pAnimationHeader )
|
|
{
|
|
*pNumKeys = 0;
|
|
*pFrameTime = 0;
|
|
return false;
|
|
}
|
|
|
|
*pNumKeys = m_pAnimationHeader->NumAnimationKeys;
|
|
*pFrameTime = 1.0f / (float)m_pAnimationHeader->AnimationFPS;
|
|
|
|
return true;
|
|
}
|