📄 terrain.cpp
字号:
//--------------------------------------------------
// Desc: LOD Terrain
// Author: artsylee/2007.1.10
//--------------------------------------------------
#include <stdio.h>
#include "Terrain.h"
#include "Common.h"
#include "SkyBox.h"
#include "Heightmap.h"
#include "ase/ASEngine.h"
extern CSkyBox skybox;
CHeightmap g_Hmap;
bool g_bLineMode = false;
CTerrain::CTerrain()
{
m_numTriangles = 0;
}
CTerrain::~CTerrain()
{
if(g_pTextureManager == NULL) return;
for(int i=0; i<2; i++)
{
g_pTextureManager->ReleaseTexture(m_hBlend[i]);
}
}
bool CTerrain::LoadTerrain()
{
// height map
g_Hmap.LoadHeightmap("Picture\\Hightmap256.raw", 256);
// LOD
FILE* fp = fopen("Picture\\lodmap.lod", "rb");
if(fp==NULL)
{
return false;
}
for(int z=MOVE_MAP_SIZE-1; z>-1; z--)
{
for(int x=0; x<MOVE_MAP_SIZE; x++)
{
fread(&m_LODmap[z][x], sizeof(unsigned char), 1, fp);
}
}
fclose(fp);
// Texture
m_hBlend[0] = g_pTextureManager->LoadTexture("Picture\\Tile_1.tga", MM_KEEPINMEMORY, 0);
m_hBlend[1] = g_pTextureManager->LoadTexture("Picture\\Tile_2.tga", MM_KEEPINMEMORY, 0);
return true;
}
void CTerrain::SmoothEdge(void)
{
for(int z=0; z<256; z++)
{
g_Hmap.m_HeightData.m_pData[z*256+255] = (g_Hmap.m_HeightData.m_pData[z*256+254]+
g_Hmap.m_HeightData.m_pData[z*256+0])/2;
}
for(int x=0; x<256; x++)
{
g_Hmap.m_HeightData.m_pData[255*256+x] = (g_Hmap.m_HeightData.m_pData[254*256+x]+
g_Hmap.m_HeightData.m_pData[0*256+x])/2;
}
g_Hmap.SaveHeightmap("Picture\\Hightmap256.raw");
}
void CTerrain::Update()
{
}
void CTerrain::Render()
{
if(g_pD3DDevice)
{
D3DXMATRIXA16 matWorld;
D3DXMatrixTranslation(&matWorld, (float)(g_Hmap.m_ViewOffsetX), 0, (float)(g_Hmap.m_ViewOffsetZ));
g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
g_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
g_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
g_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
g_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
g_pD3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
if(g_stInputInfo.KeyValue==DIK_L)
{
g_bLineMode = !g_bLineMode;
}
SET_TEXTURE_TYPE(0, m_hBlend[0]);
SET_TEXTURE_UNTYPE(1, m_hBlend[1]);
g_pD3DDevice->SetFVF(HeightmapVertex::FVF);
if(g_bLineMode)
{
g_pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
g_pD3DDevice->SetTexture(1, NULL);
g_pD3DDevice->SetTexture(0, NULL);
}
int min = g_Hmap.m_Frustum.m_minZ;
int max = g_Hmap.m_Frustum.m_maxZ;
m_numTriangles = 0;
int numArea = 0;
if(g_Hmap.m_bViewerChange)
{
m_BlendIndex = 0;
}
g_pD3DDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);
//---------------------------------------------------
// 地形Render
// (优化前: 资源消耗7.9ms-8.3ms)
// (优化后: 资源消耗3.6ms-4.7ms)
//---------------------------------------------------
for(int z=(g_Hmap.m_Frustum.m_pos[min].y); z<=(g_Hmap.m_Frustum.m_pos[max].y); z++)
{
for(int x=(g_Hmap.m_Frustum.m_LeftArray[z]); x<=(g_Hmap.m_Frustum.m_RightArray[z]); x++)
{
if(RenderTile(x, z))
numArea++;
}
}
if(m_BlendIndex>TERRAINVERTEX)
{
WriteLog(INFO_ERROR, "Terrain Vertex Error!");
}
g_pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, m_BlendIndex/3, m_BlendVertex, sizeof(HeightmapVertex));
if(g_bLineMode)
g_pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
g_pD3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
g_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
g_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
g_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
g_pD3DDevice->SetTexture(1, NULL);
// DrawSingleLine(0, 100, 0xffffffff, false, "number of triangles: %d, AREA: %d", m_numTriangles, numArea);
// DrawSingleLine(0, 100, 0xffffffff, false, "m_Index: %d", m_BlendIndex);
}
}
bool CTerrain::RenderTile(int x, int z)
{
unsigned char level = m_LODmap[z][x];
if(level==0)
{
return false;
}
if(level == 7)
DrawLevel_7(x, z);
else if(level == 6)
DrawLevel_6(x, z);
else if(level == 5)
DrawLevel_5(x, z);
else if(level == 4)
DrawLevel_4(x, z);
else if(level == 3)
DrawLevel_3(x, z);
else if(level == 2)
DrawLevel_2(x, z);
else if(level == 1)
DrawLevel_1(x, z);
// LOD5 & LOD7 渲染格子最多
if(level == 4 || level == 6)
return true;
else
return false;
}
//----------------------------------------------------
// LOD1(2格与1格的过渡层)
//----------------------------------------------------
void CTerrain::DrawLevel_1(int x, int z)
{
HeightmapVertex pV[10];
int rx = (x-128)*4;
int rz = (z-128)*4;
int index0 = g_Hmap.GetHeightIndex(x, z);
int index1 = g_Hmap.GetHeightIndex(x, z+1);
int index2 = g_Hmap.GetHeightIndex(x+1, z);
int index3 = g_Hmap.GetHeightIndex(x+1, z+1);
if(index0==-1 || index1==-1 || index2==-1 || index3==-1)
{
return;
}
int index4 = g_Hmap.GetHeightIndexOffset(index0, -1, 1);
int index5 = g_Hmap.GetHeightIndexOffset(index0, -2, 0);
int index6 = g_Hmap.GetHeightIndexOffset(index0, -2, 2);
int index7 = g_Hmap.GetHeightIndexOffset(index0, 0, 2);
int index8 = g_Hmap.GetHeightIndexOffset(index0, -3, 1);
int index9 = g_Hmap.GetHeightIndexOffset(index1, 0, 2);
int index10 = g_Hmap.GetHeightIndexOffset(index0, -1, 3);
int index11 = g_Hmap.GetHeightIndexOffset(index2, -2, 0);
int index12 = g_Hmap.GetHeightIndexOffset(index0, -3, 3);
int index20 = g_Hmap.GetHeightIndexOffset(index0, -1, 0);
int index21 = g_Hmap.GetHeightIndexOffset(index0, -2, 1);
int index22 = g_Hmap.GetHeightIndexOffset(index0, -1, 2);
int index23 = g_Hmap.GetHeightIndexOffset(index0, 0, 1);
int index24 = g_Hmap.GetHeightIndexOffset(index0, -3, 0);
int index25 = g_Hmap.GetHeightIndexOffset(index1, 0, 1);
int index26 = g_Hmap.GetHeightIndexOffset(index0, -3, 2);
int index27 = g_Hmap.GetHeightIndexOffset(index0, -2, 3);
int index28 = g_Hmap.GetHeightIndexOffset(index2, -1, 0);
int index29 = g_Hmap.GetHeightIndexOffset(index0, 0, 3);
int index30 = g_Hmap.GetHeightIndexOffset(index1, 0, 3);
int index31 = g_Hmap.GetHeightIndexOffset(index2, -3, 0);
float ax,az,bx,bz,cx,cz,dx,dz;
switch(0)
{
case 0: ax=0.0f; az=0.0f; bx=0.0f; bz=1.0f; cx=1.0f; cz=1.0f; dx=1.0f; dz=0.0f; break;
case 1: ax=0.0f; az=1.0f; bx=1.0f; bz=1.0f; cx=1.0f; cz=0.0f; dx=0.0f; dz=0.0f; break;
case 2: ax=1.0f; az=1.0f; bx=1.0f; bz=0.0f; cx=0.0f; cz=0.0f; dx=0.0f; dz=1.0f; break;
case 3: ax=1.0f; az=0.0f; bx=0.0f; bz=0.0f; cx=0.0f; cz=1.0f; dx=1.0f; dz=1.0f; break;
default:ax=1.0f; az=0.0f; bx=0.0f; bz=0.0f; cx=0.0f; cz=1.0f; dx=1.0f; dz=1.0f; break;
}
int point = 0;
pV[point++] = HeightmapVertex(float(rx+1)*10, g_Hmap.m_HeightData.m_pData[index4],
float(rz+1)*10, g_Hmap.m_pLightColor[index4], (ax+0.5f)*0.5f, (az+0.5f)*0.5f);
pV[point++] = HeightmapVertex(float(rx*10), g_Hmap.m_HeightData.m_pData[index0],
float(rz*10), g_Hmap.m_pLightColor[index0], ax, az);
if(m_LODmap[z][x-1] == 1)
{
pV[point++] = HeightmapVertex(float(rx*10), g_Hmap.m_HeightData.m_pData[index20],
float(rz+1)*10, g_Hmap.m_pLightColor[index20], (ax+(ax+bx)*0.5f)*0.5f, (az+(az+bz)*0.5f)*0.5f);
m_numTriangles++;
}
pV[point++] = HeightmapVertex(float(rx*10), g_Hmap.m_HeightData.m_pData[index5],
float(rz+2)*10, g_Hmap.m_pLightColor[index5], (ax+bx)*0.5f, (az+bz)*0.5f);
// add
pV[point++] = HeightmapVertex(float(rx+1)*10, g_Hmap.m_HeightData.m_pData[index21],
float(rz+2)*10, g_Hmap.m_pLightColor[index21], ((ax+bx)*0.5f+0.5f)*0.5f, ((az+bz)*0.5f+0.5f)*0.5f);
pV[point++] = HeightmapVertex(float(rx+2)*10, g_Hmap.m_HeightData.m_pData[index6],
float(rz+2)*10, g_Hmap.m_pLightColor[index6], 0.5f, 0.5f);
// add
pV[point++] = HeightmapVertex(float(rx+2)*10, g_Hmap.m_HeightData.m_pData[index22],
float(rz+1)*10, g_Hmap.m_pLightColor[index22], ((ax+dx)*0.5f+0.5f)*0.5f, ((az+dz)*0.5f+0.5f)*0.5f);
pV[point++] = HeightmapVertex(float(rx+2)*10, g_Hmap.m_HeightData.m_pData[index7],
float(rz*10), g_Hmap.m_pLightColor[index7], (ax+dx)*0.5f, (az+dz)*0.5f);
if(m_LODmap[z-1][x] == 1)
{
pV[point++] = HeightmapVertex(float(rx+1)*10, g_Hmap.m_HeightData.m_pData[index23],
float(rz*10), g_Hmap.m_pLightColor[index23], ((ax+dx)*0.5f+ax)*0.5f, ((az+dz)*0.5f+az)*0.5f);
m_numTriangles++;
}
pV[point++] = HeightmapVertex(float(rx*10), g_Hmap.m_HeightData.m_pData[index0],
float(rz*10), g_Hmap.m_pLightColor[index0], ax, az);
g_pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, point - 2, pV, sizeof(HeightmapVertex));
point = 0;
pV[point++] = HeightmapVertex(float(rx+1)*10, g_Hmap.m_HeightData.m_pData[index8],
float(rz+3)*10, g_Hmap.m_pLightColor[index8], (bx+0.5f)*0.5f, (bz+0.5f)*0.5f);
pV[point++] = HeightmapVertex(float(rx*10), g_Hmap.m_HeightData.m_pData[index5],
float(rz+2)*10, g_Hmap.m_pLightColor[index5], (ax+bx)*0.5f, (az+bz)*0.5f);
if(m_LODmap[z][x-1] == 1)
{
pV[point++] = HeightmapVertex(float(rx*10), g_Hmap.m_HeightData.m_pData[index24],
float(rz+3)*10, g_Hmap.m_pLightColor[index24], ((ax+bx)*0.5f+bx)*0.5f, ((az+bz)*0.5f+bz)*0.5f);
m_numTriangles++;
}
pV[point++] = HeightmapVertex(float(rx*10), g_Hmap.m_HeightData.m_pData[index1],
float(rz+4)*10, g_Hmap.m_pLightColor[index1], bx, bz);
if(m_LODmap[z+1][x] == 1)
{
pV[point++] = HeightmapVertex(float(rx+1)*10, g_Hmap.m_HeightData.m_pData[index25],
float(rz+4)*10, g_Hmap.m_pLightColor[index25], ((bx+cx)*0.5f+bx)*0.5f, ((bz+cz)*0.5f+bz)*0.5f);
m_numTriangles++;
}
pV[point++] = HeightmapVertex(float(rx+2)*10, g_Hmap.m_HeightData.m_pData[index9],
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -