📄 terrain.cpp
字号:
// Terrain.cpp: implementation of the CTerrain class.
//
//////////////////////////////////////////////////////////////////////
#include <d3dx9.h>
#include <d3d9.h>
#include <windows.h>
#include "Terrain.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CTerrain::CTerrain(LPDIRECT3DDEVICE9 pDevice,D3DVECTOR position)
{
m_pDevice=pDevice;
m_vPos=position;
m_nCol=0;
m_nRow=0;
m_CellWidth=0;
m_pIB=NULL;
m_pVB=NULL;
m_pTexture=NULL;
m_maxHeight=800;
}
#define SAFE_RELEASE(p) if(p) {p->Release();p=NULL;}
CTerrain::~CTerrain()
{
SAFE_RELEASE(m_pIB)
SAFE_RELEASE(m_pVB);
SAFE_RELEASE(m_pTexture);
delete []m_pHeightData;
}
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);
if(D3D_OK!=
m_pDevice->CreateVertexBuffer(m_nCol*m_nRow*sizeof(TVertexBuffer),
0,D3DFVF_TERRAIN, D3DPOOL_DEFAULT, &m_pVB,NULL))
OutputDebugString("创建地形顶点缓冲区失败!\n");
TVertexBuffer* pVertices;
m_pVB->Lock(0,m_nCol*m_nRow*sizeof(TVertexBuffer),(void**)&pVertices,D3DLOCK_DISCARD);
for(i=0;i<m_nCol*m_nRow;i++)
{
pVertices[i].y=m_pHeightData[i]*m_maxHeight/255.0f;
pVertices[i].x=float(i%m_nCol)*m_CellWidth;
pVertices[i].z=(-float(i/m_nCol)+m_nRow)*m_CellWidth;
pVertices[i].nx=0;
pVertices[i].ny=1;
pVertices[i].nz=0;
pVertices[i].tu=m_nTile*(i%m_nCol)/m_nCol ;
pVertices[i].tv=m_nTile*(i/m_nCol)/m_nRow ;
}
m_pVB->Unlock();
long nBufferSize=(m_nCol-1)*(m_nRow-1)*6*sizeof(DWORD);
m_pDevice->CreateIndexBuffer(nBufferSize,D3DUSAGE_WRITEONLY,
D3DFMT_INDEX32,D3DPOOL_MANAGED,&m_pIB,NULL);
DWORD* pIndex;
m_pIB->Lock(0,0,(void**)&pIndex,0);
for(i=0,j=0;i<m_nCol*m_nRow;i++)
{
if((i+1)%m_nCol && i/m_nCol!=m_nRow-1)
{
pIndex[j+0]=(WORD)i;
pIndex[j+1]=i+1;
pIndex[j+2]=i+m_nCol;
pIndex[j+3]=i+m_nCol;
pIndex[j+4]=i+1;
pIndex[j+5]=i+1+m_nCol;
j+=6;
}
}
m_pIB->Unlock();
}
void CTerrain::Render()
{
m_pDevice->SetTexture(0,m_pTexture);
m_pDevice->SetFVF(D3DFVF_TERRAIN);
m_pDevice->SetStreamSource(0,m_pVB,0,sizeof(TVertexBuffer));
m_pDevice->SetIndices(m_pIB);
SetWorldTransorm();
m_pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,
0,0,m_nCol*m_nRow,0,(m_nCol-1)*(m_nRow-1)*2);
}
void CTerrain::SetWorldTransorm()
{
D3DMATRIX matWorld;
ZeroMemory(&matWorld,sizeof(matWorld));
matWorld._11=1;
matWorld._22=1;
matWorld._33=1;
matWorld._44=1;
matWorld._41=m_vPos.x-m_nCol*m_CellWidth/2.0f ; //地形中心在m_vPos
matWorld._42=m_vPos.y;
matWorld._43=m_vPos.z-m_nRow*m_CellWidth/2.0f; //地形中心在m_vPos
m_pDevice->SetTransform(D3DTS_WORLD,&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/256.0f);
h2=(m_pHeightData[row1*m_nCol+col2]*m_maxHeight/256.0f);
h3=(m_pHeightData[row2*m_nCol+col1]*m_maxHeight/256.0f);
h4=(m_pHeightData[row2*m_nCol+col2]*m_maxHeight/256.0f);
ha=(h2*(rx-col1)+h1*(col2-rx));
hb=(h4*(rx-col1)+h3*(col2-rx));
return (hb*(rz-row1)+ha*(row2-rz));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -