NeHe OpenGL教程 第三十四课:地形
前言
声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改。对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢。
NeHe OpenGL第三十四课:地形
从高度图生成地形:
这一课将教会你如何从一个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; // 返回
}
原文及其个版本源代码下载:
NeHe OpenGL教程 第三十四课:地形的更多相关文章
- NeHe OpenGL教程 第三十八课:资源文件
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十六课:从渲染到纹理
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十五课:播放AVI
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十二课:拾取游戏
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十九课:物理模拟
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十课:碰撞检测
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十七课:卡通映射
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十三课:TGA文件
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十一课:加载模型
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
随机推荐
- shell下的作业管理[转]
作业管理 举例来说,我们在登陆 bash 后, 想要一边复制文件.一边进行数据搜寻.一边进行编译,还可以一边进行 vi 程序撰写! 当然我们可以重复登陆那六个文字介面的终端机环境中,不过,能不能在一个 ...
- 万能写入sql语句,并且防注入
通过perpare()方法和检查字段防sql注入. $pdo=new PDO('mysql:host=localhost;dbname=scms', 'root' ); $_POST=array('t ...
- css float对于之后布局的影响
后面的元素不浮动,即便设置了宽度,表面上只占了一定的宽度,但实际上占了全屏.(所以设置了overflow之后,并且之后的div设置了宽度,再设置margin-left可能不起作用). 高度对浮动的影响 ...
- 如何用Transformer+从PDF文档编辑数据
ABBYY PDF Transformer+是一款可创建.编辑.添加注释及将PDF文件转换为其他可编辑格式的通用工具,可使用该软件从PDF文档编辑机密信息,然后再发布它们,文本和图像均可编辑,本文将为 ...
- kettle常见问题解决
开源ETL工具kettle系列之常见问题 摘要:本文主要介绍使用kettle设计一些ETL任务时一些常见问题,这些问题大部分都不在官方FAQ上,你可以在kettle的论坛上找到一些问题的答案 1. J ...
- DW(四):Azure域控服务器配置
polybase集群要求使用相同的域账号,本节介绍选择用Azure虚拟机搭建自己的内网DNS服务器和域控 创建虚拟网络polybase,创建名为DNS的子网,如下图: 创建虚拟机,选择polybase ...
- html中间块居中宽度自适应
说来,这个其实不是个多难的事情,但是,若没有经验或者没有了解过html原数在浏览器中显示的顺序,可能还真是个问题,不知如何调整. 先说明下,在确定了左右两边显示的块的宽度后,再让中间块的宽度自适应,这 ...
- (转)Android-Mac电脑如何进行APK反编译-使用apktool、jd-gui
最近群里有人问如何在mac下进行apk反编译,我也没试过,以前都是在windows下进行反编译的,windows下很简单,有许多比较好的集成工具,如apkide(改之理),不过我猜mac下应该和win ...
- 微信公众平台Php版php开发(转)
http://www.1990c.com/?p=932 近在做微信公众平台开发,一口气写了二十几个功能,挺有意思的- 今天来分享一下开发经验~微信公众平台提供的接口很简单,先看看消息交互流程: 说 ...
- 关于JAVA中事件分发和监听机制实现的代码实例-绝对原创实用
http://blog.csdn.net/5iasp/article/details/37054171 文章标题:关于JAVA中事件分发和监听机制实现的代码实例 文章地址: http://blog.c ...