#include "..\..\GameEngine\GameEngine_Common.h"
#include "LODTerrain.h"
#include "Frustum.h"
#include "Camera.h"
CLODTerrain::CLODTerrain(LPDIRECT3DDEVICE9 pd3dDevice,bool bUseHeightFile){
m_pd3dDevice=pd3dDevice;
m_pFrustum=new CFrustum();
m_iTerrainSize=1024;
m_pbQuadMat=new bool[(m_iTerrainSize+1)*(m_iTerrainSize+1)];
m_fHeightScale=1.0f;
m_pucHeightData=new unsigned char[(m_iTerrainSize+1)*(m_iTerrainSize+1)];
m_fResolution=5.0f;
m_fHeightDetail=8.0f;
m_iTexMapRepeatNum=10;
m_bUseHeightFile=bUseHeightFile;
}
CLODTerrain::~CLODTerrain(){
delete[] m_pbQuadMat;
delete[] m_pucHeightData;
if(m_pVertexBuffer!=NULL){
m_pVertexBuffer->Release();
m_pVertexBuffer=NULL;
}
if(m_pTexture!=NULL){
m_pTexture->Release();
m_pTexture=NULL;
}
}
bool CLODTerrain::InitTerrain(TCHAR* szHeightFile,TCHAR* szTextureFile){
if(m_bUseHeightFile){
if(!InitTerrainByFile(szHeightFile,szTextureFile)){
return false;
}
}
else{
if(!InitTerrainByFun(szTextureFile)){
return false;
}
}
return true;
}
bool CLODTerrain::InitTerrainByFun(char* szTextureFile){
if(!InitQuadMat())
return false;
if(!InitVertexBuf())
return false;
if(FAILED(D3DXCreateTextureFromFile(m_pd3dDevice,szTextureFile,&m_pTexture)))
return false;
return true;
}
bool CLODTerrain::InitTerrainByFile(TCHAR* szHeightFile,TCHAR* szTextureFile){
m_bUseHeightFile=true;
if(!InitQuadMat())
return false;
if(!InitVertexBuf())
return false;
if(!LoadHeightData(szHeightFile))
return false;
if(FAILED(D3DXCreateTextureFromFile(m_pd3dDevice,szTextureFile,&m_pTexture)))
return false;
return true;
}
bool CLODTerrain::InitQuadMat(){
if(!m_pbQuadMat){
MessageBox(NULL,"创建地形标志数组内存不足","提示",0);
return false;
}
for(int x=0;x<=m_iTerrainSize;x++){
for(int z=0;z<=m_iTerrainSize;z++){
SetQuadMatData(x,z,false);
}
}
return true;
}
bool CLODTerrain::InitVertexBuf(){
if(FAILED(m_pd3dDevice->CreateVertexBuffer(10*sizeof(CUSTOMVERTEX),0,CUSTOMVERTEX_FVF,
D3DPOOL_MANAGED,&m_pVertexBuffer,NULL))){
MessageBox(NULL,"创建顶点缓冲区失败","提示",0);
return false;
}
return true;
}
bool CLODTerrain::LoadHeightData(TCHAR* szFileName){
FILE* pFile;
pFile=fopen(szFileName,"rb");
if(!pFile){
return false;
}
if(!m_pucHeightData){
MessageBox(NULL,"创建地形数据内存不足","提示",0);
}
fread(m_pucHeightData,1,(m_iTerrainSize+1)*(m_iTerrainSize+1),pFile);
fclose(pFile);
return true;
}
float CLODTerrain::GenerateHeightData(float x,float z){
return 8*sinf(x)*cosf(z/10)+1.0f;
}
bool CLODTerrain::GetQuadMatData(int x,int z){
return m_pbQuadMat[m_iTerrainSize*z+x];
}
void CLODTerrain::SetQuadMatData(int x,int z,bool b){
if(x>=0 && x<=m_iTerrainSize && z>=0 && z<=m_iTerrainSize){
m_pbQuadMat[m_iTerrainSize*z+x]=b;
}
}
void CLODTerrain::TrimNodeSplit(int iX,int iZ,int iNodeLength){ //去除不合法的分割
int iChildNodeOffset=iNodeLength/4;
int iChildNodeLength=iNodeLength/2;
if(iNodeLength>=4 && GetQuadMatData(iX,iZ)==true){
if((iX+iNodeLength)<=m_iTerrainSize && GetQuadMatData(iX+iNodeLength,iZ)==false){
SetChildNodeFalse(iX+iChildNodeOffset,iZ+iChildNodeOffset,iChildNodeLength);
SetChildNodeFalse(iX+iChildNodeOffset,iZ-iChildNodeOffset,iChildNodeLength);
}
if((iZ-iNodeLength)>=0 && GetQuadMatData(iX,iZ-iNodeLength)==false){
SetChildNodeFalse(iX-iChildNodeOffset,iZ-iChildNodeOffset,iChildNodeLength);
SetChildNodeFalse(iX+iChildNodeOffset,iZ-iChildNodeOffset,iChildNodeLength);
}
if((iX-iNodeLength)>=0 && GetQuadMatData(iX-iNodeLength,iZ)==false){
SetChildNodeFalse(iX-iChildNodeOffset,iZ+iChildNodeOffset,iChildNodeLength);
SetChildNodeFalse(iX-iChildNodeOffset,iZ-iChildNodeOffset,iChildNodeLength);
}
if((iZ+iNodeLength)<=m_iTerrainSize && GetQuadMatData(iX,iZ+iNodeLength)==false){
SetChildNodeFalse(iX-iChildNodeOffset,iZ+iChildNodeOffset,iChildNodeLength);
SetChildNodeFalse(iX+iChildNodeOffset,iZ+iChildNodeOffset,iChildNodeLength);
}
TrimNodeSplit(iX+iChildNodeOffset,iZ+iChildNodeOffset,iChildNodeLength);
TrimNodeSplit(iX+iChildNodeOffset,iZ-iChildNodeOffset,iChildNodeLength);
TrimNodeSplit(iX-iChildNodeOffset,iZ+iChildNodeOffset,iChildNodeLength);
TrimNodeSplit(iX-iChildNodeOffset,iZ-iChildNodeOffset,iChildNodeLength);
}
else if(GetQuadMatData(iX,iZ)==false){
SetChildNodeFalse(iX,iZ,iNodeLength);
}
}
void CLODTerrain::SetChildNodeFalse(int iX,int iZ,int iNodeLength){
int iChildNodeOffset=iNodeLength/4;
int iChildNodeLength=iNodeLength/2;
SetQuadMatData(iX,iZ,false);
if(iNodeLength>=4){
SetChildNodeFalse(iX+iChildNodeOffset,iZ+iChildNodeOffset,iChildNodeLength);
SetChildNodeFalse(iX+iChildNodeOffset,iZ-iChildNodeOffset,iChildNodeLength);
SetChildNodeFalse(iX-iChildNodeOffset,iZ-iChildNodeOffset,iChildNodeLength);
SetChildNodeFalse(iX-iChildNodeOffset,iZ+iChildNodeOffset,iChildNodeLength);
}
}
void CLODTerrain::UpdateTerrain(CCamera* pCamera){
SplitNode(m_iTerrainSize/2.0f,m_iTerrainSize/2.0f,m_iTerrainSize,pCamera);
TrimNodeSplit(m_iTerrainSize/2,m_iTerrainSize/2,m_iTerrainSize);
}
void CLODTerrain::Render(){
m_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,0),1.0f,0);
m_pd3dDevice->SetRenderState(D3DRS_LIGHTING,false);
// m_pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
// m_pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
m_pd3dDevice->SetFVF(CUSTOMVERTEX_FVF);
// m_pd3dDevice->SetTexture(0,m_pTexture);
m_pd3dDevice->BeginScene();
RenderNode(m_iTerrainSize/2.0f,m_iTerrainSize/2.0f,m_iTerrainSize);
m_pd3dDevice->EndScene();
m_pd3dDevice->Present(NULL,NULL,NULL,NULL);
}
void CLODTerrain::SplitNode(float x,float z,int iNodeLength,CCamera* pCamera){
int iX=(int)x;
int iZ=(int)z;
float y;
if(!m_bUseHeightFile)
y=m_pucHeightData[iZ*m_iTerrainSize+iX]*m_fHeightScale; //该点的高度
else
y=GenerateHeightData(x,z)*m_fHeightScale;
float fCameraDistance;
float fRule;
bool bSplit;
int iChildNodeLength;
float fChildNodeOffset;
//节点不在视截体内,设置标志后返回
m_pFrustum->GetFrustum(m_pd3dDevice,0.0f);
if(m_pFrustum->CheckCube(x,y,z,(float)iNodeLength))
m_pbQuadMat[m_iTerrainSize*iZ+iX]=true;
else{
m_pbQuadMat[m_iTerrainSize*iZ+iX]=false;
return;
}
//距离检测
D3DXVECTOR3* pCameraPos=NULL;
pCameraPos=pCamera->GetCameraPos();
fCameraDistance=(float)(fabs(pCameraPos->x-x)+
fabs(pCameraPos->y-y)+
fabs(pCameraPos->z-z));
//变形幅度估值
if(m_bUseHeightFile==true){
int iVertexOffset=iNodeLength>>1;
int iChildNodeLength=iVertexOffset>>1;
float fArrayHeightEva[9];
fArrayHeightEva[0]=m_pucHeightData[m_iTerrainSize*iZ+iX]*m_fHeightScale;
fArrayHeightEva[1]=m_pucHeightData[m_iTerrainSize*iZ+(iX+iVertexOffset)]*m_fHeightScale;
fArrayHeightEva[2]=m_pucHeightData[m_iTerrainSize*(iZ-iVertexOffset)+iX]*m_fHeightScale;
fArrayHeightEva[3]=m_pucHeightData[m_iTerrainSize*iZ+(iX-iVertexOffset)]*m_fHeightScale;
fArrayHeightEva[4]=m_pucHeightData[m_iTerrainSize*(iZ+iVertexOffset)+iX]*m_fHeightScale;
fArrayHeightEva[5]=m_pucHeightData[m_iTerrainSize*(iZ+iChildNodeLength)+(iX+iChildNodeLength)]*m_fHeightScale;
fArrayHeightEva[6]=m_pucHeightData[m_iTerrainSize*(iZ-iChildNodeLength)+(iX+iChildNodeLength)]*m_fHeightScale;
fArrayHeightEva[7]=m_pucHeightData[m_iTerrainSize*(iZ-iChildNodeLength)+(iX-iChildNodeLength)]*m_fHeightScale;
fArrayHeightEva[8]=m_pucHeightData[m_iTerrainSize*(iZ+iChildNodeLength)+(iX-iChildNodeLength)]*m_fHeightScale;
float fMaxHeight=fArrayHeightEva[0];
float fMinHeight=fArrayHeightEva[0];
for(int i=1;i<9;i++){
if(fArrayHeightEva[i]>fMaxHeight)
fMaxHeight=fArrayHeightEva[i];
if(fArrayHeightEva[i]<fMinHeight)
fMinHeight=fArrayHeightEva[i];
}
float fHeightDiff=fMaxHeight-fMinH
评论0