1194 lines
33 KiB
C++
1194 lines
33 KiB
C++
#include "StdAfx.h"
|
||
#include "../PRTerrainLib/StdAfx.h"
|
||
|
||
#include "../eterLib/ResourceManager.h"
|
||
#include "../eterlib/StateManager.h"
|
||
#include "../EterPack/EterPackManager.h"
|
||
|
||
#include "AreaTerrain.h"
|
||
#include "MapOutdoor.h"
|
||
|
||
CDynamicPool<CTerrain> CTerrain::ms_kPool;
|
||
|
||
void CTerrain::DestroySystem()
|
||
{
|
||
ms_kPool.Destroy();
|
||
}
|
||
|
||
CTerrain* CTerrain::New()
|
||
{
|
||
return ms_kPool.Alloc();
|
||
}
|
||
|
||
void CTerrain::Delete(CTerrain* pkTerrain)
|
||
{
|
||
pkTerrain->Clear();
|
||
ms_kPool.Free(pkTerrain);
|
||
}
|
||
|
||
CTerrain::CTerrain()
|
||
{
|
||
memset(&m_lpAlphaTexture, 0, sizeof(m_lpAlphaTexture));
|
||
memset(&m_lpMarkedTexture, 0, sizeof(m_lpMarkedTexture));
|
||
Initialize();
|
||
}
|
||
|
||
CTerrain::~CTerrain()
|
||
{
|
||
DeallocateMarkedSplats();
|
||
RAW_DeallocateSplats();
|
||
Clear();
|
||
}
|
||
|
||
void CTerrain::SetMapOutDoor(CMapOutdoor * pOwnerOutdoorMap)
|
||
{
|
||
m_pOwnerOutdoorMap=pOwnerOutdoorMap;
|
||
}
|
||
|
||
void CTerrain::Clear()
|
||
{
|
||
DeallocateMarkedSplats();
|
||
CTerrainImpl::Clear();
|
||
Initialize();
|
||
}
|
||
|
||
bool CTerrain::Initialize()
|
||
{
|
||
SetReady(false);
|
||
m_strName = "";
|
||
m_wX = m_wY = 0xFFFF;
|
||
m_bReady = false;
|
||
m_bMarked = false;
|
||
|
||
for (BYTE byY = 0; byY < PATCH_YCOUNT; ++byY)
|
||
for (BYTE byX = 0; byX < PATCH_XCOUNT; ++byX)
|
||
m_TerrainPatchList[byY * PATCH_XCOUNT + byX].Clear();
|
||
|
||
return true;
|
||
}
|
||
|
||
void CTerrain::LoadMiniMapTexture(const char * c_pchMiniMapFileName)
|
||
{
|
||
DWORD dwStart = ELTimer_GetMSec();
|
||
CGraphicImage * pImage = (CGraphicImage *) CResourceManager::Instance().GetResourcePointer(c_pchMiniMapFileName);
|
||
m_MiniMapGraphicImageInstance.SetImagePointer(pImage);
|
||
|
||
if (!m_MiniMapGraphicImageInstance.GetTexturePointer()->IsEmpty())
|
||
{
|
||
m_lpMiniMapTexture = m_MiniMapGraphicImageInstance.GetTexturePointer()->GetD3DTexture();
|
||
Tracef("CTerrain::LoadMiniMapTexture %d ms\n", ELTimer_GetMSec() - dwStart);
|
||
}
|
||
else
|
||
{
|
||
Tracef(" CTerrain::LoadMiniMapTexture - MiniMapTexture Error");
|
||
m_lpMiniMapTexture = NULL;
|
||
}
|
||
}
|
||
|
||
void CTerrain::LoadShadowTexture(const char * ShadowFileName)
|
||
{
|
||
DWORD dwStart = ELTimer_GetMSec();
|
||
CGraphicImage * pImage = (CGraphicImage *) CResourceManager::Instance().GetResourcePointer(ShadowFileName);
|
||
m_ShadowGraphicImageInstance.SetImagePointer(pImage);
|
||
|
||
if (!m_ShadowGraphicImageInstance.GetTexturePointer()->IsEmpty())
|
||
m_lpShadowTexture = m_ShadowGraphicImageInstance.GetTexturePointer()->GetD3DTexture();
|
||
else
|
||
{
|
||
TraceError(" CTerrain::LoadShadowTexture - ShadowTexture is Empty");
|
||
m_lpShadowTexture = NULL;
|
||
}
|
||
Tracef("CTerrain::LoadShadowTexture %d ms\n", ELTimer_GetMSec() - dwStart);
|
||
}
|
||
|
||
bool CTerrain::LoadShadowMap(const char * c_pszFileName)
|
||
{
|
||
DWORD dwStart = ELTimer_GetMSec();
|
||
Tracef("LoadShadowMap %s ", c_pszFileName);
|
||
|
||
CMappedFile file;
|
||
LPCVOID c_pvData;
|
||
|
||
if (!CEterPackManager::Instance().Get(file, c_pszFileName, &c_pvData))
|
||
{
|
||
TraceError(" CTerrain::LoadShadowMap - %s OPEN ERROR", c_pszFileName);
|
||
return false;
|
||
}
|
||
|
||
DWORD dwShadowMapSize = sizeof(WORD) * 256 * 256;
|
||
|
||
if (file.Size() != dwShadowMapSize)
|
||
{
|
||
TraceError(" CTerrain::LoadShadowMap - %s SIZE ERROR", c_pszFileName);
|
||
return false;
|
||
}
|
||
|
||
memcpy(m_awShadowMap, c_pvData, dwShadowMapSize);
|
||
|
||
Tracef("%d ms\n", ELTimer_GetMSec() - dwStart);
|
||
return true;
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
// Seamless<73><73> <20><><EFBFBD>ο<EFBFBD> <20>Լ<EFBFBD><D4BC><EFBFBD>...
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
void CTerrain::CopySettingFromGlobalSetting()
|
||
{
|
||
m_lViewRadius = m_pOwnerOutdoorMap->GetViewRadius();
|
||
m_fHeightScale = m_pOwnerOutdoorMap->GetHeightScale();
|
||
}
|
||
|
||
WORD CTerrain::WE_GetHeightMapValue(short sX, short sY)
|
||
{
|
||
if (sX>=-1 && sY>=-1 && sX<HEIGHTMAP_RAW_XSIZE-1 && sY<HEIGHTMAP_RAW_YSIZE-1)
|
||
return GetHeightMapValue(sX,sY);
|
||
|
||
BYTE byTerrainNum;
|
||
if ( !m_pOwnerOutdoorMap->GetTerrainNumFromCoord(m_wX, m_wY, &byTerrainNum) )
|
||
{
|
||
Tracef("CTerrain::WE_GetHeightMapValue : Can't Get TerrainNum from Coord %d, %d", m_wX, m_wY);
|
||
byTerrainNum = 4;
|
||
}
|
||
|
||
short sTerrainCouuntX, sTerrainCouuntY;
|
||
m_pOwnerOutdoorMap->GetTerrainCount(&sTerrainCouuntX, &sTerrainCouuntY);
|
||
|
||
CTerrain * pTerrain = NULL;
|
||
|
||
if (sY < -1)
|
||
{
|
||
if (m_wY <= 0)
|
||
{
|
||
if ( sX < -1)
|
||
{
|
||
if (m_wX <= 0)
|
||
return GetHeightMapValue(-1, -1);
|
||
else
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 1, &pTerrain))
|
||
return GetHeightMapValue(-1, -1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(sX + XSIZE, -1);
|
||
}
|
||
}
|
||
else if (sX >= HEIGHTMAP_RAW_XSIZE - 1)
|
||
{
|
||
if (m_wX >= sTerrainCouuntX - 1)
|
||
return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, -1);
|
||
else
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 1, &pTerrain))
|
||
return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, -1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(sX - XSIZE, -1);
|
||
}
|
||
}
|
||
else
|
||
return GetHeightMapValue(sX, -1);
|
||
}
|
||
else
|
||
{
|
||
if (sX < -1)
|
||
{
|
||
if (m_wX <= 0)
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 3, &pTerrain))
|
||
return GetHeightMapValue(-1, -1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(-1, sY + YSIZE);
|
||
}
|
||
else
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 4, &pTerrain))
|
||
return GetHeightMapValue(-1, -1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(sX + XSIZE, sY + YSIZE);
|
||
}
|
||
}
|
||
else if (sX >= HEIGHTMAP_RAW_XSIZE - 1)
|
||
{
|
||
if (m_wX >= sTerrainCouuntX)
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 3, &pTerrain))
|
||
return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, -1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, sY + YSIZE);
|
||
}
|
||
else
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 2, &pTerrain))
|
||
return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, -1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(sX - XSIZE, sY + YSIZE);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 3, &pTerrain))
|
||
return GetHeightMapValue(sX, -1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(sX, sY + YSIZE);
|
||
}
|
||
}
|
||
}
|
||
else if (sY >= HEIGHTMAP_RAW_YSIZE - 1)
|
||
{
|
||
if (m_wY >= sTerrainCouuntY - 1)
|
||
{
|
||
if (sX < -1)
|
||
{
|
||
if (m_wX <= 0)
|
||
return GetHeightMapValue(-1, HEIGHTMAP_RAW_XSIZE - 1);
|
||
else
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 1, &pTerrain))
|
||
return GetHeightMapValue(-1, HEIGHTMAP_RAW_XSIZE - 1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(sX + XSIZE, HEIGHTMAP_RAW_YSIZE - 1);
|
||
}
|
||
}
|
||
else if (sX >= HEIGHTMAP_RAW_XSIZE - 1)
|
||
{
|
||
if (m_wX >= sTerrainCouuntX - 1)
|
||
return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, HEIGHTMAP_RAW_YSIZE - 1);
|
||
else
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 1, &pTerrain))
|
||
return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, HEIGHTMAP_RAW_YSIZE - 1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(sX - XSIZE, HEIGHTMAP_RAW_YSIZE - 1);
|
||
}
|
||
}
|
||
else
|
||
return GetHeightMapValue(sX, HEIGHTMAP_RAW_YSIZE - 1);
|
||
}
|
||
else
|
||
{
|
||
if (sX < -1)
|
||
{
|
||
if (m_wX <= 0)
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 3, &pTerrain))
|
||
return GetHeightMapValue(-1, HEIGHTMAP_RAW_YSIZE - 1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(-1, sY - YSIZE);
|
||
}
|
||
else
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 2, &pTerrain))
|
||
return GetHeightMapValue(-1, HEIGHTMAP_RAW_XSIZE - 1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(sX + XSIZE, sY - YSIZE);
|
||
}
|
||
}
|
||
else if (sX >= HEIGHTMAP_RAW_XSIZE - 1)
|
||
{
|
||
if (m_wX >= sTerrainCouuntX - 1)
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 3, &pTerrain))
|
||
return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, HEIGHTMAP_RAW_YSIZE - 1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, sY - YSIZE);
|
||
}
|
||
else
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 4, &pTerrain))
|
||
return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, HEIGHTMAP_RAW_YSIZE - 1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(sX - XSIZE, sY - YSIZE);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 3, &pTerrain))
|
||
return GetHeightMapValue(sX, HEIGHTMAP_RAW_YSIZE - 1);
|
||
else
|
||
return pTerrain->GetHeightMapValue(sX, sY - YSIZE);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (sX < -1)
|
||
{
|
||
if (m_wX <= 0)
|
||
return GetHeightMapValue(-1, sY);
|
||
else
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 1, &pTerrain))
|
||
return GetHeightMapValue(-1, sY);
|
||
else
|
||
return pTerrain->GetHeightMapValue(sX + XSIZE, sY);
|
||
}
|
||
}
|
||
else if (sX >= HEIGHTMAP_RAW_XSIZE - 1)
|
||
{
|
||
if (m_wX >= sTerrainCouuntX - 1)
|
||
return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, sY);
|
||
else
|
||
{
|
||
if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 1, &pTerrain))
|
||
return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, sY);
|
||
else
|
||
return pTerrain->GetHeightMapValue(sX - XSIZE, sY);
|
||
}
|
||
}
|
||
else
|
||
return GetHeightMapValue(sX, sY);
|
||
}
|
||
}
|
||
|
||
bool CTerrain::GetNormal(int ix, int iy, D3DXVECTOR3 * pv3Normal)
|
||
{
|
||
long lMapWidth = XSIZE * CELLSCALE;
|
||
long lMapHeight = YSIZE * CELLSCALE;
|
||
while (ix < 0)
|
||
ix += lMapWidth;
|
||
|
||
while (iy < 0)
|
||
iy += lMapHeight;
|
||
|
||
while (ix > lMapWidth)
|
||
ix -= lMapWidth;
|
||
|
||
while (iy > lMapHeight)
|
||
iy -= lMapHeight;
|
||
|
||
ix /= CELLSCALE;
|
||
iy /= CELLSCALE;
|
||
|
||
D3DXVECTOR3 v3Noraml;
|
||
char * n = (char*) &m_acNormalMap[(iy * NORMALMAP_XSIZE + ix)*3];
|
||
pv3Normal->x = -((float)*n++) * 0.007874016f;
|
||
pv3Normal->y = ((float)*n++) * 0.007874016f;
|
||
pv3Normal->z = ((float)*n++) * 0.007874016f;
|
||
|
||
return true;
|
||
}
|
||
// Returns the height of the terrain at the given world coordinate
|
||
float CTerrain::GetHeight(int x, int y)
|
||
{
|
||
//if (0 == CELLSCALE)
|
||
//return 0.0f;
|
||
|
||
x -= m_wX * XSIZE * CELLSCALE;
|
||
y -= m_wY * YSIZE * CELLSCALE;
|
||
|
||
if (x < 0 || y < 0 || x > XSIZE * CELLSCALE || y > XSIZE * CELLSCALE)
|
||
return 0.0f;
|
||
|
||
long xdist; /* x mod size of tile */
|
||
long ydist; /* y mod size of tile */
|
||
float xslope, yslope; /* slopes of heights between vertices */
|
||
|
||
float h1, h2, h3;
|
||
long x2, y2;
|
||
float ooscale;
|
||
|
||
/* Find out the distance relative to the top left vertex of a tile */
|
||
xdist = x % CELLSCALE;
|
||
ydist = y % CELLSCALE;
|
||
|
||
/* Convert into pixel coordinates */
|
||
ooscale = 1.0f / ((float)CELLSCALE);
|
||
x /= CELLSCALE;
|
||
y /= CELLSCALE;
|
||
|
||
x2 = x; y2 = y;
|
||
/* Get the height and color of the pixel at the top left corner */
|
||
h1 = (float) GetHeightMapValue(x2, y2) * m_fHeightScale;
|
||
|
||
/* Get the height and color of the pixel at the bottom right corner */
|
||
x2 = x + 1;
|
||
y2 = y + 1;
|
||
|
||
h2 = (float) GetHeightMapValue(x2, y2) * m_fHeightScale;
|
||
|
||
/* Left triangle */
|
||
if (xdist <= ydist)
|
||
{
|
||
x2 = x;
|
||
y2 = y + 1;
|
||
|
||
h3 = (float) GetHeightMapValue(x2, y2) * m_fHeightScale;
|
||
|
||
/* Get the height of the pixel at the bottom left corner */
|
||
xslope = (h2 - h3) * ooscale;
|
||
yslope = (h3 - h1) * ooscale;
|
||
|
||
return (h1 + (xdist * xslope + ydist * yslope));
|
||
}
|
||
|
||
/* Right triangle */
|
||
x2 = x + 1;
|
||
y2 = y;
|
||
|
||
h3 = (float) GetHeightMapValue(x2, y2) * m_fHeightScale;
|
||
|
||
/* Get the height of the pixel at the top right corner */
|
||
xslope = (h3 - h1) * ooscale;
|
||
yslope = (h2 - h3) * ooscale;
|
||
|
||
return (h1 + (xdist * xslope + ydist * yslope));
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
// HeightMapCoord -> TileMapCoord
|
||
|
||
void CTerrain::CalculateNormal(long x, long y)
|
||
{
|
||
D3DXVECTOR3 normal;
|
||
|
||
normal.x = -m_fHeightScale * ((float)GetHeightMapValue((x-1),y)-(float)GetHeightMapValue((x+1),y));
|
||
normal.y = -m_fHeightScale * ((float)GetHeightMapValue(x,(y-1))-(float)GetHeightMapValue(x,(y+1)));
|
||
|
||
normal.z = 2.0f * CELLSCALE;
|
||
normal *= 127.0f / D3DXVec3Length(&normal);
|
||
|
||
int ix, iy, iz;
|
||
PR_FLOAT_TO_INT(normal.x, ix);
|
||
PR_FLOAT_TO_INT(normal.y, iy);
|
||
PR_FLOAT_TO_INT(normal.z, iz);
|
||
|
||
char * n = (char*) &m_acNormalMap[(y * NORMALMAP_XSIZE + x)*3];
|
||
|
||
*n++ = (char) ix;
|
||
*n++ = (char) iy;
|
||
*n++ = (char) iz;
|
||
}
|
||
|
||
bool CTerrain::RAW_LoadTileMap(const char * c_pszFileName, bool bBGLoading)
|
||
{
|
||
CTerrainImpl::RAW_LoadTileMap(c_pszFileName);
|
||
DWORD dwStart = ELTimer_GetMSec();
|
||
RAW_AllocateSplats(bBGLoading);
|
||
Tracef("CTerrain::RAW_AllocateSplats %d\n", ELTimer_GetMSec() - dwStart);
|
||
return true;
|
||
}
|
||
|
||
bool CTerrain::LoadHeightMap(const char * c_pszFileName)
|
||
{
|
||
CTerrainImpl::LoadHeightMap(c_pszFileName);
|
||
DWORD dwStart = ELTimer_GetMSec();
|
||
for (WORD y = 0; y < NORMALMAP_YSIZE; ++y)
|
||
for (WORD x = 0; x < NORMALMAP_XSIZE; ++x)
|
||
CalculateNormal(x, y);
|
||
|
||
Tracef("LoadHeightMap::CalculateNormal %d ms\n", ELTimer_GetMSec() - dwStart);
|
||
return true;
|
||
}
|
||
|
||
bool CTerrain::LoadAttrMap(const char *c_pszFileName)
|
||
{
|
||
return CTerrainImpl::LoadAttrMap(c_pszFileName);
|
||
}
|
||
|
||
bool CTerrain::isAttrOn(WORD wCoordX, WORD wCoordY, BYTE byAttrFlag)
|
||
{
|
||
if (wCoordX >= ATTRMAP_XSIZE || wCoordY >= ATTRMAP_YSIZE)
|
||
{
|
||
Tracef("CTerrain::isAttrOn Coordiante Error! Return false... Input Coord - X : %d, Y : %d ( Limit X : %d, Y : %d)", wCoordX, wCoordY, ATTRMAP_XSIZE, ATTRMAP_YSIZE);
|
||
return false;
|
||
}
|
||
|
||
BYTE byMapAttr = m_abyAttrMap[wCoordY * ATTRMAP_XSIZE + wCoordX];
|
||
|
||
if ( byAttrFlag < 16 )
|
||
return (byMapAttr & byAttrFlag) ? true : false;
|
||
else
|
||
{
|
||
if ( byAttrFlag/16 == byMapAttr/16)
|
||
return true;
|
||
else
|
||
return false;
|
||
}
|
||
}
|
||
|
||
BYTE CTerrain::GetAttr(WORD wCoordX, WORD wCoordY)
|
||
{
|
||
if (wCoordX >= ATTRMAP_XSIZE || wCoordY >= ATTRMAP_YSIZE)
|
||
{
|
||
Tracef("CTerrain::GetAttr Coordiante Error! Return 0... Input Coord - X : %d, Y : %d ( Limit X : %d, Y : %d)", wCoordX, wCoordY, ATTRMAP_XSIZE, ATTRMAP_YSIZE);
|
||
return 0;
|
||
}
|
||
|
||
return m_abyAttrMap[wCoordY * ATTRMAP_XSIZE + wCoordX];
|
||
}
|
||
|
||
void CTerrain::GetWaterHeight(BYTE byWaterNum, long * plWaterHeight)
|
||
{
|
||
if (byWaterNum > m_byNumWater)
|
||
{
|
||
Tracef("CTerrain::GetWaterHeight WaterNum %d(Total Num %d) ERROR!", byWaterNum, m_byNumWater);
|
||
return;
|
||
}
|
||
*plWaterHeight = m_lWaterHeight[byWaterNum];
|
||
}
|
||
|
||
bool CTerrain::GetWaterHeight(WORD wCoordX, WORD wCoordY, long * plWaterHeight)
|
||
{
|
||
BYTE byWaterNum = *(m_abyWaterMap + (wCoordY * WATERMAP_XSIZE) + wCoordX);
|
||
if (byWaterNum > m_byNumWater)
|
||
{
|
||
Tracef("CTerrain::GetWaterHeight (X %d, Y %d) ERROR!", wCoordX, wCoordY, m_byNumWater);
|
||
return false;
|
||
}
|
||
*plWaterHeight = m_lWaterHeight[byWaterNum] / 2;
|
||
|
||
return true;
|
||
}
|
||
|
||
void CTerrain::RAW_DeallocateSplats(bool bBGLoading)
|
||
{
|
||
for (DWORD i = 1; i < GetTextureSet()->GetTextureCount(); ++i)
|
||
{
|
||
TTerainSplat & rSplat = m_TerrainSplatPatch.Splats[i];
|
||
|
||
if (m_lpAlphaTexture[i])
|
||
{
|
||
ULONG ulRef;
|
||
do
|
||
{
|
||
ulRef = m_lpAlphaTexture[i]->Release();
|
||
} while(ulRef > 0);
|
||
}
|
||
|
||
rSplat.pd3dTexture = m_lpAlphaTexture[i] = NULL;
|
||
}
|
||
|
||
memset(&m_TerrainSplatPatch, 0, sizeof(m_TerrainSplatPatch));
|
||
}
|
||
|
||
void CTerrain::RAW_AllocateSplats(bool bBGLoading)
|
||
{
|
||
RAW_DeallocateSplats(bBGLoading);
|
||
DWORD dwTexCount = GetTextureSet()->GetTextureCount();
|
||
|
||
m_TerrainSplatPatch.m_bNeedsUpdate = true;
|
||
|
||
for (DWORD t = 0; t < dwTexCount; ++t)
|
||
m_TerrainSplatPatch.Splats[t].NeedsUpdate = 1;
|
||
|
||
RAW_CountTiles();
|
||
|
||
// if ( WAIT_OBJECT_0 == LockDataWrite() )
|
||
RAW_GenerateSplat(bBGLoading);
|
||
// UnlockDataWrite();
|
||
|
||
m_TerrainSplatPatch.m_bNeedsUpdate = false;
|
||
}
|
||
|
||
void CTerrain::RAW_CountTiles()
|
||
{
|
||
for (long y = 0; y < TILEMAP_RAW_YSIZE; ++y)
|
||
{
|
||
long lPatchIndexY = min(max((y-1)/PATCH_TILE_YSIZE,0), PATCH_YCOUNT - 1);
|
||
for (long x = 0; x < TILEMAP_RAW_XSIZE; ++x)
|
||
{
|
||
long lPatchIndexX = min(max((x-1)/(PATCH_TILE_XSIZE), 0), PATCH_XCOUNT - 1);
|
||
BYTE tilenum = m_abyTileMap[y * TILEMAP_RAW_XSIZE + x];
|
||
|
||
++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + lPatchIndexX][tilenum];
|
||
|
||
if ( 0 == y % PATCH_TILE_YSIZE && 0 != y && (TILEMAP_RAW_YSIZE - 2) != y)
|
||
{
|
||
++m_TerrainSplatPatch.PatchTileCount[min(PATCH_YCOUNT - 1, lPatchIndexY + 1) * PATCH_XCOUNT + lPatchIndexX][tilenum];
|
||
if ( 0 == x % PATCH_TILE_XSIZE && 0 != x && (TILEMAP_RAW_XSIZE - 2) != x)
|
||
{
|
||
++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum];
|
||
++m_TerrainSplatPatch.PatchTileCount[min(PATCH_YCOUNT - 1, lPatchIndexY + 1) * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum];
|
||
}
|
||
else if ( 1 == x % PATCH_TILE_XSIZE && (TILEMAP_RAW_XSIZE -1) != x && 1 != x)
|
||
{
|
||
++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum];
|
||
++m_TerrainSplatPatch.PatchTileCount[min(PATCH_YCOUNT - 1, lPatchIndexY + 1) * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum];
|
||
}
|
||
}
|
||
else if ( 1 == y % PATCH_TILE_YSIZE && (TILEMAP_RAW_YSIZE -1) != y && 1 != y)
|
||
{
|
||
++m_TerrainSplatPatch.PatchTileCount[max(0, lPatchIndexY - 1) * PATCH_XCOUNT + lPatchIndexX][tilenum];
|
||
if ( 0 == x % PATCH_TILE_XSIZE && 0 != x && (TILEMAP_RAW_XSIZE - 2) != x)
|
||
{
|
||
++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum];
|
||
++m_TerrainSplatPatch.PatchTileCount[max(0, lPatchIndexY - 1) * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum];
|
||
}
|
||
else if ( 1 == x % PATCH_TILE_XSIZE && (TILEMAP_RAW_XSIZE -1) != x && 1 != x)
|
||
{
|
||
++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum];
|
||
++m_TerrainSplatPatch.PatchTileCount[max(0, lPatchIndexY - 1) * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ( 0 == x % PATCH_TILE_XSIZE && 0 != x && (TILEMAP_RAW_XSIZE - 2) != x)
|
||
++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum];
|
||
else if ( 1 == x % PATCH_TILE_XSIZE && (TILEMAP_RAW_XSIZE -1) != x && 1 != x)
|
||
++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum];
|
||
}
|
||
|
||
++m_TerrainSplatPatch.TileCount[tilenum];
|
||
}
|
||
}
|
||
}
|
||
|
||
void CTerrain::RAW_GenerateSplat(bool bBGLoading)
|
||
{
|
||
if (!m_TerrainSplatPatch.m_bNeedsUpdate)
|
||
return;
|
||
|
||
m_TerrainSplatPatch.m_bNeedsUpdate = false;
|
||
|
||
BYTE abyAlphaMap[SPLATALPHA_RAW_XSIZE * SPLATALPHA_RAW_YSIZE];
|
||
BYTE * aptr;
|
||
|
||
for (DWORD i = 1; i < GetTextureSet()->GetTextureCount(); ++i)
|
||
{
|
||
TTerainSplat & rSplat = m_TerrainSplatPatch.Splats[i];
|
||
|
||
if (rSplat.NeedsUpdate)
|
||
{
|
||
if (m_TerrainSplatPatch.TileCount[i] > 0)
|
||
{
|
||
if (rSplat.Active) // We already have an alpha map which needs to be updated
|
||
{
|
||
if (m_lpAlphaTexture[i])
|
||
{
|
||
ULONG ulRef;
|
||
do
|
||
{
|
||
ulRef = m_lpAlphaTexture[i]->Release();
|
||
if (ulRef > 0)
|
||
TraceError(" CTerrain::RAW_GenerateSplat - TileCount > 0 : Alpha Texture Release(%d) ERROR", ulRef);
|
||
} while(ulRef > 0);
|
||
}
|
||
|
||
rSplat.pd3dTexture = m_lpAlphaTexture[i] = NULL;
|
||
}
|
||
|
||
rSplat.Active = 1;
|
||
rSplat.NeedsUpdate = 0;
|
||
|
||
aptr = abyAlphaMap;
|
||
|
||
for (long y = 0; y < SPLATALPHA_RAW_YSIZE; ++y)
|
||
{
|
||
for (long x = 0; x < SPLATALPHA_RAW_XSIZE; ++x)
|
||
{
|
||
long lTileMapOffset = y * TILEMAP_RAW_XSIZE + x;
|
||
|
||
BYTE byTileNum = m_abyTileMap[lTileMapOffset];
|
||
if (byTileNum == i)
|
||
*aptr = 0xFF;
|
||
else if (byTileNum > i)
|
||
{
|
||
BYTE byTileTL, byTileTR, byTileBL, byTileBR, byTileT, byTileB, byTileL, byTileR;
|
||
|
||
if ( x > 0 && y > 0 )
|
||
byTileTL = m_abyTileMap[lTileMapOffset - TILEMAP_RAW_YSIZE - 1];
|
||
else
|
||
byTileTL = 0;
|
||
if ( x < (SPLATALPHA_RAW_XSIZE - 1) && y > 0 )
|
||
byTileTR = m_abyTileMap[lTileMapOffset - TILEMAP_RAW_YSIZE + 1];
|
||
else
|
||
byTileTR = 0;
|
||
if ( x > 0 && y < (SPLATALPHA_RAW_YSIZE - 1) )
|
||
byTileBL = m_abyTileMap[lTileMapOffset + TILEMAP_RAW_YSIZE - 1];
|
||
else
|
||
byTileBL = 0;
|
||
if ( x < (SPLATALPHA_RAW_XSIZE - 1) && y < (SPLATALPHA_RAW_YSIZE - 1) )
|
||
byTileBR = m_abyTileMap[lTileMapOffset + TILEMAP_RAW_YSIZE + 1];
|
||
else
|
||
byTileBR = 0;
|
||
if ( y > 0 )
|
||
byTileT = m_abyTileMap[lTileMapOffset - TILEMAP_RAW_YSIZE];
|
||
else
|
||
byTileT = 0;
|
||
if ( y < (SPLATALPHA_RAW_YSIZE - 1) )
|
||
byTileB = m_abyTileMap[lTileMapOffset + TILEMAP_RAW_YSIZE];
|
||
else
|
||
byTileB = 0;
|
||
if ( x > 0 )
|
||
byTileL = m_abyTileMap[lTileMapOffset - 1];
|
||
else
|
||
byTileL = 0;
|
||
if ( x < (SPLATALPHA_RAW_XSIZE - 1) )
|
||
byTileR = m_abyTileMap[lTileMapOffset + 1];
|
||
else
|
||
byTileR = 0;
|
||
|
||
if (byTileTL == i || byTileTR == i || byTileBL == i || byTileBR == i ||
|
||
byTileT == i || byTileB == i || byTileL == i || byTileR == i)
|
||
*aptr = 0xFF;
|
||
else
|
||
*aptr = 0x00;
|
||
}
|
||
else
|
||
*aptr = 0x00;
|
||
|
||
++aptr;
|
||
}
|
||
}
|
||
|
||
|
||
rSplat.pd3dTexture = AddTexture32(i, abyAlphaMap, SPLATALPHA_RAW_XSIZE, SPLATALPHA_RAW_YSIZE);
|
||
}
|
||
else
|
||
{
|
||
if (rSplat.Active)
|
||
{
|
||
if (m_lpAlphaTexture[i])
|
||
{
|
||
ULONG ulRef;
|
||
do
|
||
{
|
||
ulRef = m_lpAlphaTexture[i]->Release();
|
||
if (ulRef > 0)
|
||
TraceError(" CTerrain::RAW_GenerateSplat - TileDount 0 : Alpha Texture Release(%d) ERROR", ulRef);
|
||
} while(ulRef > 0);
|
||
}
|
||
|
||
rSplat.pd3dTexture = m_lpAlphaTexture[i] = NULL;
|
||
}
|
||
rSplat.NeedsUpdate = 0;
|
||
rSplat.Active = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
LPDIRECT3DTEXTURE8 CTerrain::AddTexture32(BYTE byImageNum, BYTE * pbyImage, long lTextureWidth, long lTextureHeight)
|
||
{
|
||
assert(NULL==m_lpAlphaTexture[byImageNum]);
|
||
|
||
if (m_lpAlphaTexture[byImageNum])
|
||
m_lpAlphaTexture[byImageNum]->Release();
|
||
|
||
m_lpAlphaTexture[byImageNum]=NULL;
|
||
|
||
HRESULT hr;
|
||
D3DFORMAT format;
|
||
|
||
if(ms_bSupportDXT)
|
||
format = D3DFMT_A8R8G8B8;
|
||
else
|
||
format = D3DFMT_A4R4G4B4;
|
||
|
||
|
||
bool bResizedAndSuccess = false;
|
||
|
||
IDirect3DTexture8* pkTex=NULL;
|
||
|
||
UINT uiNewWidth = 256;
|
||
UINT uiNewHeight = 256;
|
||
hr = ms_lpd3dDevice->CreateTexture(
|
||
uiNewWidth, uiNewHeight, 5, 0,
|
||
format, D3DPOOL_MANAGED, &pkTex);
|
||
if (FAILED(hr))
|
||
{
|
||
TraceError("CTerrain::AddTexture32 - CreateTexture Error");
|
||
return NULL;
|
||
}
|
||
|
||
|
||
BYTE abResizeImage[256*256];
|
||
{
|
||
BYTE* pbDstPixel=abResizeImage;
|
||
BYTE* pbSrcPixel;
|
||
BYTE* abCurLine=pbyImage;
|
||
for (UINT y=0; y<256; ++y, abCurLine+=258)
|
||
{
|
||
for (UINT x=0; x<256; ++x)
|
||
{
|
||
pbSrcPixel=abCurLine+x;
|
||
*pbDstPixel++=
|
||
((( pbSrcPixel[0]+pbSrcPixel[1]+pbSrcPixel[2]+
|
||
pbSrcPixel[258]+pbSrcPixel[260]+
|
||
pbSrcPixel[258*2]+pbSrcPixel[258*2+1]+pbSrcPixel[258*2+2])
|
||
>>3)+pbSrcPixel[259])>>1;
|
||
}
|
||
}
|
||
|
||
D3DLOCKED_RECT d3dlr;
|
||
hr = pkTex->LockRect(0, &d3dlr, 0, 0);
|
||
if (FAILED(hr))
|
||
{
|
||
pkTex->Release();
|
||
return NULL;
|
||
}
|
||
|
||
if(ms_bSupportDXT)
|
||
PutImage32(abResizeImage, (BYTE*) d3dlr.pBits, 256, d3dlr.Pitch, 256, 256, bResizedAndSuccess);
|
||
else
|
||
PutImage16(abResizeImage, (BYTE*) d3dlr.pBits, 256, d3dlr.Pitch, 256, 256, bResizedAndSuccess);
|
||
|
||
pkTex->UnlockRect(0);
|
||
}
|
||
|
||
BYTE abResizeImage2[128*128];
|
||
|
||
BYTE* pbSrcBuffer=abResizeImage;
|
||
BYTE* pbDstBuffer=abResizeImage2;
|
||
|
||
UINT uSrcSize=256;
|
||
|
||
for (UINT uMipMapLevel=1; uMipMapLevel!=pkTex->GetLevelCount(); ++uMipMapLevel)
|
||
{
|
||
UINT uDstSize=uSrcSize>>1;
|
||
|
||
BYTE* pbDstPixel=pbDstBuffer;
|
||
BYTE* pbSrcPixel;
|
||
BYTE* abCurLine=pbSrcBuffer;
|
||
for (UINT y=0; y!=uSrcSize; y+=2, abCurLine+=uSrcSize*2)
|
||
{
|
||
for (UINT x=0; x!=uSrcSize; x+=2)
|
||
{
|
||
pbSrcPixel=abCurLine+x;
|
||
*pbDstPixel++=(pbSrcPixel[0]+pbSrcPixel[1]+pbSrcPixel[uSrcSize+0]+pbSrcPixel[uSrcSize+1])>>2;
|
||
}
|
||
}
|
||
|
||
D3DLOCKED_RECT d3dlr;
|
||
|
||
hr = pkTex->LockRect(uMipMapLevel, &d3dlr, 0, 0);
|
||
if (FAILED(hr))
|
||
continue;
|
||
|
||
if(ms_bSupportDXT)
|
||
PutImage32(pbDstBuffer, (BYTE*) d3dlr.pBits, uDstSize, d3dlr.Pitch, uDstSize, uDstSize, bResizedAndSuccess);
|
||
else
|
||
PutImage16(pbDstBuffer, (BYTE*) d3dlr.pBits, uDstSize, d3dlr.Pitch, uDstSize, uDstSize, bResizedAndSuccess);
|
||
|
||
hr = pkTex->UnlockRect(uMipMapLevel);
|
||
|
||
std::swap(pbSrcBuffer, pbDstBuffer);
|
||
uSrcSize=uDstSize;
|
||
}
|
||
|
||
m_lpAlphaTexture[byImageNum]=pkTex;
|
||
|
||
return pkTex;
|
||
}
|
||
|
||
void CTerrain::PutImage32(BYTE *src, BYTE *dst, long src_pitch, long dst_pitch, long texturewidth, long textureheight, bool bResize)
|
||
{
|
||
for (int y = 0; y < textureheight; ++y)
|
||
{
|
||
for (int x = 0; x < texturewidth; ++x)
|
||
{
|
||
DWORD packed_pixel = src[x] << 24;
|
||
*((DWORD*)(dst+x*4)) = packed_pixel;
|
||
|
||
}
|
||
|
||
dst += dst_pitch;
|
||
src += src_pitch;
|
||
}
|
||
}
|
||
|
||
void CTerrain::PutImage16(BYTE *src, BYTE *dst, long src_pitch, long dst_pitch, long texturewidth, long textureheight, bool bResize)
|
||
{
|
||
for (int y = 0; y < textureheight; ++y)
|
||
{
|
||
for (int x = 0; x < texturewidth; ++x)
|
||
{
|
||
WORD packed_pixel = src[x] << 8;
|
||
//& <20><><EFBFBD><EFBFBD> <20>ѹ<EFBFBD><D1B9><EFBFBD> <20>Ʊ<EFBFBD><C6B1><EFBFBD>
|
||
//WORD packed_pixel = (src[x]&0xF0) << 8;
|
||
*((WORD*)(dst+x*2)) = packed_pixel;
|
||
}
|
||
|
||
dst += dst_pitch;
|
||
src += src_pitch;
|
||
}
|
||
}
|
||
|
||
void CTerrain::SetCoordinate(WORD wCoordX, WORD wCoordY)
|
||
{
|
||
m_wX = wCoordX;
|
||
m_wY = wCoordY;
|
||
}
|
||
|
||
void CTerrain::CalculateTerrainPatch()
|
||
{
|
||
for (BYTE byPatchNumY = 0; byPatchNumY < PATCH_YCOUNT; ++byPatchNumY)
|
||
for (BYTE byPatchNumX = 0; byPatchNumX < PATCH_XCOUNT; ++byPatchNumX)
|
||
_CalculateTerrainPatch(byPatchNumX, byPatchNumY);
|
||
}
|
||
|
||
CTerrainPatch * CTerrain::GetTerrainPatchPtr(BYTE byPatchNumX, BYTE byPatchNumY)
|
||
{
|
||
if (byPatchNumX < 0 || byPatchNumX >= PATCH_XCOUNT || byPatchNumY < 0 || byPatchNumY >= PATCH_YCOUNT)
|
||
return NULL;
|
||
|
||
return &m_TerrainPatchList[byPatchNumY * PATCH_XCOUNT + byPatchNumX];
|
||
}
|
||
|
||
|
||
|
||
void CTerrain::_CalculateTerrainPatch(BYTE byPatchNumX, BYTE byPatchNumY)
|
||
{
|
||
if (!m_awRawHeightMap || !m_acNormalMap || !m_abyWaterMap)
|
||
return;
|
||
|
||
DWORD dwPatchNum = byPatchNumY * PATCH_XCOUNT + byPatchNumX;
|
||
|
||
CTerrainPatch& rkTerrainPatch=m_TerrainPatchList[dwPatchNum];
|
||
if (!rkTerrainPatch.NeedUpdate())
|
||
return;
|
||
|
||
const float fOpaqueWaterDepth = m_pOwnerOutdoorMap->GetOpaqueWaterDepth();
|
||
const float fOOOpaqueWaterDepth = 1.0f/fOpaqueWaterDepth;
|
||
const float fTransparentWaterDepth = 0.8f * fOpaqueWaterDepth;
|
||
|
||
rkTerrainPatch.Clear();
|
||
|
||
HardwareTransformPatch_SSourceVertex akSrcTerrainVertex[CTerrainPatch::TERRAIN_VERTEX_COUNT];
|
||
SWaterVertex akSrcWaterVertex[PATCH_XSIZE * PATCH_YSIZE * 6];
|
||
|
||
DWORD dwNormalWidth = CTerrainImpl::NORMALMAP_XSIZE * 3;
|
||
DWORD dwStartX = byPatchNumX * PATCH_XSIZE;
|
||
DWORD dwStartY = byPatchNumY * PATCH_YSIZE;
|
||
|
||
WORD * wOrigRawHeightPtr = m_awRawHeightMap + ((dwStartY+1) * HEIGHTMAP_RAW_XSIZE) + dwStartX+1;
|
||
char * chOrigNormalPtr = m_acNormalMap + (dwStartY * dwNormalWidth) + dwStartX * 3;
|
||
BYTE * byOrigWaterPtr = m_abyWaterMap + (dwStartY * WATERMAP_XSIZE) + dwStartX;
|
||
|
||
float fX, fY, fOrigX, fOrigY;
|
||
fOrigX = fX = (float)(m_wX * XSIZE * CELLSCALE) + (float)(dwStartX * CELLSCALE);
|
||
fOrigY = fY = (float)(m_wY * YSIZE * CELLSCALE) + (float)(dwStartY * CELLSCALE);
|
||
|
||
rkTerrainPatch.SetMinX(fX);
|
||
rkTerrainPatch.SetMaxX(fX + (float)(PATCH_XSIZE*CELLSCALE));
|
||
rkTerrainPatch.SetMinY(fY);
|
||
rkTerrainPatch.SetMaxY(fY + (float)(PATCH_YSIZE*CELLSCALE));
|
||
|
||
float fMinZ = 999999.0f;
|
||
float fMaxZ = -999999.0f;
|
||
WORD wNumPlainType = 0;
|
||
WORD wNumHillType = 0;
|
||
WORD wNumCliffType = 0;
|
||
|
||
bool bWaterExist=false;
|
||
|
||
SWaterVertex* lpWaterVertex=akSrcWaterVertex;
|
||
UINT uWaterVertexCount=0;
|
||
|
||
HardwareTransformPatch_SSourceVertex* lpTerrainVertex=akSrcTerrainVertex;
|
||
UINT uTerrainVertexCount=0;
|
||
|
||
D3DXVECTOR3 kNormal;
|
||
D3DXVECTOR3 kPosition;
|
||
for (DWORD dwY = dwStartY; dwY <= dwStartY + PATCH_YSIZE; ++dwY)
|
||
{
|
||
WORD * pwRawHeight = wOrigRawHeightPtr;
|
||
char * pchNormal = chOrigNormalPtr;
|
||
BYTE * pbyWater = byOrigWaterPtr;
|
||
fX = fOrigX;
|
||
|
||
for (DWORD dwX = dwStartX; dwX <= dwStartX + PATCH_XSIZE; ++dwX)
|
||
{
|
||
WORD hgt = (*pwRawHeight++);
|
||
|
||
kNormal.x = -(*pchNormal++) * 0.0078740f;
|
||
kNormal.y = (*pchNormal++) * 0.0078740f;
|
||
kNormal.z = (*pchNormal++) * 0.0078740f;
|
||
|
||
kPosition.x = +fX;
|
||
kPosition.y = -fY;
|
||
kPosition.z = (float)(hgt) * m_fHeightScale;
|
||
lpTerrainVertex->kPosition = kPosition;
|
||
lpTerrainVertex->kNormal = kNormal;
|
||
|
||
if (0.5f > kNormal.z) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> 30<33><30> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD>. Cliff type<70><65><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
++wNumCliffType;
|
||
else if (0.8660254f > kNormal.z) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> 60<36><30> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD>. Hill type<70><65><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
++wNumHillType;
|
||
else // <20><> <20>̻<EFBFBD><CCBB><EFBFBD> plain Ÿ<><C5B8>
|
||
++wNumPlainType;
|
||
|
||
if (kPosition.z > fMaxZ)
|
||
fMaxZ = kPosition.z;
|
||
if (kPosition.z < fMinZ)
|
||
fMinZ = kPosition.z;
|
||
|
||
if (0 <= dwX && 0 <= dwY && XSIZE > dwX && YSIZE > dwY &&
|
||
(dwStartX + PATCH_XSIZE) != dwX && (dwStartY + PATCH_YSIZE) != dwY)
|
||
{
|
||
BYTE byNumWater = (*pbyWater++);
|
||
|
||
if (byNumWater != 0xFF)
|
||
{
|
||
long lWaterHeight = m_lWaterHeight[byNumWater];
|
||
if (-1 != lWaterHeight)
|
||
{
|
||
float fWaterTerrainHeightDifference0 = (float)(lWaterHeight - (long)hgt);
|
||
if (fWaterTerrainHeightDifference0 >= fTransparentWaterDepth)
|
||
fWaterTerrainHeightDifference0 = fTransparentWaterDepth;
|
||
if (fWaterTerrainHeightDifference0 <= 0.0f)
|
||
fWaterTerrainHeightDifference0 = 0.0f;
|
||
|
||
float fWaterTerrainHeightDifference1 = (float)(lWaterHeight - (long)(*(pwRawHeight + CTerrainImpl::HEIGHTMAP_RAW_XSIZE - 1)));
|
||
if (fWaterTerrainHeightDifference1 >= fTransparentWaterDepth)
|
||
fWaterTerrainHeightDifference1 = fTransparentWaterDepth;
|
||
if (fWaterTerrainHeightDifference1 <= 0.0f)
|
||
fWaterTerrainHeightDifference1 = 0.0f;
|
||
|
||
float fWaterTerrainHeightDifference2 = (float)(lWaterHeight - (long)(*(pwRawHeight)));
|
||
if (fWaterTerrainHeightDifference2 >= fTransparentWaterDepth)
|
||
fWaterTerrainHeightDifference2 = fTransparentWaterDepth;
|
||
if (fWaterTerrainHeightDifference2 <= 0.0f)
|
||
fWaterTerrainHeightDifference2 = 0.0f;
|
||
|
||
float fWaterTerrainHeightDifference3 = (float)(lWaterHeight - (long)(*(pwRawHeight + CTerrainImpl::HEIGHTMAP_RAW_XSIZE)));
|
||
if (fWaterTerrainHeightDifference3 >= fTransparentWaterDepth)
|
||
fWaterTerrainHeightDifference3 = fTransparentWaterDepth;
|
||
if (fWaterTerrainHeightDifference3 <= 0.0f)
|
||
fWaterTerrainHeightDifference3 = 0.0f;
|
||
|
||
DWORD dwAlpha0;
|
||
DWORD dwAlpha1;
|
||
DWORD dwAlpha2;
|
||
DWORD dwAlpha3;
|
||
|
||
PR_FLOAT_TO_INT(fWaterTerrainHeightDifference0 * fOOOpaqueWaterDepth * 255.0f, dwAlpha0);
|
||
PR_FLOAT_TO_INT(fWaterTerrainHeightDifference1 * fOOOpaqueWaterDepth * 255.0f, dwAlpha1);
|
||
PR_FLOAT_TO_INT(fWaterTerrainHeightDifference2 * fOOOpaqueWaterDepth * 255.0f, dwAlpha2);
|
||
PR_FLOAT_TO_INT(fWaterTerrainHeightDifference3 * fOOOpaqueWaterDepth * 255.0f, dwAlpha3);
|
||
|
||
DWORD dwAlphaKey=(dwAlpha0<<24)|(dwAlpha1<<16)|(dwAlpha2<<8)|dwAlpha3;
|
||
if (dwAlphaKey!=0)
|
||
{
|
||
assert(lpWaterVertex<akSrcWaterVertex+PATCH_XSIZE * PATCH_YSIZE * 6);
|
||
lpWaterVertex->x = fX;
|
||
lpWaterVertex->y = -fY;
|
||
lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale;
|
||
lpWaterVertex->dwDiffuse = ((dwAlpha0 << 24) & 0xFF000000) | 0x000000FF;// 0x000F939B
|
||
lpWaterVertex++;
|
||
|
||
lpWaterVertex->x = fX;
|
||
lpWaterVertex->y = -fY - float(CELLSCALE);
|
||
lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale;
|
||
lpWaterVertex->dwDiffuse = ((dwAlpha1 << 24) & 0xFF000000) | 0x00FFFFFF;
|
||
lpWaterVertex++;
|
||
|
||
lpWaterVertex->x = fX + float(CELLSCALE);
|
||
lpWaterVertex->y = -fY;
|
||
lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale;
|
||
lpWaterVertex->dwDiffuse = ((dwAlpha2 << 24) & 0xFF000000) | 0x00FFFFFF;
|
||
lpWaterVertex++;
|
||
|
||
lpWaterVertex->x = fX + float(CELLSCALE);
|
||
lpWaterVertex->y = -fY;
|
||
lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale;
|
||
lpWaterVertex->dwDiffuse = ((dwAlpha2 << 24) & 0xFF000000) | 0x00FFFFFF;
|
||
lpWaterVertex++;
|
||
|
||
lpWaterVertex->x = fX;
|
||
lpWaterVertex->y = -fY - float(CELLSCALE);
|
||
lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale;
|
||
lpWaterVertex->dwDiffuse = ((dwAlpha1 << 24) & 0xFF000000) | 0x00FFFFFF;
|
||
lpWaterVertex++;
|
||
|
||
lpWaterVertex->x = fX + float(CELLSCALE);
|
||
lpWaterVertex->y = -fY - float(CELLSCALE);
|
||
lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale;
|
||
lpWaterVertex->dwDiffuse = ((dwAlpha3 << 24) & 0xFF0000FF) | 0x00FFFFFF;
|
||
lpWaterVertex++;
|
||
|
||
uWaterVertexCount+=6;
|
||
bWaterExist = true;
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
++lpTerrainVertex;
|
||
++uTerrainVertexCount;
|
||
fX += float(CELLSCALE);
|
||
}
|
||
|
||
wOrigRawHeightPtr += CTerrainImpl::HEIGHTMAP_RAW_XSIZE;
|
||
chOrigNormalPtr += dwNormalWidth;
|
||
byOrigWaterPtr += CTerrainImpl::XSIZE;
|
||
fY += float(CELLSCALE);
|
||
}
|
||
|
||
if (wNumPlainType <= max(wNumHillType, wNumCliffType))
|
||
{
|
||
if (wNumCliffType <= wNumHillType)
|
||
rkTerrainPatch.SetType(CTerrainPatch::PATCH_TYPE_HILL);
|
||
else
|
||
rkTerrainPatch.SetType(CTerrainPatch::PATCH_TYPE_CLIFF);
|
||
}
|
||
|
||
rkTerrainPatch.SetWaterExist(bWaterExist);
|
||
|
||
rkTerrainPatch.SetMinZ(fMinZ);
|
||
rkTerrainPatch.SetMaxZ(fMaxZ);
|
||
|
||
assert((PATCH_XSIZE+1)*(PATCH_YSIZE+1)==uTerrainVertexCount);
|
||
rkTerrainPatch.BuildTerrainVertexBuffer(akSrcTerrainVertex);
|
||
|
||
if (bWaterExist)
|
||
rkTerrainPatch.BuildWaterVertexBuffer(akSrcWaterVertex, uWaterVertexCount);
|
||
|
||
rkTerrainPatch.NeedUpdate(false);
|
||
}
|
||
|
||
void CTerrain::AllocateMarkedSplats(BYTE * pbyAlphaMap)
|
||
{
|
||
TTerainSplat & rAttrSplat = m_MarkedSplatPatch.Splats[0];
|
||
HRESULT hr;
|
||
|
||
if (m_lpMarkedTexture)
|
||
{
|
||
ULONG ulRef;
|
||
do
|
||
{
|
||
ulRef = m_lpMarkedTexture->Release();
|
||
} while(ulRef > 0);
|
||
}
|
||
|
||
do
|
||
{
|
||
hr = ms_lpd3dDevice->CreateTexture(ATTRMAP_XSIZE, ATTRMAP_YSIZE, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_lpMarkedTexture);
|
||
} while(FAILED(hr));
|
||
|
||
D3DLOCKED_RECT d3dlr;
|
||
do
|
||
{
|
||
hr = m_lpMarkedTexture->LockRect(0, &d3dlr, 0, 0);
|
||
} while(FAILED(hr));
|
||
|
||
PutImage32(pbyAlphaMap, (BYTE*) d3dlr.pBits, ATTRMAP_XSIZE, d3dlr.Pitch, ATTRMAP_XSIZE, ATTRMAP_YSIZE);
|
||
|
||
do
|
||
{
|
||
hr = m_lpMarkedTexture->UnlockRect(0);
|
||
} while(FAILED(hr));
|
||
|
||
rAttrSplat.pd3dTexture = m_lpMarkedTexture;
|
||
m_bMarked = true;
|
||
}
|
||
|
||
void CTerrain::DeallocateMarkedSplats()
|
||
{
|
||
TTerainSplat & rSplat = m_MarkedSplatPatch.Splats[0];
|
||
if (m_lpMarkedTexture)
|
||
{
|
||
ULONG ulRef;
|
||
do
|
||
{
|
||
ulRef = m_lpMarkedTexture->Release();
|
||
} while(ulRef > 0);
|
||
}
|
||
|
||
rSplat.pd3dTexture = NULL;
|
||
m_lpMarkedTexture = NULL;
|
||
m_bMarked = FALSE;
|
||
|
||
memset(&m_MarkedSplatPatch, 0, sizeof(m_MarkedSplatPatch));
|
||
}
|