📄 game_terrain.cpp
字号:
#include "Game_User.h"
CTerrain::CTerrain(LPDIRECT3DDEVICE9 pDevice,D3DVECTOR position)
{
m_pMesh = NULL;
m_pDevice = pDevice;
m_vPos = position;
m_nCol = 0;
m_nRow = 0;
m_CellWidth = 0;
m_dwNumOfVertices= 0;
m_dwNumOfIndices = 0;
m_dwNumOfPolygons= 0;
m_pTexture = NULL;
m_maxHeight = 800;
//设置基本的材质
D3DCOLORVALUE Diffuse = {1.0, 1.0, 1.0, 0.0};
D3DCOLORVALUE Ambient = {1.0, 1.0, 1.0, 0.0};
D3DCOLORVALUE Specular = {0.0, 0.0, 0.0, 0.0};
D3DCOLORVALUE Emissive = {0.0, 0.0, 0.0, 0.0};
SetMaterial(Diffuse, Ambient, Specular, Emissive, 0);
}
CTerrain::~CTerrain()
{
SAFE_RELEASE(m_pMesh);
SAFE_RELEASE(m_pTexture);
SAFE_DELARRAY(m_pHeightData);
//SAFE_DELETE(m_dwNumOfVertices);
//SAFE_DELETE(m_dwNumOfIndices);
//SAFE_DELETE(m_dwNumOfPolygons);
m_pDevice = NULL;
}
void CTerrain::Initialize(char* strTerrain,char* strTexture,
float cellWidth,float height,float nTile)
{
m_nTile=nTile;
m_CellWidth=cellWidth;
m_maxHeight=height;
D3DXCreateTextureFromFile(m_pDevice,
strTexture, &m_pTexture); //创建纹理
//用GDI对象来读取位图,但是会转换成DIB位图
long i=0,j=0;
BITMAP bmp;
HBITMAP hBmp;
HDC hDC;
HBITMAP oldBmp;
hDC = CreateCompatibleDC(NULL);
hBmp = (HBITMAP)LoadImage(NULL,strTerrain,
IMAGE_BITMAP,m_nCol,m_nRow,LR_LOADFROMFILE);
oldBmp = (HBITMAP)SelectObject(hDC,hBmp);
//从高度图中读取高度信息
GetObject(hBmp, sizeof(bmp), &bmp);
m_nCol = bmp.bmWidth;
m_nRow = bmp.bmHeight;
m_pHeightData = new BYTE[m_nCol*m_nRow];
DWORD color;
for(i=0; i<m_nRow; i++)
for(j=0; j<m_nCol; j++)
{
color = GetPixel(hDC,j,i);
m_pHeightData[i*m_nCol+j] = *(BYTE*)&color; //取红色通道 0xAABBGGRR
}
DeleteObject(oldBmp);
DeleteObject(hDC);
DeleteObject(hBmp);
m_dwNumOfVertices = m_nRow * m_nCol;
m_dwNumOfPolygons = (m_nCol-1)*(m_nRow-1)*2;
D3DXCreateMeshFVF(m_dwNumOfPolygons,m_dwNumOfVertices,D3DXMESH_MANAGED,D3DFVF_TERRAIN,m_pDevice,&m_pMesh);
TVertexBuffer* pVertices;
m_pMesh->LockVertexBuffer(0,(void**)&pVertices);
for(i=0;i<(long)m_dwNumOfVertices;i++)
{
pVertices[i].y = m_pHeightData[i];
pVertices[i].x = float(i%m_nCol);
pVertices[i].z = -float(i/m_nCol)+m_nRow;
pVertices[i].nx = 0;
pVertices[i].ny = 1;
pVertices[i].nz = 0;
/*pVertices[i].tu = m_nTile*pVertices[i].x/m_nCol ;
pVertices[i].tv = m_nTile*pVertices[i].z/m_nRow ;*/
pVertices[i].tu = pVertices[i].x/m_nCol ;
pVertices[i].tv = pVertices[i].z/m_nRow ;
}
m_pMesh->UnlockVertexBuffer();
WORD* pIndex;
m_pMesh->LockIndexBuffer(0,(void**)&pIndex);
for(i=0,j=0;i<(long)m_dwNumOfVertices;i++)
{
if((i+1)%m_nCol && i/m_nCol!=m_nRow-1)
{
pIndex[j+0]=(WORD)i;
pIndex[j+1]=(WORD)(i+1);
pIndex[j+2]=(WORD)(i+m_nCol);
pIndex[j+3]=(WORD)(i+m_nCol);
pIndex[j+4]=(WORD)(i+1);
pIndex[j+5]=(WORD)(i+1+m_nCol);
j+=6;
}
}
m_pMesh->UnlockIndexBuffer();
SetWorldTransorm();
}
void CTerrain::Render()
{
m_pDevice->SetTexture(0,m_pTexture);
//m_pDevice->SetFVF(D3DFVF_TERRAIN);
m_pDevice->SetTransform(D3DTS_WORLD,&m_matWorld);
m_pMesh->DrawSubset( 0 );
}
void CTerrain::SetWorldTransorm()
{
D3DMATRIX matWorld;
ZeroMemory(&matWorld,sizeof(matWorld));
matWorld._11=m_CellWidth;
matWorld._22=m_maxHeight/255.0f;
matWorld._33=m_CellWidth;
matWorld._44=1;
//地形的世界坐标系是以原点为中心
matWorld._41=m_vPos.x-m_nCol*m_CellWidth/2 ; //地形中心在m_vPos(原点)
matWorld._42=m_vPos.y;
matWorld._43=m_vPos.z-m_nRow*m_CellWidth/2; //地形中心在m_vPos
m_pDevice->SetTransform(D3DTS_WORLD,&matWorld);
m_matWorld = matWorld;
};
//一个不怎么好的插值算法
float CTerrain::GetHeight(float x,float z)
{
x+=m_vPos.x+m_CellWidth*m_nCol/2.0f;
z+=m_vPos.z+m_CellWidth*m_nRow/2.0f;
float rx,rz;
rx=x/m_CellWidth;
rz=m_nRow-z/m_CellWidth;
long col1,row1,col2,row2;
float h1,h2,h3,h4,ha,hb;
col1=DWORD(rx);
row1=DWORD(rz);
if(col1>m_nCol || col1<0 ||row1>m_nRow || row1<0) return 0;
else
{ //双线性插值法计算
col2=(col1==m_nCol)?col1:col1+1;
row2=(row1==m_nRow)?row1:row1+1;
h1=(m_pHeightData[row1*m_nCol+col1]*m_maxHeight/255.0f);
h2=(m_pHeightData[row1*m_nCol+col2]*m_maxHeight/255.0f);
h3=(m_pHeightData[row2*m_nCol+col1]*m_maxHeight/255.0f);
h4=(m_pHeightData[row2*m_nCol+col2]*m_maxHeight/255.0f);
ha=(h2*(rx-col1)+h1*(col2-rx));
hb=(h4*(rx-col1)+h3*(col2-rx));
return (hb*(rz-row1)+ha*(row2-rz));
}
}
bool CTerrain::SetMaterial(D3DCOLORVALUE Diffuse, D3DCOLORVALUE Ambient,
D3DCOLORVALUE Specular, D3DCOLORVALUE Emissive,
float rPower)
{
//设置漫反射
m_matMaterial.Diffuse = Diffuse;
//设置环境光
m_matMaterial.Ambient = Ambient;
//设置镜面反射
m_matMaterial.Specular = Specular;
m_matMaterial.Power = rPower;
//设置反射
m_matMaterial.Emissive = Emissive;
return true;
}
//vPos为摄象机经过地形逆变换之后的位置
bool CTerrain::GetGroundRect(D3DXVECTOR3 vPos,D3DXVECTOR3* vTL,D3DXVECTOR3* vTR,D3DXVECTOR3* vBL,D3DXVECTOR3* vBR)
{
vTL->x = (float)((int)vPos.x);
vTL->z = (float)((int)vPos.z + 1);
vTL->y = m_pHeightData[(m_nRow - ((int)vPos.z + 1))*m_nCol + ((int)vPos.x)];
vTR->x = (float)((int)vPos.x + 1);
vTR->z = (float)((int)vPos.z + 1);
vTR->y = m_pHeightData[(m_nRow - ((int)vPos.z + 1))*m_nCol + ((int)vPos.x + 1)];
vBL->x = (float)((int)vPos.x);
vBL->z = (float)((int)vPos.z);
vBL->y = m_pHeightData[(m_nRow - ((int)vPos.z))*m_nCol + ((int)vPos.x)];
vBR->x = (float)((int)vPos.x + 1);
vBR->z = (float)((int)vPos.z);
vBR->y = m_pHeightData[(m_nRow - ((int)vPos.z))*m_nCol + ((int)vPos.x + 1)];
return true;
}
HRESULT CTerrain::GetTerrainVertex(D3DXVECTOR3 *cross,DWORD index,float u,float v)
{
WORD* pIndices;
WORD index1,index2,index3;
D3DXVECTOR3 v1,v2,v3;
m_pMesh->LockIndexBuffer(0,(void**)&pIndices);
index1=pIndices[index*3];
index2=pIndices[index*3+1];
index3=pIndices[index*3+2];
m_pMesh->UnlockIndexBuffer();
TVertexBuffer* pcvVertices;
m_pMesh->LockVertexBuffer (0,(void**)&pcvVertices);
v1.x=pcvVertices[index1].x;
v1.y=pcvVertices[index1].y;
v1.z=pcvVertices[index1].z;
v2.x=pcvVertices[index2].x;
v2.y=pcvVertices[index2].y;
v2.z=pcvVertices[index2].z;
v3.x=pcvVertices[index3].x;
v3.y=pcvVertices[index3].y;
v3.z=pcvVertices[index3].z;
m_pMesh->UnlockVertexBuffer();
*cross = v1 + u * (v2 - v1) + v * (v3 - v1);
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -