client/GameLib/MapOutdoorRender.cpp

961 lines
30 KiB
C++

#include "StdAfx.h"
#include "MapOutdoor.h"
#include "TerrainPatch.h"
#include "AreaTerrain.h"
#include "TerrainQuadtree.h"
#include "../eterlib/Camera.h"
#include "../eterlib/StateManager.h"
#define MAX_RENDER_SPALT 150
CArea::TCRCWithNumberVector m_dwRenderedCRCWithNumberVector;
CMapOutdoor::TTerrainNumVector CMapOutdoor::FSortPatchDrawStructWithTerrainNum::m_TerrainNumVector;
void CMapOutdoor::RenderTerrain()
{
if (!IsVisiblePart(PART_TERRAIN))
return;
if (!m_bSettingTerrainVisible)
return;
// Inserted by levites
if (!m_pTerrainPatchProxyList)
return;
CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera();
if (!pCamera)
return;
BuildViewFrustum(ms_matView * ms_matProj);
D3DXVECTOR3 v3Eye = pCamera->GetEye();
m_fXforDistanceCaculation = -v3Eye.x;
m_fYforDistanceCaculation = -v3Eye.y;
//////////////////////////////////////////////////////////////////////////
// Push
m_PatchVector.clear();
__RenderTerrain_RecurseRenderQuadTree(m_pRootNode);
// 거리순 정렬
std::sort(m_PatchVector.begin(),m_PatchVector.end());
// 그리기 위한 벡터 세팅
if (CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE)
__RenderTerrain_RenderSoftwareTransformPatch();
else
__RenderTerrain_RenderHardwareTransformPatch();
}
void CMapOutdoor::__RenderTerrain_RecurseRenderQuadTree(CTerrainQuadtreeNode *Node, bool bCullCheckNeed)
{
if (bCullCheckNeed)
{
switch (__RenderTerrain_RecurseRenderQuadTree_CheckBoundingCircle(Node->center, Node->radius))
{
case VIEW_ALL:
// all child nodes need not cull check
bCullCheckNeed = false;
break;
case VIEW_PART:
break;
case VIEW_NONE:
// no need to render
return;
}
// if no need cull check more
// -> bCullCheckNeed = false;
}
if (Node->Size == 1)
{
D3DXVECTOR3 v3Center = Node->center;
float fDistance = fMAX(fabs(v3Center.x + m_fXforDistanceCaculation), fabs(-v3Center.y + m_fYforDistanceCaculation));
__RenderTerrain_AppendPatch(v3Center, fDistance, Node->PatchNum);
}
else
{
if (Node->NW_Node != NULL)
__RenderTerrain_RecurseRenderQuadTree(Node->NW_Node, bCullCheckNeed);
if (Node->NE_Node != NULL)
__RenderTerrain_RecurseRenderQuadTree(Node->NE_Node, bCullCheckNeed);
if (Node->SW_Node != NULL)
__RenderTerrain_RecurseRenderQuadTree(Node->SW_Node, bCullCheckNeed);
if (Node->SE_Node != NULL)
__RenderTerrain_RecurseRenderQuadTree(Node->SE_Node, bCullCheckNeed);
}
}
int CMapOutdoor::__RenderTerrain_RecurseRenderQuadTree_CheckBoundingCircle(const D3DXVECTOR3 & c_v3Center, const float & c_fRadius)
{
const int count = 6;
D3DXVECTOR3 center = c_v3Center;
center.y = -center.y;
int i;
float distance[count];
for(i = 0; i < count; ++i)
{
distance[i] = D3DXPlaneDotCoord(&m_plane[i], &center);
if (distance[i] <= -c_fRadius)
return VIEW_NONE;
}
for(i = 0; i < count;++i)
{
if (distance[i] <= c_fRadius)
return VIEW_PART;
}
return VIEW_ALL;
}
void CMapOutdoor::__RenderTerrain_AppendPatch(const D3DXVECTOR3& c_rv3Center, float fDistance, long lPatchNum)
{
assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::__RenderTerrain_AppendPatch");
if (!m_pTerrainPatchProxyList[lPatchNum].isUsed())
return;
m_pTerrainPatchProxyList[lPatchNum].SetCenterPosition(c_rv3Center);
m_PatchVector.push_back(std::make_pair(fDistance, lPatchNum));
}
void CMapOutdoor::ApplyLight(DWORD dwVersion, const D3DLIGHT8& c_rkLight)
{
m_kSTPD.m_dwLightVersion=dwVersion;
STATEMANAGER.SetLight(0, &c_rkLight);
}
// 2004. 2. 17. myevan. 모든 부분을 보이게 초기화 한다
void CMapOutdoor::InitializeVisibleParts()
{
m_dwVisiblePartFlags=0xffffffff;
}
// 2004. 2. 17. myevan. 특정 부분을 보이게 하거나 감추는 함수
void CMapOutdoor::SetVisiblePart(int ePart, bool isVisible)
{
DWORD dwMask=(1<<ePart);
if (isVisible)
{
m_dwVisiblePartFlags|=dwMask;
}
else
{
DWORD dwReverseMask=~dwMask;
m_dwVisiblePartFlags&=dwReverseMask;
}
}
// 2004. 2. 17. myevan. 특정 부분이 보이는지 알아내는 함수
bool CMapOutdoor::IsVisiblePart(int ePart)
{
DWORD dwMask=(1<<ePart);
if (dwMask & m_dwVisiblePartFlags)
return true;
return false;
}
// Splat 개수 제한
void CMapOutdoor::SetSplatLimit(int iSplatNum)
{
m_iSplatLimit = iSplatNum;
}
std::vector<int> & CMapOutdoor::GetRenderedSplatNum(int * piPatch, int * piSplat, float * pfSplatRatio)
{
*piPatch = m_iRenderedPatchNum;
*piSplat = m_iRenderedSplatNum;
*pfSplatRatio = m_iRenderedSplatNumSqSum/float(m_iRenderedPatchNum);
return m_RenderedTextureNumVector;
}
CArea::TCRCWithNumberVector & CMapOutdoor::GetRenderedGraphicThingInstanceNum(DWORD * pdwGraphicThingInstanceNum, DWORD * pdwCRCNum)
{
*pdwGraphicThingInstanceNum = m_dwRenderedGraphicThingInstanceNum;
*pdwCRCNum = m_dwRenderedCRCNum;
return m_dwRenderedCRCWithNumberVector;
}
void CMapOutdoor::RenderBeforeLensFlare()
{
m_LensFlare.DrawBeforeFlare();
if (!mc_pEnvironmentData)
{
TraceError("CMapOutdoor::RenderBeforeLensFlare mc_pEnvironmentData is NULL");
return;
}
m_LensFlare.Compute(mc_pEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND].Direction);
}
void CMapOutdoor::RenderAfterLensFlare()
{
m_LensFlare.AdjustBrightness();
m_LensFlare.DrawFlare();
}
void CMapOutdoor::RenderCollision()
{
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (GetAreaPointer(i, &pArea))
pArea->RenderCollision();
}
}
void CMapOutdoor::RenderScreenFiltering()
{
m_ScreenFilter.Render();
}
void CMapOutdoor::RenderSky()
{
if (IsVisiblePart(PART_SKY))
m_SkyBox.Render();
}
void CMapOutdoor::RenderCloud()
{
if (IsVisiblePart(PART_CLOUD))
m_SkyBox.RenderCloud();
}
void CMapOutdoor::RenderTree()
{
if (IsVisiblePart(PART_TREE))
CSpeedTreeForestDirectX8::Instance().Render();
}
void CMapOutdoor::SetInverseViewAndDynamicShaodwMatrices()
{
CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera();
if (!pCamera)
return;
m_matViewInverse = pCamera->GetInverseViewMatrix();
D3DXVECTOR3 v3Target = pCamera->GetTarget();
D3DXVECTOR3 v3LightEye(v3Target.x - 1.732f * 1250.0f,
v3Target.y - 1250.0f,
v3Target.z + 2.0f * 1.732f * 1250.0f);
D3DXMatrixLookAtRH(&m_matLightView, &v3LightEye, &v3Target, &D3DXVECTOR3(0.0f, 0.0f, 1.0f));
m_matDynamicShadow = m_matViewInverse * m_matLightView * m_matDynamicShadowScale;
}
void CMapOutdoor::OnRender()
{
#ifdef __PERFORMANCE_CHECKER__
DWORD t1=ELTimer_GetMSec();
SetInverseViewAndDynamicShaodwMatrices();
SetBlendOperation();
DWORD t2=ELTimer_GetMSec();
RenderArea();
DWORD t3=ELTimer_GetMSec();
if (!m_bEnableTerrainOnlyForHeight)
RenderTerrain();
DWORD t4=ELTimer_GetMSec();
RenderTree();
DWORD t5=ELTimer_GetMSec();
DWORD tEnd=ELTimer_GetMSec();
if (tEnd-t1<7)
return;
static FILE* fp=fopen("perf_map_render.txt", "w");
fprintf(fp, "MAP.Total %d (Time %d)\n", tEnd-t1, ELTimer_GetMSec());
fprintf(fp, "MAP.ENV %d\n", t2-t1);
fprintf(fp, "MAP.OBJ %d\n", t3-t2);
fprintf(fp, "MAP.TRN %d\n", t4-t3);
fprintf(fp, "MAP.TRE %d\n", t5-t4);
#else
SetInverseViewAndDynamicShaodwMatrices();
SetBlendOperation();
RenderArea();
RenderTree();
if (!m_bEnableTerrainOnlyForHeight)
RenderTerrain();
RenderBlendArea();
#endif
}
struct FAreaRenderShadow
{
void operator () (CGraphicObjectInstance * pInstance)
{
pInstance->RenderShadow();
pInstance->Hide();
}
};
struct FPCBlockerHide
{
void operator () (CGraphicObjectInstance * pInstance)
{
pInstance->Hide();
}
};
struct FRenderPCBlocker
{
void operator () (CGraphicObjectInstance * pInstance)
{
pInstance->Show();
CGraphicThingInstance* pThingInstance = dynamic_cast <CGraphicThingInstance*> (pInstance);
if (pThingInstance != NULL)
{
if (pThingInstance->HaveBlendThing())
{
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
pThingInstance->BlendRender();
return;
}
}
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
pInstance->RenderPCBlocker();
}
};
void CMapOutdoor::RenderEffect()
{
if (!IsVisiblePart(PART_OBJECT))
return;
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (GetAreaPointer(i, &pArea))
{
pArea->RenderEffect();
}
}
}
struct CMapOutdoor_LessThingInstancePtrRenderOrder
{
bool operator() (CGraphicThingInstance* pkLeft, CGraphicThingInstance* pkRight)
{
//TODO : Camera위치기반으로 소팅
CCamera * pCurrentCamera = CCameraManager::Instance().GetCurrentCamera();
const D3DXVECTOR3 & c_rv3CameraPos = pCurrentCamera->GetEye();
const D3DXVECTOR3 & c_v3LeftPos = pkLeft->GetPosition();
const D3DXVECTOR3 & c_v3RightPos = pkRight->GetPosition();
return D3DXVec3LengthSq(&D3DXVECTOR3(c_rv3CameraPos - c_v3LeftPos)) < D3DXVec3LengthSq(&D3DXVECTOR3(c_rv3CameraPos - c_v3RightPos) );
}
};
struct CMapOutdoor_FOpaqueThingInstanceRender
{
inline void operator () (CGraphicThingInstance * pkThingInst)
{
pkThingInst->Render();
}
};
struct CMapOutdoor_FBlendThingInstanceRender
{
inline void operator () (CGraphicThingInstance * pkThingInst)
{
pkThingInst->BlendRender();
}
};
void CMapOutdoor::RenderArea(bool bRenderAmbience)
{
if (!IsVisiblePart(PART_OBJECT))
return;
m_dwRenderedCRCNum = 0;
m_dwRenderedGraphicThingInstanceNum = 0;
m_dwRenderedCRCWithNumberVector.clear();
// NOTE - 20041201.levites.던젼 그림자 추가
for (int j = 0; j < AROUND_AREA_NUM; ++j)
{
CArea * pArea;
if (GetAreaPointer(j, &pArea))
{
pArea->RenderDungeon();
}
}
#ifndef WORLD_EDITOR
// PCBlocker
std::for_each(m_PCBlockerVector.begin(), m_PCBlockerVector.end(), FPCBlockerHide());
// Shadow Receiver
if (m_bDrawShadow && m_bDrawChrShadow)
{
if (mc_pEnvironmentData != NULL)
STATEMANAGER.SetRenderState(D3DRS_FOGCOLOR, 0xFFFFFFFF);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
// Transform
STATEMANAGER.SaveTransform(D3DTS_TEXTURE1, &m_matDynamicShadow);
STATEMANAGER.SetTexture(1, m_lpCharacterShadowMapTexture);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_BORDER);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_BORDER);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_BORDERCOLOR, 0xFFFFFFFF);
std::for_each(m_ShadowReceiverVector.begin(), m_ShadowReceiverVector.end(), FAreaRenderShadow());
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXCOORDINDEX);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSU);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSV);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_BORDERCOLOR);
STATEMANAGER.RestoreTransform(D3DTS_TEXTURE1);
if (mc_pEnvironmentData != NULL)
STATEMANAGER.SetRenderState(D3DRS_FOGCOLOR, mc_pEnvironmentData->FogColor);
}
#endif
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, TRUE);
bool m_isDisableSortRendering=false;
if (m_isDisableSortRendering)
{
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (GetAreaPointer(i, &pArea))
{
pArea->Render();
m_dwRenderedCRCNum += pArea->DEBUG_GetRenderedCRCNum();
m_dwRenderedGraphicThingInstanceNum += pArea->DEBUG_GetRenderedGrapphicThingInstanceNum();
CArea::TCRCWithNumberVector & rCRCWithNumberVector = pArea->DEBUG_GetRenderedCRCWithNumVector();
CArea::TCRCWithNumberVector::iterator aIterator = rCRCWithNumberVector.begin();
while (aIterator != rCRCWithNumberVector.end())
{
DWORD dwCRC = (*aIterator++).dwCRC;
CArea::TCRCWithNumberVector::iterator aCRCWithNumberVectorIterator =
std::find_if(m_dwRenderedCRCWithNumberVector.begin(), m_dwRenderedCRCWithNumberVector.end(), CArea::FFindIfCRC(dwCRC));
if ( m_dwRenderedCRCWithNumberVector.end() == aCRCWithNumberVectorIterator)
{
CArea::TCRCWithNumber aCRCWithNumber;
aCRCWithNumber.dwCRC = dwCRC;
aCRCWithNumber.dwNumber = 1;
m_dwRenderedCRCWithNumberVector.push_back(aCRCWithNumber);
}
else
{
CArea::TCRCWithNumber & rCRCWithNumber = *aCRCWithNumberVectorIterator;
rCRCWithNumber.dwNumber += 1;
}
}
#ifdef WORLD_EDITOR
if (bRenderAmbience)
pArea->RenderAmbience();
#endif
}
}
std::sort(m_dwRenderedCRCWithNumberVector.begin(), m_dwRenderedCRCWithNumberVector.end(), CArea::CRCNumComp());
}
else
{
static std::vector<CGraphicThingInstance*> s_kVct_pkOpaqueThingInstSort;
s_kVct_pkOpaqueThingInstSort.clear();
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (GetAreaPointer(i, &pArea))
{
pArea->CollectRenderingObject(s_kVct_pkOpaqueThingInstSort);
#ifdef WORLD_EDITOR
if (bRenderAmbience)
pArea->RenderAmbience();
#endif
}
}
std::sort(s_kVct_pkOpaqueThingInstSort.begin(), s_kVct_pkOpaqueThingInstSort.end(), CMapOutdoor_LessThingInstancePtrRenderOrder());
std::for_each(s_kVct_pkOpaqueThingInstSort.begin(), s_kVct_pkOpaqueThingInstSort.end(), CMapOutdoor_FOpaqueThingInstanceRender());
}
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
#ifndef WORLD_EDITOR
// Shadow Receiver
if (m_bDrawShadow && m_bDrawChrShadow)
{
std::for_each(m_ShadowReceiverVector.begin(), m_ShadowReceiverVector.end(), std::void_mem_fun(&CGraphicObjectInstance::Show));
}
#endif
}
void CMapOutdoor::RenderBlendArea()
{
if (!IsVisiblePart(PART_OBJECT))
return;
static std::vector<CGraphicThingInstance*> s_kVct_pkBlendThingInstSort;
s_kVct_pkBlendThingInstSort.clear();
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (GetAreaPointer(i, &pArea))
{
pArea->CollectBlendRenderingObject(s_kVct_pkBlendThingInstSort);
}
}
if (s_kVct_pkBlendThingInstSort.size() != 0)
{
//STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
//STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
//STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
//STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
//STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
//STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
//// Transform
//STATEMANAGER.SaveTransform(D3DTS_TEXTURE1, &m_matDynamicShadow);
//STATEMANAGER.SetTexture(1, m_lpCharacterShadowMapTexture);
//STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
//STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
//STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
//STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
//STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_BORDER);
//STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_BORDER);
//STATEMANAGER.SaveTextureStageState(1, D3DTSS_BORDERCOLOR, 0xFFFFFFFF);
////std::for_each(m_ShadowReceiverVector.begin(), m_ShadowReceiverVector.end(), FAreaRenderShadow());
//STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXCOORDINDEX);
//STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS);
//STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSU);
//STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSV);
//STATEMANAGER.RestoreTextureStageState(1, D3DTSS_BORDERCOLOR);
//STATEMANAGER.RestoreTransform(D3DTS_TEXTURE1);
std::sort(s_kVct_pkBlendThingInstSort.begin(), s_kVct_pkBlendThingInstSort.end(), CMapOutdoor_LessThingInstancePtrRenderOrder());
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
std::for_each(s_kVct_pkBlendThingInstSort.begin(), s_kVct_pkBlendThingInstSort.end(), CMapOutdoor_FBlendThingInstanceRender());
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND);
STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND);
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
}
}
void CMapOutdoor::RenderDungeon()
{
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (!GetAreaPointer(i, &pArea))
continue;
pArea->RenderDungeon();
}
}
void CMapOutdoor::RenderPCBlocker()
{
#ifndef WORLD_EDITOR
// PCBlocker
if (m_PCBlockerVector.size() != 0)
{
STATEMANAGER.SetTexture(0, NULL);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
STATEMANAGER.SaveTransform(D3DTS_TEXTURE1, &m_matBuildingTransparent);
STATEMANAGER.SetTexture(1, m_BuildingTransparentImageInstance.GetTexturePointer()->GetD3DTexture());
std::for_each(m_PCBlockerVector.begin(), m_PCBlockerVector.end(), FRenderPCBlocker());
STATEMANAGER.SetTexture(1, NULL);
STATEMANAGER.RestoreTransform(D3DTS_TEXTURE1);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXCOORDINDEX);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSU);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSV);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
}
#endif
}
void CMapOutdoor::SelectIndexBuffer(BYTE byLODLevel, WORD * pwPrimitiveCount, D3DPRIMITIVETYPE * pePrimitiveType)
{
#ifdef WORLD_EDITOR
*pwPrimitiveCount = m_wNumIndices - 2;
*pePrimitiveType = D3DPT_TRIANGLESTRIP;
STATEMANAGER.SetIndices(m_IndexBuffer.GetD3DIndexBuffer(), 0);
#else
if (0 == byLODLevel)
{
*pwPrimitiveCount = m_wNumIndices[byLODLevel] - 2;
*pePrimitiveType = D3DPT_TRIANGLESTRIP;
}
else
{
*pwPrimitiveCount = m_wNumIndices[byLODLevel]/3;
*pePrimitiveType = D3DPT_TRIANGLELIST;
}
STATEMANAGER.SetIndices(m_IndexBuffer[byLODLevel].GetD3DIndexBuffer(), 0);
#endif
}
void CMapOutdoor::SetPatchDrawVector()
{
assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::__SetPatchDrawVector");
m_PatchDrawStructVector.clear();
std::vector<std::pair<float, long> >::iterator aDistancePatchVectorIterator;
TPatchDrawStruct aPatchDrawStruct;
aDistancePatchVectorIterator = m_PatchVector.begin();
while(aDistancePatchVectorIterator != m_PatchVector.end())
{
std::pair<float, long> adistancePatchPair = *aDistancePatchVectorIterator;
CTerrainPatchProxy * pTerrainPatchProxy = &m_pTerrainPatchProxyList[adistancePatchPair.second];
if (!pTerrainPatchProxy->isUsed())
{
++aDistancePatchVectorIterator;
continue;
}
long lPatchNum = pTerrainPatchProxy->GetPatchNum();
if (lPatchNum < 0)
{
++aDistancePatchVectorIterator;
continue;
}
BYTE byTerrainNum = pTerrainPatchProxy->GetTerrainNum();
if (0xFF == byTerrainNum)
{
++aDistancePatchVectorIterator;
continue;
}
CTerrain * pTerrain;
if (!GetTerrainPointer(byTerrainNum, &pTerrain))
{
++aDistancePatchVectorIterator;
continue;
}
aPatchDrawStruct.fDistance = adistancePatchPair.first;
aPatchDrawStruct.byTerrainNum = byTerrainNum;
aPatchDrawStruct.lPatchNum = lPatchNum;
aPatchDrawStruct.pTerrainPatchProxy = pTerrainPatchProxy;
m_PatchDrawStructVector.push_back(aPatchDrawStruct);
++aDistancePatchVectorIterator;
}
std::stable_sort(m_PatchDrawStructVector.begin(), m_PatchDrawStructVector.end(), FSortPatchDrawStructWithTerrainNum());
}
float CMapOutdoor::__GetNoFogDistance()
{
return (float)(CTerrainImpl::CELLSCALE * m_lViewRadius) * 0.5f;
}
float CMapOutdoor::__GetFogDistance()
{
return (float)(CTerrainImpl::CELLSCALE * m_lViewRadius) * 0.75f;
}
struct FPatchNumMatch
{
long m_lPatchNumToCheck;
FPatchNumMatch(long lPatchNum)
{
m_lPatchNumToCheck = lPatchNum;
}
bool operator() (std::pair<long, BYTE> aPair)
{
return m_lPatchNumToCheck == aPair.first;
}
};
void CMapOutdoor::NEW_DrawWireFrame(CTerrainPatchProxy * pTerrainPatchProxy, WORD wPrimitiveCount, D3DPRIMITIVETYPE ePrimitiveType)
{
DWORD dwFillMode = STATEMANAGER.GetRenderState(D3DRS_FILLMODE);
STATEMANAGER.SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
DWORD dwFogEnable = STATEMANAGER.GetRenderState(D3DRS_FOGENABLE);
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, FALSE);
STATEMANAGER.SetTexture(0, NULL);
STATEMANAGER.SetTexture(1, NULL);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.DrawIndexedPrimitive(ePrimitiveType, 0, m_iPatchTerrainVertexCount, 0, wPrimitiveCount);
STATEMANAGER.SetRenderState(D3DRS_FILLMODE, dwFillMode);
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, dwFogEnable);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
}
void CMapOutdoor::DrawWireFrame(long patchnum, WORD wPrimitiveCount, D3DPRIMITIVETYPE ePrimitiveType)
{
assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::DrawWireFrame");
CTerrainPatchProxy * pTerrainPatchProxy= &m_pTerrainPatchProxyList[patchnum];
if (!pTerrainPatchProxy->isUsed())
return;
long sPatchNum = pTerrainPatchProxy->GetPatchNum();
if (sPatchNum < 0)
return;
BYTE ucTerrainNum = pTerrainPatchProxy->GetTerrainNum();
if (0xFF == ucTerrainNum)
return;
DWORD dwFillMode = STATEMANAGER.GetRenderState(D3DRS_FILLMODE);
STATEMANAGER.SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
DWORD dwFogEnable = STATEMANAGER.GetRenderState(D3DRS_FOGENABLE);
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, FALSE);
STATEMANAGER.SetTexture(0, NULL);
STATEMANAGER.SetTexture(1, NULL);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.DrawIndexedPrimitive(ePrimitiveType, 0, m_iPatchTerrainVertexCount, 0, wPrimitiveCount);
STATEMANAGER.SetRenderState(D3DRS_FILLMODE, dwFillMode);
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, dwFogEnable);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
}
// Attr
void CMapOutdoor::RenderMarkedArea()
{
if (!m_pTerrainPatchProxyList)
return;
m_matWorldForCommonUse._41 = 0.0f;
m_matWorldForCommonUse._42 = 0.0f;
STATEMANAGER.SetTransform(D3DTS_WORLD, &m_matWorldForCommonUse);
WORD wPrimitiveCount;
D3DPRIMITIVETYPE eType;
SelectIndexBuffer(0, &wPrimitiveCount, &eType);
D3DXMATRIX matTexTransform, matTexTransformTemp;
D3DXMatrixScaling(&matTexTransform, m_fTerrainTexCoordBase * 32.0f, -m_fTerrainTexCoordBase * 32.0f, 0.0f);
D3DXMatrixMultiply(&matTexTransform, &m_matViewInverse, &matTexTransform);
STATEMANAGER.SaveTransform(D3DTS_TEXTURE0, &matTexTransform);
STATEMANAGER.SaveTransform(D3DTS_TEXTURE1, &matTexTransform);
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
static long lStartTime = timeGetTime();
float fTime = float((timeGetTime() - lStartTime)%3000) / 3000.0f;
float fAlpha = fabs(fTime - 0.5f) / 2.0f + 0.1f;
STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, D3DXCOLOR(1.0f, 1.0f, 1.0f, fAlpha));
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_MIPFILTER, D3DTEXF_POINT);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
STATEMANAGER.SetTexture(0, m_attrImageInstance.GetTexturePointer()->GetD3DTexture());
RecurseRenderAttr(m_pRootNode);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXCOORDINDEX);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXCOORDINDEX);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_MINFILTER);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_MAGFILTER);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_MIPFILTER);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSU);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSV);
STATEMANAGER.RestoreTransform(D3DTS_TEXTURE0);
STATEMANAGER.RestoreTransform(D3DTS_TEXTURE1);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND);
STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND);
}
void CMapOutdoor::RecurseRenderAttr(CTerrainQuadtreeNode *Node, bool bCullEnable)
{
if (bCullEnable)
{
if (__RenderTerrain_RecurseRenderQuadTree_CheckBoundingCircle(Node->center, Node->radius)==VIEW_NONE)
return;
}
{
if (Node->Size == 1)
{
DrawPatchAttr(Node->PatchNum);
}
else
{
if (Node->NW_Node != NULL)
RecurseRenderAttr(Node->NW_Node, bCullEnable);
if (Node->NE_Node != NULL)
RecurseRenderAttr(Node->NE_Node, bCullEnable);
if (Node->SW_Node != NULL)
RecurseRenderAttr(Node->SW_Node, bCullEnable);
if (Node->SE_Node != NULL)
RecurseRenderAttr(Node->SE_Node, bCullEnable);
}
}
}
void CMapOutdoor::DrawPatchAttr(long patchnum)
{
CTerrainPatchProxy * pTerrainPatchProxy = &m_pTerrainPatchProxyList[patchnum];
if (!pTerrainPatchProxy->isUsed())
return;
long sPatchNum = pTerrainPatchProxy->GetPatchNum();
if (sPatchNum < 0)
return;
BYTE ucTerrainNum = pTerrainPatchProxy->GetTerrainNum();
if (0xFF == ucTerrainNum)
return;
// Deal with this material buffer
CTerrain * pTerrain;
if (!GetTerrainPointer(ucTerrainNum, &pTerrain))
return;
if (!pTerrain->IsMarked())
return;
WORD wCoordX, wCoordY;
pTerrain->GetCoordinate(&wCoordX, &wCoordY);
m_matWorldForCommonUse._41 = -(float) (wCoordX * CTerrainImpl::XSIZE * CTerrainImpl::CELLSCALE);
m_matWorldForCommonUse._42 = (float) (wCoordY * CTerrainImpl::YSIZE * CTerrainImpl::CELLSCALE);
D3DXMATRIX matTexTransform, matTexTransformTemp;
D3DXMatrixMultiply(&matTexTransform, &m_matViewInverse, &m_matWorldForCommonUse);
D3DXMatrixMultiply(&matTexTransform, &matTexTransform, &m_matStaticShadow);
STATEMANAGER.SetTransform(D3DTS_TEXTURE1, &matTexTransform);
TTerrainSplatPatch & rAttrSplatPatch = pTerrain->GetMarkedSplatPatch();
STATEMANAGER.SetTexture(1, rAttrSplatPatch.Splats[0].pd3dTexture);
STATEMANAGER.SetVertexShader(D3DFVF_XYZ | D3DFVF_NORMAL);
STATEMANAGER.SetStreamSource(0, pTerrainPatchProxy->HardwareTransformPatch_GetVertexBufferPtr()->GetD3DVertexBuffer(), m_iPatchTerrainVertexSize);
#ifdef WORLD_EDITOR
STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, m_iPatchTerrainVertexCount, 0, m_wNumIndices - 2);
#else
STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, m_iPatchTerrainVertexCount, 0, m_wNumIndices[0] - 2);
#endif
}