www.pudn.com > 林海血原源代码.zip > Heightmap.cpp


// Heightmap.cpp: implementation of the CHeightmap class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "Heightmap.h" 
#include "stdio.h" 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
MOVE_VERTEX    * CHeightmap::m_pMovemap=NULL; 
unsigned char  * CHeightmap::m_pTmap=NULL; 
unsigned char  * CHeightmap::m_pCovermap=NULL; 
 
VERTEX         * CHeightmap::m_pViewPos=NULL; 
VERTEX         * CHeightmap::m_pSunPos =NULL; 
float          * CHeightmap::m_pViewRotX=NULL; 
float          * CHeightmap::m_pViewRotY=NULL; 
bool             CHeightmap::m_bSunVisible=true; 
 
int              CHeightmap::m_numUser=0; 
BOUNDARY_2D      CHeightmap::m_rect=BOUNDARY_2D(0,0,0,0); 
CHeightmap::CHeightmap() 
{ 
	if(m_numUser==0) 
	{ 
		/////////read terrain map 
    	if(!ReadTerrainmapFile()) 
		{ 
		    MessageBox(0, "read heightmap failed", "Error", MB_OK | MB_ICONERROR); 
		    return ; 
		} 
    	if(!ReadPlantmapFile()) 
		{ 
		    MessageBox(0, "read plantmap failed", "Error", MB_OK | MB_ICONERROR); 
		    return ; 
		} 
		m_pMovemap =new MOVE_VERTEX [256*256]; 
 
        m_pViewPos =new VERTEX; 
        m_pSunPos  =new VERTEX; 
		m_pViewRotX=new float; 
		m_pViewRotY=new float; 
 
	} 
	m_numUser++; 
} 
 
CHeightmap::~CHeightmap() 
{ 
	m_numUser--; 
	if(m_pTmap!=NULL && m_pCovermap!=NULL && (m_numUser==0)) 
	{ 
		delete [] m_pTmap; 
		delete [] m_pCovermap; 
		delete [] m_pMovemap; 
 
		delete    m_pViewPos; 
		delete    m_pSunPos; 
		delete    m_pViewRotY; 
		delete    m_pViewRotX; 
		m_pTmap=NULL; 
		m_pCovermap=NULL; 
		m_pMovemap=NULL; 
 
		m_pViewPos=NULL; 
		m_pSunPos =NULL; 
		m_pViewRotY=NULL; 
		m_pViewRotX=NULL; 
 
	} 
} 
unsigned char CHeightmap::GetHeightmapPointValue(VERTEX *checked) 
{ 
	/* 
	POINT point=ConvertToHeightmap(checked); 
	return m_pTmap[256*point.y + point.x];*/ 
	return 0; 
} 
float CHeightmap::GetHeight(VERTEX *checked) 
{ 
	POINT point=ConvertToHeightmap(checked); 
	float Xpos,Zpos; 
 
	if(checked->xpos<0) 
	    Xpos=1+checked->xpos*0.1f-int(checked->xpos*0.1f); 
	else 
	    Xpos=checked->xpos*0.1f-int(checked->xpos*0.1f); 
	if(checked->zpos<0) 
	    Zpos=1+checked->zpos*0.1f-int(checked->zpos*0.1f); 
	else  
		Zpos=checked->zpos*0.1f-int(checked->zpos*0.1f); 
 
    /////////////////////// 
	float ypos; 
	float h11,h12,h22,h21; 
	float ha,hb; 
	//////////check Xpos and Zpos 
	//////////////////////////// 
	int addx=point.x+1; 
	int addy=point.y+1; 
	if(addx==256)addx=0; 
	if(addy==256)addy=0; 
 
    h11=float(m_pTmap[256*(point.y+0) + (point.x+0)]); 
    h12=float(m_pTmap[256*(addy) + (point.x+0)]); 
    h21=float(m_pTmap[256*(point.y+0) + addx]); 
    h22=float(m_pTmap[256*(addy) + addx]); 
 
	ha=h11+Xpos*(h21-h11); 
	hb=h12+Xpos*(h22-h12);	 
 
    ypos=ha +Zpos*(hb-ha); 
 
	return ypos; 
 
} 
float CHeightmap::GetHeight(float xpos,float zpos) 
{ 
   VERTEX temp=VERTEX(xpos,0,zpos); 
   float ypos=GetHeight(&temp); 
   return ypos; 
} 
 
bool CHeightmap::CollideCheck(VERTEX viewPos,VERTEX objPos,float step) 
{ 
 
	float dy=viewPos.ypos-objPos.ypos; 
	float dx=viewPos.xpos-objPos.xpos; 
	float dz=viewPos.zpos-objPos.zpos; 
 
	int signx,signy,signz; 
	if(dx<0) 
	{dx=-dx; signx=-1;} 
	else 
        signx=1; 
	if(dy<0) 
	{dy=-dy; signy=-1;} 
	else 
        signy=1; 
	if(dz<0) 
	{dz=-dz; signz=-1;} 
	else 
        signz=1; 
 
	float terrainHeight=GetHeight(&viewPos); 
	float CurLineHeight=viewPos.ypos; 
	 
	float CurZ=viewPos.zpos; 
	float CurX=viewPos.xpos; 
 
	if(dz>dx) 
	{ 
		int times=int(dz/step); 
		float deltaH=dy/times; 
		float deltax=signx*dx*step/dz; 
        for(int i=0;iCurLineHeight)return true; 
            CurLineHeight -= signy*deltaH; 
			terrainHeight=GetHeight(CurX,CurZ); 
			CurX-=deltax; 
			CurZ-=signz*step; 
		} 
	} 
	else 
	{ 
		int times=int(dx/step); 
		float deltaH=dy/times; 
		float deltaz=signz*dz*step/dx; 
        for(int i=0;iCurLineHeight)return true; 
            CurLineHeight -= signy*deltaH; 
			terrainHeight=GetHeight(CurX,CurZ); 
			CurZ-=deltaz; 
			CurX-=signx*step; 
		} 
	} 
    return false; 
} 
bool CHeightmap::IsInFrustum(VERTEX checked) 
{ 
	POINT point=ConvertToMovemap(checked); 
	if(point.x==0 && point.y==0)return false; 
 
	return true; 
 
} 
bool CHeightmap::CheckSunVisible() 
{ 
	if(!m_bSunVisible)return false; 
 
	float dx=m_pViewPos->xpos-m_pSunPos->xpos ; 
	float dz=m_pViewPos->zpos-m_pSunPos->zpos ; 
	float dy=m_pViewPos->ypos-m_pSunPos->ypos ; 
     
	float absx=dx; 
	if(absx<0)absx=-absx; 
 
	float absz=dz; 
	if(absz<0)absz=-absz; 
 
	float max=absz; 
	if(absx>max)max=absx; 
 
	max=200/max; 
 
	dx=dx*max; 
	dz=dz*max; 
	dy=dy*max*0.85f; 
 
	VERTEX checkPos=VERTEX(m_pViewPos->xpos-dx,m_pViewPos->ypos-dy,m_pViewPos->zpos-dz); 
 
	return !CollideCheck(*m_pViewPos,checkPos,2); 
} 
POINT CHeightmap::ConvertToHeightmap(VERTEX *pos) 
{ 
	POINT point; 
	if(pos->xpos<0) 
	    point.x=255+int(pos->xpos*0.1f)%256; 
	else 
		point.x=int(pos->xpos*0.1f)%256; 
	if(pos->zpos<0) 
	    point.y=255+int(pos->zpos*0.1f)%256; 
	else  
		point.y=int(pos->zpos*0.1f)%256; 
 
	return point; 
} 
POINT CHeightmap::ConvertToMovemap(VERTEX pos) 
{ 
 	POINT point; 
     
	point.x=int((pos.xpos-m_pViewPos->xpos)*0.05f)+128; 
	point.y=int((pos.zpos-m_pViewPos->zpos)*0.05f)+128; 
	if(point.xm_rect.maxx ) 
	{    
		POINT p; 
	    p.x=p.y=0; 
		return p; 
	} 
	if(point.ym_rect.maxz ) 
	{    
		POINT p; 
	    p.x=p.y=0; 
		return p; 
	} 
  
	return point; 
} 
bool CHeightmap::ReadTerrainmapFile() 
{ 
	FILE *fp; 
	fp=fopen("Terrains/ter256.bmp","rb"); 
	if(!fp)return false; 
 
	BITMAPFILEHEADER fileheader; 
	fread(&fileheader,sizeof(BITMAPFILEHEADER),1,fp); 
	if(fileheader.bfType!=19778)return false; 
 
    m_pTmap=new unsigned char[256*256]; 
	if(m_pTmap==NULL)return false; 
 
    fseek(fp,1078,SEEK_SET); 
	for(int z=255;z>-1;z--) 
		for(int x=0;x<256;x++) 
		{ 
			fread(&m_pTmap[256*z+x],sizeof(unsigned char),1,fp);	 
		}	 
 
	fclose(fp); 
    return true; 
} 
bool CHeightmap::ReadPlantmapFile() 
{ 
	FILE *fp; 
	fp=fopen("plants/plantmap.bmp","rb"); 
	if(!fp)return false; 
 
	BITMAPFILEHEADER fileheader; 
	fread(&fileheader,sizeof(BITMAPFILEHEADER),1,fp); 
	if(fileheader.bfType!=19778)return false; 
 
    m_pCovermap=new unsigned char[256*256]; 
	if(m_pCovermap==NULL)return false; 
 
    fseek(fp,1078,SEEK_SET); 
	for(int z=255;z>-1;z--) 
		for(int x=0;x<256;x++) 
		{ 
			fread(&m_pCovermap[256*z+x],sizeof(unsigned char),1,fp);	 
		}	 
	fclose(fp); 
    return true; 
} 
int  CHeightmap::GetPosInMovemap(int x,int z) 
{ 
    return m_pMovemap[(128+z)*256+128+x].zpos*256+m_pMovemap[(128+z)*256+128+x].xpos; 
}