Qt opengl assimp使用骨骼动画代码
时间: 2023-10-13 17:06:41 浏览: 114
以下是一个简单的使用 Qt、OpenGL 和 Assimp 库加载和播放带有骨骼动画的模型的代码示例:
```c++
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
GLWidget(QWidget *parent = nullptr)
: QOpenGLWidget(parent)
, m_shaderProgram(nullptr)
, m_vao(nullptr)
, m_vertexBuffer(QOpenGLBuffer::VertexBuffer)
, m_indexBuffer(QOpenGLBuffer::IndexBuffer)
, m_animationTime(0.0f)
{}
protected:
void initializeGL() override
{
// 初始化 OpenGL 函数
initializeOpenGLFunctions();
// 创建着色器程序
m_shaderProgram = new QOpenGLShaderProgram(this);
m_shaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, "shader.vert");
m_shaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, "shader.frag");
m_shaderProgram->bindAttributeLocation("position", 0);
m_shaderProgram->bindAttributeLocation("normal", 1);
m_shaderProgram->link();
// 加载模型
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile("model.dae", aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_LimitBoneWeights | aiProcess_GenSmoothNormals | aiProcess_CalcTangentSpace | aiProcess_JoinIdenticalVertices | aiProcess_ValidateDataStructure);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
qCritical("Error loading model: %s", importer.GetErrorString());
return;
}
// 初始化骨骼动画
m_animation = std::make_unique<SkeletonAnimation>(scene);
// 创建顶点数组对象
m_vao = new QOpenGLVertexArrayObject(this);
m_vao->create();
m_vao->bind();
// 创建顶点缓冲区
m_vertexBuffer.create();
m_vertexBuffer.bind();
m_vertexBuffer.allocate(m_animation->vertices().data(), m_animation->vertices().size() * sizeof(Vertex));
// 创建索引缓冲区
m_indexBuffer.create();
m_indexBuffer.bind();
m_indexBuffer.allocate(m_animation->indices().data(), m_animation->indices().size() * sizeof(unsigned int));
// 设置顶点属性指针
m_shaderProgram->enableAttributeArray(0);
m_shaderProgram->setAttributeBuffer(0, GL_FLOAT, offsetof(Vertex, position), 3, sizeof(Vertex));
m_shaderProgram->enableAttributeArray(1);
m_shaderProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, normal), 3, sizeof(Vertex));
// 绑定骨骼动画的顶点着色器 uniform 变量
m_shaderProgram->bind();
m_animation->bindUniforms(m_shaderProgram);
// 解绑顶点数组对象
m_vao->release();
}
void resizeGL(int w, int h) override
{
// 设置视口大小
glViewport(0, 0, w, h);
}
void paintGL() override
{
// 清空颜色缓冲区和深度缓冲区
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 设置模型矩阵、视图矩阵和投影矩阵
QMatrix4x4 modelMatrix;
modelMatrix.setToIdentity();
modelMatrix.translate(0.0f, -1.0f, 0.0f);
modelMatrix.scale(0.05f);
QMatrix4x4 viewMatrix;
viewMatrix.setToIdentity();
viewMatrix.translate(0.0f, 0.0f, -5.0f);
QMatrix4x4 projectionMatrix;
projectionMatrix.setToIdentity();
projectionMatrix.perspective(45.0f, width() / static_cast<float>(height()), 0.1f, 100.0f);
// 计算骨骼动画的变换矩阵
std::vector<QMatrix4x4> boneTransforms = m_animation->boneTransforms(m_animationTime);
// 更新骨骼动画的顶点着色器 uniform 变量
m_animation->updateUniforms(m_shaderProgram, boneTransforms);
// 绑定顶点数组对象和着色器程序
m_vao->bind();
m_shaderProgram->bind();
// 绘制模型
glDrawElements(GL_TRIANGLES, m_animation->indices().size(), GL_UNSIGNED_INT, nullptr);
// 解绑顶点数组对象和着色器程序
m_vao->release();
m_shaderProgram->release();
// 更新骨骼动画的时间
m_animationTime += 0.01f;
if (m_animationTime > m_animation->duration())
{
m_animationTime = 0.0f;
}
}
private:
QOpenGLShaderProgram *m_shaderProgram;
QOpenGLVertexArrayObject *m_vao;
QOpenGLBuffer m_vertexBuffer;
QOpenGLBuffer m_indexBuffer;
std::unique_ptr<SkeletonAnimation> m_animation;
float m_animationTime;
};
```
其中,`SkeletonAnimation` 是一个自定义类,用于加载和播放带有骨骼动画的模型。你需要根据你的模型格式和需求来修改此类的实现。`shader.vert` 和 `shader.frag` 是用于绘制模型的顶点着色器和片段着色器。你需要根据你的模型格式和需求来编写这些着色器的代码。
阅读全文