转自【翻译】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;     // 返回

  }

原文及其个版本源代码下载:

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=34

 

NeHe OpenGL教程 第三十四课:地形的更多相关文章

  1. NeHe OpenGL教程 第三十八课:资源文件

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  2. NeHe OpenGL教程 第三十六课:从渲染到纹理

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  3. NeHe OpenGL教程 第三十五课:播放AVI

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  4. NeHe OpenGL教程 第三十二课:拾取游戏

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  5. NeHe OpenGL教程 第三十九课:物理模拟

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  6. NeHe OpenGL教程 第三十课:碰撞检测

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  7. NeHe OpenGL教程 第三十七课:卡通映射

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  8. NeHe OpenGL教程 第三十三课:TGA文件

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  9. NeHe OpenGL教程 第三十一课:加载模型

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

随机推荐

  1. poj2186 强连通

    题意:有 n 头牛,以及一些喜欢关系,牛 A 喜欢牛 B,这种关系可以传递,问有多少头牛被牧场上所有牛喜欢. 首先强连通,因为在同一个强连通分量中牛是等价的,然后对于一个有向无环图看是否只有一个强连通 ...

  2. HTML里的id等属性命名需要注意

    提交 $(function(){ $('#submit').click(function(){ $('#form').submit() }) }) 这里的代码无法完成提交,因为id被命名为submit ...

  3. C 语言中 free() 函数简单分析

    又是一个睡不着的夜晚,现在是凌晨03:16,不知道是不是感冒的原因,头脑并不是清醒,但是就是睡不着.摸着黑打开电脑,洗了杯子抓了点茶叶,然后打开饮水机电源.舍友们都睡着了,我戴着耳机听着轻音乐,也能听 ...

  4. Linux驱动设计——并发与竞态控制

    并发的概念:多个执行单元同时.并行被执行. 共享资源:硬件资源(IO/外设等),软件上的全局变量.静态变量等. 四种并发控制机制(对共享资源互斥的访问):原子操作.自旋锁(spinlock).信号量( ...

  5. 为什么说Parcelable 比Serializable更高效

    本文转载自:http://blog.csdn.net/androidzhaoxiaogang/article/details/8172539 什么是序列化,实现序列化的目的是什么? 讨论这个问题之前, ...

  6. java的nio之:java的nio的原理

    转载:http://weixiaolu.iteye.com/blog/1479656 Java NIO原理图文分析及代码实现 前言: 最近在分析hadoop的RPC(Remote Procedure ...

  7. oracle中如何指定表字段自增

    背景介绍: SQL SERVER可以在int类型的字段后加上identity(1,1),该字段就会从1开始,按照+1的方式自增,将这个字段设置为主键,有利于我们进行数据的插入操作.MySql中可以使用 ...

  8. 委托,C#本身的委托(Action Func)

    1.Action 分为带泛型的和不带泛型的,带泛型可传入任何类型的参数. 格式如下: using System; using System.Collections.Generic; using Sys ...

  9. postgreSQL 时间线

    “时间线”(Timeline)是PG一个很有特色的概念,在备份恢复方面的文档里面时有出现.但针对这个概念的详细解释却很少,也让人不太好理解,我们在此仔细解析一下. 时间线的引入 为了理解引入时间线的背 ...

  10. MyEclipse设置内存

    Tomcat直接启动正常,通过myeclipse启动tomcat内存溢出. MyEclipse启动Tomcat无视catalina.bat中设置内存大小的问题. 在 tomcat的catalina.b ...