terrain.cpp
来自「x3d_new.rar」· C++ 代码 · 共 497 行 · 第 1/2 页
CPP
497 行
#include "StdAfx.h"
#include ".\terrain.h"
#include "xUtil.h"
#include <d3dx9tex.h>
#define TEXTURE_SIZE 256
CTerrain::CTerrain(void)
: m_pTexture(NULL)
, m_Patchs(NULL)
, m_bDrawNormal(false)
, m_fHeightScale(0.2f)
, m_nSize(0)
, m_nPatchSize(0)
{
}
CTerrain::~CTerrain(void)
{
Destroy();
}
bool CTerrain::Create(int nSize)
{
assert(m_pDevice);
assert(m_pDeviceCaps);
m_nSize = nSize;
// 计算片区尺寸最大值
int nMaxPatchSize = (int)sqrt((double)m_pDeviceCaps->MaxVertexIndex);
m_nPatchSize = m_nSize;
while(m_nPatchSize > nMaxPatchSize)
m_nPatchSize >>= 1;
// 创建"米"字索引模板
if(!m_RiceIndicesMng.Create())return false;
// 创建地形数据
if(!m_field.Create(m_nSize))return false;
assert(m_field.IsValid());
// 创建地形块数组
int nTierCount = m_nSize / m_nPatchSize;
int nPatchCount = nTierCount * nTierCount;
m_Patchs = new SPatch[nPatchCount];
if(!m_Patchs)return false;
// 开始创建创建模型、索引
int nPatchBorderSize = m_nPatchSize + 1;
int nPatchVertexCount = nPatchBorderSize * nPatchBorderSize;
int nMaxTilesNum = CField::CalculateMaxTileNum(m_nPatchSize);
D3DFORMAT index_format; // 索引格式
int nBytePerIndex; // 单位索引占用字节数
if(m_pDeviceCaps->MaxVertexIndex > 65536)
{
index_format = D3DFMT_INDEX32;
nBytePerIndex = 4;
}
else
{
index_format = D3DFMT_INDEX16;
nBytePerIndex = 2;
}
for(int iz = 0; iz < nTierCount; ++iz)
{
for(int ix = 0; ix < nTierCount; ++ix)
{
SPatch& rPatch = m_Patchs[iz * nTierCount + ix];
// 创建模型
if(FAILED(m_pDevice->CreateVertexBuffer(sizeof(SVertexData) * nPatchVertexCount,
0, SVertexData::FVF, D3DPOOL_DEFAULT, &rPatch.m_pVB, NULL)))
return false;
// 创建法线模型
if(FAILED(m_pDevice->CreateVertexBuffer(sizeof(SNormalVertexData) * (nPatchVertexCount * 2),
0, SNormalVertexData::FVF, D3DPOOL_DEFAULT, &rPatch.m_pVBNormal, NULL)))
return false;
// 创建索引缓冲 (每个"块" 最多有8个三角形,所以共24个顶点)
if(FAILED(m_pDevice->CreateIndexBuffer(
nMaxTilesNum * 24 * nBytePerIndex, 0, index_format, D3DPOOL_DEFAULT, &rPatch.m_pIB, NULL)))
return false;
}
}
// 读取细节纹理
if(FAILED(D3DXCreateTextureFromFileEx(m_pDevice, "detailMap.tga", D3DX_DEFAULT, D3DX_DEFAULT,
0, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &m_pDetailTexture )))
return false;
// 设置材质
SetupMaterial();
// 创建纹理
assert(m_pDevice);
if(FAILED(m_pDevice->CreateTexture(
TEXTURE_SIZE, TEXTURE_SIZE, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pTexture, NULL)))
return false;
// 读取纹理文件
m_TexturePainter.SetDevice(m_pDevice);
m_TexturePainter.SetField(&m_field);
m_TexturePainter.SetSize(TEXTURE_SIZE);
m_TexturePainter.AddElement("lowestTile.tga", 5);
m_TexturePainter.AddElement("lowTile.tga", 5);
m_TexturePainter.AddElement("HighTile.tga", 5);
m_TexturePainter.AddElement("highestTile.tga", 20);
return true;
}
void CTerrain::Destroy()
{
// 纹理
release_ptr(m_pTexture);
release_ptr(m_pDetailTexture);
// 片区
int nTierCount = m_nSize / m_nPatchSize;
int nPatchCount = nTierCount * nTierCount;
for(int i = 0; i < nPatchCount; ++i)
{
release_ptr(m_Patchs[i].m_pIB);
release_ptr(m_Patchs[i].m_pVB);
release_ptr(m_Patchs[i].m_pVBNormal);
}
delete_ary(m_Patchs);
// 工具
m_RiceIndicesMng.Destroy();
m_field.Destroy();
m_TexturePainter.ClearElement();
}
void CTerrain::SetupMaterial()
{
// 设置材质
m_Material.Power = 0.3f;
m_Material.Diffuse = D3DXCOLOR(0.2f, 0.2f, 0.2f, 0.2f);
m_Material.Specular = D3DXCOLOR(0.1f, 0.1f, 0.1f, 0.1f);
m_Material.Ambient = D3DXCOLOR(0.0f, 0.0f, 0.0f, 0.0f);
m_Material.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 0.0f);
}
HRESULT CTerrain::SetupGeometry()
{
assert(m_pDevice);
assert(m_field.IsValid());
const unsigned char* byHeights = m_field.GetHeights();
int nTierCount = m_nSize / m_nPatchSize;
int nPatchBorderSize = m_nPatchSize + 1;
int nPatchVertexCount = nPatchBorderSize * nPatchBorderSize;
for(int ipz = 0; ipz < nTierCount; ++ipz)
{
for(int ipx = 0; ipx < nTierCount; ++ipx)
{
SPatch& rPatch = m_Patchs[ipz * nTierCount + ipx];
assert(rPatch.m_pVB);
SVertexData* pVertices = NULL;
if(FAILED(rPatch.m_pVB->Lock(0, nPatchVertexCount, (LPVOID*)&pVertices, 0)))return E_FAIL;
// 开始设置顶点数据
int iIndex = 0;
for(int iz = 0; iz < nPatchBorderSize; ++iz)
{
for(int ix = 0; ix < nPatchBorderSize; ++ix)
{
int itx = ipx * m_nPatchSize + ix;
int ity = ipz * m_nPatchSize + iz;
pVertices[iIndex].position.x = (float)itx;
pVertices[iIndex].position.y = m_field.GetHeight(itx, ity) * m_fHeightScale;
pVertices[iIndex].position.z = (float)ity;
pVertices[iIndex].tu = (float)itx / m_field.GetBorderSize();
pVertices[iIndex].tv = (float)ity / m_field.GetBorderSize();
pVertices[iIndex].tu1 = itx * 0.1f;
pVertices[iIndex].tv1 = ity * 0.1f;
++iIndex;
}
}
// ..根据定点设置法线(近似值)
for(int i = 0; i < nPatchVertexCount; ++i)
{
pVertices[i].normal.x = 0.0f;
pVertices[i].normal.y = 1.0f;
pVertices[i].normal.z = 0.0f;
}
// ..根据定点设置法线(近似值)
for(int iz = 1; iz < nPatchBorderSize - 1; ++iz)
{
for(int ix = 1; ix < nPatchBorderSize - 1; ++ix)
{
int iIndex = iz * nPatchBorderSize + ix;
D3DXVECTOR3 vNormal;
vNormal.x = pVertices[iIndex - 1].position.y - pVertices[iIndex + 1].position.y;
vNormal.y = 1.0f;
vNormal.z = pVertices[iIndex - nPatchBorderSize].position.y - pVertices[iIndex + nPatchBorderSize].position.y;
D3DXVec3Normalize(&pVertices[iIndex].normal, &vNormal);
}
}
if(FAILED(rPatch.m_pVB->Unlock()))return E_FAIL;
}
}
return D3D_OK;
}
HRESULT CTerrain::SetupNormalGeometry(void)
{
assert(m_pDevice);
assert(m_field.IsValid());
int nTierCount = m_nSize / m_nPatchSize;
int nPatchBorderSize = m_nPatchSize + 1;
int nPatchVertexCount = nPatchBorderSize * nPatchBorderSize;
int nNormalVertexCount = nPatchVertexCount * 2;
for(int ipz = 0; ipz < nTierCount; ++ipz)
{
for(int ipx = 0; ipx < nTierCount; ++ipx)
{
SPatch& rPatch = m_Patchs[ipz * nTierCount + ipx];
assert(rPatch.m_pVB);
assert(rPatch.m_pVBNormal);
SNormalVertexData* pNormalVertices = NULL;
if(FAILED(rPatch.m_pVBNormal->Lock(0, nNormalVertexCount, (LPVOID*)&pNormalVertices, 0)))return E_FAIL;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?