当前位置: 首页 > news >正文

NeHe OpenGL第三十四课:地形

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








本文转自 yarin 51CTO博客,原文链接:http://blog.51cto.com/yarin/381886,如需转载请自行联系原作者

相关文章:

  • ansible-playbook批量部署zabbix
  • 艾伟_转载:C#来创建和读取XML文档
  • 一例HP ADG数据恢复成功(8×73GB SCSI)
  • 艾伟_转载:LINQ to SQL、NHibernate比较(二)-- LINQ to SQL实例
  • php经典面试题
  • JavaScript控制图片横向滚动代码
  • 关于服务器缓存的思考
  • 伸向开源世界的“橄榄枝”
  • 运营中心:网站分析、网络广告注释
  • Fedora8上Apache Httpd与Tomcat6初集成
  • 转贴:下辈子,无论爱与不爱,都不会再见
  • 塔式,机架,刀片服务器
  • 静态网页和动态网页
  • 安全运维之:服务器遭受攻击后的一般处理过程
  • TNF拮抗剂相关炎性神经系统疾病
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • CAP理论的例子讲解
  • docker python 配置
  • echarts的各种常用效果展示
  • Electron入门介绍
  • Java精华积累:初学者都应该搞懂的问题
  • Nacos系列:Nacos的Java SDK使用
  • PHP变量
  • python3 使用 asyncio 代替线程
  • SSH 免密登录
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • Windows Containers 大冒险: 容器网络
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 排序算法之--选择排序
  • 使用docker-compose进行多节点部署
  • 使用SAX解析XML
  • 学习JavaScript数据结构与算法 — 树
  • 用quicker-worker.js轻松跑一个大数据遍历
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • 在Mac OS X上安装 Ruby运行环境
  • 字符串匹配基础上
  • 06-01 点餐小程序前台界面搭建
  • 《天龙八部3D》Unity技术方案揭秘
  • HanLP分词命名实体提取详解
  • ​如何防止网络攻击?
  • ​香农与信息论三大定律
  • #考研#计算机文化知识1(局域网及网络互联)
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (转)ABI是什么
  • (转)ObjectiveC 深浅拷贝学习
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(二)...
  • .NET/C# 的字符串暂存池
  • /proc/stat文件详解(翻译)
  • @EnableAsync和@Async开始异步任务支持
  • @Not - Empty-Null-Blank
  • [2019.2.28]BZOJ4033 [HAOI2015]树上染色
  • [AIGC] MySQL存储引擎详解
  • [AX]AX2012开发新特性-禁止表或者表字段