wayland(xdg_wm_base) + egl + opengles 使用 Assimp 加载3D model 最简实例(十三)

文章目录

  • 前言
  • 一、3D model 文件介绍
    • 1. 3d model 介绍
      • 1.1 如何获取3d model 文件
      • 1.2 3d model 的文件格式
      • 1.3 obj模型数据格式
    • 2. 3d 立方体 model 实例——cube.obj
  • 二、Assimp 介绍
    • 1. Assimp 简介
    • 2.ubuntu 上安装libassimp
    • 3. 使用Assimp 解析 cube.obj 文件
      • 3.1 assimp_load_cube.cpp 文件内容如下
      • 3.2 编译
      • 3.3 运行
  • 三、opengles 使用 Assimp 加载 3D 立方体 model 实例
    • 1. egl_wayland_assimp_cube.c
    • 2. xdg-shell-client-protocol.h 和 xdg-shell-protocol.c
    • 3. 编译
    • 4. 运行
  • 总结
  • 参考资料


前言

`本文主要介绍opengles 如何使用 第三方库Assimp(基于C++) 加载一个最简当的3d 立方体model
软硬件环境:
硬件:PC
软件:ubuntu22.04 egl1.4 weston9.0 opengles3.0 libassimp.so.5.2.0


一、3D model 文件介绍

1. 3d model 介绍

1.1 如何获取3d model 文件

模型通常都是通过Blender、3DS Max或者Maya这样的3D建模工具(3D Modeling Tool)精心制作出来的

1.2 3d model 的文件格式

模型的文件格式有很多种,每一种都会以它们自己的方式来导出模型数据。像是Wavefront的.obj这样的模型格式,只包含了模型数据以及材质信息,像是模型颜色和漫反射/镜面光贴图。而以XML为基础的Collada文件格式则非常的丰富,包含模型、光照、多种材质、动画数据、摄像机、完整的场景信息等等。Wavefront的.obj格式通常被认为是一个易于解析的模型格式

1.3 obj模型数据格式

  • 以#开始的行为注释行
  • usemtl 和 mtllib表示的材质相关数据
  • o 引入一个新的object
  • v 表示顶点坐标
  • vt 表示顶点纹理坐标
  • vn 表示顶点法线
  • f 表示一个面,面使用1/2/8这样格式,表示顶点坐标/纹理坐标/法线的索引,这里索引的是前面用v,vt,vn定义的数据

2. 3d 立方体 model 实例——cube.obj

最简单的3d 立方体model 文件 cube.obj 内容如下
cube.obj

# Number of vertices: 8
v -0.5 0.5 0.5
v -0.5 -0.5 0.5
v 0.5 -0.5 0.5
v 0.5 0.5 0.5
v 0.5 0.5 -0.5
v 0.5 -0.5 -0.5
v -0.5 -0.5 -0.5
v -0.5 0.5 -0.5# Number of Polygons: 12
f 1 2 3
f 1 3 4
f 4 3 6
f 4 6 5
f 5 6 7
f 5 7 8
f 8 7 2
f 8 2 1
f 2 7 6
f 2 6 3
f 8 1 4
f 8 4 5

在PC 上使用3D 查看器打开cube.obj 文件,如下图所示
在这里插入图片描述

二、Assimp 介绍

1. Assimp 简介

一个非常流行的模型导入库是Assimp,它是Open Asset Import Library(开放的资产导入库)的缩写。Assimp能够导入很多种不同的模型文件格式(并也能够导出部分的格式),它会将所有的模型数据加载至Assimp的通用数据结构中。当Assimp加载完模型之后,我们就能够从Assimp的数据结构中提取我们所需的所有数据了。由于Assimp的数据结构保持不变,不论导入的是什么种类的文件格式,它都能够将我们从这些不同的文件格式中抽象出来,用同一种方式访问我们需要的数据。
当使用Assimp导入一个模型的时候,它通常会将整个模型加载进一个场景(Scene)对象,它会包含导入的模型/场景中的所有数据。Assimp会将场景载入为一系列的节点(Node),每个节点包含了场景对象中所储存数据的索引,每个节点都可以有任意数量的子节点。Assimp数据结构的(简化)模型如下:
在这里插入图片描述

  • 一个Mesh对象本身包含了渲染所需要的所有相关数据,像是顶点位置、法向量、纹理坐标、面(Face)和物体的材质;
  • 一个网格包含了多个面。Face代表的是物体的渲染图元(Primitive)(三角形、方形、点)。一个面包含了组成图元的顶点的索引。由于顶点和索引是分开的,使用一个索引缓冲来渲染是非常简单的;
  • 一个网格也包含了一个Material对象,它包含了一些函数能让我们获取物体的材质属性,比如说颜色和纹理贴图(比如漫反射和镜面光贴图);
  • 当使用建模工具对物体建模的时候,艺术家通常不会用单个形状创建出整个模型。通常每个模型都由几个子模型/形状组合而成。组合模型的每个单独的形状就叫做一个网格(Mesh)。比如说有一个人形的角色:艺术家通常会将头部、四肢、衣服、武器建模为分开的组件,并将这些网格组合而成的结果表现为最终的模型。一个网格是我们在OpenGL中绘制物体所需的最小单位(顶点数据、索引和材质属性)。一个模型(通常)会包括多个网格;

所以,我们需要做的第一件事是将一个物体加载到Scene对象中,遍历节点,获取对应的Mesh对象(我们需要递归搜索每个节点的子节点),并处理每个Mesh对象来获取顶点数据、索引以及它的材质属性。最终的结果是一系列的网格数据,我们会将它们包含在一个Model对象中

2.ubuntu 上安装libassimp

使用如下命令可以在ubuntu 上安装 libassimp
sudo apt install libassimp-dev
安装完成后,在/usr/lib/x86_64-linux-gnu/目录下就能看到libassimp相关的库文件,如下图所示
在这里插入图片描述

3. 使用Assimp 解析 cube.obj 文件

3.1 assimp_load_cube.cpp 文件内容如下

#include <iostream>
#include <stdio.h>
#include <GLES3/gl3.h>// 使用 Assimp 加载模型文件
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>int main()
{Assimp::Importer importer;const aiScene* scene = importer.ReadFile("./cube.obj", aiProcess_Triangulate | aiProcess_FlipUVs);if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {// 加载模型失败printf("cube.obj load failed\n");return -1;}aiMesh* mesh = scene->mMeshes[0];printf("mesh->mNumVertices = %d\n", mesh->mNumVertices);printf("mesh->mNumFaces = %d\n", mesh->mNumFaces);// 获取顶点坐标数据printf("cube vVertices : \n");GLfloat* vVertices = new GLfloat[mesh->mNumVertices * 3];for (unsigned int i = 0; i < mesh->mNumVertices; i++) {vVertices[i * 3] = mesh->mVertices[i].x;vVertices[i * 3 + 1] = mesh->mVertices[i].y;vVertices[i * 3 + 2] = mesh->mVertices[i].z;printf("%.1f, %.1f, %.1f,\n", vVertices[i * 3], vVertices[i * 3 + 1], vVertices[i * 3 + 2]);}// 获取面索引数据printf("cube indices : \n");GLushort* indices = new GLushort[mesh->mNumFaces * 3];for (unsigned int i = 0; i < mesh->mNumFaces; i++) {for (unsigned int j = 0; j < 3; j++) {indices[i * 3 + j] = mesh->mFaces[i].mIndices[j];}printf("%d, %d, %d,\n", indices[i * 3], indices[i * 3 + 1], indices[i * 3 + 2]);}return 0;
}

3.2 编译

使用如下命令对 assimp_load_cube.cpp 文件进行编译
g++ assimp_load_cube.cpp -o assimp_load_cube -lassimp
编译成功会在当前目录下得到可执行文件 assimp_load_cube

3.3 运行

将cube.obj 和 可执行文件 assimp_load_cube 放到同一个目录下,执行 ./assimp_load_cube 命令,打印解析出来的顶点坐标和顶点索引信息如下:

lkh@ubuntu:~/lkh2024/opengles_test$ ./assimp_load_cube 
mesh->mNumVertices = 36
mesh->mNumFaces = 12
cube vVertices : 
-0.5, 0.5, 0.5,
-0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
-0.5, 0.5, 0.5,
0.5, -0.5, 0.5,
0.5, 0.5, 0.5,
0.5, 0.5, 0.5,
0.5, -0.5, 0.5,
0.5, -0.5, -0.5,
0.5, 0.5, 0.5,
0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
0.5, 0.5, -0.5,
0.5, -0.5, -0.5,
-0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
-0.5, -0.5, -0.5,
-0.5, 0.5, -0.5,
-0.5, 0.5

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【机器人最短路径规划问题(栅格地图)】基于遗传算法求解

基于遗传算法求解机器人最短路径规划问题&#xff08;栅格地图&#xff09;的仿真结果 仿真结果&#xff1a; 路径长度的变化曲线&#xff1a; 遗传算法优化后的机器人避障路径&#xff1a;

华为ipv6 over ipv4 GRE隧道配置

思路&#xff1a; PC1访问PC2时&#xff0c;会先构造源ipv6为2001:1::2&#xff0c;目的IPV6为2001:2::2的ipv6报文&#xff0c;然后查看PC1的路由表&#xff0c;发送到R1&#xff0c;r1接收后&#xff0c;以目的IPV6地址2001:2::2查询IPV6路由表&#xff0c;出接口为tun0/0/0…

SpringMVC 学习(十)之异常处理

目录 1 异常处理介绍 2 通过 SimpleMappingExceptionResolver 实现 3 通过接口 HandlerExceptionResolver 实现 4 通过 ExceptionHandler 注解实现&#xff08;推荐&#xff09; 1 异常处理介绍 在 SpringMVC中&#xff0c;异常处理器&#xff08;Exceptio…

CGI程序与ShellShock漏洞

CGI是什么&#xff1f; CGI&#xff08;通用网关接口&#xff0c;Common Gateway Interface&#xff09;程序是一种用于在Web服务器上执行动态内容的技术。与服务器上普通的后端代码相比&#xff0c;CGI程序有几个区别&#xff1a; 执行环境&#xff1a; CGI程序在服务器上作为…

处理异常(Exception)

1、什么是异常 在实际工作中&#xff0c;我们遇到的情况不可能是非常完美的。比如&#xff1a;你写的某个模块&#xff0c;用户输入不一定符合你的要求&#xff1b;你的程序要打开某个文件&#xff0c;这个文件可能不存在或者文件格式不对&#xff1b;你要读取数据库的数据&am…

2024牛客寒假算法基础集训营1(补题)

文章目录 ABCDEFGHIJKL A n的范围很小暴力直接 O ( n 3 ) O(n^3) O(n3)直接做就行。 我还傻的统计了一下前后缀&#xff0c;不过怎么写都行这道题。 #include <bits/stdc.h> #define int long long #define rep(i,a,b) for(int i (a); i < (b); i) #define fep(i,…

【appium】App类型、页面元素|UiAutomator与appium|App元素定位

目录 一、App前端基础知识 1、App类型划分 2、App类型对比 3、App页面元素 App页面元素分为布局和控件两种 常见布局&#xff1a; 常见控件&#xff1a;定位软件&#xff1a;appium和sdk自带的uiautomatorviewer都可以定位 二、App元素定位 1、id定位 2、text定位 3…

【Java EE初阶二十六】简单的表白墙(二)

2. 后端服务器部分 2.1 服务器分析 2.2 代码编写 2.2.2 前端发起一个ajax请求 2.2.3 服务器读取上述请求,并计算出响应 服务器需要使用 jackson 读取到前端这里的数据,并且进行解析&#xff1a; 代码运行图&#xff1a; 2.2.4 回到前端代码&#xff0c;处理服务器返回的响应…

from tensorflow.keras.layers import Dense,Flatten,Input报错无法引用

from tensorflow.keras.layers import Dense,Flatten,Input 打印一下路径&#xff1a; import tensorflow as tf import keras print(tf.__path__) print(keras.__path__) [E:\\开发工具\\pythonProject\\studyLL\\venv\\lib\\site-packages\\keras\\api\\_v2, E:\\开发工具\\…

Python 实现 ROC指标计算(变动率指标):股票技术分析的利器系列(15)

Python 实现 ROC指标计算(变动率指标&#xff09;&#xff1a;股票技术分析的利器系列&#xff08;15&#xff09; 介绍算法公式 代码rolling函数介绍核心代码计算OSC 完整代码 介绍 ROC&#xff08;变动率指标&#xff09;是一种技术分析指标&#xff0c;用于衡量价格变动的速…

windows系统使用Vscode在WSL调试golang本地进程

背景&#xff1a; windows10企业版 vscodegolang1.20 wsl编译运行。 vscode 使用本地wsl进行进程attach操作&#xff0c;发现&#xff1a;Access is denied. 本地进程启动&#xff0c;vscode调试进程。windows-Linux控制台: Starting: C:\Users\book\go\bin\dlv.exe dap --l…

Ubuntu Mysql Innodb cluster集群搭建+MaxScale负载均衡(读写分离)

Ubuntu系统版本 20.04.3 LTS (Focal Fossa) 、64位系统。 cat /etc/os-release查看Ubuntu系统是32位还是64位 uname -m如果显示“i686”,则表示安装了32位操作系统。如果显示“x86_64”,则表示安装了64位操作系统。 一、安装MySql 参考: https://blog.csdn.net/qq_3712…

什么是去中心化云计算?

去中心化云计算是一种新型的云计算方式&#xff0c;它与传统的中心化云计算不同&#xff0c;将数据和计算任务分布到多个节点上&#xff0c;而不是将数据集中存储在中心服务器上。这种云计算方式具有许多优势&#xff0c;包括提高数据安全性、降低运营成本、增强可扩展性和灵活…

MCU最小系统电路设计(以STM32F103C8T6为例)

目录 一、何为最小系统&#xff1f; 二、最小系统电路设计 1.电源 &#xff08;1&#xff09;各种名词解释 &#xff08;2&#xff09;为什么会有VDD_1 _2 _3区分&#xff1f; &#xff08;3&#xff09;Mirco USB &#xff08;4&#xff09;5v->3.3v滤波电路 &#…

Unity(第九部)物体类

拿到物体的某些数据 using System.Collections; using System.Collections.Generic; using UnityEngine;public class game : MonoBehaviour {// Start is called before the first frame updatevoid Start(){//拿到当前脚本所挂载的游戏物体//GameObject go this.gameObject;…

naive-ui-admin 表格去掉工具栏toolbar

使用naive-ui-admin的时候&#xff0c;有时候不需要显示工具栏&#xff0c;工具栏太占地方了。 1.在src/components/Table/src/props.ts 里面添加属性 showToolbar 默认显示&#xff0c;在不需要的地方传false。也可以默认不显示 &#xff0c;这个根据需求来。 2.在src/compo…

历史新知网:寄快递寄个电脑显示器要多少钱?

以下文字信息由&#xff08;新史知识网&#xff09;编辑整理发布。 让我们赶紧来看看吧&#xff01; 问题1&#xff1a;快递寄电脑显示器要多少钱&#xff1f; 此物有多重&#xff1f; 顺丰寄就可以了&#xff0c;但是必须是原包装的&#xff0c;不然不好寄。 问题2&#xff1…

vue项目从后端下载文件显示进度条或者loading

//API接口 export const exportDownload (params?: Object, peCallback?: Function) > {return new Promise((resolve, reject) > {axios({method: get,url: ,headers: {access_token: ${getToken()},},responseType: blob,params,onDownloadProgress: (pe) > {peC…

React Switch用法及手写Switch实现

问&#xff1a;如果注册的路由特别多&#xff0c;找到一个匹配项以后还会一直往下找&#xff0c;我们想让react找到一个匹配项以后不再继续了&#xff0c;怎么处理&#xff1f;答&#xff1a;<Switch>独特之处在于它只绘制子元素中第一个匹配的路由元素。 如果没有<Sw…

GCN,R-GCN,岭回归,SVR,随机森林,Adaboost

图卷积神经网络(graph convolutional network, GCN),它将卷积神经网络拓展到图结构形式 中&#xff0c;GCN因可以很好地融合图结构数据的结构特征和属性特征并且有较好的组合泛化能力而被广泛使用。 关系图卷积神经网络(relational-graph convolutional network, R-GCN)&#…