Chinaunix首页 | 论坛 | 博客
  • 博客访问: 397688
  • 博文数量: 158
  • 博客积分: 1227
  • 博客等级: 少尉
  • 技术积分: 946
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-20 16:19
文章分类
文章存档

2016年(1)

2015年(1)

2012年(107)

2011年(49)

分类:

2012-03-23 11:30:13

原文地址:第34课 作者:landuochong

从高度图生成地形:

这一课将教会你如何从一个2D的灰度图创建地形

欢迎来到新的一课,Ben Humphrey写了这一课的代码,它是基于第一课所写的。

在这一课里,我们将教会你如何使用地形,你将知道高度图这个概念。

下面我们来定义一些全局变量,MAP_SIZE是你使用的高度图的大小,在这一课 里我们使用1024*1024的地图。STEP_SIZE设置高度图中相邻顶点之间的距离。HEIGHT_RATIO设置在高度方向的缩放比例,越大地形 看起来越陡峭。bRender设置使用多边形还是线绘制地形。
#define		MAP_SIZE	1024				
#define STEP_SIZE 16 // 相邻顶点的距离
#define HEIGHT_RATIO 1.5f
bool bRender = TRUE; // true为多边形渲染,false为线渲染
下面的代码用来保存高度数据
BYTE g_HeightMap[MAP_SIZE*MAP_SIZE];				// 保存高度数据

float scaleValue = 0.15f; // 地形的缩放比例
下面的函数从文件中加载高度数据
// 从*.raw文件中加载高度数据
void LoadRawFile(LPSTR strName, int nSize, BYTE *pHeightMap)
{
FILE *pFile = NULL;

// 打开文件
pFile = fopen( strName, "rb" );

// 如果文件不能打开
if ( pFile == NULL )
{
// 提示错误,退出
MessageBox(NULL, "不能打开高度图文件", "错误", MB_OK);
return;
}
	// 读取文件数据到pHeightMap数组中
fread( pHeightMap, 1, nSize, pFile );

// 读取是否成功
int result = ferror( pFile );

// 如果不成功,提示错误退出
if (result)
{
MessageBox(NULL, "读取数据失败", "错误", MB_OK);
}

// 关闭文件
fclose(pFile);
}
InitGL函数基本没有变化,只是加入了加载高度图的函数
// 载入1024*1024的高度图道g_HeightMap数组中

LoadRawFile("Data/Terrain.raw", MAP_SIZE * MAP_SIZE, g_HeightMap);
下面的函数返回(x,y)点的高度
int Height(BYTE *pHeightMap, int X, int Y)			// 下面的函数返回(x,y)点的高度
{
int x = X % MAP_SIZE; // 限制X的值在0-1024之间
int y = Y % MAP_SIZE; // 限制Y的值在0-1024之间

if(!pHeightMap) return 0; // 检测高度图是否存在,不存在则返回0
返回(x,y)的高度
	return pHeightMap[x + (y * MAP_SIZE)];			// 返回(x,y)的高度
}
按高度设置顶点的颜色,越高的地方越亮
void SetVertexColor(BYTE *pHeightMap, int x, int y)			// 按高度设置顶点的颜色,越高的地方越亮
{
if(!pHeightMap) return;

float fColor = -0.15f + (Height(pHeightMap, x, y ) / 256.0f);

// 设置顶点的颜色
glColor3f(0.0f, 0.0f, fColor );
}
下面的函数在OpenGL中,根据高度图渲染输出地形
void RenderHeightMap(BYTE pHeightMap[])				// 根据高度图渲染输出地形
{
int X = 0, Y = 0; // 设置循环变量
int x, y, z;

if(!pHeightMap) return; // 确认高度图存在
	if(bRender)						// 选择渲染模式
glBegin( GL_QUADS ); // 渲染为四边形
else
glBegin( GL_LINES ); // 渲染为直线

下面的函数求得每一点的坐标和颜色,调用OpenGL渲染
	for ( X = 0; X < MAP_SIZE; X += STEP_SIZE )
for ( Y = 0; Y < MAP_SIZE; Y += STEP_SIZE )
{
// 绘制(x,y)处的顶点
// 获得(x,y,z)坐标
x = X;
y = Height(pHeightMap, X, Y );
z = Y;

// 设置顶点颜色
SetVertexColor(pHeightMap, x, z);

glVertex3i(x, y, z); // 调用OpenGL绘制顶点的命令

// 绘制(x,y+1)处的顶点
x = X;
y = Height(pHeightMap, X, Y + STEP_SIZE );
z = Y + STEP_SIZE ;
SetVertexColor(pHeightMap, x, z);
glVertex3i(x, y, z);

//
绘制(x+1,y+1)处的顶点
x = X + STEP_SIZE;
y = Height(pHeightMap, X + STEP_SIZE, Y + STEP_SIZE );
z = Y + STEP_SIZE ;
SetVertexColor(pHeightMap, x, z);
glVertex3i(x, y, z);

// 绘制(x+1,y)处的顶点
x = X + STEP_SIZE;
y = Height(pHeightMap, X + STEP_SIZE, Y );
z = Y;
SetVertexColor(pHeightMap, x, z);
glVertex3i(x, y, z);
}
glEnd();
	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);			// 重置颜色
}
DrawGLScene函数基本没变化,只是设置了视点和缩放系数,调用上面的函数绘制出地形。
// 设置视点
gluLookAt(212, 60, 194, 186, 55, 171, 0, 1, 0);
glScalef(scaleValue, scaleValue * HEIGHT_RATIO, scaleValue);
	RenderHeightMap(g_HeightMap);				// 渲染高度图

return TRUE;
}
WndProc()函数基本没有变化,只是加入了单击左键的相应函数
		case WM_LBUTTONDOWN:				// 是否单击鼠标左键
{
bRender = !bRender; // 改变渲染模式
return 0; // 返回
}
阅读(311) | 评论(0) | 转发(0) |
0

上一篇:第33课

下一篇:第35课

给主人留下些什么吧!~~