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.mfbz.cn/a/413916.html

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

相关文章

BL0942 内置时钟免校准计量芯片 用于智能家居领域 低成本

BL0939是上海贝岭股份有限公司开发的一款用于智能家居领域进行电能测量的专用芯片&#xff0c;支持两路测量&#xff0c;可同时进行计量和漏电故障检测&#xff0c;漏电检测电流可设&#xff0c;响应时间快&#xff0c;具有体积小&#xff0c;外围电路简单&#xff0c;成本低廉…

javaWeb个人学习02

会话技术 会话: 用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束.在一次会话中包含多次请求和响应 会话跟踪: 一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一个浏览器,以便在同一次会话的多次请求之间共享数据 会话跟踪方案: …

python Matplotlib Tkinter-->tab切换3

环境 python:python-3.12.0-amd64 包: matplotlib 3.8.2 pillow 10.1.0 import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk import tkinter as tk import tkinter.messagebox as messagebox import …

【leetcode】破解闯关密码 模板字符串

/*** param {number[]} password* return {string}*/ var crackPassword function(password) {return minNumspassword.sort((a,b)>{if(${a}${b}-${b}${a}>0){return 1;}else{return -1;}}).join(""); };巧用模板字符串对数组进行排序

react 路由的基本原理及实现

1. react 路由原理 不同路径渲染不同的组件 有两种实现方式 ● HasRouter 利用hash实现路由切换 ● BrowserRouter 实现h5 API实现路由切换 1. 1 HasRouter 利用hash 实现路由切换 1.2 BrowserRouter 利用h5 Api实现路由的切换 1.2.1 history HTML5规范给我们提供了一个…

HTML5 CSS3 提高

一&#xff0c;HTML5的新特性 这些新特性都有兼容性问题&#xff0c;基本是IE9以上版本的浏览器才支持&#xff0c;如果不考虑兼容性问题&#xff0c;可以大量使用这些新特性。 1.1新增语义化标签 注意&#xff1a; 1这种语义化标签主要是针对搜索引擎的 2这些新标签在页面…

第十四天-网络爬虫基础

1.什么是爬虫 1.爬虫&#xff08;又被称为网页蜘蛛&#xff0c;网络机器人&#xff09;&#xff0c;是按照一定规则&#xff0c;自动的抓取万维网中的程序或者脚本&#xff0c;是搜索引擎的重要组成&#xff1b;比如&#xff1a;百度、 2.爬虫应用&#xff1a;1.搜索引擎&…

XXE 漏洞简单研究

近期在做个基础的 web 常见漏洞的 ppt&#xff0c;主要参考 OWASP TOP 10 2017RC2&#xff0c;此版本中增加了 XXE 攻击&#xff0c;所以自己简单的研究下 XXE 攻击。XXE&#xff08;XML External Entity&#xff09;XML 外部实体&#xff0c;当前端和后端通信数据采用 xml&…

阿里云ECS服务器vCPU是什么意思?

阿里云ECS服务器vCPU和CPU是什么意思&#xff1f;CPU和vCPU有什么区别&#xff1f;一台云服务器ECS实例的CPU选项由CPU物理核心数和每核线程数决定&#xff0c;CPU是中央处理器&#xff0c;一个CPU可以包含若干个物理核&#xff0c;通过超线程HT&#xff08;Hyper-Threading&am…

矩阵的范数 matrix norm Frobenius norm 弗罗贝尼乌斯 范数

1&#xff0c;矩阵范数的定义 矩阵的范数&#xff0c;matrix norm即矩阵的模&#xff1b;它把一个矩阵空间变成为赋范线性空间&#xff1b; 从一个矩阵空间映射到非负实数的函数 满足以下条件&#xff1a; 1&#xff0c;严格的正定性。对于 , 则 ; and if , must ; 2&…

【Python】Code2flow学习笔记

1 Code2flow介绍 Code2flow是一个代码可视化工具库&#xff0c;旨在帮助开发人员更好地理解和分析代码&#xff1a; 可以将Python代码转换为流程图&#xff0c;以直观的方式展示代码的执行流程和逻辑结构。具有简单易用、高度可定制化和美观的特点&#xff0c;适用于各种代码…

团结引擎——DotNet Wasm方案

参考&#xff1a;团结引擎 DotNet WebAssembly(Wasm) 介绍 一、当前编译流程 通过IL2CPP将C#转成C/C&#xff1b;通过Emscripen将C/C转成WebAssembly&#xff1b; 二、 当前存在问题 IL2CPP在处理类似泛型、反射结构时&#xff0c;由于缺少运行时信息&#xff0c;必须全量生…

基于Springboot的计算机知识竞赛网站(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的计算机知识竞赛网站&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

11 PLL IP核

PLL IP 核简介 锁相环&#xff08;PLL&#xff09;作为一种反馈控制电路&#xff0c;其特点是利用外部输入的参考信号来控制环路内部震荡信号的频率和相位。因为锁相环可以实现输出信号频率对输入信号频率的自动跟踪&#xff0c;所以锁相环通常用于闭环跟踪电路。锁相环在工作…

六、防御保护---防火墙内容安全篇

六、防御保护---防火墙内容安全篇 一、IAE&#xff08;Intelligent Awareness Engine&#xff09;引擎二、深度检测技术(DFI和DPI&#xff09;2.1 DPI -- 深度包检测技术2.1.1 基于“特征字”的检测技术2.1.2 基于应用网关的检测技术2.1.3 基于行为模式的检测技术 2.2 DFI -- 深…

MySQL的事务与隔离级别

1. 什么是事务&#xff1f; 数据库中的事务是指对数据库执行一批操作&#xff0c;而这些操作最终要么全部执行成功&#xff0c;要么全部失败&#xff0c;不会存在部分成功的情况。这个时候就需要用到事务。 最经典的例子就是转账&#xff0c;你要给朋友小白转 1000 块钱&…

【Java 基础】Java 数组、方法极致精讲

《Java 零基础入门到精通》专栏持续更新中。通过本专栏你将学习到 Java 从入门到进阶再到实战的全套完整内容,所有内容均将集中于此专栏。无论是初学者还是有经验的开发人员,都可从本专栏获益。 订阅专栏后添加我微信或者进交流群,进群可找我领取 前端/Java/大数据/Python/低…

华为手动ipv6-to-ipv4隧道

中间r2的两个接口配置两个地址就行了&#xff0c;其它什么都不用配置 两边出接口R1和R3手动隧道建立&#xff1a;先把IPV4打通&#xff0c;并配置默认路由 再起隧道接口上进行配置&#xff0c;再配置带隧道的默认路由 PC上和上联接口网关只有IPV6地址 最终两个PC可以ping通 …

vue3的echarts从后端获取数据,用于绘制图表

场景需求&#xff1a;后端采用flask通过pymysql从数据库获取数据&#xff0c;并返回给前端。前端vue3利用axios获取数据并运用到echarts绘制图表。 第一步&#xff0c;vue中引入echarts 首先vue下载echarts npm install echarts 然后在main.js文件写如下代码 import {create…

Python入门到精通(九)——Python数据可视化

Python数据可视化 一、JSON数据格式 1、定义 2、python数据和JSON数据转换 二、pyecharts 三、折线图 四、地图 五、动态柱状图 一、JSON数据格式 1、定义 JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据JSON本质上是一个带有特定格式的字符…