Qt opengl assimp加载骨骼动画
时间: 2023-10-07 12:08:16 浏览: 256
Qt使用assimp加载fbx动画,assimp 3.3.1、Qt 5.6.1、Mingw4.9.2
要在 Qt 中使用 OpenGL 和 Assimp 加载骨骼动画,可以按照以下步骤进行操作:
1. 首先,确保已经安装了 Qt 和 OpenGL,并且已经链接了 OpenGL 库。
2. 安装 Assimp 库,并链接到项目中。可以使用以下命令在 Ubuntu 上安装 Assimp:
```
sudo apt-get install libassimp-dev
```
3. 创建一个 Qt OpenGL 窗口,并初始化 OpenGL 上下文。
4. 使用 Assimp 加载带有骨骼动画的模型文件。可以使用以下代码加载模型:
```
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile("model.dae", aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenSmoothNormals | aiProcess_LimitBoneWeights);
```
这将加载名为“model.dae”的模型文件,并对模型进行三角化、翻转纹理坐标、生成平滑法线和限制骨骼权重。
5. 将模型数据存储在 OpenGL 缓冲区中。可以使用以下代码将顶点、索引和骨骼数据存储在缓冲区中:
```
GLuint vao, vbo, ibo, boneBuffer;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices, GL_STATIC_DRAW);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * numIndices, indices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) offsetof(Vertex, position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) offsetof(Vertex, normal));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) offsetof(Vertex, texCoord));
glGenBuffers(1, &boneBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, boneBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(BoneData) * numBones, boneData, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, boneBuffer);
```
这将创建一个顶点数组对象(VAO),并将顶点、索引和骨骼数据存储在相应的缓冲区中。还将启用顶点属性,并将骨骼数据绑定到着色器存储缓冲区中。
6. 加载骨骼动画数据。可以使用以下代码加载骨骼数据:
```
aiNode* rootNode = scene->mRootNode;
aiAnimation* animation = scene->mAnimations[0];
std::map<std::string, const aiNodeAnim*> nodeAnimations;
for (unsigned int i = 0; i < animation->mNumChannels; i++)
{
const aiNodeAnim* nodeAnim = animation->mChannels[i];
nodeAnimations[nodeAnim->mNodeName.C_Str()] = nodeAnim;
}
Bone rootBone;
rootBone.name = "root";
rootBone.parentIndex = -1;
loadBones(rootNode, -1, boneData, boneIds, boneWeights, rootBone, nodeAnimations);
```
这将递归遍历模型的节点树,并加载每个节点的骨骼数据。还将创建一个骨骼根节点,并将所有骨骼数据存储在 boneData、boneIds 和 boneWeights 数组中。
7. 在渲染循环中,更新骨骼动画并将骨骼矩阵传递给着色器。可以使用以下代码更新骨骼数据:
```
float time = getTime(); // 获取当前时间
glm::mat4 globalInverseTransform = glm::inverse(convertMatrix(scene->mRootNode->mTransformation));
glm::mat4 identityMatrix(1.0f);
glm::mat4 modelMatrix = identityMatrix;
glm::mat4 viewMatrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 5.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 projectionMatrix = glm::perspective(glm::radians(45.0f), 1.0f, 0.1f, 100.0f);
glm::mat4 mvpMatrix = projectionMatrix * viewMatrix * modelMatrix;
std::vector<glm::mat4> boneTransforms(numBones);
updateBones(animation, time, rootNode, identityMatrix, globalInverseTransform, nodeAnimations, boneTransforms);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "u_mvpMatrix"), 1, GL_FALSE, glm::value_ptr(mvpMatrix));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "u_boneTransforms"), numBones, GL_FALSE, glm::value_ptr(boneTransforms[0]));
```
这将获取当前时间并计算模型的 MVP 矩阵。还将更新骨骼数据,并将骨骼变换矩阵传递给着色器。
8. 在着色器中使用骨骼数据进行顶点变换。可以使用以下代码在着色器中应用骨骼变换:
```
#version 330
layout(location = 0) in vec3 a_position;
layout(location = 1) in vec3 a_normal;
layout(location = 2) in vec2 a_texCoord;
layout(location = 3) in int a_boneIds[4];
layout(location = 4) in float a_boneWeights[4];
uniform mat4 u_mvpMatrix;
uniform mat4 u_boneTransforms[50];
out vec3 v_normal;
out vec2 v_texCoord;
void main()
{
vec4 position = vec4(a_position, 1.0);
vec4 normal = vec4(a_normal, 0.0);
mat4 boneTransform = u_boneTransforms[a_boneIds[0]] * a_boneWeights[0];
boneTransform += u_boneTransforms[a_boneIds[1]] * a_boneWeights[1];
boneTransform += u_boneTransforms[a_boneIds[2]] * a_boneWeights[2];
boneTransform += u_boneTransforms[a_boneIds[3]] * a_boneWeights[3];
position = boneTransform * position;
normal = boneTransform * normal;
gl_Position = u_mvpMatrix * position;
v_normal = normalize(normal.xyz);
v_texCoord = a_texCoord;
}
```
这将使用骨骼变换矩阵对顶点进行变换,并将变换后的顶点位置和法线传递给片段着色器。
这就是在 Qt 中使用 OpenGL 和 Assimp 加载骨骼动画的基本步骤。
阅读全文