地形本质上由一个个顶点(x,y,z)组成多个三角面连接而成。

地形有两种来源:
  1.美术使用3dmax、maya、bleader工具,画点、线、面,导出三维模型,然后在游戏中加载进来,进行绘制。
  2.软件自身使用数据生成,如通过一张高度图生成。

涉及函数

opengl 绘制网格

     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

代码:

下面Terrain 类就是生成一个简单的平面地形网格。
Terrain.hpp

#pragma once#include <GL/glew.h>
#include <vector>struct  TerrainVert {float   x, y, z;
};//使用索引方式绘制地形class Terrain {public:typedef std::vector<TerrainVert>    ArrayVertex;typedef std::vector<unsigned short> ArrayIndex;public:ArrayVertex _vertex;ArrayIndex  _index;int         _drawSize;public:Terrain(void);~Terrain(void);void setup(float w, float h);void render();
};

Terrain.cpp

#include "terrain.hpp"Terrain::Terrain(void) {}Terrain::~Terrain(void) {}void Terrain::setup(float w, float h) {float   step = 1;float   startX = -w * 0.5f;float   startZ = -h * 0.5f;float   halfW = w * 0.5f;float   halfH = h * 0.5f;_drawSize = (w / step) * 2;//产生顶点数据for (float z = startZ; z <= halfW; z += step) {for (float x = startX; x <= halfH; x += step) {TerrainVert vert0 = { x,  0,  z };_vertex.push_back(vert0);}}//计算索引数据size_t  col = int(w / step + 0.5f) + 1;size_t  row = int(h / step + 0.5f) + 1;for (size_t r = 0; r < row - 1; ++r) {for (size_t i = 0; i < col - 1; ++i) {_index.push_back((r + 0) * col + i);_index.push_back((r + 1) * col + i);_index.push_back((r + 0) * col + i + 1);_index.push_back((r + 1) * col + i);_index.push_back((r + 0) * col + i + 1);_index.push_back((r + 1) * col + i + 1);}}
}void Terrain::render() {glEnableClientState(GL_VERTEX_ARRAY);glDisableClientState(GL_TEXTURE_COORD_ARRAY);glVertexPointer(3, GL_FLOAT, sizeof(TerrainVert), &_vertex[0].x);glDrawElements(GL_TRIANGLES, _index.size(), GL_UNSIGNED_SHORT, &_index.front());
}

main.cpp


/*
* 该实例演示 绘制地形网格。
* 地形原理:地形主要由很多三角形组成,terrain类 主要是生成很多三角形组成一个地面,然后采用索引缓存绘制
*/#define GLEW_STATIC
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>#include <GL/glew.h>
#include <GLFW/glfw3.h>#include <glm/vec3.hpp> // glm::vec3
#include <glm/vec4.hpp> // glm::vec4
#include <glm/mat4x4.hpp> // glm::mat4
#include <glm/ext/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale
#include <glm/ext/matrix_clip_space.hpp>#include "FreeImage.h"#include "Terrain.hpp"#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )  //这行是取消显示控制台char szTitle[64] = "opengl view";//glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);//创建一个点
//glm::mat4 trans = glm::mat4(1.0f);//创建单位矩阵
//Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;GLfloat ratio = 1.f;
GLfloat xpos, ypos;glm::vec3 _eye(0, 50, 50);
glm::vec3 _lookAt(0, 0, 0);
glm::vec3 _up(0, 1, 0);glm::mat4 _matProj = glm::mat4(1.0f);//创建单位矩阵
glm::mat4 _matView = glm::mat4(1.0f);//创建单位矩阵float size = 100.0f;//顶点数据
struct Vertex {float x, y, z;float u, v;
};Vertex g_cubeVertices[] =
{{ -1.0f, -1.0f, 1.0f, 0.0f, 0.0f },{ 1.0f, -1.0f, 1.0f, 1.0f, 0.0f },{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ -1.0f, 1.0f, 1.0f, 0.0f, 1.0f },{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f },{ -1.0f, 1.0f, -1.0f, 1.0f, 1.0f },{ 1.0f, 1.0f, -1.0f, 0.0f, 1.0f },{ 1.0f, -1.0f, -1.0f, 0.0f, 0.0f },{ -1.0f, 1.0f, -1.0f, 0.0f, 1.0f },{ -1.0f, 1.0f, 1.0f, 0.0f, 0.0f },{ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f },{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f },{ -1.0f, -1.0f, -1.0f, 1.0f, 1.0f },{ 1.0f, -1.0f, -1.0f, 0.0f, 1.0f },{ 1.0f, -1.0f, 1.0f, 0.0f, 0.0f },{ -1.0f, -1.0f, 1.0f, 1.0f, 0.0f },{ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f },{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },{ 1.0f, -1.0f, 1.0f, 0.0f, 0.0f },{ -1.0f, -1.0f, -1.0f, 0.0f, 0.0f },{ -1.0f, -1.0f, 1.0f, 1.0f, 0.0f },{ -1.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ -1.0f, 1.0f, -1.0f, 0.0f, 1.0f },// 地面数据{ -size, -1.0f, -size, 0.0f, 0.0f },{ -size, -1.0f, size, 100.0f, 0.0f },{ size, -1.0f, size, 100.0f, 100.0f },{ size, 0.0f, -size, 0.0f, 100.0f }
};//纹理ID
GLuint  _texture;
GLuint  _vbo;//地面纹理
GLuint  _texGround;Terrain _terrain;static void error_callback(int error, const char* description) {fputs(description, stderr);
}static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {std::cout << "key " << key << std::endl;switch(key) {case GLFW_KEY_ESCAPE:glfwSetWindowShouldClose(window, GL_TRUE);break;case GLFW_KEY_UP:_eye.z  -=  0.1f;   //这里修改摄像机参数break;case GLFW_KEY_DOWN:_eye.z  +=  0.1f;break;case GLFW_KEY_RIGHT:_eye.x  -=  1.0f;break;case GLFW_KEY_LEFT:_eye.x  +=  1.0f;break;default:break;}
}static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {if(action != GLFW_PRESS)return;switch(button) {case GLFW_MOUSE_BUTTON_LEFT:std::cout << "Mosue left button clicked!" << std::endl;break;case GLFW_MOUSE_BUTTON_MIDDLE:std::cout << "Mosue middle button clicked!" << std::endl;break;case GLFW_MOUSE_BUTTON_RIGHT:std::cout << "Mosue right button clicked!" << std::endl;break;default:return;}return;
}static void cursor_position_callback(GLFWwindow* window, double x, double y) {//std::cout << "Mouse position move to X: " << x << " Y: " << y << std::endl;xpos = float((x - WIDTH / 2) / WIDTH) * 2;ypos = float(0 - (y - HEIGHT / 2) / HEIGHT) * 2;return;
}static void scroll_callback(GLFWwindow* window, double x, double y) {return;
}static unsigned createTexture(int w, int h, const void* data, GLenum type) {unsigned    texId;glGenTextures(1, &texId);glBindTexture(GL_TEXTURE_2D, texId);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexImage2D(GL_TEXTURE_2D, 0, type, w, h, 0, type, GL_UNSIGNED_BYTE, data);return  texId;
}
/**
*   使用FreeImage加载图片
*/
static unsigned createTextureFromImage(const char* fileName) {//1 获取图片格式FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);if(fifmt == FIF_UNKNOWN) {return  0;}//2 加载图片FIBITMAP    *dib = FreeImage_Load(fifmt, fileName, 0);FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(dib);//3 获取数据指针FIBITMAP*   temp = dib;dib = FreeImage_ConvertTo32Bits(dib);FreeImage_Unload(temp);BYTE*   pixels = (BYTE*)FreeImage_GetBits(dib);int     width = FreeImage_GetWidth(dib);int     height = FreeImage_GetHeight(dib);for(int i = 0; i < width * height * 4; i += 4) {BYTE temp = pixels[i];pixels[i] = pixels[i + 2];pixels[i + 2] = temp;}unsigned    res = createTexture(width, height, pixels, GL_RGBA);FreeImage_Unload(dib);return      res;
}static void onInit() {_texture    =   createTextureFromImage("../res/1.jpg");_texGround  =   createTextureFromImage("../res/dimian.jpg");glGenBuffers(1, &_vbo);glBindBuffer(GL_ARRAY_BUFFER, _vbo);glBufferData(GL_ARRAY_BUFFER, sizeof(g_cubeVertices), g_cubeVertices, GL_STATIC_DRAW);glBindBuffer(GL_ARRAY_BUFFER, 0);_terrain.setup(100, 100);glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);  //opengl 绘制网格
}static void onDestory() {glDeleteTextures(1, &_texture);glDeleteTextures(1, &_texGround);glDeleteBuffers(1, &_vbo);   //删除VBO 显存中释放VBO内存
}// 绘制
static void render(GLFWwindow * window) {glClearColor(0, 0, 0, 1);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glEnable(GL_DEPTH_TEST);glEnable(GL_TEXTURE_2D);glMatrixMode(GL_MODELVIEW);_matView = glm::lookAt(_eye, _lookAt, _up); //使用glm数学库 根据公式计算得到视图矩阵  这公式可以推倒出来//摄像机围绕目标旋转//static float angle = 0; //旋转角度//float r = 10;           //旋转半径//_eye.x = cos(angle * glm::pi<double>() / 180) * r;//_eye.z = sin(angle * glm::pi<double>() / 180) * r;//angle += 1;  //角度每帧加一glm::mat4 matVP = _matProj * _matView;glLoadMatrixf(&matVP[0][0]);glBindTexture(GL_TEXTURE_2D, _texture);glEnableClientState(GL_VERTEX_ARRAY);glEnableClientState(GL_TEXTURE_COORD_ARRAY);//开始使用ID为 _vbo  的buffer 接下来的操作针对这个VBOglBindBuffer(GL_ARRAY_BUFFER, _vbo);float* addrVertex = (float*)0;float* uvAddress = (float*)12;glVertexPointer(3, GL_FLOAT, sizeof(Vertex), addrVertex);glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), uvAddress);// 绘制 立方体glDrawArrays(GL_QUADS, 0, 24);glBindBuffer(GL_ARRAY_BUFFER, 0);//绘制地面//glLoadIdentity(); //这里打开 地面就不会跟着旋转 说明摄像机操作的是模型矩阵_terrain.render();glfwSwapBuffers(window);glfwPollEvents();
}int main(void) {GLFWwindow * window;glfwSetErrorCallback(error_callback);if(!glfwInit())return -1;window = glfwCreateWindow(WIDTH, HEIGHT, szTitle, NULL, NULL);if(!window) {glfwTerminate();exit(EXIT_FAILURE);}glfwSetKeyCallback(window, key_callback);glfwSetMouseButtonCallback(window, mouse_button_callback);glfwSetCursorPosCallback(window, cursor_position_callback);glfwSetScrollCallback(window, scroll_callback);glfwMakeContextCurrent(window);glewExperimental = GL_TRUE;glewInit();onInit();glViewport(0, 0, WIDTH, HEIGHT); //设置opengl视口 即看到的显示区域_matProj = glm::perspective(glm::radians(60.0f), float(WIDTH) / float(HEIGHT), 0.1f, 1000.0f);//使用glm数学库 根据公式计算得到投影矩阵  这公式可以推倒出来while(!glfwWindowShouldClose(window)) {render(window);}onDestory();glfwDestroyWindow(window);glfwTerminate();return 0;
}

运行结果:

openGL学习笔记三十七:绘制简单地图相关推荐

  1. openGL学习笔记三: glu库及使用

      glu库,是对gl的部分封装,似乎对gl的辅助,操作系统自带. VS环境设置: 项目属性----链接器----附加依赖项----添加库文件GlU32.Lib 代码: #include <gl ...

  2. brisk matlab,opencv学习笔记三十七:BRISK特征点检测与匹配

    简介 BRISK算法是2011年ICCV上<BRISK:Binary Robust Invariant Scalable Keypoints>文章中,提出来的一种特征提取算法,也是一种二进 ...

  3. OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7888 ...

  4. OpenCV学习笔记(十七):查找并绘制轮廓:findContours(),drawContours(),approxPolyDP()

    OpenCV学习笔记(十七):查找并绘制轮廓:findContours() 1.findContours() 函数 该函数使用Suzuki85算法从二值图像中检索轮廓.轮廓线是一种用于形状分析.目标检 ...

  5. OpenGL学习笔记(一)绘制点线面及多面体

    OpenGL学习笔记(一)绘制点线面及多面体 绘制点线面 #include <iostream> #include <GL/GLUT.h> #define PI 3.14159 ...

  6. SurfaceFlinger学习笔记(三)之SurfaceFlinger进程

    概述 本系列是基于android Q 即android10 SurfaceFlinger学习笔记(一)应用启动流程 SurfaceFlinger学习笔记(二)之Surface SurfaceFling ...

  7. 【OpenGL学习笔记⑧】——键盘控制正方体+光源【冯氏光照模型 光照原理 环境光照+漫反射光照+镜面光照】

    ✅ 重点参考了 LearnOpenGL CN 的内容,但大部分知识内容,小编已作改写,以方便读者理解. 文章目录 零. 成果预览图 一. 光照原理与投光物的配置 1.1 光照原理 1.2 投光物 二. ...

  8. 【OpenGL学习笔记⑥】——3D变换【旋转的正方体 实现地月系统 旋转+平移+缩放】

    ✈️ 文章目录 零. 成果预览图 一.3D立方体的顶点数组 二.纹理旋转 三.纹理缩放 四.画n个3D图形 五.轨道的数学公式 六.深度缓冲(Z 缓冲) 七.完整代码 八.参考附录: 神器的正方体 ☁ ...

  9. OpenCV学习笔记(十七):图像修补:inpaint()

    OpenCV学习笔记(十七):图像修补:inpaint() inpaint()函数 使用区域邻域在图像中还原选定区域. void inpaint( InputArray src, // 表示要修复的图 ...

最新文章

  1. (已解决)ImportError attempted relative import with no known parent package
  2. ASP .NET Core Web Razor Pages系列教程四:使用数据库进行交互(SqlServer 版)
  3. 人脸识别“热”中的冷思考:道德伦理问题值得深思
  4. 深度学习笔记4:Self-Taught Learning and Unsupervised Feature Learning
  5. 获取下月第一天_获取当前月 下月 下下月 的第一天和最一天
  6. resultType 和resultMap 的区别?
  7. 运维前线:一线运维专家的运维方法、技巧与实践导读
  8. 卷积神经网络CNN基本原理和相关基本概念
  9. oracle下载,linux版本的oracle数据库下载
  10. tomcat设置编码问题
  11. 【笔记】逻辑门图解—与门、或门、非门、与非门、或非门、异或门、同或门
  12. 1168: mxh对lfx的询问(前缀和+素数表)
  13. MP3中设置播放顺序的软件《闪存式MP3伴侣》
  14. seo单页html模板,竞价单页模板设计思路
  15. 大地水准面 地球椭球体 大地基准面 地图投影理解
  16. 作为一个渗透测试学习者必知必读的好书推荐
  17. python 判断大于等于且小于等于_关于if语句:检查python中值是否大于、小于或等于零的更好方法...
  18. [C++]<numeric>头文件介绍
  19. NodeJS 之 fs 模块(文件操作)
  20. 郑航计算机专业就业率,郑州航空工业管理学院好就业吗?附学校就业率最高的专业名单...

热门文章

  1. EasyRecovery是最好用的手机数据恢复工具
  2. 学习笔记(17):零基础掌握 Python 入门到实战-重复利用,事半功倍
  3. 龙贝格方法计算椭圆周长
  4. android usb投影win10,win10如何投影到安卓平板上
  5. 无线个人区域网WPAN 802.11局域网的MAC层协议 CSMA/CA
  6. 微信公众号+获取文章内容【只是记录自己的学习过程】
  7. 洛谷三月月赛——P5238 整数校验器
  8. Android之Notification的多种用法
  9. babe的l使用步骤记录
  10. 视频画面滚动字幕怎么做,让你几分钟学会的方法