文章目录
- 前言
- 一、3d 立方体 model 属性相关文件
-
- 1. cube.obj
- 2. cube.Mtl
- 3. 纹理图片 cordeBouee4.jpg
- 二、代码实例
-
- 1. 依赖库和头文件
-
- 1.1 assimp
- 1.2 stb_image.h
- 2. egl_wayland_obj_cube.cpp
- 3. Matrix.h 和 Matrix.cpp
- 4. xdg-shell-client-protocol.h 和 xdg-shell-protocol.c
- 5. 编译
- 6. 运行
- 总结
- 参考资料
前言
本文主要介绍opengles 如何使用 第三方库Assimp(基于C++) 加载一个最简单的带纹理 的3d 立方体model,3d 立方体 model 信息存储在 cube.obj 中,纹理图片信息存储在cube.Mtl 材质文件中,主要是介绍如何使用Assimp 解析Mtl 文件。
软硬件环境:
硬件:PC
软件:ubuntu22.04 egl1.4 weston9.0 opengles3.0 libassimp.so.5.2.0
一、3d 立方体 model 属性相关文件
.obj文件是一种常见的三维模型文件格式,它包含了描述三维模型的顶点、法线、纹理坐标和面信息等,通常,.obj文件会搭配使用.mtl文件(材质文件)来定义模型的材质属性。
1. cube.obj
本文的例子由于没有使用光照相关的属性,因此,cube.obj 中可以没有法线相关的信息
cube.obj 内容如下:
# 3D Cube with texture coordinates
mtllib cube.Mtl
usemtl cubeMaterial
# 顶点坐标
v -1.0 -1.0 1.0
v -1.0 1.0 1.0
v 1.0 1.0 1.0
v 1.0 -1.0 1.0
v -1.0 -1.0 -1.0
v -1.0 1.0 -1.0
v 1.0 1.0 -1.0
v 1.0 -1.0 -1.0
# 纹理坐标
vt 0.0 0.0
vt 0.0 1.0
vt 1.0 1.0
vt 1.0 0.0
# 面
f 1/1 2/2 3/3
f 1/1 3/3 4/4
f 4/1 3/2 7/3
f 4/1 7/3 8/4
f 8/2 7/1 6/4
f 8/2 6/4 5/3
f 5/3 6/4 2/1
f 5/3 2/1 1/2
f 2/2 6/3 7/4
f 2/2 7/4 3/1
f 5/4 1/1 4/2
f 5/4 4/2 8/3
2. cube.Mtl
本文的例子由于没有使用光照相关的属性,因此,cube.Mtl 中可以没有材质光照相关的信息
cube.Mtl 信息如下:
newmtl cubeMaterial
map_Kd cordeBouee4.jpg
3. 纹理图片 cordeBouee4.jpg
二、代码实例
1. 依赖库和头文件
1.1 assimp
本文是通过使用assimp 来解析3d model 相关的文件,因此需要在 ubuntu 上安装 libassimp.so 库, 安装命令可以查看前面的文章《wayland(xdg_wm_base) + egl + opengles 使用 Assimp 加载3D model 最简实例(十四)》
1.2 stb_image.h
使用 stb_image.h 中相关的接口加载.jpg格式的纹理图片,如何获取 stb_image.h 头文件,可以查看之前的文章《wayland(xdg_wm_base) + egl + opengles 渲染使用纹理贴图的旋转 3D 立方体实例(十三)》
2. egl_wayland_obj_cube.cpp
egl_wayland_obj_cube.cpp 代码如下(示例):
#include <wayland-client.h>
#include <wayland-server.h>
#include <wayland-egl.h>
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include "Matrix.h"
#include "xdg-shell-client-protocol.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
// 使用 Assimp 加载模型文件
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#define WIDTH 800
#define HEIGHT 600
struct wl_display *display = NULL;
struct wl_compositor *compositor = NULL;
struct xdg_wm_base *wm_base = NULL;
struct wl_registry *registry = NULL;
//opengles global var
GLuint projectionLocation;
GLuint modelLocation;
GLuint viewLocation;
GLuint simpleCubeProgram;
GLuint samplerLocation;
GLuint textureId;
aiMesh *mesh;
aiMaterial *material;
GLfloat *vVertices;
GLfloat *vTextures;
GLushort *indices;
GLuint indices_num;
GLuint vao,vbo1,vbo2,ebo;
float projectionMatrix[16];
float modelMatrix[16];
float viewMatrix[16];
float angleX = 30.0f;
float angleY = 0.0f;
float angleZ = 0.0f;
struct window {
struct wl_surface *surface;
struct xdg_surface *xdg_surface;
struct xdg_toplevel *xdg_toplevel;
struct wl_egl_window *egl_window;
};
static void
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
{
xdg_wm_base_pong(shell, serial);
}
/*for xdg_wm_base listener*/
static const struct xdg_wm_base_listener wm_base_listener = {
xdg_wm_base_ping,
};
/*for registry listener*/
static void registry_add_object(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
{
if (!strcmp(interface, "wl_compositor")) {
compositor = (struct wl_compositor *)wl_registry_bind(registry, name, &wl_compositor_interface, 1);
} else if (strcmp(interface, "xdg_wm_base") == 0) {
wm_base = (struct xdg_wm_base *)wl_registry_bind(registry, name,
&xdg_wm_base_interface, 1);
xdg_wm_base_add_listener(wm_base, &wm_base_listener, NULL);
}
}
void registry_remove_object(void *data, struct wl_registry