Qt OpenGL textures详解

1. 初始化opengl资源

 Q_INIT_RESOURCE:textures(资源名称)

QSurfaceFormat:定义3d面显示方式

如果在vs+qt vs tools 中无法正常显示3d图形,则需加入以下代码:

format.setStenciBufferSize(8);

format.setVersion(1,1);版本号根据用户安装的Qt版本来更改

2. 继承QOpenGLWidget和QOpenGLFunctions类

 自定义一个用于显示3D的控件

重写最小尺寸

 重写正常尺寸

 重写初始化函数

 重写绘制函数

 重写大小改变函数

 重写鼠标左键按下函数

 重写鼠标移动函数

 重写鼠标释放函数

 定义6个纹理对象

 定义1个用户代码片段对象

 定义1个缓冲区

 定义24个3维坐标

定义一个存放3维坐标的vector

 给缓存对象申请空间

3. 加载显示3D图形

构建6个面对象

 定时旋转其中一个实例

 这样就大功告成了,这时候运行程序就会看到旋转的带有6个面的3D图形,如果显示不出来,证明初始化资源失败了,一般是opengl version对应不上,才会导致图形渲染程序失败!

以下是使用Assimp库和QtOpenGL实现骨骼动画的代码: 首先,需要在Qt项目中添加Assimp库的头文件和链接库: ```c++ #include <assimp/Importer.hpp> #include <assimp/scene.h> #include <assimp/postprocess.h> #pragma comment(lib, "assimp-vc141-mt.lib") ``` 接下来,需要定义一个结构体来存储骨骼信息: ```c++ struct BoneInfo { aiMatrix4x4 boneOffset; aiMatrix4x4 finalTransformation; }; struct VertexBoneData { int IDs[4]; float Weights[4]; VertexBoneData() { memset(IDs, 0, sizeof(IDs)); memset(Weights, 0, sizeof(Weights)); } }; ``` 然后,需要定义一个类来加载模型、骨骼信息和动画数据: ```c++ class Model { public: Model(const std::string& path); ~Model(); void Draw(GLuint shaderProgram); void BoneTransform(float timeInSeconds, std::vector<aiMatrix4x4>& transforms); private: void LoadModel(const std::string& path); void ProcessNode(aiNode* node, const aiScene* scene); void ProcessMesh(aiMesh* mesh, const aiScene* scene); void LoadBones(unsigned int meshIndex, aiMesh* mesh, std::vector<VertexBoneData>& bones); void LoadAnimations(const aiScene* scene); void ReadNodeHierarchy(float animationTime, const aiNode* node, const aiMatrix4x4& parentTransform); const aiNodeAnim* FindNodeAnim(const aiAnimation* animation, const std::string& nodeName); void CalcInterpolatedScaling(aiVector3D& out, float animationTime, const aiNodeAnim* nodeAnim); void CalcInterpolatedRotation(aiQuaternion& out, float animationTime, const aiNodeAnim* nodeAnim); void CalcInterpolatedPosition(aiVector3D& out, float animationTime, const aiNodeAnim* nodeAnim); GLuint m_VAO; GLuint m_VBO; GLuint m_EBO; std::vector<BoneInfo> m_BoneInfo; std::map<std::string, unsigned int> m_BoneMapping; unsigned int m_NumBones; std::vector<VertexBoneData> m_Bones; std::vector<Texture> m_Textures; std::vector<Mesh> m_Meshes; std::string m_Directory; std::vector<aiMatrix4x4> m_BoneTransforms; std::vector<Animation> m_Animations; float m_TimeInSeconds; float m_TickPerSecond; }; ``` 在实现类的成员函数时,需要依次实现加载模型、骨骼信息和动画数据的函数。其中,加载模型的函数主要是使用Assimp库中的函数来读取模型文件,提取网格数据和纹理数据。加载骨骼信息的函数则需要遍历每个网格,提取顶点对应的骨骼编号和权重,以及每个骨骼的变换矩阵。加载动画数据的函数需要遍历每个动画,提取动画名称、时间长度、帧率和关键帧数据。 当加载完模型、骨骼信息和动画数据后,就可以在绘制函数中使用骨骼动画了。具体操作是,在每个动画关键帧的时间点上,计算每个骨骼的变换矩阵,然后将这些矩阵传递给着色器,进行渲染。计算变换矩阵的函数如下: ```c++ void Model::BoneTransform(float timeInSeconds, std::vector<aiMatrix4x4>& transforms) { aiMatrix4x4 identityMatrix; float ticksPerSecond = m_TickPerSecond != 0 ? m_TickPerSecond : 25.0f; float timeInTicks = timeInSeconds * ticksPerSecond; float animationTime = fmod(timeInTicks, m_TimeInSeconds); ReadNodeHierarchy(animationTime, m_Scene->mRootNode, identityMatrix); transforms.resize(m_NumBones); for (unsigned int i = 0; i < m_NumBones; i++) { transforms[i] = m_BoneInfo[i].finalTransformation; } } ``` 在计算变换矩阵时,需要遍历骨骼节点树,找到每个节点对应的关键帧数据,然后进行插值计算。具体实现过程可以参考以下代码: ```c++ void Model::ReadNodeHierarchy(float animationTime, const aiNode* node, const aiMatrix4x4& parentTransform) { std::string nodeName(node->mName.data); const aiAnimation* animation = m_Animations[0].m_Animation; aiMatrix4x4 nodeTransform = node->mTransformation; const aiNodeAnim* nodeAnim = FindNodeAnim(animation, nodeName); if (nodeAnim) { aiVector3D scaling; CalcInterpolatedScaling(scaling, animationTime, nodeAnim); aiMatrix4x4 scalingMatrix; aiMatrix4x4::Scaling(scaling, scalingMatrix); aiQuaternion rotation; CalcInterpolatedRotation(rotation, animationTime, nodeAnim); aiMatrix4x4 rotationMatrix = aiMatrix4x4(rotation.GetMatrix()); aiVector3D position; CalcInterpolatedPosition(position, animationTime, nodeAnim); aiMatrix4x4 translationMatrix; aiMatrix4x4::Translation(position, translationMatrix); nodeTransform = translationMatrix * rotationMatrix * scalingMatrix; } aiMatrix4x4 globalTransform = parentTransform * nodeTransform; if (m_BoneMapping.find(nodeName) != m_BoneMapping.end()) { unsigned int boneIndex = m_BoneMapping[nodeName]; m_BoneTransforms[boneIndex] = globalTransform * m_BoneInfo[boneIndex].boneOffset; } for (unsigned int i = 0; i < node->mNumChildren; i++) { ReadNodeHierarchy(animationTime, node->mChildren[i], globalTransform); } } ``` 最后,在着色器中使用骨骼信息来进行顶点变换,实现骨骼动画的效果。具体操作是,在顶点着色器中传递每个顶点对应的骨骼编号和权重,然后根据骨骼变换矩阵来计算顶点的最终位置。示例代码如下: ```glsl #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; layout (location = 2) in vec2 aTexCoords; layout (location = 3) in ivec4 aBoneIDs; layout (location = 4) in vec4 aWeights; uniform mat4 model; uniform mat4 view; uniform mat4 projection; uniform mat4 boneTransforms[100]; out vec3 FragPos; out vec3 Normal; out vec2 TexCoords; void main() { mat4 boneTransform = boneTransforms[aBoneIDs[0]] * aWeights[0]; boneTransform += boneTransforms[aBoneIDs[1]] * aWeights[1]; boneTransform += boneTransforms[aBoneIDs[2]] * aWeights[2]; boneTransform += boneTransforms[aBoneIDs[3]] * aWeights[3]; vec4 pos = boneTransform * vec4(aPos, 1.0); gl_Position = projection * view * model * pos; FragPos = vec3(model * pos); Normal = mat3(transpose(inverse(model))) * aNormal; TexCoords = aTexCoords; } ``` 以上就是使用Assimp库和QtOpenGL实现骨骼动画的代码。需要注意的是,在实际开发中,还需要考虑一些特殊情况,比如模型中没有骨骼信息或者动画数据,或者骨骼数量超过了硬件限制等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值