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;
}