265 lines
6.6 KiB
C++
265 lines
6.6 KiB
C++
#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();
|
|
}
|