• NeHe OpenGL教程 第三十四课:地形


    转自【翻译】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

     
  • 相关阅读:
    LightOJ
    LightOJ
    51Nod 1021~1023 石子合并 (逐步加强版) 【dp】
    BZOJ1036 [ZJOI2008]树的统计Count 【树链剖分+线段树维护】
    51Nod 1677 treecnt 【树形dp+组合数学+逆元】
    逆元 【数学】
    51Nod 1705七星剑 【概率dp】
    BZOJ 1064 [Noi2008]假面舞会 【bfs】
    51 nod 1443 路径和树 【最短路径】
    BZOJ 1013 [JSOI2008]球形空间产生器sphere 【高斯消元】
  • 原文地址:https://www.cnblogs.com/arxive/p/6239532.html
Copyright © 2020-2023  润新知