client/GameLib/DungeonBlock.cpp

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();
}