⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 terrain.cpp

📁 在程序中根据3D地形的高度图动态地生成光照图,其中已包含了3D地形混合纹理生成的代码,使用C++和OpenGL进行编写.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include "Terrain.h"

//----------------------------------------------------------------------
// 函数名称:HeightMap::TextureTileManeger::~TextureTileManeger - public
// 描述:析构函数
// 参数:None
// 返回:None
//----------------------------------------------------------------------
HeightMap::TextureTileManeger::~TextureTileManeger()
{
	// 删除所有载入的纹理对象 
	for (size_t i = 0; i < m_vecTexture.size(); ++i)
	{
		if (m_vecTexture[i] != NULL)
		{
			delete m_vecTexture[i];
		}
	}

	// 删除所有载入的纹理对象的作用区域
	for (size_t i = 0; i < m_vecTextureRegion.size(); ++i)
	{
		if (m_vecTextureRegion[i] != NULL)
		{
			delete m_vecTextureRegion[i];
		}
	}
}

//-----------------------------------------
// 函数名称:HeightMap::~HeightMap - public
// 描述:虚析构函数
// 参数:None
// 返回:None
//-----------------------------------------
HeightMap::~HeightMap()
{	
	// 删除高度数据
	CleanUpHeightData();
	// 释放地形纹理数据资源
	CleanUpTerrainTextureData();
}

//-----------------------------------------------
// 函数名称:HeightMap::CleanUpHeightData - public
// 描述:释放高度数据资源
// 参数:None
// 返回:None
//-----------------------------------------------
GLvoid HeightMap::CleanUpHeightData()
{
	delete [] m_pHeightData;
	m_pHeightData = NULL;
	m_iHeightMapSize  = 0;
	m_fScale = 0.0f;
}

//-----------------------------------------------
// 函数名称:HeightMap::CleanUpHeightData - public
// 描述:释放地形纹理数据资源
// 参数:None
// 返回:None
//-----------------------------------------------
GLvoid HeightMap::CleanUpTerrainTextureData()
{
	// 删除地形纹理数据
	if (m_uiTerrainTextureID != 0)
	{
		glDeleteLists(m_uiTerrainTextureID, 1);
		m_uiTerrainTextureID = 0;
	}
	if (m_pTerrainData != NULL)
	{
		delete [] m_pTerrainData;
		m_pTerrainData = NULL;
	}
}

//--------------------------------------------------------
// 函数名称:HeightMap::CleanUpIlluminationData - public
// 描述:释放光照数据资源
// 参数:None
// 返回:None
//--------------------------------------------------------
GLvoid HeightMap::CleanUpIlluminationData()
{
	delete [] m_pIlluminationData;
	m_pIlluminationData = NULL;
	m_iIlluminationMapSize  = 0;
	m_IlluminationType = NoIllumination;
}

//-----------------------------------------------------
// 函数名称:HeightMap::LoadHeightMapFromFile - public
// 描述:从文件载入高度图
// 参数:heightMapFilePath - 高度图文件路径
//		size - 高度图的尺寸
// 返回:GL_TRUR - 成功载入高度图文件
//		G_FALSE - 载入高度图文件失败
//-----------------------------------------------------
GLboolean HeightMap::LoadHeightMapFromFile(const string &heightMapFilePath, GLint size)
{
	// 文件指针
	FILE* pFile = NULL;
	// 打开文件
	pFile = fopen(heightMapFilePath.c_str(), "rb");

	// 错误检测
	if (pFile == NULL)
	{
		// 错误信息:打开文件错误
		return GL_FALSE;
	}

	// 检测是否类中已保存有高度图
	if (m_pHeightData != NULL)
	{
		CleanUpHeightData();	// 卸载之前的高度图
	}

	// 记录尺寸信息
	m_iHeightMapSize = size;
	// 为高度图分配内存
	m_pHeightData = new GLubyte[m_iHeightMapSize*m_iHeightMapSize];

	// 读取高度图的高度信息,0 -- 255的值
	fread(m_pHeightData, 1, m_iHeightMapSize*m_iHeightMapSize, pFile);

	// 关闭文件
	fclose(pFile);
	return GL_TRUE;
}

//----------------------------------------------------
// 函数名称:HeightMap::WriteHeightMapToFile - public
// 描述:将当前保存在类中的高度图数据写进一个文件中
// 参数:heightMapFileName - 写进文件位置
// 返回:GL_TRUE - 成功将高度图数据写进文件中
//		GL_FALSE - 将高度图数据写进文件中失败
//----------------------------------------------------
GLboolean HeightMap::WriteHeightMapToFile(const string &heightMapFileName) const
{
	// 检测类中是否保存有高度图
	if (m_pHeightData == NULL)
	{
		// 错误信息:此类对象中未保存有任何高度图
		return GL_FALSE;
	}

	// 文件指针
	FILE* pFile = NULL;
	// 创建文件
	pFile = fopen(heightMapFileName.c_str(), "wb");
	if (pFile == NULL)
	{
		// 错误信息:创建高度图文件失败
		return GL_FALSE;
	}

	// 将高度图的高度数据写进高度文件中
	fwrite(m_pHeightData, 1, m_iHeightMapSize*m_iHeightMapSize, pFile);

	// 关闭文件
	fclose(pFile);
	return GL_TRUE;
}

//-----------------------------------------------------------
// 函数名称:HeightMap::LoadIlluminationMapFromFile - public
// 描述:从文件中载入照明图
// 参数:illuminationFilePath - 照明图文件路径
//		size - 照明图的尺寸
// 返回:GL_TRUR - 成功载入照明图文件
//		G_FALSE - 载入照明图文件失败
//-----------------------------------------------------------
GLboolean HeightMap::LoadIlluminationMapFromFile(const string &illuminationFilePath, GLint size)
{
	// 文件指针
	FILE* pFile = NULL;
	// 打开文件
	pFile = fopen(illuminationFilePath.c_str(), "rb");

	// 错误检测
	if (pFile == NULL)
	{
		// 错误信息:打开文件错误
		return GL_FALSE;
	}

	// 检测是否类中已保存有照明图
	if (m_pIlluminationData != NULL)
	{
		CleanUpIlluminationData();	// 卸载之前的照明图
	}

	// 记录尺寸信息
	m_iIlluminationMapSize = size;
	// 为照明图分配内存
	m_pIlluminationData = new GLubyte[m_iIlluminationMapSize*m_iIlluminationMapSize];

	// 读取高度图的高度信息,0 -- 255的值
	fread(m_pIlluminationData, 1, m_iIlluminationMapSize*m_iIlluminationMapSize, pFile);

	// 关闭文件
	fclose(pFile);
	return GL_TRUE;
}

//---------------------------------------------------------
// 函数名称:HeightMap::WriteIlluminationMapToFile - public
// 描述:将照明图写进一个文件中
// 参数:illuminationMapFileName - 写进文件位置
// 返回:GL_TRUE - 成功将照明图数据写进文件中
//		GL_FALSE - 将照明图数据写进文件中失败
//---------------------------------------------------------
GLboolean HeightMap::WriteIlluminationMapToFile(const string &illuminationMapFileName) const
{
	// 检测类中是否保存有高度图
	if (m_pIlluminationData == NULL)
	{
		// 错误信息:此类对象中未保存有任何照明图
		return GL_FALSE;
	}

	// 文件指针
	FILE* pFile = NULL;
	// 创建文件
	pFile = fopen(illuminationMapFileName.c_str(), "wb");
	if (pFile == NULL)
	{
		// 错误信息:创建高度图文件失败
		return GL_FALSE;
	}

	// 将高度图的高度数据写进高度文件中
	fwrite(m_pIlluminationData, 1, m_iIlluminationMapSize*m_iIlluminationMapSize, pFile);

	// 关闭文件
	fclose(pFile);
	return GL_TRUE;
}

//-------------------------------------------------
// 函数名称:HeightMap::NormalizeTerrain - private
// 描述:规范化地形高度值到0 -- 255的范围内
// 参数:heightData - 临时保存的GLfloat高度数据
// 返回:GL_TRUE -成功规范化地形
//		GL_FALSE - 规范化地形失败
//-------------------------------------------------
GLboolean HeightMap::NormalizeTerrain(GLfloat *heightData)
{
	// 保存最大和最小高度值
	GLfloat fMin = heightData[0];
	GLfloat fMax = heightData[0];
	GLuint uiTotalSize = m_iHeightMapSize*m_iHeightMapSize;

	// 计算最大和最小高度值
	for(GLuint i = 1; i < uiTotalSize; ++i)
	{
		if(heightData[i] > fMax)
		{
			fMax = heightData[i];
		}
		else if(heightData[i] < fMin) 
		{
			fMin = heightData[i];
		}
	}

	// 错误检测
	if(fMax <= fMin)
	{
		// 错误信息;生成的高度不正确,规范化地形错误
		return GL_FALSE;
	}

	// 计算高度差
	GLfloat fHeightDifference = fMax - fMin;

	// 将高度值缩放到0.0f -- 255.0f的范围内
	for(GLuint i = 0; i < uiTotalSize; ++i)
	{
		heightData[i] = (heightData[i] - fMin)/fHeightDifference*255.0f;
	}
	return GL_TRUE;
}

//-----------------------------------------------------
// 函数名称:HeightMap::FilterHeightArea - private
// 描述:为使用Fault Formation算法生成地形进行过滤融合
// 参数:heightData - 临时保存的GLfloat高度数据
//		stride - 过滤点的间隔数
//		filter - 过滤线性差值混合参数
// 返回:None
//-----------------------------------------------------
GLvoid HeightMap::FilterHeightArea(GLfloat *heightData, GLint stride, GLuint count, GLfloat filter)
{
	GLfloat previousHeight = heightData[0];	// 前一点的高度
	GLuint uiStride  = stride;	// 记录跨距

	// 过滤整个地形,与前一个高度值进行线性差值
	for(GLuint i = 0; i < count - 1; ++i)
	{
		heightData[uiStride] = filter*previousHeight + (1.0f - filter)*heightData[uiStride];
		previousHeight = heightData[uiStride];	// 为下一个线性差值做准备
		uiStride += stride;
	}
}

//-----------------------------------------------------
// 函数名称:HeightMap::FilterHeightField - private
// 描述:以各个方向对整个地形进行过滤融合
// 参数:heightData - 临时保存的GLfloat高度数据
//		filter - 过滤线性差值混合参数
// 返回:None
//-----------------------------------------------------
GLvoid HeightMap::FilterHeightField(GLfloat *heightData, GLfloat filter)
{
	// 对过滤算法的理解:从左右上下四个
	//方向对高度图值进行差值融合,以
	// 使整个高度图趋向于平滑

	// 临时变量
	GLint i;

	// 对高度图的每一行自左向右过滤地形
	for(i = 0; i < m_iHeightMapSize; ++i)
	{
		FilterHeightArea(&heightData[m_iHeightMapSize*i], 1, m_iHeightMapSize, filter);
	}

	// 对高度图的每一行自右向左过滤地形
	for(i = 0; i < m_iHeightMapSize; ++i)
	{
		FilterHeightArea(&heightData[m_iHeightMapSize*i + m_iHeightMapSize - 1], -1, m_iHeightMapSize, filter);
	}

	// 对高度图的每一列自上向下过滤地形
	for(i = 0; i < m_iHeightMapSize; ++i)
	{
		FilterHeightArea(&heightData[i], m_iHeightMapSize, m_iHeightMapSize, filter);
	}

	// 对高度图的每一列自下向上过滤地形
	for(i = 0; i < m_iHeightMapSize; ++i)
	{
		FilterHeightArea(&heightData[m_iHeightMapSize*(m_iHeightMapSize - 1) + i], -m_iHeightMapSize, m_iHeightMapSize, filter);
	}
}

//-------------------------------------------------------
// 函数名称:HeightMap::GenerateTerrainWithFault - public
// 描述:使用Fault Formation算法生成地形
// 参数:size - 地形的尺寸
//		iterationTime - 指定生成地形的跌代次数
//		minHeight - 地形的最小高度
//		maxHeight - 地形的最大高度
//		filter - 过滤地形的参数
// 返回:GLTRUE -  成功生成地形

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -