QT6绘制3D动画

Qt6 3D动画绘制详解

Qt6 提供了强大的 3D 图形渲染能力,通过 Qt3D 模块可以轻松实现 3D 动画效果。本文将详细介绍如何在 Qt6 中使用 Qt3D 模块创建和渲染 3D 动画。

一、Qt3D 模块概述

Qt3D 是 Qt 提供的 3D 图形框架,支持:

  • 3D 场景管理
  • 材质和光照系统
  • 相机控制
  • 动画系统
  • 粒子效果

在 Qt6 中,Qt3D 已经成为核心模块的一部分,使用更加方便。

二、环境配置

1. 添加依赖

在项目文件(.pro)中添加:

QT += 3dcore 3drender 3dinput 3dextras

2. 头文件包含

#include <QGuiApplication>
#include <QQuickView>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DExtras/QOrbitCameraController>
#include <Qt3DCore/QEntity>
#include <Qt3DRender/QCamera>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DCore/QTransform>
#include <Qt3DAnimations/QAnimationClip>
#include <Qt3DAnimations/QAnimator>
#include <Qt3DAnimations/QChannelMapper>
#include <Qt3DCore/QAnimationAspect>

三、基础 3D 场景设置

1. 创建 3D 窗口

Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();
QWidget *container = QWidget::createWindowContainer(view);

2. 设置场景根实体

Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
view->setRootEntity(rootEntity);

3. 添加相机

Qt3DRender::QCamera *camera = view->camera();
camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
camera->setPosition(QVector3D(0, 0, 40.0f));
camera->setUpVector(QVector3D(0, 1, 0));
camera->setViewCenter(QVector3D(0, 0, 0));

4. 添加相机控制器

Qt3DExtras::QOrbitCameraController *camController = new Qt3DExtras::QOrbitCameraController(rootEntity);
camController->setCamera(camera);

四、创建 3D 对象

1. 创建立方体

// 创建立方体实体
Qt3DCore::QEntity *cubeEntity = new Qt3DCore::QEntity(rootEntity);

// 创建几何体
Qt3DExtras::QCuboidMesh *cubeMesh = new Qt3DExtras::QCuboidMesh();

// 创建材质
Qt3DExtras::QPhongMaterial *cubeMaterial = new Qt3DExtras::QPhongMaterial();
cubeMaterial->setDiffuse(Qt::red);

// 创建变换组件
Qt3DCore::QTransform *cubeTransform = new Qt3DCore::QTransform();

// 将组件添加到实体
cubeEntity->addComponent(cubeMesh);
cubeEntity->addComponent(cubeMaterial);
cubeEntity->addComponent(cubeTransform);

五、实现 3D 动画

1. 使用 QPropertyAnimation 实现简单动画

#include <QPropertyAnimation>

// 创建动画
QPropertyAnimation *anim = new QPropertyAnimation(cubeTransform, "rotation");
anim->setDuration(2000); // 2秒
anim->setLoopCount(-1);  // 无限循环
anim->setStartValue(QQuaternion::fromAxisAndAngle(QVector3D(0, 1, 0), 0));
anim->setEndValue(QQuaternion::fromAxisAndAngle(QVector3D(0, 1, 0), 360));

// 启动动画
anim->start();

2. 使用 Qt3DAnimations 模块实现复杂动画

2.1 创建动画剪辑
Qt3DAnimations::QAnimationClip *animationClip = new Qt3DAnimations::QAnimationClip();
animationClip->setDuration(2000); // 2秒

// 创建关键帧数据
QVector<Qt3DCore::QTransform *> keyframes;
for (int i = 0; i < 100; ++i) {
    Qt3DCore::QTransform *transform = new Qt3DCore::QTransform();
    transform->setRotation(QQuaternion::fromAxisAndAngle(
        QVector3D(0, 1, 0), i * 3.6)); // 每帧旋转3.6度
    keyframes.append(transform);
}

// 添加关键帧到动画剪辑
animationClip->setKeyframeData(keyframes);

2.2 创建动画控制器
Qt3DAnimations::QAnimator *animator = new Qt3DAnimations::QAnimator(rootEntity);
animator->setClip(animationClip);

// 创建通道映射器
Qt3DAnimations::QChannelMapper *channelMapper = new Qt3DAnimations::QChannelMapper();
channelMapper->setTarget(cubeTransform);

animator->setChannelMapper(channelMapper);
animator->start();

3. 使用 QML 实现 3D 动画

Qt3D 也支持通过 QML 实现动画,更加简洁:

import QtQuick 2.15
import Qt3D.Core 2.15
import Qt3D.Render 2.15
import Qt3D.Input 2.15
import Qt3D.Extras 2.15
import Qt3D.Animations 2.15

Entity {
    id: root
    
    Camera {
        id: camera
        projectionType: CameraLens.PerspectiveProjection
        fieldOfView: 45
        aspectRatio: 16/9
        nearPlane: 0.1
        farPlane: 1000.0
        position: Qt.vector3d(0, 0, 40.0)
        upVector: Qt.vector3d(0, 1, 0)
        viewCenter: Qt.vector3d(0, 0, 0)
    }
    
    OrbitCameraController {
        camera: camera
    }
    
    components: [
        RenderSettings {
            activeFrameGraph: ForwardRenderer {
                camera: camera
                clearColor: "black"
            }
        },
        InputSettings { }
    ]
    
    Entity {
        id: cubeEntity
        
        CuboidMesh {
            id: cubeMesh
        }
        
        PhongMaterial {
            id: cubeMaterial
            diffuse: "red"
        }
        
        Transform {
            id: cubeTransform
        }
        
        components: [cubeMesh, cubeMaterial, cubeTransform]
        
        // 添加动画
        NumberAnimation {
            target: cubeTransform
            property: "rotationX"
            from: 0
            to: 360
            duration: 2000
            loops: Animation.Infinite
        }
        
        NumberAnimation {
            target: cubeTransform
            property: "rotationY"
            from: 0
            to: 360
            duration: 2000
            loops: Animation.Infinite
            running: false // 不同步运行
            delay: 1000 // 延迟1秒开始
        }
    }
}

六、高级动画技术

1. 骨骼动画

// 创建骨骼层次结构
Qt3DCore::QEntity *skeletonRoot = new Qt3DCore::QEntity(rootEntity);
Qt3DCore::QEntity *bone1 = new Qt3DCore::QEntity(skeletonRoot);
Qt3DCore::QEntity *bone2 = new Qt3DCore::QEntity(bone1);

// 创建骨骼变换
Qt3DCore::QTransform *bone1Transform = new Qt3DCore::QTransform();
bone1->addComponent(bone1Transform);

Qt3DCore::QTransform *bone2Transform = new Qt3DCore::QTransform();
bone2->addComponent(bone2Transform);

// 创建骨骼动画
Qt3DAnimations::QAnimationClip *skeletonClip = new Qt3DAnimations::QAnimationClip();
// 设置骨骼关键帧...

2. 形变动画

// 创建形变目标
Qt3DCore::QEntity *target1 = new Qt3DCore::QEntity(rootEntity);
Qt3DCore::QEntity *target2 = new Qt3DCore::QEntity(rootEntity);

// 创建混合形状
Qt3DCore::QBlendShape *blendShape = new Qt3DCore::QBlendShape(cubeEntity);
blendShape->addTarget(target1, 0.0f);
blendShape->addTarget(target2, 1.0f);

// 创建形变动画
QPropertyAnimation *morphAnim = new QPropertyAnimation(blendShape, "weights");
morphAnim->setDuration(2000);
morphAnim->setKeyValueAt(0.0, QVector<float>({0.0f}));
morphAnim->setKeyValueAt(0.5, QVector<float>({0.5f}));
morphAnim->setKeyValueAt(1.0, QVector<float>({1.0f}));
morphAnim->setLoopCount(-1);
morphAnim->start();

七、性能优化

  1. ​批量渲染​​:合并相同材质的对象
  2. ​LOD技术​​:根据距离使用不同细节级别的模型
  3. ​实例化渲染​​:重复使用相同网格的多个实例
  4. ​异步加载​​:后台加载大型资源
  5. ​剔除技术​​:视锥剔除、遮挡剔除

八、完整示例

1. 基于C++的旋转立方体

#include <QGuiApplication>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DExtras/QOrbitCameraController>
#include <Qt3DCore/QEntity>
#include <Qt3DRender/QCamera>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DCore/QTransform>
#include <QPropertyAnimation>

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);
    
    Qt3DExtras::Qt3DWindow view;
    QWidget *container = QWidget::createWindowContainer(&view);
    container->resize(800, 600);
    
    Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
    view.setRootEntity(rootEntity);
    
    // 创建相机
    Qt3DRender::QCamera *camera = view.camera();
    camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
    camera->setPosition(QVector3D(0, 0, 40.0f));
    camera->setUpVector(QVector3D(0, 1, 0));
    camera->setViewCenter(QVector3D(0, 0, 0));
    
    // 添加相机控制器
    Qt3DExtras::QOrbitCameraController *camController = 
        new Qt3DExtras::QOrbitCameraController(rootEntity);
    camController->setCamera(camera);
    
    // 创建立方体
    Qt3DCore::QEntity *cubeEntity = new Qt3DCore::QEntity(rootEntity);
    Qt3DExtras::QCuboidMesh *cubeMesh = new Qt3DExtras::QCuboidMesh();
    Qt3DExtras::QPhongMaterial *cubeMaterial = new Qt3DExtras::QPhongMaterial();
    cubeMaterial->setDiffuse(Qt::red);
    Qt3DCore::QTransform *cubeTransform = new Qt3DCore::QTransform();
    
    cubeEntity->addComponent(cubeMesh);
    cubeEntity->addComponent(cubeMaterial);
    cubeEntity->addComponent(cubeTransform);
    
    // 创建旋转动画
    QPropertyAnimation *anim = new QPropertyAnimation(cubeTransform, "rotation");
    anim->setDuration(2000);
    anim->setLoopCount(-1);
    anim->setStartValue(QQuaternion::fromAxisAndAngle(QVector3D(0, 1, 0), 0));
    anim->setEndValue(QQuaternion::fromAxisAndAngle(QVector3D(0, 1, 0), 360));
    anim->start();
    
    container->show();
    return app.exec();
}

2. 基于QML的3D动画

import QtQuick 2.15
import Qt3D.Core 2.15
import Qt3D.Render 2.15
import Qt3D.Input 2.15
import Qt3D.Extras 2.15
import Qt3D.Animations 2.15

ApplicationWindow {
    visible: true
    width: 800
    height: 600
    
    Entity {
        id: root
        
        Camera {
            id: camera
            projectionType: CameraLens.PerspectiveProjection
            fieldOfView: 45
            aspectRatio: 16/9
            nearPlane: 0.1
            farPlane: 1000.0
            position: Qt.vector3d(0, 0, 40.0)
            upVector: Qt.vector3d(0, 1, 0)
            viewCenter: Qt.vector3d(0, 0, 0)
        }
        
        OrbitCameraController {
            camera: camera
        }
        
        components: [
            RenderSettings {
                activeFrameGraph: ForwardRenderer {
                    camera: camera
                    clearColor: "black"
                }
            },
            InputSettings { }
        ]
        
        Entity {
            id: cubeEntity
            
            CuboidMesh {
                id: cubeMesh
            }
            
            PhongMaterial {
                id: cubeMaterial
                diffuse: "red"
            }
            
            Transform {
                id: cubeTransform
            }
            
            components: [cubeMesh, cubeMaterial, cubeTransform]
            
            // 添加动画
            NumberAnimation {
                target: cubeTransform
                property: "rotationX"
                from: 0
                to: 360
                duration: 2000
                loops: Animation.Infinite
            }
            
            NumberAnimation {
                target: cubeTransform
                property: "rotationY"
                from: 0
                to: 360
                duration: 2000
                loops: Animation.Infinite
                running: false
                delay: 1000
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

code_shenbing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值