openGL学习笔记三十七:绘制简单地图
生活随笔
收集整理的這篇文章主要介紹了
openGL学习笔记三十七:绘制简单地图
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
??地形本質(zhì)上由一個(gè)個(gè)頂點(diǎn)(x,y,z)組成多個(gè)三角面連接而成。
地形有兩種來源:
??1.美術(shù)使用3dmax、maya、bleader工具,畫點(diǎn)、線、面,導(dǎo)出三維模型,然后在游戲中加載進(jìn)來,進(jìn)行繪制。
??2.軟件自身使用數(shù)據(jù)生成,如通過一張高度圖生成。
涉及函數(shù)
opengl 繪制網(wǎng)格
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);代碼:
下面Terrain 類就是生成一個(gè)簡單的平面地形網(wǎng)格。
Terrain.hpp
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;//產(chǎn)生頂點(diǎn)數(shù)據(jù)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);}}//計(jì)算索引數(shù)據(jù)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
/* * 該實(shí)例演示 繪制地形網(wǎng)格。 * 地形原理:地形主要由很多三角形組成,terrain類 主要是生成很多三角形組成一個(gè)地面,然后采用索引緩存繪制 */#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\"" ) //這行是取消顯示控制臺(tái)char szTitle[64] = "opengl view";//glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);//創(chuàng)建一個(gè)點(diǎn) //glm::mat4 trans = glm::mat4(1.0f);//創(chuàng)建單位矩陣 //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);//創(chuàng)建單位矩陣 glm::mat4 _matView = glm::mat4(1.0f);//創(chuàng)建單位矩陣float size = 100.0f;//頂點(diǎn)數(shù)據(jù) 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 },// 地面數(shù)據(jù){ -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; //這里修改攝像機(jī)參數(shù)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 獲取數(shù)據(jù)指針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 繪制網(wǎng)格 }static void onDestory() {glDeleteTextures(1, &_texture);glDeleteTextures(1, &_texGround);glDeleteBuffers(1, &_vbo); //刪除VBO 顯存中釋放VBO內(nèi)存 }// 繪制 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數(shù)學(xué)庫 根據(jù)公式計(jì)算得到視圖矩陣 這公式可以推倒出來//攝像機(jī)圍繞目標(biāo)旋轉(zhuǎn)//static float angle = 0; //旋轉(zhuǎn)角度//float r = 10; //旋轉(zhuǎn)半徑//_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 接下來的操作針對這個(gè)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(); //這里打開 地面就不會(huì)跟著旋轉(zhuǎn) 說明攝像機(jī)操作的是模型矩陣_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); //設(shè)置opengl視口 即看到的顯示區(qū)域_matProj = glm::perspective(glm::radians(60.0f), float(WIDTH) / float(HEIGHT), 0.1f, 1000.0f);//使用glm數(shù)學(xué)庫 根據(jù)公式計(jì)算得到投影矩陣 這公式可以推倒出來while(!glfwWindowShouldClose(window)) {render(window);}onDestory();glfwDestroyWindow(window);glfwTerminate();return 0; }運(yùn)行結(jié)果:
總結(jié)
以上是生活随笔為你收集整理的openGL学习笔记三十七:绘制简单地图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java将汉字转化为拼音
- 下一篇: 网易mc显示服务器异常,明日之后:一天之