歡迎來到新的一課,Ben Humphrey寫了這一課的代碼,它是基于第一課所寫的。
在這一課里,我們將教會你如何使用地形,你將知道高度圖這個概念。
下面我們來定義一些全局變量,MAP_SIZE是你使用的高度圖的大小,在這一課里我們使用1024*1024的地圖。STEP_SIZE設置高度圖中相鄰頂點之間的距離。HEIGHT_RATIO設置在高度方向的縮放比例,越大地形看起來越陡峭。bRender設置使用多邊形還是線繪制地形。
#define MAP_SIZE 1024
#define STEP_SIZE 16 // 相鄰頂點的距離
#define HEIGHT_RATIO 1.5f
bool bRender = TRUE; // true為多邊形渲染,false為線渲染
下面的代碼用來保存高度數據
BYTE g_HeightMap[MAP_SIZE*MAP_SIZE]; // 保存高度數據
float scaleValue = 0.15f; // 地形的縮放比例
下面的函數從文件中加載高度數據
// 從*.raw文件中加載高度數據
void LoadRawFile(LPSTR strName, int nSize, BYTE *pHeightMap)
{
FILE *pFile = NULL;
// 打開文件
pFile = fopen( strName, "rb" );
// 如果文件不能打開
if ( pFile == NULL )
{
// 提示錯誤,退出
MessageBox(NULL, "不能打開高度圖文件", "錯誤", MB_OK);
return;
}
// 讀取文件數據到pHeightMap數組中
fread( pHeightMap, 1, nSize, pFile );
// 讀取是否成功
int result = ferror( pFile );
// 如果不成功,提示錯誤退出
if (result)
{
MessageBox(NULL, "讀取數據失敗", "錯誤", MB_OK);
}
// 關閉文件
fclose(pFile);
}
InitGL函數基本沒有變化,只是加入了加載高度圖的函數
// 載入1024*1024的高度圖道g_HeightMap數組中
LoadRawFile("Data/Terrain.raw", MAP_SIZE * MAP_SIZE, g_HeightMap);
下面的函數返回(x,y)點的高度
int Height(BYTE *pHeightMap, int X, int Y) // 下面的函數返回(x,y)點的高度
{
int x = X % MAP_SIZE; // 限制X的值在0-1024之間
int y = Y % MAP_SIZE; // 限制Y的值在0-1024之間
if(!pHeightMap) return 0; // 檢測高度圖是否存在,不存在則返回0
返回(x,y)的高度
return pHeightMap[x + (y * MAP_SIZE)]; // 返回(x,y)的高度
}
按高度設置頂點的顏色,越高的地方越亮
void SetVertexColor(BYTE *pHeightMap, int x, int y) // 按高度設置頂點的顏色,越高的地方越亮
{
if(!pHeightMap) return;
float fColor = -0.15f + (Height(pHeightMap, x, y ) / 256.0f);
// 設置頂點的顏色
glColor3f(0.0f, 0.0f, fColor );
}
下面的函數在OpenGL中,根據高度圖渲染輸出地形
void RenderHeightMap(BYTE pHeightMap[]) // 根據高度圖渲染輸出地形
{
int X = 0, Y = 0; // 設置循環變量
int x, y, z;
if(!pHeightMap) return; // 確認高度圖存在
if(bRender) // 選擇渲染模式
glBegin( GL_QUADS ); // 渲染為四邊形
else
glBegin( GL_LINES ); // 渲染為直線
下面的函數求得每一點的坐標和顏色,調用OpenGL渲染
for ( X = 0; X < MAP_SIZE; X += STEP_SIZE )
for ( Y = 0; Y < MAP_SIZE; Y += STEP_SIZE )
{
// 繪制(x,y)處的頂點
// 獲得(x,y,z)坐標
x = X;
y = Height(pHeightMap, X, Y );
z = Y;
// 設置頂點顏色
SetVertexColor(pHeightMap, x, z);
glVertex3i(x, y, z); // 調用OpenGL繪制頂點的命令
// 繪制(x,y+1)處的頂點
x = X;
y = Height(pHeightMap, X, Y + STEP_SIZE );
z = Y + STEP_SIZE ;
SetVertexColor(pHeightMap, x, z);
glVertex3i(x, y, z);
// 繪制(x+1,y+1)處的頂點
x = X + STEP_SIZE;
y = Height(pHeightMap, X + STEP_SIZE, Y + STEP_SIZE );
z = Y + STEP_SIZE ;
SetVertexColor(pHeightMap, x, z);
glVertex3i(x, y, z);
// 繪制(x+1,y)處的頂點
x = X + STEP_SIZE;
y = Height(pHeightMap, X + STEP_SIZE, Y );
z = Y;
SetVertexColor(pHeightMap, x, z);
glVertex3i(x, y, z);
}
glEnd();
glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // 重置顏色
}
DrawGLScene函數基本沒變化,只是設置了視點和縮放系數,調用上面的函數繪制出地形。
// 設置視點
gluLookAt(212, 60, 194, 186, 55, 171, 0, 1, 0);
glScalef(scaleValue, scaleValue * HEIGHT_RATIO, scaleValue);
RenderHeightMap(g_HeightMap); // 渲染高度圖
return TRUE;
}
WndProc()函數基本沒有變化,只是加入了單擊左鍵的相應函數
case WM_LBUTTONDOWN: // 是否單擊鼠標左鍵
{
bRender = !bRender; // 改變渲染模式
return 0; // 返回
}
上面就是所有繪制地形的代碼了,簡單吧。
希望你喜歡這個教程!