qt - 如何在 qml 中旋转 3d 立方体?

标签 qt 3d qml

我正在使用 QtQuick 在 Qt Creator 中开发应用程序。此应用程序的目的是在手指的帮助下在 3 个维度上旋转立方体。

我设法开发了与手指运动相关的 Action 创建,但我完全停留在立方体与手指相关的旋转上。

我尝试创建一个关于当前点和先前点以及法向量的方向向量。我在立方体的 x 和 y 方向应用了欧拉旋转,但在某个点,立方体没有按预期旋转。

这是我的应用程序主页的 qml 代码:

ma​​in.qml

import QtQuick 2.15
import QtQuick.Window 2.14
import QtQuick3D 1.15
import Qt3D.Input 2.0
import QtQuick.Controls 2.1
import Qt3D.Extras 2.15

Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("MouseArea Demo")

        MouseArea{
            property int previousX: -1
            property int previousY: -1

            anchors.fill : parent

            onPressed: {

                previousX = mouseX;
                previousY = mouseY;
            }

            onPositionChanged: {

                let direction = Qt.vector2d(mouseX - previousX, mouseY - previousY).normalized();
                let normal = Qt.vector2d(direction.y, direction.x).normalized();
                console.log("direction : " + direction);
                console.log("normal : " + normal);
                cube.eulerRotation.x += normal.x * 3;
                cube.eulerRotation.y += normal.y * 3;



                previousX = mouseX;
                previousY = mouseY
            }

            onReleased: {

                previousX = -1;
                previousY = -1;

            }
        }

    View3D {
        id: view
        anchors.fill: parent
        camera: camera
        renderMode: View3D.Overlay


        PerspectiveCamera {
            id: camera
            position: Qt.vector3d(0, 200, 300)
            eulerRotation.x: -30

        }

        DirectionalLight {
            eulerRotation.x: -30
        }

        Model {

            id: cube
            visible: true
            position: Qt.vector3d(0, 0, 0)
            source: "#Cube"
            materials: [ DefaultMaterial {
                    diffuseMap: Texture {
                        id: texture
                        source: "../build-colorpicker2d-Desktop_Qt_5_15_2_GCC_64bit-Debug/res.png"
                    }
                }
            ]                       
        }
    }

}

这是一段视频,内容是我 2 天前与您讨论的关于 y 旋转问题的内容。

亲切的问候。

enter image description here

最佳答案

首先,您应该将此添加到您的 .pro 文件中:

QT += qml quick 3dcore 3dinput 3dquick 3dlogic  3dquickextras  3dextras

我在 qml 中有 3 个类:ma​​in.qmlRootEntity.qmlSOrbitCameraController.qml

我有一个 Scene3D,我可以在其中放置所有实体。我创建一个单独的类并将其命名为 RootEntity。 这种方式更重要的一点是我在类里面使用的orbitController。这使得您可以通过鼠标旋转立方体,为此您需要实体。因此,我使用 Scene3D 和 Entity 而不是 view3d 和模型。

ma​​in.qml中:

import QtQuick 2.12
import QtQuick.Scene3D 2.12
import QtQuick.Window 2.12

import "."

Window {
    visible: true
    width: 640
    height: 480

    Scene3D
    {
        id : scene3d
        anchors.fill: parent
        focus: true
        aspects: ["render", "logic", "input"]
        hoverEnabled: true
        cameraAspectRatioMode: Scene3D.AutomaticAspectRatio


        antialiasing: true

        RootEntity
        {
            id:root
        }

    }

}

RootEntity.qml中:

import QtQuick 2.0

import Qt3D.Core 2.12
import Qt3D.Render 2.12
import Qt3D.Extras 2.12
import Qt3D.Input 2.12

import "."


Entity {
    id: root

    //create camera

    Camera {
        id: mainCamera
        projectionType: CameraLens.PerspectiveProjection
        fieldOfView: 45
        aspectRatio: 16/9
        nearPlane : 0.1
        farPlane : 1000.0
        position: Qt.vector3d(0.0, 4.49373, -3.78577)
        upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
        viewCenter: Qt.vector3d(0.0, 0.5, 0.0)
    }

    //use my class instead of OrbitCameraController

    SOrbitCameraController {
        id: mainCameraController
        camera: mainCamera
    }

    components: [
        RenderSettings {

            Viewport {
                normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0)
                RenderSurfaceSelector {
                    CameraSelector {
                        id: cameraSelector
                        camera: mainCamera
                        FrustumCulling {
                            ClearBuffers {
                                buffers: ClearBuffers.AllBuffers
                                clearColor: "#444449"
                                NoDraw {}
                            }
                            LayerFilter {
                                filterMode: LayerFilter.DiscardAnyMatchingLayers
                                layers: [topLayer]
                            }
                            LayerFilter {
                                filterMode: LayerFilter.AcceptAnyMatchingLayers
                                layers: [topLayer]
                                ClearBuffers {
                                    buffers: ClearBuffers.DepthBuffer
                                }
                            }
                        }
                    }
                }
            }
        },
        InputSettings {}
        ,
        ScreenRayCaster
        {
            id:screenRayCaster
            onHitsChanged:
            {
                drawLineMesh(hits)

            }

        }
    ]

    Layer {
        id: topLayer
        recursive: true
    }


    Entity {
        id: cubeEntity
        components: [
            CuboidMesh
            {
                xExtent: 1
                yExtent: 1
                zExtent: 1


            }

            ,

            Transform {
                id: t
                translation: Qt.vector3d(0, 0, 0)

            }
            ,
            PhongMaterial
            {
                ambient: "red"
            }


        ]

    }

}

SOrbitCameraController.qml 中:

import Qt3D.Core 2.0
import Qt3D.Render 2.0
import Qt3D.Input 2.0

Entity{
    id: root
    property Camera camera;
    property real dt: 0.001
    property real linearSpeed: 1
    property real lookSpeed: 500
    property real zoomLimit: 0.16

    MouseDevice {
        id: mouseDevice
        sensitivity: 0.001 // Make it more smooth
    }

    MouseHandler {
        id: mh
        readonly property vector3d upVect: Qt.vector3d(0, 1, 0)
        property point lastPos;
        property real pan;
        property real tilt;
        sourceDevice: mouseDevice

        onPanChanged: root.camera.panAboutViewCenter(pan, upVect);
        onTiltChanged: root.camera.tiltAboutViewCenter(tilt);

        onPressed: {
            lastPos = Qt.point(mouse.x, mouse.y);
        }
        onPositionChanged: {
            // You can change the button as you like for rotation or translation
            if (mouse.buttons === 1){ // Left button for rotation
                pan = -(mouse.x - lastPos.x) * dt * lookSpeed;
                tilt = (mouse.y - lastPos.y) * dt * lookSpeed;
            } else if (mouse.buttons === 2) { // Right button for translate
                var rx = -(mouse.x - lastPos.x) * dt * linearSpeed;
                var ry = (mouse.y - lastPos.y) * dt * linearSpeed;
                camera.translate(Qt.vector3d(rx, ry, 0))
            } else if (mouse.buttons === 3) { // Left & Right button for zoom
                ry = (mouse.y - lastPos.y) * dt * linearSpeed
                zoom(ry)
            }

            lastPos = Qt.point(mouse.x, mouse.y)
        }
        onWheel: {
            zoom(wheel.angleDelta.y * dt * linearSpeed)
        }

        function zoom(ry) {
            if (ry > 0 && zoomDistance(camera.position, camera.viewCenter) < zoomLimit) {
                return
            }

            camera.translate(Qt.vector3d(0, 0, ry), Camera.DontTranslateViewCenter)
        }

        function zoomDistance(posFirst, posSecond) {
            return posSecond.minus(posFirst).length()
        }
    }
}

最后是我的 ma​​in.cpp :

#include <QGuiApplication>
#include <QQmlApplicationEngine>

int  main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication        app(argc, argv);
    QQmlApplicationEngine  engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty())
    {
        return -1;
    }

    return app.exec();
}

输出 enter image description here

关于qt - 如何在 qml 中旋转 3d 立方体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68542807/

相关文章:

c++ - QGraphicsItem 和 Tab 键顺序

c++ - 从具有 bigendian 格式的 QByteArray 获取 float 组的有效方法

c++ - Qt库,子类窗口拦截消息?

javascript - 如何使用 THREE.js 将样条曲线拉伸(stretch)到场景的原点

css - 当应用多个旋转时计算元素 Angular 最佳方法是什么

audio - 3D空间中声源位置的计算

c++ - Qt:QML Int溢出

qt - 包含QT header ,但找不到QSslError的标识符

c++ - 从 plasmoid qml 调用 c++ 槽

c++ - 在 QML 上异步更新多个 QQuickPaintedItem