#include <vector>
#include "sas.h"
#include "DXUT.h"
#include "resource.h"
#include "App.h"
#include "Camera.h"
#include "FileSystem.h"
#include "Model.h"
#include "Render.h"
ModelSubset* ModelSubset::GetNextModelSubset()
{
return CastMeshContainerToModelSubset( Container->pNextMeshContainer );
}
DXVMESHCONTAINER* ModelSubset::AsMeshContainer()
{
return Container;
}
Material::~Material()
{
SAFE_DELETE(Effect);
};
ModelSubset* ModelSubset::CastMeshContainerToModelSubset( const D3DXMESHCONTAINER* a )
{
return a ? ((DXVMESHCONTAINER*)a)->Owner : NULL;
}
DXVMESHCONTAINER* ModelSubset::CastModelSubsetToMeshContainer( const ModelSubset* a )
{
return a ? a->Container : NULL;
}
Transform* Transform::GetFirstChild()
{
return (Transform*)( pFrameFirstChild );
}
Transform* Transform::GetNextSibling()
{
return (Transform*)( pFrameSibling );
}
ModelSubset* Transform::GetModelSubset()
{
return pMeshContainer ? ((DXVMESHCONTAINER*)pMeshContainer)->Owner : NULL;
}
D3DXFRAME* Transform::AsFrame()
{
return this;
}
DXVMESHCONTAINER::DXVMESHCONTAINER(ModelSubset* owner)
{
Name = NULL;
MeshData.pMesh = NULL;
pMaterials = NULL;
pEffects = NULL;
pAdjacency = NULL;
pSkinInfo = NULL;
pNextMeshContainer = NULL;
Owner = owner;
}
DXVMESHCONTAINER::~DXVMESHCONTAINER()
{
SAFE_DELETE_ARRAY( Name );
SAFE_RELEASE( MeshData.pMesh );
if(pMaterials != Render::GetDefaultMaterial()
&& pEffects != Render::GetDefaultEffectInstance())
{
for( UINT iMat=0; iMat < NumMaterials; iMat++ )
{
if(pMaterials != NULL)
SAFE_DELETE_ARRAY( pMaterials[iMat].pTextureFilename );
if(pEffects != NULL)
{
SAFE_DELETE_ARRAY( pEffects[iMat].pEffectFilename );
for( UINT iDef=0; iDef < pEffects[iMat].NumDefaults; iDef++ )
{
SAFE_DELETE_ARRAY( pEffects[iMat].pDefaults[iDef].pParamName );
SAFE_DELETE_ARRAY( pEffects[iMat].pDefaults[iDef].pValue );
}
}
}
SAFE_DELETE_ARRAY( pMaterials );
SAFE_DELETE_ARRAY( pEffects );
}
SAFE_DELETE_ARRAY( pAdjacency );
SAFE_RELEASE( pSkinInfo );
LOOPSAFE_DELETE( pNextMeshContainer, DXVMESHCONTAINER );
if(Owner)
{
Owner->Container = NULL;
LOOPSAFE_DELETE(Owner, ModelSubset);
}
}
Transform::Transform()
{
Name=NULL;
D3DXMatrixIdentity( &TransformationMatrix );
pMeshContainer = NULL;
pFrameFirstChild = NULL;
pFrameSibling = NULL;
D3DXMatrixIdentity( &WorldMatrix );
}
//--------------------------------------------------------------------------------------
Transform::~Transform()
{
LOOPSAFE_DELETE( pFrameFirstChild, Transform );
LOOPSAFE_DELETE( pFrameSibling, Transform );
LOOPSAFE_DELETE( pMeshContainer, DXVMESHCONTAINER );
SAFE_DELETE_ARRAY( Name );
}
//--------------------------------------------------------------------------------------
ModelSubset::ModelSubset()
{
pBoundValueTable = NULL;
Container = new DXVMESHCONTAINER(this);
}
//--------------------------------------------------------------------------------------
ModelSubset::~ModelSubset()
{
for( UINT i=0; i < Materials.size(); i++ )
{
SAFE_DELETE( Materials[i] );
}
Materials.clear();
SAFE_DELETE( pBoundValueTable );
if(Container)
{
Container->Owner = NULL;
LOOPSAFE_DELETE(Container, DXVMESHCONTAINER);
}
}
//--------------------------------------------------------------------------------------
void Transform::UpdateMatrices( const D3DXMATRIX* pParentMatrix )
{
// Concatenate all matrices in the chain
if (pParentMatrix != NULL)
D3DXMatrixMultiply(&WorldMatrix, &TransformationMatrix, pParentMatrix);
else
WorldMatrix = TransformationMatrix;
for( Transform* itr = GetFirstChild();
(itr != NULL);
itr = itr->GetNextSibling() )
{
itr->UpdateMatrices( &WorldMatrix );
}
}
//--------------------------------------------------------------------------------------
HRESULT Transform::UpdateSkins(Transform* root)
{
HRESULT hr = S_OK;
if(root == NULL)
root = this;
for(ModelSubset* meshIterator = GetModelSubset() ;
(meshIterator != NULL) && SUCCEEDED(hr);
meshIterator = meshIterator->GetNextModelSubset() )
{
hr = meshIterator->UpdateSkins( *root, WorldMatrix );
if(FAILED(hr)) return hr;
}
for( Transform* itr = GetFirstChild();
(itr != NULL) && SUCCEEDED(hr);
itr = itr->GetNextSibling() )
{
hr = itr->UpdateSkins( root );
}
return hr;
}
//--------------------------------------------------------------------------------------
HRESULT ModelSubset::UpdateSkins( Transform& root, const D3DXMATRIX& worldMatrix )
{
HRESULT hr = S_OK;
// if there is a skinmesh, then setup the bone matrices
if ( HasSkin() )
{
static std::vector< D3DXMATRIX > BonePalette;
static std::vector< D3DXMATRIX > BoneInverseTransposePalette;
UINT cBones = GetBoneCount();
if(BonePalette.size() < cBones )
BonePalette.resize(cBones);
if(BoneInverseTransposePalette.size() < cBones )
BoneInverseTransposePalette.resize(cBones);
D3DXMATRIX worldToLocal;
D3DXMatrixInverse( &worldToLocal, NULL, &worldMatrix);
//prepare palette
for (UINT iBone = 0; iBone < cBones; iBone++)
{
D3DXMATRIX tmpMatrix;
Transform* pTransform = (Transform*) D3DXFrameFind( root.AsFrame(), GetBoneName(iBone) );
if (pTransform == NULL)
{
D3DXMatrixIdentity( &BonePalette[iBone] );
D3DXMatrixIdentity( &BoneInverseTransposePalette[iBone] );
}
else
{
D3DXMATRIX meshToJointToWorld;
D3DXMatrixMultiply
(
&tmpMatrix,
GetBoneOffset(iBone),
&pTransform->WorldMatrix
);
D3DXMatrixMultiply
(
&BonePalette[iBone],
&tmpMatrix,
&worldToLocal
);
D3DXMatrixInverse( &tmpMatrix, NULL, &BonePalette[iBone] );
D3DXMatrixTranspose( &BoneInverseTransposePalette[iBone], &tmpMatrix );
}
}
hr = UpdateSkins( &BonePalette.front(), &BoneInverseTransposePalette.front() );
}
return hr;
}
//--------------------------------------------------------------------------------------
char* ModelLoader::DuplicateString( LPCSTR Name )
{
if( NULL == Name )
return NULL;
char* result = NULL;
// No work to be done if name is NULL
// Allocate a new buffer
const UINT length = (UINT)strlen(Name) + 1;
result = new CHAR[length];
if( NULL == result )
return NULL;
// Copy the string and return
if( S_OK != StringCchCopyA( result, length, Name ) )
{
SAFE_DELETE_ARRAY(result);
return NULL;
}
return result;
}
//--------------------------------------------------------------------------------------
HRESULT ModelLoader::CreateFrame( LPCSTR Name, D3DXFRAME** ppFrameOut )
{
HRESULT hr = S_OK;
// Start clean
(*ppFrameOut) = NULL;
// Create a new frame
Transform* pNew = CreateTransform();
if( NULL == pNew )
{
hr = E_OUTO