#include "StdAfx.h" #include "DungeonBlock.h" #include "../eterlib/StateManager.h" class CDungeonModelInstance : public CGrannyModelInstance { public: CDungeonModelInstance() {} virtual ~CDungeonModelInstance() {} void RenderDungeonBlock() { if (IsEmpty()) return; STATEMANAGER.SetVertexShader(ms_pnt2VS); LPDIRECT3DVERTEXBUFFER8 lpd3dRigidPNTVtxBuf = m_pModel->GetPNTD3DVertexBuffer(); if (lpd3dRigidPNTVtxBuf) { STATEMANAGER.SetStreamSource(0, lpd3dRigidPNTVtxBuf, sizeof(TPNT2Vertex)); RenderMeshNodeListWithTwoTexture(CGrannyMesh::TYPE_RIGID, CGrannyMaterial::TYPE_BLEND_PNT); } } void RenderDungeonBlockShadow() { if (IsEmpty()) return; STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, 0xffffffff); STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE); STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR); STATEMANAGER.SetVertexShader(ms_pnt2VS); LPDIRECT3DVERTEXBUFFER8 lpd3dRigidPNTVtxBuf = m_pModel->GetPNTD3DVertexBuffer(); if (lpd3dRigidPNTVtxBuf) { STATEMANAGER.SetStreamSource(0, lpd3dRigidPNTVtxBuf, sizeof(TPNT2Vertex)); RenderMeshNodeListWithoutTexture(CGrannyMesh::TYPE_RIGID, CGrannyMaterial::TYPE_BLEND_PNT); } STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG1); STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLOROP); STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAOP); STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND); STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND); } }; struct FUpdate { float fElapsedTime; D3DXMATRIX * pmatWorld; void operator() (CGrannyModelInstance * pInstance) { pInstance->Update(CGrannyModelInstance::ANIFPS_MIN); pInstance->UpdateLocalTime(fElapsedTime); pInstance->Deform(pmatWorld); } }; void CDungeonBlock::Update() { Transform(); FUpdate Update; Update.fElapsedTime = 0.0f; Update.pmatWorld = &m_worldMatrix; for_each(m_ModelInstanceContainer.begin(), m_ModelInstanceContainer.end(), Update); } struct FRender { void operator() (CDungeonModelInstance * pInstance) { pInstance->RenderDungeonBlock(); } }; void CDungeonBlock::Render() { // if (!isShow()) // return; for_each(m_ModelInstanceContainer.begin(), m_ModelInstanceContainer.end(), FRender()); } struct FRenderShadow { void operator() (CDungeonModelInstance * pInstance) { pInstance->RenderDungeonBlockShadow(); } }; void CDungeonBlock::OnRenderShadow() { for_each(m_ModelInstanceContainer.begin(), m_ModelInstanceContainer.end(), FRenderShadow()); } struct FBoundBox { D3DXVECTOR3 * m_pv3Min; D3DXVECTOR3 * m_pv3Max; FBoundBox(D3DXVECTOR3 * pv3Min, D3DXVECTOR3 * pv3Max) { m_pv3Min = pv3Min; m_pv3Max = pv3Max; } void operator() (CGrannyModelInstance * pInstance) { pInstance->GetBoundBox(m_pv3Min, m_pv3Max); } }; bool CDungeonBlock::GetBoundingSphere(D3DXVECTOR3 & v3Center, float & fRadius) { v3Center = m_v3Center; fRadius = m_fRadius; D3DXVec3TransformCoord(&v3Center, &v3Center, &GetTransform()); return true; } void CDungeonBlock::OnUpdateCollisionData(const CStaticCollisionDataVector * pscdVector) { assert(pscdVector); CStaticCollisionDataVector::const_iterator it; for(it = pscdVector->begin();it!=pscdVector->end();++it) { AddCollision(&(*it),&GetTransform()); } } void CDungeonBlock::OnUpdateHeighInstance(CAttributeInstance * pAttributeInstance) { assert(pAttributeInstance); SetHeightInstance(pAttributeInstance); } bool CDungeonBlock::OnGetObjectHeight(float fX, float fY, float * pfHeight) { if (m_pHeightAttributeInstance && m_pHeightAttributeInstance->GetHeight(fX, fY, pfHeight)) return true; return false; } void CDungeonBlock::BuildBoundingSphere() { D3DXVECTOR3 v3Min, v3Max; for_each(m_ModelInstanceContainer.begin(), m_ModelInstanceContainer.end(), FBoundBox(&v3Min, &v3Max)); m_v3Center = (v3Min+v3Max) * 0.5f; m_fRadius = D3DXVec3Length(&(v3Max-v3Min))*0.5f + 150.0f; // extra length for attached objects } bool CDungeonBlock::Intersect(float * pfu, float * pfv, float * pft) { TModelInstanceContainer::iterator itor = m_ModelInstanceContainer.begin(); for (; itor != m_ModelInstanceContainer.end(); ++itor) { CDungeonModelInstance * pInstance = *itor; if (pInstance->Intersect(&CGraphicObjectInstance::GetTransform(), pfu, pfv, pft)) return true; } return false; } void CDungeonBlock::GetBoundBox(D3DXVECTOR3 * pv3Min, D3DXVECTOR3 * pv3Max) { pv3Min->x = +10000000.0f; pv3Min->y = +10000000.0f; pv3Min->z = +10000000.0f; pv3Max->x = -10000000.0f; pv3Max->y = -10000000.0f; pv3Max->z = -10000000.0f; TModelInstanceContainer::iterator itor = m_ModelInstanceContainer.begin(); for (; itor != m_ModelInstanceContainer.end(); ++itor) { CDungeonModelInstance * pInstance = *itor; D3DXVECTOR3 v3Min; D3DXVECTOR3 v3Max; pInstance->GetBoundBox(&v3Min, &v3Max); pv3Min->x = min(v3Min.x, pv3Min->x); pv3Min->y = min(v3Min.x, pv3Min->y); pv3Min->z = min(v3Min.x, pv3Min->z); pv3Max->x = max(v3Max.x, pv3Max->x); pv3Max->y = max(v3Max.x, pv3Max->y); pv3Max->z = max(v3Max.x, pv3Max->z); } } bool CDungeonBlock::Load(const char * c_szFileName) { Destroy(); m_pThing = (CGraphicThing *)CResourceManager::Instance().GetResourcePointer(c_szFileName); m_pThing->AddReference(); if (m_pThing->GetModelCount() <= 0) { TraceError("CDungeonBlock::Load(filename=%s) - model count is %d\n", c_szFileName, m_pThing->GetModelCount()); return false; } m_ModelInstanceContainer.reserve(m_pThing->GetModelCount()); for (int i = 0; i < m_pThing->GetModelCount(); ++i) { CDungeonModelInstance * pModelInstance = new CDungeonModelInstance; pModelInstance->SetMainModelPointer(m_pThing->GetModelPointer(i), &m_kDeformableVertexBuffer); DWORD dwVertexCount = pModelInstance->GetVertexCount(); m_kDeformableVertexBuffer.Destroy(); m_kDeformableVertexBuffer.Create( dwVertexCount, D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED); m_ModelInstanceContainer.push_back(pModelInstance); } return true; } void CDungeonBlock::__Initialize() { m_v3Center = D3DXVECTOR3(0.0f, 0.0f, 0.0f); m_fRadius = 0.0f; m_pThing = NULL; } void CDungeonBlock::Destroy() { if (m_pThing) { m_pThing->Release(); m_pThing = NULL; } stl_wipe(m_ModelInstanceContainer); __Initialize(); } CDungeonBlock::CDungeonBlock() { __Initialize(); } CDungeonBlock::~CDungeonBlock() { Destroy(); }