OpenGL OBJ 文件读取示例

以下是一个完整的示例,展示如何使用 OpenGL 和 tinyobjloader 库来读取并渲染 OBJ 文件。

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(OpenGL_OBJ_Example)

find_package(OpenGL REQUIRED)
find_package(glfw3 3.3 REQUIRED)

add_subdirectory(tinyobjloader)

add_executable(OpenGL_OBJ_Example main.cpp)
target_link_libraries(OpenGL_OBJ_Example PRIVATE OpenGL::GL glfw tinyobjloader::tinyobjloader)

main.cpp

#include <iostream>
#include <vector>
#include <tiny_obj_loader.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

// 顶点结构体
struct Vertex {
    float position[3];
    float normal[3];
    float texcoord[2];
};

std::vector<Vertex> vertices;
std::vector<unsigned int> indices;

// 加载OBJ文件
bool loadOBJ(const std::string& filepath) {
    tinyobj::attrib_t attrib;
    std::vector<tinyobj::shape_t> shapes;
    std::vector<tinyobj::material_t> materials;
    std::string warn, err;

    // 使用tinyobjloader库加载OBJ文件
    bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filepath.c_str());

    if (!warn.empty()) {
        std::cout << "警告: " << warn << std::endl;
    }

    if (!err.empty()) {
        std::cerr << "错误: " << err << std::endl;
    }

    if (!ret) {
        return false;
    }

    // 解析形状中的顶点数据
    for (const auto& shape : shapes) {
        for (const auto& index : shape.mesh.indices) {
            Vertex vertex = {};

            vertex.position[0] = attrib.vertices[3 * index.vertex_index + 0];
            vertex.position[1] = attrib.vertices[3 * index.vertex_index + 1];
            vertex.position[2] = attrib.vertices[3 * index.vertex_index + 2];

            if (!attrib.normals.empty()) {
                vertex.normal[0] = attrib.normals[3 * index.normal_index + 0];
                vertex.normal[1] = attrib.normals[3 * index.normal_index + 1];
                vertex.normal[2] = attrib.normals[3 * index.normal_index + 2];
            }

            if (!attrib.texcoords.empty()) {
                vertex.texcoord[0] = attrib.texcoords[2 * index.texcoord_index + 0];
                vertex.texcoord[1] = attrib.texcoords[2 * index.texcoord_index + 1];
            }

            vertices.push_back(vertex);
            indices.push_back(indices.size());
        }
    }

    return true;
}

// 渲染函数
void render() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 绑定并绘制模型
    // 使用glDrawElements或glDrawArrays函数绘制加载的顶点和索引

    glfwSwapBuffers(glfwGetCurrentContext());
}

int main() {
    // 初始化GLFW
    if (!glfwInit()) {
        std::cerr << "初始化GLFW失败" << std::endl;
        return -1;
    }

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL OBJ Loader", NULL, NULL);
    if (!window) {
        std::cerr << "创建GLFW窗口失败" << std::endl;
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);

    // 初始化GLEW
    if (glewInit() != GLEW_OK) {
        std::cerr << "初始化GLEW失败" << std::endl;
        return -1;
    }

    glEnable(GL_DEPTH_TEST);

    // 加载OBJ文件
    if (!loadOBJ("path/to/your/model.obj")) {
        std::cerr << "加载OBJ文件失败" << std::endl;
        return -1;
    }

    // 渲染循环
    while (!glfwWindowShouldClose(window)) {
        render();
        glfwPollEvents();
    }

    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;
}

解释

  1. CMakeLists.txt:配置CMake项目,添加OpenGL和GLFW依赖,并包含 tinyobjloader 库。
  2. main.cpp
    • 顶点结构体:定义顶点结构体,包含位置、法线和纹理坐标。
    • loadOBJ函数:使用 tinyobjloader 库加载OBJ文件,将顶点数据解析到 verticesindices 向量中。
    • render函数:清除缓冲区,并使用OpenGL函数绘制模型。
    • main函数:初始化GLFW和GLEW,创建窗口,加载OBJ文件,并进入渲染循环。

这个示例展示了如何使用 tinyobjloader 库来加载一个OBJ文件并在OpenGL中进行渲染。通过GLFW库创建窗口和处理输入,并使用GLEW库加载OpenGL函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/713707.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

windows系统,家庭自用NAS。本地局域网 Docker安装nextcloud

windows系统&#xff0c;家庭自用NAS。本地局域网 Docker安装nextcloud 1、docker安装 太简单了&#xff0c;直接去搜一搜。 docker-compose 相关命令 docker-compose down docker compose up -d2、还是使用老的 在你需要挂载的目录下&#xff0c;新建一个文件&#xff0c;…

航顺MCU概览

前言: 截止2023年底,全国有3451家芯片设计公司,已经IPO的就有168家,尚未IPO的3283家中超过一半的年营收在1000万以下,迅猛发展的几年的确有些国产芯片开始站上赛道,这也是国际大背景下的一种必然选择,毕竟突然间出现的大市场需要国产顶上,但资本市场是周期性的,国产替…

港科夜闻 | 香港科大与香港科大(广州)合推红鸟跨校园学习计划,共享教学资源,促进港穗学生交流学习...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大与香港科大(广州)合推“红鸟跨校园学习计划”&#xff0c;共享教学资源&#xff0c;促进港穗学生交流学习。香港科大与香港科大(广州)6月14日共同宣布推出“红鸟跨校园学习计划”&#xff0c;以进一步加强两校学…

transformer和Non-local

两者本质上是一个东西&#xff0c;都是用来求自注意力的&#xff0c;但具体而言还是有一些差别&#xff1b; 1&#xff1a;首先说Non-local&#xff0c;它是像素级别的self-attention,算的是图片中各个像素点对指定像素点的影响&#xff1b; 2&#xff1a;transformer我们拿s…

算法人生(22):从“生成对抗网络”看“逆商提升”

​ 在图像生成与编辑、音频合成、视频生成领域里&#xff0c;有一个非常重要的深度学习方法——生成对抗网络&#xff08;简称GANs&#xff09;&#xff0c;它是由两个神经网络组成的模型&#xff0c;分别为生成器&#xff08;Generator&#xff09;和判别器&#xff08;Discr…

移动硬盘数据恢复方法哪个好?六个硬盘恢复,新手也能用!

移动硬盘数据恢复方法哪个好&#xff1f;移动硬盘&#xff0c;作为我们存储重要数据的常用设备&#xff0c;一旦里面的视频、文档、音频等资料突然消失&#xff0c;确实会令人烦恼和担忧。然而&#xff0c;因为数据丢失的原因可能多种多样&#xff0c;因此恢复方法也会有所不同…

【嵌入式DIY实例】-Nokia 5110显示DS3231 RTC数据

Nokia 5110显示DS3231 RTC数据 文章目录 Nokia 5110显示DS3231 RTC数据1、硬件准备与接线2、代码实现本文将介绍如何使用 ESP8266 NodeMCU 板和 DS3231 RTC 模块制作一个简单的数字实时时钟,其中可以使用连接到 NodeMCU 的两个按钮设置时间和日期,并将它们打印在诺基亚 5110 …

Ubuntu server 24 (Linux) 新增磁盘 lvm 动态扩容磁盘空间

1 新增一块硬盘 #查看 sudo fdisk -l #重新分区&#xff0c;转换成lvm类型 sudo fdisk /dev/sdb 2 查看磁盘 df -h3 lvm 配置 #查看lvm逻辑卷 sudo lvdisplay #创建物理卷 sudo pvcreate /dev/sdb1 #扩展卷组 sudo vgextend ubuntu-vg /dev/sdb1 #扩展逻辑卷 sudo lvexte…

【Linux】pycharmgit相关操作

目录 1. git安装配置2. 相关内容3. pycharm连接远程仓库3.1 配置3.2 clone远程仓库3.3 本地仓库上传远程 4. 分支管理4.1 更新代码4.2 新建分支4.3 分支合并4.4 代码比对 5. 版本管理6. 命令行操作6.1 配置git6.2 基础操作6.3 分支操作 1. git安装配置 下载链接&#xff1a;官…

从数据库到数据仓库:数据仓库导论

导言 本文为数据仓库导论&#xff0c;旨在介绍数据仓库的基本理念和应用场景&#xff0c;帮助读者理解数据仓库的重要性及其在企业中的实际应用。 数据仓库作为重要的数据管理和分析工具&#xff0c;已经发展了30多年&#xff0c;其过程中生态和技术都发生了巨大的变化。尽管…

1832javaERP管理系统之能力物料管理Myeclipse开发mysql数据库servlet结构java编程计算机网页项目

一、源码特点 java erp管理系统之能力物料管理是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助采用了serlvet设计&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统采用web模式&#xff0c;系统主要采用 B/S模式开发。开发环境为TOMCAT7.0,My…

深入理解指针(四)

目录 1. 回调函数是什么? ​2. qsort使用举例 2.1冒泡排序 2.2使用qsort函数排序整型数据 ​2.3 使用qsort排序结构数据(名字) 2.4 使用qsort排序结构数据(年龄) 3. qsort函数的模拟实现 1. 回调函数是什么? 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数…

CSS概述

CSS是一种样式表语言&#xff0c;用于为HTML文档控制外观&#xff0c;定义布局。例如&#xff0c; CSS涉及字体、颜色、边距、高度、宽度、背景图像、高级定位等方面 。 ● 可将页面的内容与表现形式分离&#xff0c;页面内容存放在HTML文档中&#xff0c;而用 于定义表现形式…

第五十七周:文献阅读

目录 摘要 Abstract 文献阅读&#xff1a;基于遗传算法的PM2.5时间序列预测深度学习模型超参数优化 一、现有问题 二、提出方法 三、方法论 1、HPO&#xff08;猎人猎物算法&#xff09; 2、深度学习算法 递归神经网络&#xff08;RNN&#xff09; LSTM GRU 3、GA…

20240613日志:COPAL

Location: Beijing 1 大模型剪枝 Fig. 1.1大模型压缩-剪枝 剪枝的分类&#xff1a;结构化修剪对于简化大型语言模型和提高其效率尤其相关。非结构化修剪关注的是选择性地去除单个权重&#xff0c;旨在消除网络中不那么关键的连接。 修剪的基于阶段的分类&#xff1a;修剪可以在…

解决Pycharm远程连接WSL2的python解释器,使用调试模式时显示超时的问题

环境 windows 11wsl2ubuntu20.04pycharm2023.3.3 问题 Pycharm远程连接WSL2的python解释器&#xff0c;使用调试模式时显示超时 分析 TCP连接错误。 解决方法 windows高级防火墙设置->入站规则->找到pycharm2023.3.3的TCP连接规则->双击允许连接 步骤截图见下…

【C语言】解决C语言报错:Use of Uninitialized Variable

文章目录 简介什么是Use of Uninitialized VariableUse of Uninitialized Variable的常见原因如何检测和调试Use of Uninitialized Variable解决Use of Uninitialized Variable的最佳实践详细实例解析示例1&#xff1a;局部变量未初始化示例2&#xff1a;数组未初始化示例3&…

Explain Python Machine Learning Models with SHAP Library

Explain Python Machine Learning Models with SHAP Library – Minimatech &#xff08;能翻墙直接看原文&#xff09; Explain Python Machine Learning Models with SHAP Library 11 September 2021Muhammad FawiMachine Learning Using SHapley Additive exPlainations …

Linux--MQTT(二)通信基本原理

一、MQTT 通信基本原理 MQTT 是一种基于 客户端 - 服务端 架构的消息传输协议&#xff0c;所以在 MQTT 协议通信中&#xff0c;有两个最为重要的角色&#xff0c;它们便是服务端 和 客户端 。 举例&#xff1a;若开发板向“芯片温度”这一主题发布消息&#xff0c;那么服务…

父亲节:我要做爸爸的健康监督员

父亲节将至&#xff0c;总想着能为爸爸做些什么&#xff0c;来表达我们的感激与关爱。在这个特殊的日子里&#xff0c;成为爸爸的健康监督员&#xff0c;用华为 Watch 4 的智慧健康功能&#xff0c;任何时刻都可以关注爸爸的健康状况&#xff0c;放心又安心了。 用一键微体检…