Skip to content
  • 首页
  • 留言
  • 关于

Share the joys of programming and technology

OpenGL模型加载-附源码

OpenGL模型加载-附源码

2021年1月24日 liyanliang Comments 0 Comment
阅读次数: 197

效果:

摘要:

使用ssimp并创建实际的加载和转换。目标是创建另一个类来完整地表示一个模型,或者说是包含多个网格,甚至是多个物体的模型。一个包含木制阳台、塔楼、甚至游泳池的房子可能仍会被加载为一个模型。我们会使用Assimp来加载模型,并将它转换(Translate)至多个Mesh对象。

首先需要调用的函数是loadModel,它会从构造器中直接调用。在loadModel中,我们使用Assimp来加载模型至Assimp的一个叫做scene的数据结构中。一旦我们有了这个场景对象,我们就能访问到加载后的模型中所有所需的数据了。

主要代码:

​
//#define STB_IMAGE_IMPLEMENTATION
#include "glad.c"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
​
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
​
#include <learnopengl/shader_m.h>
#include <learnopengl/camera.h>
#include <learnopengl/model.h>
​
#include <iostream>
​
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow *window);
​
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
​
// camera
Camera camera(glm::vec3(0.0f, 4.0f, 6.0f));
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
bool firstMouse = true;
​
// timing
float deltaTime = 0.0f;
float lastFrame = 0.0f;
​
int main()
{
    // glfw: initialize and configure
    // ------------------------------
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
​
#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
​
    // glfw window creation
    // --------------------
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    glfwSetCursorPosCallback(window, mouse_callback);
    glfwSetScrollCallback(window, scroll_callback);
​
    // tell GLFW to capture our mouse
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
​
    // glad: load all OpenGL function pointers
    // ---------------------------------------
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
​
    // tell stb_image.h to flip loaded texture's on the y-axis (before loading model).
    stbi_set_flip_vertically_on_load(true);
​
    // configure global opengl state
    // -----------------------------
    glEnable(GL_DEPTH_TEST);
​
    // build and compile shaders
    // -------------------------
    Shader lightingShader("5.1.light_casters.vs", "5.1.light_casters.fs");
​
    // build and compile shaders
    // -------------------------
    //Shader ourShader("1.model_loading.vs", "1.model_loading.fs");
​
    // load models
    // -----------
    Model ourModel("resources/objects/cyborg/cyborg.obj");
​
​
    // draw in wireframe
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
​
    // --------------------
    lightingShader.use();
    lightingShader.setInt("material.diffuse", 0);
    lightingShader.setInt("material.specular", 1);
​
    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        // per-frame time logic
        // --------------------
        float currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;
​
        // input
        // -----
        processInput(window);
​
        // render
        // ------
        glClearColor(0.2f, 0.5f, 0.5f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
​
        // be sure to activate shader when setting uniforms/drawing objects
        lightingShader.use();
        lightingShader.setVec3("light.direction", -0.2f, -1.0f, -0.3f);
        lightingShader.setVec3("viewPos", camera.Position);
​
        // light properties
        lightingShader.setVec3("light.ambient", 0.9f, 0.9f, 0.9f);
        lightingShader.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f);
        lightingShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
​
        // material properties
        lightingShader.setFloat("material.shininess", 32.0f);
​
        // don't forget to enable shader before setting uniforms
        //lightingShader.use();
​
        // view/projection transformations
        glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
        glm::mat4 view = camera.GetViewMatrix();
        lightingShader.setMat4("projection", projection);
        lightingShader.setMat4("view", view);
​
        // render the loaded model
        glm::mat4 model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f)); // translate it down so it's at the center of the scene
        model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f)); // it's a bit too big for our scene, so scale it down
        lightingShader.setMat4("model", model);
        ourModel.Draw(lightingShader);
​
​
        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
​
    // glfw: terminate, clearing all previously allocated GLFW resources.
    // ------------------------------------------------------------------
    glfwTerminate();
    return 0;
}
​
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
​
    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        camera.ProcessKeyboard(FORWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        camera.ProcessKeyboard(BACKWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
        camera.ProcessKeyboard(LEFT, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
        camera.ProcessKeyboard(RIGHT, deltaTime);
}
​
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // make sure the viewport matches the new window dimensions; note that width and 
    // height will be significantly larger than specified on retina displays.
    glViewport(0, 0, width, height);
}
​
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
    if (firstMouse)
    {
        lastX = xpos;
        lastY = ypos;
        firstMouse = false;
    }
​
    float xoffset = xpos - lastX;
    float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
​
    lastX = xpos;
    lastY = ypos;
​
    camera.ProcessMouseMovement(xoffset, yoffset);
}
​
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
    camera.ProcessMouseScroll(yoffset);
}
​
​

参考资料:

https://learnopengl-cn.github.io/03%20Model%20Loading/03%20Model/

完整的项目代码:

链接:https://pan.baidu.com/s/1IZbmCldx_4N4bAeeWhT2dA
提取码:vtbh

相关文章

  • LearnOpenGL脑图汇总LearnOpenGL脑图汇总
  • OpenGL 几何着色器的应用OpenGL 几何着色器的应用
  • OpenGL绘制桥梁模型OpenGL绘制桥梁模型
  • Modern OpenGL绘制圆柱体Modern OpenGL绘制圆柱体
  • OpenGL绘制旋转立方体OpenGL绘制旋转立方体
  • OpenGL实现多光源-附项目源码OpenGL实现多光源-附项目源码

OpenGL
OpenGL

Post navigation

PREVIOUS
Midas XD [错误] 右侧挡土墙的最下端深度必须小于地基的最下端深度
NEXT
RGB的CString格式转换为COLORREF

发表回复 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

近期文章

  • ANR崩溃日志查看方法
  • 通过数学方法来计算short类型的变量w的低八位x和高八位
  • 3dTiles数据解析
  • Games101和Games202脑图汇总
  • LearnOpenGL脑图汇总
  • IBL计算总结
  • C++实现一个简单的语言解释器
  • OpenGL-法线贴图(Normal Mapping)
  • OpenGL-卡通着色(Cartoon)
  • OpenGL几何着色器实现贝塞尔曲线
  • WinDbg检查内存泄漏
  • OpenGL雾化效果实现-每像素雾化
  • OpenGL实现billboard效果(CPU)
  • 算法:寻找异常数字
  • OpenGL 几何着色器的应用
  • Midas XD-构件详图开发
  • Midas XD-选筋助手开发
  • Civil Designer开发-检测规范自动生成控制截面
  • Civil Designer开发-公路桥梁承载能力检算评定
  • Midas W-满堂支架快速建模助手开发

全站热点

  • C++编写的情人节小程序 (2,077)
  • 提取最小封闭区域 (1,691)
  • Modern OpenGL绘制圆柱体 (1,603)
  • OpenGL开发环境搭建-GLFW与GLAD配置 超详细 (1,452)
  • 截面特性计算程序-附源码 (1,284)
  • OpenGL绘制旋转立方体 (1,102)
  • 判断一个点是否在闭合区域内 (1,030)
  • WordPress分页插件 – WP-PageNavi的使用(替换现有脚本) (947)
  • OpenGL实现billboard效果(CPU) (863)
  • Midas W-满堂支架快速建模助手开发 (830)
  • 从DLL中动态加载一个函数:LoadLibrary和GetProcAddress的使用 (745)
  • Midas XD [错误] 右侧挡土墙的最下端深度必须小于地基的最下端深度 (707)
  • 两跨连续梁影响线绘制-附源码 (684)
  • 土木想往土木软件开发方向发展,应该如何准备 (678)
  • OpenGL几何着色器实现贝塞尔曲线 (661)
  • 通过Spy++抓取窗口以查询对话框id (609)
  • 使用ODA数据库出现 “ODA_ASSUME”: 找不到标识符的错误 (547)
  • #pragma message 编译时提示信息 (525)
  • OpenGL雾化效果实现-每像素雾化 (504)
  • midas XD2020的开发 (472)

分类

  • C# (3)
  • C++ (19)
  • GIS (1)
  • MFC (3)
  • ObjectARX (2)
  • OpenGL (11)
  • Revit开发 (1)
  • 学习笔记 (2)
  • 岩土 (2)
  • 算法 (1)
  • 结构设计 (7)
  • 职场生涯 (1)
  • 计算几何 (3)

归档

  • 2024 年 12 月 (1)
  • 2024 年 10 月 (1)
  • 2024 年 9 月 (1)
  • 2023 年 3 月 (2)
  • 2022 年 10 月 (1)
  • 2022 年 3 月 (1)
  • 2022 年 2 月 (1)
  • 2022 年 1 月 (5)
  • 2021 年 11 月 (7)
  • 2021 年 6 月 (3)
  • 2021 年 5 月 (2)
  • 2021 年 3 月 (2)
  • 2021 年 2 月 (8)
  • 2021 年 1 月 (18)

标签

3dtiles anr Bezier Curves BillBoard C++ CDN CivilDesigner DLL EasyX fog glTF MFC Midas W Midas XD NormalMapping ObjectARX ODA OpenGL OpenXML Open XML PBR revit WinDbg 基坑设计 影响线 截面特性 桥梁 桥梁检测 桥梁设计 算法 计算几何 设计模式

书签

  • 李燕良的CSDN
  • 崔济东的博客
  • C++爱好者博客
  • 陈学伟的博客
  • 贾苏的博客
  • 陈睦锋的博客
  • 孙勇的博客

统计

  • 0
  • 316
  • 122
  • 280
  • 140
  • 266,162
  • 76,554

实时访问地域

© 2025   liyanliang.net Copyright. All Rights Reserved.