181 lines
6.7 KiB
C++
181 lines
6.7 KiB
C++
// TerrainDecal.cpp: implementation of the CTerrainDecal class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "../eterLib/StateManager.h"
|
|
#include "../PRTerrainLib/StdAfx.h"
|
|
|
|
#include "TerrainDecal.h"
|
|
#include "MapOutdoor.h"
|
|
#include "AreaTerrain.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CTerrainDecal::CTerrainDecal(CMapOutdoor * pMapOutdoor):m_pMapOutdoor(pMapOutdoor)
|
|
{
|
|
|
|
}
|
|
|
|
CTerrainDecal::~CTerrainDecal()
|
|
{
|
|
CDecal::Clear();
|
|
}
|
|
|
|
void CTerrainDecal::Make(D3DXVECTOR3 v3Center, D3DXVECTOR3 v3Normal, D3DXVECTOR3 v3Tangent, float fWidth, float fHeight, float fDepth)
|
|
{
|
|
Clear();
|
|
m_v3Center = v3Center;
|
|
m_v3Normal = v3Normal;
|
|
|
|
D3DXVECTOR3 v3Binormal;
|
|
D3DXVec3Normalize(&v3Normal, &v3Normal);
|
|
D3DXVec3Normalize(&v3Tangent, &v3Tangent);
|
|
D3DXVec3Cross(&v3Binormal, &m_v3Normal, &v3Tangent);
|
|
D3DXVec3Normalize(&v3Binormal, &v3Binormal);
|
|
|
|
// Calculate boundary planes
|
|
float fd = D3DXVec3Dot(&m_v3Center, &v3Tangent);
|
|
m_v4LeftPlane = D3DXPLANE(v3Tangent.x, v3Tangent.y, v3Tangent.z, fWidth * 0.5f - fd);
|
|
m_v4RightPlane = D3DXPLANE(-v3Tangent.x, -v3Tangent.y, -v3Tangent.z, fWidth * 0.5f + fd);
|
|
|
|
fd = D3DXVec3Dot(&m_v3Center, &v3Binormal);
|
|
m_v4BottomPlane = D3DXPLANE(v3Binormal.x, v3Binormal.y, v3Binormal.z, fHeight * 0.5f - fd);
|
|
m_v4TopPlane = D3DXPLANE(-v3Binormal.x, -v3Binormal.y, -v3Binormal.z, fHeight * 0.5f + fd);
|
|
|
|
fd = D3DXVec3Dot(&m_v3Center, &m_v3Normal);
|
|
m_v4FrontPlane = D3DXPLANE(-m_v3Normal.x, -m_v3Normal.y, -m_v3Normal.z, fDepth + fd);
|
|
m_v4BackPlane = D3DXPLANE(m_v3Normal.x, m_v3Normal.y, m_v3Normal.z, fDepth - fd);
|
|
|
|
// Begin with empty mesh
|
|
m_dwVertexCount = 0;
|
|
m_dwPrimitiveCount = 0;
|
|
|
|
// Add this point, determine which surfaces may be affected by this decal and call ClipMesh().
|
|
|
|
float fSearchRadius = fMAX(fWidth, fHeight);// 0.75f >= sqrtf(2)/2;
|
|
float fMinX = v3Center.x - fSearchRadius;
|
|
float fMaxX = v3Center.x + fSearchRadius;
|
|
float fMinY = fabs(v3Center.y) - fSearchRadius;
|
|
float fMaxY = fabs(v3Center.y) + fSearchRadius;
|
|
|
|
DWORD dwAffectedPrimitiveCount = 0;
|
|
D3DXVECTOR3 v3AffectedVertex[MAX_SEARCH_VERTICES];
|
|
D3DXVECTOR3 v3AffectedNormal[MAX_SEARCH_VERTICES];
|
|
memset(v3AffectedVertex, 0, sizeof(v3AffectedVertex));
|
|
memset(v3AffectedNormal, 0, sizeof(v3AffectedNormal));
|
|
|
|
SearchAffectedTerrainMesh(fMinX, fMaxX, fMinY, fMaxY, &dwAffectedPrimitiveCount, v3AffectedVertex, v3AffectedNormal);
|
|
|
|
ClipMesh(dwAffectedPrimitiveCount, v3AffectedVertex, v3AffectedNormal);
|
|
|
|
// Assign texture mapping coordinates
|
|
float fOne_over_w = 1.0f / fWidth;
|
|
float fOne_over_h = 1.0f / fHeight;
|
|
for (DWORD dwi = 0; dwi < m_dwVertexCount; ++dwi)
|
|
{
|
|
D3DXVECTOR3 v3 = m_Vertices[dwi].position - m_v3Center;
|
|
float fu = -D3DXVec3Dot(&v3, &v3Binormal) * fOne_over_w + 0.5f;
|
|
float fv = -D3DXVec3Dot(&v3, &v3Tangent) * fOne_over_h + 0.5f;
|
|
m_Vertices[dwi].texCoord = D3DXVECTOR2(fu, fv);
|
|
}
|
|
}
|
|
|
|
/*
|
|
void CTerrainDecal::Update()
|
|
{
|
|
}
|
|
*/
|
|
|
|
void CTerrainDecal::Render()
|
|
{
|
|
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
|
|
|
STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
|
|
STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
|
|
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
|
|
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
|
|
|
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
|
|
|
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
|
|
|
CDecal::Render();
|
|
|
|
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXCOORDINDEX);
|
|
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS);
|
|
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSU);
|
|
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSV);
|
|
|
|
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
|
|
}
|
|
|
|
void CTerrainDecal::SearchAffectedTerrainMesh(float fMinX,
|
|
float fMaxX,
|
|
float fMinY,
|
|
float fMaxY,
|
|
DWORD * pdwAffectedPrimitiveCount,
|
|
D3DXVECTOR3 * pv3AffectedVertex,
|
|
D3DXVECTOR3 * pv3AffectedNormal)
|
|
{
|
|
if (!m_pMapOutdoor)
|
|
return;
|
|
int iMinX, iMaxX, iMinY, iMaxY;
|
|
PR_FLOAT_TO_INT(fMinX, iMinX);
|
|
PR_FLOAT_TO_INT(fMaxX, iMaxX);
|
|
PR_FLOAT_TO_INT(fMinY, iMinY);
|
|
PR_FLOAT_TO_INT(fMaxY, iMaxY);
|
|
|
|
iMinX -= iMinX % CTerrainImpl::CELLSCALE;
|
|
iMaxX -= iMaxX % CTerrainImpl::CELLSCALE;
|
|
iMinY -= iMinY % CTerrainImpl::CELLSCALE;
|
|
iMaxY -= iMaxY % CTerrainImpl::CELLSCALE;
|
|
|
|
for(int iy = iMinY; iy <= iMaxY; iy += CTerrainImpl::CELLSCALE)
|
|
{
|
|
if (iy < 0)
|
|
continue;
|
|
WORD wTerrainNumY = iy / CTerrainImpl::TERRAIN_YSIZE;
|
|
for(int ix = iMinX; ix <= iMaxX; ix += CTerrainImpl::CELLSCALE)
|
|
{
|
|
if (ix < 0)
|
|
continue;
|
|
WORD wTerrainNumX = ix / CTerrainImpl::TERRAIN_YSIZE;
|
|
|
|
BYTE byTerrainNum;
|
|
if (!m_pMapOutdoor->GetTerrainNumFromCoord(wTerrainNumX, wTerrainNumY, &byTerrainNum))
|
|
continue;
|
|
CTerrain * pTerrain;
|
|
if (!m_pMapOutdoor->GetTerrainPointer(byTerrainNum, &pTerrain))
|
|
continue;
|
|
|
|
float fHeightLT = pTerrain->GetHeight(ix, iy) + m_cfDecalEpsilon;
|
|
float fHeightRT = pTerrain->GetHeight(ix + CTerrainImpl::CELLSCALE, iy) + m_cfDecalEpsilon;
|
|
float fHeightLB = pTerrain->GetHeight(ix, iy + CTerrainImpl::CELLSCALE) + m_cfDecalEpsilon;
|
|
float fHeightRB = pTerrain->GetHeight(ix + CTerrainImpl::CELLSCALE, iy + CTerrainImpl::CELLSCALE) + m_cfDecalEpsilon;
|
|
|
|
*pdwAffectedPrimitiveCount += 2;
|
|
|
|
*pv3AffectedVertex++ = D3DXVECTOR3((float)ix, (float)(-iy), fHeightLT);
|
|
*pv3AffectedVertex++ = D3DXVECTOR3((float)ix, (float)(-iy - CTerrainImpl::CELLSCALE), fHeightLB);
|
|
*pv3AffectedVertex++ = D3DXVECTOR3((float)(ix + CTerrainImpl::CELLSCALE), (float)(-iy), fHeightRT);
|
|
*pv3AffectedVertex++ = D3DXVECTOR3((float)(ix + CTerrainImpl::CELLSCALE), (float)(-iy), fHeightRT);
|
|
*pv3AffectedVertex++ = D3DXVECTOR3((float)ix, (float)(-iy - CTerrainImpl::CELLSCALE), fHeightLB);
|
|
*pv3AffectedVertex++ = D3DXVECTOR3((float)(ix + CTerrainImpl::CELLSCALE), (float)(-iy - CTerrainImpl::CELLSCALE), fHeightRB);
|
|
|
|
*pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
|
*pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
|
*pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
|
*pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
|
*pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
|
*pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
|
}
|
|
}
|
|
}
|