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 + -
显示快捷键?