286 lines
8.4 KiB
C++
286 lines
8.4 KiB
C++
// Decal.cpp: implementation of the CDecal class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "Decal.h"
|
|
#include "StateManager.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// CDecal
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CDecal::CDecal():m_cfDecalEpsilon(0.25f)
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
CDecal::~CDecal()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void CDecal::Clear()
|
|
{
|
|
m_v3Center = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
|
|
m_v3Normal = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
|
|
|
|
m_v4LeftPlane = D3DXPLANE(0.0f, 0.0f, 0.0f, 0.0f);
|
|
m_v4RightPlane = D3DXPLANE(0.0f, 0.0f, 0.0f, 0.0f);
|
|
m_v4TopPlane = D3DXPLANE(0.0f, 0.0f, 0.0f, 0.0f);
|
|
m_v4BottomPlane = D3DXPLANE(0.0f, 0.0f, 0.0f, 0.0f);
|
|
m_v4FrontPlane = D3DXPLANE(0.0f, 0.0f, 0.0f, 0.0f);
|
|
m_v4BackPlane = D3DXPLANE(0.0f, 0.0f, 0.0f, 0.0f);
|
|
|
|
m_dwVertexCount = 0;
|
|
m_dwPrimitiveCount = 0;
|
|
|
|
m_TriangleFanStructVector.clear();
|
|
|
|
memset(m_Vertices, 0, sizeof(m_Vertices));
|
|
memset(m_Indices, 0, sizeof(m_Indices));
|
|
}
|
|
|
|
void CDecal::ClipMesh(DWORD dwPrimitiveCount, const D3DXVECTOR3 *c_pv3Vertex, const D3DXVECTOR3 *c_pv3Normal)
|
|
{
|
|
D3DXVECTOR3 v3NewVertex[9];
|
|
D3DXVECTOR3 v3NewNormal[9];
|
|
|
|
// Clip one triangle at a time
|
|
for(DWORD dwi = 0; dwi < dwPrimitiveCount; ++dwi)
|
|
{
|
|
const D3DXVECTOR3 & v3_1 = c_pv3Vertex[3 * dwi];
|
|
const D3DXVECTOR3 & v3_2 = c_pv3Vertex[3 * dwi + 1];
|
|
const D3DXVECTOR3 & v3_3 = c_pv3Vertex[3 * dwi + 2];
|
|
|
|
D3DXVECTOR3 v3Cross;
|
|
D3DXVec3Cross(&v3Cross, &(v3_2 - v3_1), &(v3_3 - v3_1));
|
|
if (D3DXVec3Dot(&m_v3Normal, &v3Cross) > ( m_cfDecalEpsilon ) * D3DXVec3Length(&v3Cross))
|
|
{
|
|
v3NewVertex[0] = v3_1;
|
|
v3NewVertex[1] = v3_2;
|
|
v3NewVertex[2] = v3_3;
|
|
|
|
v3NewNormal[0] = c_pv3Normal[3 * dwi];
|
|
v3NewNormal[1] = c_pv3Normal[3 * dwi + 1];
|
|
v3NewNormal[2] = c_pv3Normal[3 * dwi + 2];
|
|
|
|
DWORD dwCount = ClipPolygon(3, v3NewVertex, v3NewNormal, v3NewVertex, v3NewNormal);
|
|
if ((dwCount != 0) && (!AddPolygon(dwCount, v3NewVertex, v3NewNormal))) break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CDecal::AddPolygon(DWORD dwAddCount, const D3DXVECTOR3 *c_pv3Vertex, const D3DXVECTOR3 * /*c_pv3Normal */)
|
|
{
|
|
if (m_dwVertexCount + dwAddCount >= MAX_DECAL_VERTICES)
|
|
return false;
|
|
|
|
TTRIANGLEFANSTRUCT aTriangleFanStruct;
|
|
aTriangleFanStruct.m_wMinIndex = m_dwVertexCount;
|
|
aTriangleFanStruct.m_dwVertexCount = dwAddCount;
|
|
aTriangleFanStruct.m_dwPrimitiveCount = dwAddCount - 2;
|
|
aTriangleFanStruct.m_dwVBOffset = m_dwVertexCount;
|
|
|
|
m_TriangleFanStructVector.push_back(aTriangleFanStruct);
|
|
|
|
DWORD dwCount = m_dwVertexCount;
|
|
|
|
// Add polygon as a triangle fan
|
|
WORD * wIndex = m_Indices + dwCount;
|
|
|
|
m_dwPrimitiveCount += dwAddCount - 2;
|
|
//float fOne_over_1MinusDecalEpsilon = 1.0f / (1.0f - m_cfDecalEpsilon);
|
|
|
|
// Assign vertex colors
|
|
for (DWORD dwVertexNum = 0; dwVertexNum < dwAddCount; ++dwVertexNum)
|
|
{
|
|
*wIndex++ = (WORD) dwCount;
|
|
m_Vertices[dwCount].position = c_pv3Vertex[dwVertexNum];
|
|
//const D3DXVECTOR3 & v3Normal = c_pv3Normal[dwVertexNum];
|
|
//float fAlpha = (D3DXVec3Dot(&m_v3Normal, &v3Normal) / D3DXVec3Length(&v3Normal) - m_cfDecalEpsilon) * fOne_over_1MinusDecalEpsilon;
|
|
//m_Vertices[dwCount].diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, (fAlpha > 0.0f) ? fAlpha : 0.0f);
|
|
m_Vertices[dwCount].diffuse = 0xFFFFFFFF;
|
|
++dwCount;
|
|
}
|
|
|
|
m_dwVertexCount = dwCount;
|
|
return true;
|
|
}
|
|
|
|
DWORD CDecal::ClipPolygon(DWORD dwVertexCount,
|
|
const D3DXVECTOR3 *c_pv3Vertex,
|
|
const D3DXVECTOR3 *c_pv3Normal,
|
|
D3DXVECTOR3 *c_pv3NewVertex,
|
|
D3DXVECTOR3 *c_pv3NewNormal) const
|
|
{
|
|
D3DXVECTOR3 v3TempVertex[9];
|
|
D3DXVECTOR3 v3TempNormal[9];
|
|
|
|
// Clip against all six planes
|
|
DWORD dwCount = ClipPolygonAgainstPlane(m_v4LeftPlane, dwVertexCount, c_pv3Vertex, c_pv3Normal, v3TempVertex, v3TempNormal);
|
|
if (dwCount != 0)
|
|
{
|
|
dwCount = ClipPolygonAgainstPlane(m_v4RightPlane, dwCount, v3TempVertex, v3TempNormal, c_pv3NewVertex, c_pv3NewNormal);
|
|
if (dwCount != 0)
|
|
{
|
|
dwCount = ClipPolygonAgainstPlane(m_v4BottomPlane, dwCount, c_pv3NewVertex, c_pv3NewNormal, v3TempVertex, v3TempNormal);
|
|
if (dwCount != 0)
|
|
{
|
|
dwCount = ClipPolygonAgainstPlane(m_v4TopPlane, dwCount, v3TempVertex, v3TempNormal, c_pv3NewVertex, c_pv3NewNormal);
|
|
if (dwCount != 0)
|
|
{
|
|
dwCount = ClipPolygonAgainstPlane(m_v4BackPlane, dwCount, c_pv3NewVertex, c_pv3NewNormal, v3TempVertex, v3TempNormal);
|
|
if (dwCount != 0)
|
|
{
|
|
dwCount = ClipPolygonAgainstPlane(m_v4FrontPlane, dwCount, v3TempVertex, v3TempNormal, c_pv3NewVertex, c_pv3NewNormal);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return dwCount;
|
|
}
|
|
|
|
DWORD CDecal::ClipPolygonAgainstPlane(const D3DXPLANE& c_rv4Plane,
|
|
DWORD dwVertexCount,
|
|
const D3DXVECTOR3 *c_pv3Vertex,
|
|
const D3DXVECTOR3 *c_pv3Normal,
|
|
D3DXVECTOR3 *c_pv3NewVertex,
|
|
D3DXVECTOR3 *c_pv3NewNormal)
|
|
{
|
|
bool bNegative[10];
|
|
|
|
// Classify vertices
|
|
DWORD dwNegativeCount = 0;
|
|
for (DWORD dwi = 0; dwi < dwVertexCount; ++dwi)
|
|
{
|
|
bool bNeg = (D3DXPlaneDotCoord(&c_rv4Plane, &c_pv3Vertex[dwi]) < 0.0F);
|
|
bNegative[dwi] = bNeg;
|
|
dwNegativeCount += bNeg;
|
|
}
|
|
|
|
// Discard this polygon if it's completely culled
|
|
if (dwNegativeCount == dwVertexCount)
|
|
return 0;
|
|
|
|
DWORD dwCount = 0;
|
|
for (DWORD dwCurIndex = 0; dwCurIndex < dwVertexCount; ++dwCurIndex)
|
|
{
|
|
// dwPrevIndex is the index of the previous vertex
|
|
DWORD dwPrevIndex = (dwCurIndex != 0) ? dwCurIndex - 1 : dwVertexCount - 1;
|
|
|
|
if (bNegative[dwCurIndex])
|
|
{
|
|
if (!bNegative[dwPrevIndex])
|
|
{
|
|
// Current vertex is on negative side of plane,
|
|
// but previous vertex is on positive side.
|
|
const D3DXVECTOR3& v3_1 = c_pv3Vertex[dwPrevIndex];
|
|
const D3DXVECTOR3& v3_2 = c_pv3Vertex[dwCurIndex];
|
|
float ft = D3DXPlaneDotCoord(&c_rv4Plane, &v3_1) / (c_rv4Plane.a * (v3_1.x - v3_2.x) + c_rv4Plane.b * (v3_1.y - v3_2.y) + c_rv4Plane.c * (v3_1.z - v3_2.z));
|
|
c_pv3NewVertex[dwCount] = v3_1 * (1.0f - ft) + v3_2 * ft;
|
|
const D3DXVECTOR3& v3_n1 = c_pv3Normal[dwPrevIndex];
|
|
const D3DXVECTOR3& v3_n2 = c_pv3Normal[dwCurIndex];
|
|
c_pv3NewNormal[dwCount] = v3_n1 * (1.0f - ft) + v3_n2 * ft;
|
|
++dwCount;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bNegative[dwPrevIndex])
|
|
{
|
|
// Current vertex is on positive side of plane,
|
|
// but previous vertex is on negative side.
|
|
const D3DXVECTOR3& v3_1 = c_pv3Vertex[dwCurIndex];
|
|
const D3DXVECTOR3& v3_2 = c_pv3Vertex[dwPrevIndex];
|
|
float ft = D3DXPlaneDotCoord(&c_rv4Plane, &v3_1) / (c_rv4Plane.a * (v3_1.x - v3_2.x) + c_rv4Plane.b * (v3_1.y - v3_2.y) + c_rv4Plane.c * (v3_1.z - v3_2.z));
|
|
c_pv3NewVertex[dwCount] = v3_1 * (1.0f - ft) + v3_2 * ft;
|
|
const D3DXVECTOR3& v3_n1 = c_pv3Normal[dwCurIndex];
|
|
const D3DXVECTOR3& v3_n2 = c_pv3Normal[dwPrevIndex];
|
|
c_pv3NewNormal[dwCount] = v3_n1 * (1.0f - ft) + v3_n2 * ft;
|
|
++dwCount;
|
|
}
|
|
|
|
// Include current vertex
|
|
c_pv3NewVertex[dwCount] = c_pv3Vertex[dwCurIndex];
|
|
c_pv3NewNormal[dwCount] = c_pv3Normal[dwCurIndex];
|
|
++dwCount;
|
|
}
|
|
}
|
|
|
|
// Return number of vertices in clipped polygon
|
|
return dwCount;
|
|
}
|
|
|
|
/*
|
|
void CDecal::Update()
|
|
{
|
|
}
|
|
*/
|
|
|
|
void CDecal::Render()
|
|
{
|
|
D3DXMATRIX matWorld;
|
|
D3DXMatrixIdentity(&matWorld);
|
|
STATEMANAGER.SetTransform(D3DTS_WORLD, &matWorld);
|
|
|
|
STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1);
|
|
|
|
for (DWORD dwi = 0; dwi < m_TriangleFanStructVector.size(); ++dwi)
|
|
STATEMANAGER.DrawIndexedPrimitiveUP(D3DPT_TRIANGLEFAN,
|
|
m_TriangleFanStructVector[dwi].m_wMinIndex,
|
|
m_TriangleFanStructVector[dwi].m_dwVertexCount,
|
|
m_TriangleFanStructVector[dwi].m_dwPrimitiveCount,
|
|
m_Indices + m_TriangleFanStructVector[dwi].m_wMinIndex,
|
|
D3DFMT_INDEX16,
|
|
m_Vertices,
|
|
sizeof(TPDTVertex));
|
|
}
|
|
|
|
/*
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CDecalManager
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CDecalManager aDecalManager;
|
|
|
|
CDecalManager::CDecalManager()
|
|
{
|
|
m_DecalPtrVector.clear();
|
|
}
|
|
|
|
CDecalManager::~CDecalManager()
|
|
{
|
|
m_DecalPtrVector.clear();
|
|
}
|
|
|
|
void CDecalManager::Add(CDecal * pDecal)
|
|
{
|
|
m_DecalPtrVector.push_back(pDecal);
|
|
}
|
|
|
|
void CDecalManager::Remove(CDecal * pDecal)
|
|
{
|
|
std::vector<CDecal *>::iterator aIterator;
|
|
for (aIterator = m_DecalPtrVector.begin(); aIterator != m_DecalPtrVector.end();)
|
|
{
|
|
if (*aIterator == pDecal)
|
|
aIterator = m_DecalPtrVector.erase(aIterator);
|
|
else
|
|
++aIterator;
|
|
}
|
|
}
|
|
|
|
void CDecalManager::Update()
|
|
{
|
|
for (DWORD dwi = 0; dwi < m_DecalPtrVector.size(); ++dwi)
|
|
m_DecalPtrVector[dwi]->Update();
|
|
}
|
|
|
|
void CDecalManager::Render()
|
|
{
|
|
for (DWORD dwi = 0; dwi < m_DecalPtrVector.size(); ++dwi)
|
|
m_DecalPtrVector[dwi]->Render();
|
|
}
|
|
*/
|