www.pudn.com > notWow.rar > Model.cpp
#include "Model.h"
#include "Random.h"
extern Random g_Random;
int slotOrder[] =
{
CS_SHIRT,
CS_HEAD,
CS_NECK,
CS_SHOULDER,
CS_PANTS,
CS_BOOTS,
CS_CHEST,
CS_TABARD,
CS_BELT,
CS_BRACERS,
CS_GLOVES,
CS_HAND_RIGHT,
CS_HAND_LEFT,
CS_CAPE,
CS_QUIVER
};
int slotOrderWithRobe[] =
{
CS_SHIRT,
CS_HEAD,
CS_NECK,
CS_SHOULDER,
CS_BOOTS,
CS_PANTS,
CS_BRACERS,
CS_CHEST,
CS_GLOVES,
CS_TABARD,
CS_BELT,
CS_HAND_RIGHT,
CS_HAND_LEFT,
CS_CAPE,
CS_QUIVER
};
bool M2Model::InitCommom(char *M2File,int Size)
{
uint32 i;
HRESULT hr;
// get header
ModelHeader Header;
memcpy(&Header,M2File,sizeof(Header));
// get global sequences
if (Header.nGlobalSequences)
{
m_nGlobalSequences = Header.nGlobalSequences;
m_pGlobalSequences = new int[Header.nGlobalSequences];
memcpy(m_pGlobalSequences, (M2File + Header.ofsGlobalSequences),Header.nGlobalSequences * sizeof(int));
}
// ***********************************
// Build Attachments
if ((m_nAttachments = Header.nAttachments) > 0)
{
m_pAttachments = new ModelAttachment[m_nAttachments];
ModelAttachmentDef *attachments = (ModelAttachmentDef*)(M2File + Header.ofsAttachments);
for ( i = 0; i < m_nAttachments; ++ i)
{
m_pAttachments[i].Init(attachments[i],this);
}
}
if (Header.nAttachLookup)
{
int16 *p = (int16*)(M2File + Header.ofsAttachLookup);
for ( i = 0; i < Header.nAttachLookup; ++ i)
{
m_AttachmentLookup[i] = p[i];
}
}
// ************************************
// Light
if ((m_nLights = Header.nLights) > 0 )
{
m_pLights = new ModelLight[m_nLights];
ModelLightDef *lDefs = (ModelLightDef*)(M2File + Header.ofsLights);
for ( i = 0; i < m_nLights ; ++ i)
m_pLights[i].Init(M2File, lDefs[i], m_pGlobalSequences);
}
// ************************************
// Colors
if ((m_nColors = Header.nColors) > 0 )
{
m_pColors = new ModelColor[m_nColors];
ModelColorDef *colorDefs = (ModelColorDef*)(M2File + Header.ofsColors);
for ( i = 0; i < m_nColors; ++ i)
m_pColors[i].Init(M2File, colorDefs[i], m_pGlobalSequences);
}
// ************************************
// init transparency
if ((m_nTransparencies = Header.nTransparency) > 0 )
{
m_pTransparencies = new ModelTransparency[m_nTransparencies];
ModelTransDef *trDefs = (ModelTransDef*)(M2File + Header.ofsTransparency);
for ( i = 0; i < m_nTransparencies ; ++ i)
m_pTransparencies[i].Init(M2File, trDefs[i], m_pGlobalSequences);
}
// ***********************************
// Bounds
if ( (m_nBoundVertices = Header.nBoundingVertices) > 0)
{
m_pBoundVertices = new D3DXVECTOR3[m_nBoundVertices];
D3DXVECTOR3 *b = (D3DXVECTOR3*)(M2File + Header.ofsBoundingVertices);
for ( i = 0; i < m_nBoundVertices ; ++ i)
m_pBoundVertices[i] = fixCoordSystem(b[i]);
}
if ( ( m_nBoundIndices = Header.nBoundingTriangles ) > 0)
{
m_pBoundIndices = new uint16[m_nBoundIndices];
memcpy(m_pBoundIndices, M2File + Header.ofsBoundingTriangles, m_nBoundIndices*sizeof(uint16));
}
// ***********************************
// Particle systems
if ( (m_nPS = Header.nParticleEmitters) > 0)
{
ModelParticleEmitterDef *pdefs = (ModelParticleEmitterDef *)(M2File + Header.ofsParticleEmitters);
m_pPS = new ParticleSystem[m_nPS];
for ( i = 0; i < m_nPS ; ++ i)
{
m_pPS[i].Init(M2File, pdefs[i], m_pGlobalSequences,this);
}
}
return true;
}
bool M2Model::InitStatic(char *M2File,int Size)
{
uint32 i;
HRESULT hr;
// get header
ModelHeader Header;
memcpy(&Header,M2File,sizeof(Header));
// get original/global vertices list and fix
MODELSTATICVERTEX* pOrigVertices = new MODELSTATICVERTEX [Header.nVertices];
ModelVertex* ptOrigVertices = (ModelVertex*)(M2File + Header.ofsVertices);
int nOrigVertices = Header.nVertices;
for (i = 0; i < nOrigVertices; ++ i)
{
pOrigVertices[i].Pos = fixCoordSystem(ptOrigVertices[i].Pos);
pOrigVertices[i].Normal = fixCoordSystem(ptOrigVertices[i].Normal);
pOrigVertices[i].Texcoord = ptOrigVertices[i].Texcoords;
}
m_pBC = NULL;
// ****************************************
// Create Vertices and Indices from a View
// the original vertices is global vertices list.
// in a view,it gives a vertex indices list and a
// triangle(face) indices list.
// the vertex index is to the global
// vertices list.the index is this vertex's offset in
// global vertices list
// and the face index is to the vertex
// indices in the view
ModelView* pViews = (ModelView*)(M2File+ Header.ofsViews);
// choose a view
// there one or more views,select the first one here
int iViewChose = 0;
// the index to global vertices list
uint16 *VertexIndex = (uint16*)(M2File + pViews[iViewChose].ofsIndex);
m_nVertices = pViews->nIndex;
// the triangles(face)'s three vertices index to VertexIndex
uint16 *Triangles = (uint16*)(M2File + pViews[iViewChose].ofsTris);
m_nIndices = pViews[iViewChose].nTris;
uint16* pIndices = new uint16[m_nIndices];
for (i = 0; i < m_nIndices; ++ i)
{
pIndices[i] = VertexIndex[Triangles[i]];
}
// Create the vertex buffer
if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( m_nVertices * sizeof(MODELSTATICVERTEX),
0, MODELSTATICVERTEX::FVF ,
D3DPOOL_MANAGED, &m_pVB, NULL ) ) )
{
return false;
}
// Create the Index buffer
if( FAILED( hr = m_pd3dDevice->CreateIndexBuffer( m_nIndices * sizeof(uint16),
0, D3DFMT_INDEX16,
D3DPOOL_MANAGED, &m_pIB, NULL ) ) )
{
return false;
}
// fill the stream with original vertices info
MODELSTATICVERTEX* pVBVertices;
if( FAILED( hr = m_pVB->Lock( 0, 0, (VOID**)&pVBVertices, 0 ) ) )
return hr;
memcpy(pVBVertices,pOrigVertices,sizeof(MODELSTATICVERTEX)*nOrigVertices);
m_pVB->Unlock();
// Fill the index buffer
uint16* pIBIndex;
if( FAILED(m_pIB->Lock( 0, 0, (VOID**)&pIBIndex, 0 ) ) )
return false;
memcpy(pIBIndex,pIndices,sizeof(uint16)*m_nIndices);
m_pIB->Unlock();
delete [] pIndices;
delete [] pOrigVertices;
// ***********************************
// Get the Geosets
m_pShowGeosets = new bool[pViews[iViewChose].nSub];
// textures
ModelTextureDef *texdef = (ModelTextureDef*)(M2File + Header.ofsTextures);
if (Header.nTextures)
{
m_pTexturesID = new TextureID[Header.nTextures];
for (size_t i=0; i 0 )
{
m_pRenderPass = new ModelRenderPass[m_nRenderPass];
for( i = 0 ; i < m_nRenderPass ; ++ i)
{
m_pRenderPass[i].Init(M2File,pViews[iViewChose],Header,i);
}
}
// transparent parts come later
// std::sort(passes.begin(), passes.end());
return true;
}
bool M2Model::InitVB(char *M2File,int Size)
{
uint32 i;
HRESULT hr;
// get header
ModelHeader Header;
memcpy(&Header,M2File,sizeof(Header));
// ************************************
// Initialize the BonesContainer
// the Matrix Pallette
int nBones;
nBones = Header.nBones;
assert(nBones < 128);
// if m_nBones is greater then 128
// the index will be change into unsigned char type
bool* bBone = new bool[nBones]; // is the bone used in vertices blending
memset(bBone,0,sizeof(bool)*nBones);
// get original/global vertices list and fix
MODELVBVERTEX* pOrigVertices = new MODELVBVERTEX [Header.nVertices];
ModelVertex* ptOrigVertices = (ModelVertex*)(M2File + Header.ofsVertices);
int nOrigVertices = Header.nVertices;
for (i = 0; i < nOrigVertices; ++ i)
{
pOrigVertices[i].Pos = fixCoordSystem(ptOrigVertices[i].Pos);
pOrigVertices[i].Normal = fixCoordSystem(ptOrigVertices[i].Normal);
pOrigVertices[i].Texcoord = ptOrigVertices[i].Texcoords;
pOrigVertices[i].Blend1 = (float)ptOrigVertices[i].Weights[0] / 255.0f;
pOrigVertices[i].Blend2 = (float)ptOrigVertices[i].Weights[1] / 255.0f;
pOrigVertices[i].Blend3 = (float)ptOrigVertices[i].Weights[2] / 255.0f;
for(int j = 0 ; j < 4; ++ j)
{
assert(ptOrigVertices[i].Bones[j] < 128);
bBone[ptOrigVertices[i].Bones[j]] = true;
}
}
D3DXComputeBoundingSphere((D3DXVECTOR3*)pOrigVertices,nOrigVertices,
sizeof(MODELVBVERTEX),&m_vCenter,&m_fRadius );
D3DXComputeBoundingBox( (D3DXVECTOR3*)pOrigVertices, nOrigVertices,
sizeof(MODELVBVERTEX),&m_vMin,&m_vMax);
// get the count of bones which referenced by vetex blending
// and fix the indices
int Count = 0;
char BlendIndex[128]; //128 is max bones count
memset(BlendIndex,-1,128*sizeof(char));
for(int j = 0 ; j < nBones ; ++ j)
{
if(bBone[j])
{
BlendIndex[j] = Count;
++ Count;
}
}
// renumber the matrices pallette by BlendIndex
for (i = 0; i < nOrigVertices; ++ i)
{
for(int j = 0 ; j < 4 ; ++ j)
{
ptOrigVertices[i].Bones[j] = (uint8)BlendIndex[ptOrigVertices[i].Bones[j]];
}
pOrigVertices[i].Indices = *((DWORD*)ptOrigVertices[i].Bones);
}
m_pBC = new BonesContainer;
m_pBC->Init(nBones,Count,BlendIndex,M2File,Header,m_pGlobalSequences);
delete [] bBone;
// ****************************************
// Create Vertices and Indices from a View
// the original vertices is global vertices list.
// in a view,it gives a vertex indices list and a
// triangle(face) indices list.
// the vertex index is to the global
// vertices list.the index is this vertex's offset in
// global vertices list
// and the face index is to the vertex
// indices in the view
ModelView* pViews = (ModelView*)(M2File+ Header.ofsViews);
// choose a view
// there one or more views,select the first one here
int iViewChose = 0;
// the index to global vertices list
uint16 *VertexIndex = (uint16*)(M2File + pViews[iViewChose].ofsIndex);
m_nVertices = pViews->nIndex;
// the triangles(face)'s three vertices index to VertexIndex
uint16 *Triangles = (uint16*)(M2File + pViews[iViewChose].ofsTris);
m_nIndices = pViews[iViewChose].nTris;
uint16* pIndices = new uint16[m_nIndices];
for (i = 0; i < m_nIndices; ++ i)
{
pIndices[i] = VertexIndex[Triangles[i]];
}
// Create the vertex buffer
if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( m_nVertices * sizeof(MODELVBVERTEX),
0, MODELVBVERTEX::FVF ,
D3DPOOL_MANAGED, &m_pVB, NULL ) ) )
{
return false;
}
// Create the Index buffer
if( FAILED( hr = m_pd3dDevice->CreateIndexBuffer( m_nIndices * sizeof(uint16),
0, D3DFMT_INDEX16,
D3DPOOL_MANAGED, &m_pIB, NULL ) ) )
{
return false;
}
// fill the stream with original vertices info
MODELVBVERTEX* pVBVertices;
if( FAILED( hr = m_pVB->Lock( 0, 0, (VOID**)&pVBVertices, 0 ) ) )
return false;
memcpy(pVBVertices,pOrigVertices,sizeof(MODELVBVERTEX)*nOrigVertices);
m_pVB->Unlock();
// Fill the index buffer
uint16* pIBIndex;
if( FAILED(m_pIB->Lock( 0, 0, (VOID**)&pIBIndex, 0 ) ) )
return false;
memcpy(pIBIndex,pIndices,sizeof(uint16)*m_nIndices);
m_pIB->Unlock();
delete [] pIndices;
delete [] pOrigVertices;
// ***********************************
// Get the Geosets
m_pShowGeosets = new bool[pViews[iViewChose].nSub];
// textures
ModelTextureDef *texdef = (ModelTextureDef*)(M2File + Header.ofsTextures);
m_nTextures = Header.nTextures;
if (Header.nTextures)
{
m_pTexturesID = new TextureID[Header.nTextures];
for (size_t i=0; i 0 )
{
m_pRenderPass = new ModelRenderPass[m_nRenderPass];
for( i = 0 ; i < m_nRenderPass ; ++ i)
{
m_pRenderPass[i].Init(M2File,pViews[iViewChose],Header,i);
}
}
// std::sort(passes.begin(), passes.end());
return true;
}
bool M2Model::Init(char* pFile,int Size,MODELTYPE Type,LPDIRECT3DDEVICE9 pd3dDevice)
{
if(pd3dDevice == NULL)
return false;
Free();
m_pd3dDevice = pd3dDevice;
m_Type = Type;
m_Effect.Init(pd3dDevice);
bool rs = InitCommom(pFile,Size);
if(Type == MODEL_CHARACTER || Type == MODEL_CREATURE)
rs &= InitVB(pFile,Size);
else
rs &= InitStatic(pFile,Size);
if(!rs)
Free();
return rs;
}
void M2Model::SetDetails(char Geosets[])
{
// set geosets
for (int j = 0; j < m_nRenderPass ; ++ j)
{
int id = m_pRenderPass[j].m_GeosetID;
//if(id == 0)
// continue;
// hide top-of-head if we have hair.
//if (id == 1)
//{
// id为1是光头
//showGeosets[j] = bald;
//}
for (int i = 0; i < 16; ++ i)
{
// 一个人物共有16种Geoset,他们的id是从 100*i -- 100*(i+1)的
// 100*i是它的基id,cd.geosets[i]是它的偏移id
// 好像就i = 0 (发型)可以有id = 0;
// 其他的都没有偏移id为0的
// 这个只要利用id的 起始号+cd.geosets[i]就可以得到 所选择的cd.geosets[i]的真正id
// 并标示showGeosets[i],来画geoset[i]
int a = i*100, b = (i+1) * 100;
if (id>a && idFree();
if(m_pPS != NULL)
{
for(i = 0 ; i < m_nPS ; ++ i)
m_pPS[i].Free();
}
m_Effect.Free();
for(int i = 0 ; i < m_nTextures ; ++ i)
{
g_TexMgr.Delete(m_pTexturesID[i]);
}
SAFE_DELETE_A(m_pShowGeosets);
SAFE_DELETE_A(m_pGlobalSequences);
SAFE_DELETE_A(m_pAttachments);
SAFE_DELETE_A(m_pTexturesID);
SAFE_DELETE_A(m_pBoundVertices);
SAFE_DELETE_A(m_pBoundIndices);
SAFE_DELETE_A(m_pTransparencies);
SAFE_DELETE_A(m_pLights);
SAFE_DELETE_A(m_pColors);
SAFE_DELETE_A(m_pRenderPass);
SAFE_DELETE(m_pBC);
SAFE_DELETE_A(m_pPS);
SAFE_RELEASE(m_pVB);
SAFE_RELEASE(m_pIB);
m_pd3dDevice = NULL;
}
void M2Model::Update(D3DXMATRIX* pmatViewProj)
{
/*
// software vertex blending
for(int i = 0 ; i < m_nOrigVertices ; ++ i)
{
char index[4];
memcpy(index,&pVBVertices[i].Indices,sizeof(DWORD));
D3DXVECTOR3 v(0.0f,0.0f,0.0f);
D3DXVECTOR3 tv = VxM(&pVBVertices[i].Pos ,&pMat[index[0]]);
v += tv * pVBVertices[i].Blend1;
tv = VxM(&pVBVertices[i].Pos ,&pMat[index[1]]);
v += tv * pVBVertices[i].Blend2;
tv = VxM(&pVBVertices[i].Pos ,&pMat[index[2]]);
v += tv * pVBVertices[i].Blend3;
tv = VxM(&pVBVertices[i].Pos ,&pMat[index[3]]);
v += tv * (1 - pVBVertices[i].Blend3 - pVBVertices[i].Blend2 - pVBVertices[i].Blend1);
pVBVertices[i].Pos = v;
}
*/
// Set Effect Parameter
m_Effect.SetViewProjMatrix(pmatViewProj );
if(m_Type == MODEL_CHARACTER || m_Type == MODEL_CREATURE)
{
m_Effect.SetMatrixPalette(m_pBC->GetMatrices(),m_pBC->GetBlendMatricesCount());
}
}
bool M2Model::Render(float CameraDist,bool bFar)
{
UINT nPasses,iPass;
HRESULT hr;
bool rs = true;
// m_pEffect->SetTexture(m_hTexture,g_TexMgr.GetTexture(0));
DWORD FVF;
int VertexSize;
if(m_Type == MODEL_CHARACTER || m_Type == MODEL_CREATURE)
{
FVF = MODELVBVERTEX::FVF;
VertexSize = sizeof(MODELVBVERTEX);
}
else
{
//FVF = MODELSTATICVERTEX::FVF;
//VertexSize = sizeof(MODELSTATICVERTEX);
}
m_pd3dDevice->SetFVF( FVF );
m_pd3dDevice->SetIndices( m_pIB );
m_pd3dDevice->SetStreamSource( 0, m_pVB,0,VertexSize );
m_Effect.SetTechnique(m_Type);
m_Effect.Begin(&nPasses, 0);
for (iPass = 0; iPass < nPasses; iPass++)
{
m_Effect.BeginPass(iPass);
for(int i = 0 ; i < m_nRenderPass ; ++ i)
{
if(!m_pRenderPass[i].SetState(this))
continue;
hr = m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,
0,
m_pRenderPass[i].m_VertexStart,
m_pRenderPass[i].m_VertexCount, // number of vertices
m_pRenderPass[i].m_IndexStart,
m_pRenderPass[i].m_IndexCount/3); // number of primitives
rs &= SUCCEEDED(hr);
}
m_Effect.EndPass();
}
m_Effect.End();
return rs;
}
D3DXMATRIX* M2Model::SetupAttachment(int id)
{
int l = m_AttachmentLookup[id];
if (l > -1)
return m_pAttachments[l].Setup();
return NULL;
}
void M2Model::SetAnimation(int Anim,int &Time)
{
if(m_Time == Time && m_Anim == Anim)
return;
m_Anim = Anim;
m_Time = m_pBC->GetAnimations()[m_Anim].timeEnd - m_pBC->GetAnimations()[m_Anim].timeStart;
m_Time = Time % m_Time;
Time = m_Time;
m_pBC->SetupBoneMatrices(m_Anim,m_Time);
}
bool M2Model::NewLoop(int Anim,int Time)
{
int LoopTime;
LoopTime = m_pBC->GetAnimations()[Anim].timeEnd - m_pBC->GetAnimations()[Anim].timeStart;
if(Time >= LoopTime)
return true;
else
return false;
}
void M2Model::Move(float x,float y,float z,int Dir)
{
float sinDir = Math::Sin(Dir);
float cosDir = Math::Cos(Dir);
m_Effect.SetPosition(&D3DXVECTOR4(x,y,z,0));
m_Effect.SetDirection(&D3DXVECTOR4(sinDir,cosDir,0,0));
}
bool M2Model::Reset()
{
return m_Effect.Reset();
}
void M2Model::Lost()
{
m_Effect.Lost();
}
bool XModel::Init(char *M2File,int Size)
{
LPD3DXPMESH pPMesh = NULL;
LPD3DXBUFFER pAdjacencyBuffer = NULL;
LPD3DXBUFFER pMtrlBuffer = NULL;
HRESULT hr;
DWORD nMat;
LPDIRECT3DVERTEXBUFFER9 pVB = NULL;
void* pVertices = NULL;
// Load the mesh
if( FAILED(hr = D3DXLoadMeshFromXInMemory(M2File,Size,D3DXMESH_MANAGED,m_pd3dDevice,
&pAdjacencyBuffer, &pMtrlBuffer, NULL,
&nMat, &m_pMesh ) ) )
goto End;
m_pMesh->OptimizeInplace(D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
(DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL );
m_nTextures = nMat;
m_pMtrls = new D3DXMATERIAL[nMat];
memcpy(m_pMtrls,pMtrlBuffer->GetBufferPointer(),sizeof(D3DXMATERIAL)*nMat);
if( m_nTextures > 0 )
{
m_pTexturesID = new TextureID[m_nTextures];
// Copy each material and create its texture
for( int i = 0; i < m_nTextures; ++ i )
{
if( m_pMtrls[i].pTextureFilename )
{
m_pTexturesID[i] = g_TexMgr.AddTexture((LPCSTR)m_pMtrls[i].pTextureFilename);
}
}
}
hr = m_pMesh->GetVertexBuffer( &pVB );
if( FAILED(hr) )
goto End;
hr = pVB->Lock( 0, 0, &pVertices, 0 );
if( FAILED(hr) )
goto End;
D3DXComputeBoundingSphere((D3DXVECTOR3*)pVertices,m_pMesh->GetNumVertices(),
D3DXGetFVFVertexSize(m_pMesh->GetFVF()),
&m_vCenter,&m_fRadius );
D3DXComputeBoundingBox( (D3DXVECTOR3*)pVertices, m_pMesh->GetNumVertices(),
D3DXGetFVFVertexSize(m_pMesh->GetFVF()),
&m_vMin,&m_vMax);
pVB->Unlock();
// Generate progressive meshes
hr = D3DXGeneratePMesh( m_pMesh, (DWORD*)pAdjacencyBuffer->GetBufferPointer(),
NULL, NULL, 1, D3DXMESHSIMP_VERTEX, &pPMesh );
if( FAILED(hr) )
{
m_ppPMeshes = NULL;
m_nPMeshes = 0;
hr = S_OK;
goto End;
}
DWORD cVerticesMin = pPMesh->GetMinVertices();
DWORD cVerticesMax = pPMesh->GetMaxVertices();
DWORD cVerticesPerMesh = ( cVerticesMax - cVerticesMin + 10 ) / 10;
m_nPMeshes = (DWORD)ceil( (cVerticesMax - cVerticesMin + 1) / (float)cVerticesPerMesh );
if(m_nPMeshes <= 1)
{
m_ppPMeshes = NULL;
m_nPMeshes = 0;
hr = S_OK;
goto End;
}
m_ppPMeshes = new LPD3DXPMESH[m_nPMeshes];
ZeroMemory( m_ppPMeshes, sizeof(LPD3DXPMESH) * m_nPMeshes );
// Clone all the separate pmeshes
for( int iPMesh = 0; iPMesh < m_nPMeshes; iPMesh++ )
{
hr = pPMesh->ClonePMeshFVF( D3DXMESH_MANAGED | D3DXMESH_VB_SHARE, pPMesh->GetFVF(), m_pd3dDevice, &m_ppPMeshes[iPMesh] );
if( FAILED(hr) )
goto End;
hr = m_ppPMeshes[iPMesh]->TrimByVertices( cVerticesMin + cVerticesPerMesh * iPMesh, cVerticesMin + cVerticesPerMesh * (iPMesh+1), NULL, NULL);
if( FAILED(hr) )
goto End;
hr = m_ppPMeshes[iPMesh]->OptimizeBaseLOD( D3DXMESHOPT_VERTEXCACHE, NULL );
if( FAILED(hr) )
goto End;
}
// Set current to be maximum number of vertices
int iPMeshCur = m_nPMeshes - 1;
hr = m_ppPMeshes[iPMeshCur]->SetNumVertices( cVerticesMax );
if( FAILED(hr) )
goto End;
End:
SAFE_RELEASE( pPMesh);
SAFE_RELEASE( pVB );
SAFE_RELEASE( pAdjacencyBuffer );
SAFE_RELEASE( pMtrlBuffer );
if( FAILED(hr) )
return false;
else
return true;
}
bool XModel::Init(char* pFile,int Size,MODELTYPE Type,LPDIRECT3DDEVICE9 pd3dDevice)
{
if(pd3dDevice == NULL)
return false;
Free();
m_pd3dDevice = pd3dDevice;
m_Type = Type;
m_Effect.Init(pd3dDevice);
bool rs = Init(pFile,Size);
if(!rs)
Free();
return rs;
}
void XModel::Free()
{
SAFE_RELEASE( m_pMesh );
for( int i = 0; i < m_nPMeshes; i++ )
SAFE_RELEASE( m_ppPMeshes[i] );
m_nPMeshes = 0;
SAFE_DELETE_A(m_ppPMeshes);
SAFE_DELETE_A(m_pTexturesID);
SAFE_DELETE_A(m_pMtrls);
m_Effect.Free();
m_pd3dDevice = NULL;
}
void XModel::Lost()
{
m_Effect.Lost();
}
bool XModel::Reset()
{
m_Effect.Reset();
return true;
}
void XModel::Move(float x,float y,float z,int Dir)
{
float sinDir = Math::Sin(Dir);
float cosDir = Math::Cos(Dir);
m_Effect.SetPosition(&D3DXVECTOR4(x,y,z,0));
m_Effect.SetDirection(&D3DXVECTOR4(sinDir,cosDir,0,0));
}
void XModel::Update(D3DXMATRIX* pmatViewProj)
{
m_Effect.SetViewProjMatrix(pmatViewProj);
}
bool XModel::Render(float CameraDist,bool bFar)
{
int Num = -1;
if(m_ppPMeshes != NULL)
{
//float Dist = 60.0f / (m_nPMeshes + 1);
//int n = (int)(CameraDist / Dist);
//if(n >= 1)
// pPMesh = m_ppPMeshes[m_nPMeshes - n];
Num = m_nPMeshes - 1;
}
if(m_Type & MODEL_DFACE)
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
else
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
if(m_Type & MODEL_TRANS)
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
else
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
if(m_Type & MODEL_ATEST )
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE , TRUE);
else
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE , FALSE);
UINT nPasses,iPass;
D3DXVECTOR4 Vec;
int i;
if((m_Type & MODEL_WORLD) && bFar)
m_Effect.SetTechnique(EFFECT_WORLD_FAR);
else
m_Effect.SetTechnique(m_Type);
m_Effect.Begin(&nPasses, 0);
for (iPass = 0; iPass < nPasses; iPass++)
{
m_Effect.BeginPass(iPass);
for( i = 0; i < m_nTextures; ++ i )
{
//m_pd3dDevice->SetTexture(0,g_TexMgr.GetTexture(m_pTexturesID[i]));
m_Effect.SetTexture(g_TexMgr.GetTexture(m_pTexturesID[i]));
Vec.x = m_pMtrls[i].MatD3D.Diffuse.r;
Vec.y = m_pMtrls[i].MatD3D.Diffuse.g;
Vec.z = m_pMtrls[i].MatD3D.Diffuse.b;
Vec.w = m_pMtrls[i].MatD3D.Diffuse.a;
m_Effect.SetDiffuse(&Vec);
//Vec.x = m_pMtrls[i].MatD3D.Ambient.r;
//Vec.y = m_pMtrls[i].MatD3D.Ambient.g;
//Vec.z = m_pMtrls[i].MatD3D.Ambient.b;
//Vec.w = m_pMtrls[i].MatD3D.Ambient.a;
//m_Effect.SetAmbient(&Vec);
Vec.x = m_pMtrls[i].MatD3D.Emissive.r;
Vec.y = m_pMtrls[i].MatD3D.Emissive.g;
Vec.z = m_pMtrls[i].MatD3D.Emissive.b;
Vec.w = m_pMtrls[i].MatD3D.Emissive.a;
m_Effect.SetEmissive(&Vec);
Vec.x = m_pMtrls[i].MatD3D.Specular.r;
Vec.y = m_pMtrls[i].MatD3D.Specular.g;
Vec.z = m_pMtrls[i].MatD3D.Specular.b;
Vec.w = m_pMtrls[i].MatD3D.Specular.a;
m_Effect.SetSpecular(&Vec);
m_Effect.CommitChanges();
if(m_ppPMeshes != NULL)
m_ppPMeshes[Num]->DrawSubset( i );
else
m_pMesh->DrawSubset( i );
}
m_Effect.EndPass();
}
m_Effect.End();
return true;
}
//
// 求得变换后的近似BoundBox
//
void IModel::GetBoundBox(float x,float y,float z,int Dir,D3DXVECTOR3* pMin,D3DXVECTOR3* pMax)
{
float sinDir = Math::Sin(Dir);
float cosDir = Math::Cos(Dir);
D3DXVECTOR3 vMin(m_vMin);
D3DXVECTOR3 vMax(m_vMax);
float fx[4],fz[4];
fx[0] = cosDir * vMin.x + sinDir * vMax.z;
fz[0]= -sinDir * vMin.x + cosDir * vMax.z;
fx[1]= cosDir * m_vMin.x + sinDir * m_vMax.z;
fz[1] = -sinDir * m_vMin.x + cosDir * m_vMax.z;
fx[2] = cosDir * vMin.x + sinDir *vMin.z;
fz[2] = -sinDir * vMin.x + cosDir * vMin.z;
fx[3] = cosDir * m_vMax.x + sinDir * m_vMax.z;
fz[3] = -sinDir * m_vMax.x + cosDir * m_vMax.z;
vMin.x = min(min(fx[0],fx[1]),min(fx[2],fx[3]));
vMin.z = min(min(fz[0],fz[1]),min(fz[2],fz[3]));
vMax.x = max(max(fx[0],fx[1]),max(fx[2],fx[3]));
vMax.z = max(max(fz[0],fz[1]),max(fz[2],fz[3]));
*pMin = D3DXVECTOR3(x,y,z) + vMin;
*pMax = D3DXVECTOR3(x,y,z) + vMax;
}