heightmap.cpp
来自「3D游戏展示程序」· C++ 代码 · 共 618 行 · 第 1/2 页
CPP
618 行
//--------------------------------------------------
// Desc: 高度图
// Author: artsylee/2006.12.27
//--------------------------------------------------
#include <stdio.h>
#include "Heightmap.h"
#include "Common.h"
#include "ase/ASEngine.h"
const DWORD HeightmapVertex::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
CHeightmap::CHeightmap()
{
m_HeightData.m_pData = NULL;
m_HeightData.m_Size = 0;
m_Vb = NULL;
m_Ib = NULL;
m_pLightColor = NULL;
m_pVertex = NULL;
m_pMovemap = NULL;
m_ViewRotY = 0.0f;
m_ViewPos = D3DXVECTOR3(1000, 20, 3150);
m_bViewerChange = true;
}
CHeightmap::~CHeightmap()
{
Release();
}
void CHeightmap::Release(void)
{
UnLoadHeightmap();
if(m_Vb)
{
m_Vb->Release();
m_Vb = NULL;
}
if(m_Ib)
{
m_Ib->Release();
m_Ib = NULL;
}
if(m_pMovemap != NULL)
{
delete [] m_pMovemap;
m_pMovemap = NULL;
}
if(m_pLightColor)
{
delete [] m_pLightColor;
m_pLightColor = NULL;
}
if(m_pVertex)
{
delete [] m_pVertex;
m_pVertex = NULL;
}
}
//----------------------------------------------------
// 加载高度图
//----------------------------------------------------
bool CHeightmap::LoadHeightmap(char* szFilename, int iSize)
{
if(szFilename == NULL || szFilename[0]==0 || !iSize)
return false;
Release();
FILE* pFile = fopen(szFilename, "rb");
if(pFile == NULL)
{
WriteLog(INFO_ERROR, "Can't Load Heightmap[%s]", szFilename);
return false;
}
m_HeightData.m_pData = new unsigned char[iSize*iSize];
if(m_HeightData.m_pData==NULL)
return false;
fread(m_HeightData.m_pData, iSize*iSize, 1, pFile);
fclose(pFile);
m_HeightData.m_Size = iSize;
m_Size = iSize;
// light map
m_pLightColor = new DWORD[m_Size*m_Size];
if(m_pLightColor == NULL)
return false;
D3DXVECTOR3 directionToLight(0.0f, -10.0f, 0.0f);
ComputeDiffuse(&directionToLight);
// Vertex
/*
m_pVertex = new HeightmapVertex[m_Size*m_Size];
if(m_pVertex==NULL)
return false;
CreateVertex();
*/
m_pMovemap = new Move_Vertex[MOVE_MAP_SIZE*MOVE_MAP_SIZE];
if(m_pMovemap == NULL)
return false;
return true;
}
//----------------------------------------------------
// 保存高度图
//----------------------------------------------------
bool CHeightmap::SaveHeightmap(char* szFilename)
{
if(szFilename == NULL || szFilename[0]==0)
return false;
if(m_HeightData.m_pData == NULL)
{
return false;
}
FILE* pFile = fopen(szFilename, "wb");
if(pFile == NULL)
{
return false;
}
fwrite(m_HeightData.m_pData, m_HeightData.m_Size*m_HeightData.m_Size, 1, pFile);
fclose(pFile);
return true;
}
//----------------------------------------------------
// 释放高度图
//----------------------------------------------------
bool CHeightmap::UnLoadHeightmap()
{
if(m_HeightData.m_pData!=NULL)
{
delete [] m_HeightData.m_pData;
m_HeightData.m_pData = NULL;
m_HeightData.m_Size = 0;
}
return true;
}
//----------------------------------------------------
// 更新高度图
//----------------------------------------------------
void CHeightmap::UpdateHeightmap(void)
{
m_Frustum.m_ViewerRotate = m_ViewRotY;
m_Frustum.UpdateFrustum();
//---------------------------------------
// 该节太消耗资源(远处显示有点小问题)
//---------------------------------------
/*
for(int i=0; i<MOVE_MAP_SIZE*MOVE_MAP_SIZE; i++)
{
m_pMovemap[i].xpos = -1;
m_pMovemap[i].zpos = -1;
}
*/
int offsetx = int(m_ViewPos.x * WORLD_TO_MOVE);
if(m_ViewPos.x<0.0f) offsetx -= 1;
int offsetz = int(m_ViewPos.z * WORLD_TO_MOVE);
if(m_ViewPos.z<0.0f) offsetz -= 1;
int min = m_Frustum.m_minZ;
int max = m_Frustum.m_maxZ;
for(int z=(m_Frustum.m_pos[min].y); z<=(m_Frustum.m_pos[max].y); z++)
{
int zpos = ((z-MOVE_MAP_SIZE/2+offsetz)*MOVE_MAP_SCALE)%m_Size;
if(zpos<=0) zpos = -zpos;
else zpos = m_Size-zpos;
int xpos = (((m_Frustum.m_LeftArray[z])-MOVE_MAP_SIZE/2+offsetx)*MOVE_MAP_SCALE)%m_Size;
if(xpos<0) xpos = m_Size+xpos;
for(int x=(m_Frustum.m_LeftArray[z]); x<=(m_Frustum.m_RightArray[z]); x++)
{
m_pMovemap[z*MOVE_MAP_SIZE+x].xpos = xpos;
m_pMovemap[z*MOVE_MAP_SIZE+x].zpos = zpos;
xpos += 4;
if(xpos>m_Size-4)
{
xpos = 0;
}
}
}
m_ViewOffsetZ = offsetz*40;
m_ViewOffsetX = offsetx*40;
}
//----------------------------------------------------
// 显示地形
//----------------------------------------------------
void CHeightmap::Render(void)
{
}
//----------------------------------------------------
// 观察者Y轴坐标
//----------------------------------------------------
float CHeightmap::GetYPosition(void)
{
return GetHeight(m_ViewPos.x, m_ViewPos.z);
}
//----------------------------------------------------
// 观察者位置
//----------------------------------------------------
void CHeightmap::SetViewPosition(D3DXVECTOR3 viewpos)
{
m_ViewPos = viewpos;
m_bViewerChange = true;
}
//----------------------------------------------------
// 观察者Y轴的旋转角度
//----------------------------------------------------
void CHeightmap::SetViewRotateY(float angle)
{
if(abs(angle-m_ViewRotY)>=1.0f)
{
m_ViewRotY = angle;
m_bViewerChange = true;
}
}
//----------------------------------------------------
// 填充顶点
//----------------------------------------------------
bool CHeightmap::FillVertexBuffer(void)
{
return true;
}
//----------------------------------------------------
// 由移动位置取得高度索引
//----------------------------------------------------
int CHeightmap::GetHeightIndex(int movemapX, int movemapZ)
{
int movemapindex = movemapZ*MOVE_MAP_SIZE+movemapX;
if(m_pMovemap[movemapindex].zpos>=0 && m_pMovemap[movemapindex].xpos>=0)
{
return m_pMovemap[movemapindex].zpos*m_Size + m_pMovemap[movemapindex].xpos;
}
else
{
return -1;
}
}
//----------------------------------------------------
// 由索引偏移取得高度索引
//----------------------------------------------------
int CHeightmap::GetHeightIndexOffset(int index, char offsetZ, char offsetX)
{
int retIndex = index + offsetZ*m_Size + offsetX;
int num;
if(retIndex>=0 && retIndex<m_Size*m_Size)
{
return retIndex;
}
if(retIndex-offsetX>=0 && retIndex-offsetZ<m_Size*m_Size)
{
if(retIndex<0) return retIndex+m_Size*m_Size;
else return retIndex-m_Size*m_Size;
}
else
{
if(retIndex-offsetX<0) num = index+(m_Size+offsetZ)*m_Size;
else num = index+(m_Size-offsetZ)*m_Size;
}
if(num+offsetX>=0 && num+offsetX<m_Size*m_Size)
{
return num+offsetX;
}
else if(num+offsetX<0) return num+offsetX+m_Size*m_Size;
else return num+offsetX-m_Size*m_Size;
}
//----------------------------------------------------
// 获取精确高度(三次线性插值)
//----------------------------------------------------
float CHeightmap::GetHeight(D3DXVECTOR3 *checked)
{
POINT point = ConvertToHeightmap(checked);
//小数部分
float Xpos,Zpos;
if(checked->x<0)
{
Xpos = 1+checked->x*WORLD_TO_HEIGHT-int(checked->x*WORLD_TO_HEIGHT);
}
else
{
Xpos = checked->x*WORLD_TO_HEIGHT-int(checked->x*WORLD_TO_HEIGHT);
}
if(checked->z<=0)
{
Zpos = -(checked->z*WORLD_TO_HEIGHT-int(checked->z*WORLD_TO_HEIGHT));
}
else
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?