Direct9學習之--------------------------地形

一. 地形的作用:

  

          地形,不言而喻是用來描繪遊戲中高山 盆地 平原等地貌,用於確定對象在遊戲世界的空間高度。


二. 地形基本原理:

       地形的實現是用地形網格(N行M列矩形網格)和高度圖實現,地形網格用於繪製地表,高度圖信息則用來表示地形高度。通過高度圖的不同高度使地形形成高山盆地等。(高度圖中保存了地形高度信息)


       地形網格主要作用是模擬地表,其構成是N行M列的頂點形成的N*M個長方行網格,我們暫時定義每個小長方形網格爲整個地形的一個地形塊.


              


高度圖則保存了網格中麼個頂點的高度信息,用於模擬高山盆地等高度變化


             


三. 地形基本實現方式及代碼:


     實現步驟:

        1. 初始化地形網格或者地形頂點緩衝及地形紋理
        2. 加載高度圖獲取地形高度信息或者自定義高度信息

3. 繪製地形


具體相關代碼:

a. 初始化地形網格數據(此處是已頂點緩衝形式創建當然也可以直接加載MESH更加方便)

注: 此處僅僅是初始化地形網格數據根據地形長寬創建地形的頂點緩衝數據

struct TerrainVertices
{
VECTOR3 vPos;
//VECTOR3 vNoraml;
VECTOR2 vTex;
};
#define D3DFVF_TERRAINVERTEX (D3DFVF_XYZ /*| D3DFVF_NORMAL*/| D3DFVF_TEX1)

HRESULT hr = pDevice->CreateVertexBuffer( nVertexCount * sizeof(TerrainVertices),
D3DUSAGE_WRITEONLY, D3DFVF_TERRAINVERTEX,
D3DPOOL_MANAGED, &m_pVertexBuf, NULL );


if ( FAILED( hr ) )
{
return false;
}


TerrainVertices* pVertices;
if( FAILED( m_pVertexBuf->Lock( 0, 0, (void**)&pVertices, 0 ) ) )
{
Release();
return false;
}


int  fLongCellSpacing = (int)m_fLongth / ( m_nLongCount - 1 );
int  fWidthCellSpacing = (int)m_fWidth / ( m_nWidthCount - 1 );
int startX = (int)- m_fLongth / 2;
int startZ =  (int)m_fWidth / 2;


// coordinates to end generating vertices at
int endX =  (int)m_fLongth / 2;
int endZ = (int)- m_fWidth / 2;


float uCoordIncrementSize = 1.0f / (float)m_nLongCount;
float vCoordIncrementSize = 1.0f / (float)m_nWidthCount;


//初始化網格頂點數據
int i = 0;
for(int z = startZ; z >= endZ; z -= fWidthCellSpacing)
{
int j = 0;
for(int x = startX; x <= endX; x += fLongCellSpacing)
{
// compute the correct index into the vertex buffer and heightmap
// based on where we are in the nested loop.
int index = i * m_nLongCount + j;
float y = GetHeight( float(x), float(z) );
pVertices[index].vPos = VECTOR3( (float)x, y, (float)z );
pVertices[index].vTex = VECTOR2( (float)j * uCoordIncrementSize, (float)i * vCoordIncrementSize );


j++; // next column
}
i++; // next row
}


m_pVertexBuf->Unlock();


b. 加載高度圖或者計算高度信息也就是GetHeight函數(代碼提供了兩種方式)

注: 此處纔是地形高度圖的主要之所在,GetHeight函數中未被註釋部分是自己YY計算地形高度就表現而言沒有問題,但用的採取更多的是用高度圖標識地形高度,(即被註釋掉部分代碼)。其基本原理是加載一個高度圖紋理,並且讀取出高度圖中顏色信息數據,根據這些數據對應到地形中某點的高度。例如高度圖中第一行第一列顏色值則對應地形網格中第一行第一列頂點高度值。爲此對於地形上任意一點的高度可以通過其最近頂點高度線性比例求得。(例如:要求(x,z)點高度 應先求得(x,z)在地形中哪個地形塊,根據地形快四個頂點高度及(x,z)位置用線性插值的方式可以求出(x,z)點高度信息)


// 根據點X Z計算高度
float Terrain::GetHeight( float fX, float fZ )
{
float y = 0.0f;


y += 7.0f * cosf( 0.051f*fX + 0.0f ) * sinf( 0.055f*fX + 0.0f );
y += 7.0f * cosf( 0.053f*fZ + 0.0f ) * sinf( 0.057f*fZ + 0.0f );
y += 1.0f * cosf( 0.101f*fX + 0.0f ) * sinf( 0.105f*fX + 0.0f );
y += 1.0f * cosf( 0.103f*fZ + 0.0f ) * sinf( 0.107f*fZ + 0.0f );
y += 1.0f * cosf( 0.251f*fX + 0.0f ) * sinf( 0.255f*fX + 0.0f );
y += 1.0f * cosf( 0.253f*fZ + 0.0f ) * sinf( 0.257f*fZ + 0.0f );
return y;
/**
// 若沒有高度圖則默認高度爲0
if ( 0 == m_pHeightTex )
{
return 0.0f;
}


float fLongthStart = - m_fLongth / 2.0f * m_nLongCount;
float fWidthStart = m_fWidth / 2.0f;


// 定位改座標點所在地圖中網格位置
float fLongth = m_nLongCount * ( fX - fWidthStart ) / m_fLongth;
float fWidth = m_nWidthCount * ( 1 - ( fZ + fWidthStart ) / m_fWidth );


// 判斷當前所在點受上半部分還是下半部分三角形影響
UINT nWidth = (int)fWidth;
UINT nLongth = (int)fLongth;


if ( nLongth < 0 || nLongth >= m_nHeighLongth || nWidth < 0 || nWidth >= m_nHeighWidth )
{
return 0.0f;
}


// 定義三角形三個頂點高度
float fFirst = 0.0f;
float fScened = 0.0f;
float fThird = 0.0f;
if ( fWidth - float(nWidth) > 0.5 )
{
fFirst = m_fHeighList[ nWidth*m_nHeighLongth + nLongth ];
fScened = m_fHeighList[ nWidth*m_nHeighLongth + nLongth + 1 ];
fThird = m_fHeighList[ (nWidth + 1)*m_nHeighLongth + nLongth + 1 ];
}
else
{
fFirst = m_fHeighList[ nWidth*m_nHeighLongth + nLongth ];
fScened = m_fHeighList[ (nWidth + 1)*m_nHeighLongth + nLongth + 1 ];
fThird = m_fHeighList[ nWidth*m_nHeighLongth + nLongth + 1 ];
}


float fHeight = 0.0f;
float fLongPer = fLongth - nLongth;
float fWidthPer = fWidth - nWidth;


fHeight = ( fFirst * fLongPer + fScened * ( 1 - fLongPer ) + fFirst * fWidthPer + fThird * ( 1- fWidthPer ) ) / 2.0f; 
return fHeight;
*/
}

c. 繪製的地形

當然繪製的方式很簡單即繪製頂點緩衝區中頂點(如果用MESH做則直接繪製MESH)在此不再贅述。


四. 效果展示:


模擬山地地形



模擬大海


五. 其他:


地形不只單單包含山地盆地 配合合理的貼圖 再加上UV動畫或者頂點動畫技術也可以模擬海洋等。

發佈了25 篇原創文章 · 獲贊 2 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章