运行结果:
源代码:
TerrainClass.h:
#pragma once
//=============================================================================
//一个封装了三维地形系统的类的头文件
//=============================================================================
#include <d3d9.h>
#include <d3dx9.h>
#include <vector>
#include <fstream>
#include "D3DUtil.h"
class TerrainClass
{
private:
LPDIRECT3DDEVICE9 m_pd3dDevice; //D3D设备
LPDIRECT3DTEXTURE9 m_pTexture; //纹理
LPDIRECT3DVERTEXBUFFER9 m_pVertexBuffer; //顶点缓存
LPDIRECT3DINDEXBUFFER9 m_pIndexBuffer; //索引缓存
int m_nCellsPerRow; //每行的单元格数目
int m_nCellsPerCol; //每列的单元格数目
int m_nVertsPerRow; //每行的顶点数
int m_nVertsPerCol; //每列的顶点数
int m_nNumVertices; //顶点总数
float m_fTerrainWidth; //地形的宽度
float m_fTerrainDepth; //地形的深度
float m_fCellSpacing; //单元格间的间距
float m_fHeightScale; //高度缩放系数
std::vector<float> m_vHeightInfo; //用于存放高度信息
//定义一个地形的FVF格式
struct TERRAINVERTEX
{
float x, y, z;
float u, v;
TERRAINVERTEX(float _x, float _y, float _z, float _u, float _v):
x(_x), y(_y), z(_z), u(_u), v(_v){}
static const DWORD FVF = D3DFVF_XYZ | D3DFVF_TEX1;
};
public:
TerrainClass(LPDIRECT3DDEVICE9 pd3dDevice); //构造函数
~TerrainClass(void); //析构函数
bool LoadTerrainFromFile(wchar_t *pRawFileName, wchar_t *pTextureName); //从文件加载高度图和纹理的函数
bool InitTerrain(int nRows, int nCols, float fSpace, float fScale); //地形初始化函数
void RenderTerrain(D3DXMATRIX *pMatWorld, bool bDrawFrame = false); //地形渲染函数
};
TerrainClass.cpp
#include "TerrainClass.h"
//=============================================================================
//一个封装了三维地形系统的类的源文件
//=============================================================================
//-----------------------------------------------------------------------------
//构造函数
//-----------------------------------------------------------------------------
TerrainClass::TerrainClass(LPDIRECT3DDEVICE9 pd3dDevice)
{
//给各个成员变量赋初值
m_pd3dDevice = pd3dDevice;
m_pTexture = NULL;
m_pVertexBuffer = NULL;
m_pIndexBuffer = NULL;
m_nCellsPerRow = 0;
m_nCellsPerCol = 0;
m_nVertsPerRow = 0;
m_nVertsPerCol = 0;
m_nNumVertices = 0;
m_fTerrainWidth = 0.0f;
m_fTerrainDepth = 0.0f;
m_fCellSpacing = 0.0f;
m_fHeightScale = 0.0f;
}
//-----------------------------------------------------------------------------
//加载地形高度信息以及纹理
//-----------------------------------------------------------------------------
bool TerrainClass::LoadTerrainFromFile(wchar_t *pRawFileName, wchar_t *pTextureName)
{
//从文件中读取高度信息
std::ifstream inFile;
inFile.open(pRawFileName, std::ios::binary); //用二进制的方式打开文件
inFile.seekg(0, std::ios::end); //把文件移动到文件末尾
//用模板定义一个vector<byte>的变量inData并初始化,其值为缓冲区的当前位置,即缓冲区大小
std::vector<byte> inData(inFile.tellg());
//将文件指针移动到文件的开头,准备读取高度信息
inFile.seekg(std::ios::beg);
//读取整个高度信息
inFile.read((char *)&inData[0], inData.size());
//操作结束,可以关闭文件了
inFile.close();
//遍历整个缓冲区,将inData中的值赋给m_vHeightInfo
for(unsigned int i = 0; i < inData.size(); ++i)
m_vHeightInfo.push_back(inData[i]);
//加载地形纹理
if(FAILED(D3DXCreateTextureFromFile(m_pd3dDevice, pTextureName, &m_pTexture)))
return false;
return true;
}
//-----------------------------------------------------------------------------
//初始化地形的高度,填充顶点和索引缓存
//-----------------------------------------------------------------------------
bool TerrainClass::InitTerrain(int nRows, int nCols, float fSpace, float fScale)
{
m_nCellsPerRow = nRows; //每行的单元格数目
m_nCellsPerCol = nCols; //每列的单元格数目
m_fCellSpacing = fSpace; //单元格间的间距
m_fHeightScale = fScale; //高度缩放系数
m_nVertsPerRow = nRows + 1; //每行的顶点数
m_nVertsPerCol = nCols + 1; //每列的顶点数
m_nNumVertices = m_nVertsPerRow * m_nVertsPerCol; //顶点总数
m_fTerrainWidth = nRows * fSpace; //地形的宽度
m_fTerrainDepth = nCols * fSpace; //地形的深度
//通过一个for循环,逐个把地形原始高度乘以缩放系数,得到缩放后的高度
for(unsigned int i = 0; i < m_vHeightInfo.size(); ++i)
m_vHeightInfo[i] *= fScale;
//处理地形的顶点
//创建顶点缓存
if(FAILED(m_pd3dDevice->CreateVertexBuffer(m_nNumVertices * sizeof(TERRAINVERTEX),
D3DUSAGE_WRITEONLY, TERRAINVERTEX::FVF, D3DPOOL_MANAGED, &m_pVertexBuffer, 0)))
return false;
//加锁