缩放Qt3D的相机

问题描述 投票:0回答:2

如何为Qt3D

Camera
的FOV实现两指捏合手势处理?

FirstPersonCameraController
OrbitCameraController
相机控制器处理鼠标/触摸板事件。后者甚至具有
zoomLimit
属性,但其含义不是我缩放场景所需的(从立方体贴图内部,相机位置固定为
(0, 0, 0)
)。我用的是前一种。它可以正确处理鼠标拖动和单指触摸事件,但不能处理两指捏合手势。

我可以通过简单的方式自定义

PinchArea
来与Qt3D
Camera
交互吗?或者 Qt Quick 的 API 在这个意义上与 Qt3D 的 API 是正交的?

qt qml pinchzoom qt3d
2个回答
1
投票

使用 PinchArea 的捏更新事件来查找有关捏合的信息:根据文档

捏合参数提供有关捏合手势的信息, 包括捏合的规模、中心和角度。这些值 仅反映自当前手势开始以来的变化,并且 因此不受最小和最大限制的限制 捏属性。

所以你应该能够做类似的事情:

Camera {
    id: myCamera
}

PinchArea {
    onPinchUpdated: {
        myCamera.fieldOfView = pinch.scale*someFactor
    } 
}

这可以在您拥有的任何可以访问捏合和相机的自定义 QML 中完成。 如果它是自定义脚本,您始终可以将相机作为属性传递

property Camera myCamera

1
投票

我最终得到了

PinchArea
MouseArea
的组合:

import QtQml 2.2

import QtQuick 2.9
import QtQuick.Scene3D 2.0

import Qt3D.Core 2.9
import Qt3D.Extras 2.9
import Qt3D.Render 2.9
import Qt3D.Input 2.1
import Qt3D.Logic 2.0

import PanoEntity 1.0
import Utility 1.0

Item {
    property url panorama
    onPanoramaChanged: {
        if (panorama.toString().length !== 0) {
            if (panoEntity.setPanorama(panorama)) {
                basicCamera.position = Qt.vector3d(0.0, 0.0, 0.0)
                basicCamera.upVector = Qt.vector3d(0.0, 0.0, 1.0)
                basicCamera.viewCenter = panoEntity.pano.dir
                pinchArea.updateFov(defaultFov)
            }
        }
    }

    property Image previewImage

    property real fovMin: 20.0
    property real defaultFov: 60.0
    property real fovMax: 90.0

    property real sensitivity: 1.5
    property real pinchSensitivity: 0.5

    Scene3D {
        id: scene3d

        anchors.fill: parent

        aspects: ["render", "input", "logic"]
        cameraAspectRatioMode: Scene3D.AutomaticAspectRatio // basicCamera.aspectRatio = width / height
        multisample: true

        Entity {
            Camera {
                id: basicCamera

                projectionType: CameraLens.PerspectiveProjection
                nearPlane: 0.1
                farPlane: 2.0 * Math.SQRT2
            }

            RenderSettings {
                id: renderSettings

                renderPolicy: scene3d.visible ? RenderSettings.Always : RenderSettings.OnDemand

                ForwardRenderer {
                    camera: basicCamera

                    clearColor: "transparent"
                }
            }

            InputSettings {
                id: inputSettings
            }

            components: [renderSettings, inputSettings]

            PanoEntity {
                id: panoEntity

                MemoryBarrier {
                    waitFor: MemoryBarrier.All
                }
            }
        }
    }
    PinchArea {
        id: pinchArea

        anchors.fill: parent

        function updateFov(newFov) {
            if (newFov > fovMax) {
                newFov = fovMax
            } else if (newFov < fovMin) {
                newFov = fovMin
            }
            var eps = 1.0 / 60.0
            if (Math.abs(basicCamera.fieldOfView - newFov) > eps) {
                basicCamera.fieldOfView = newFov
                zoomer.fov = newFov
            }
        }

        function updatePinch(pinch) {
            updateFov(basicCamera.fieldOfView * (1.0 + (pinch.previousScale - pinch.scale) * pinchSensitivity))
        }

        onPinchUpdated: {
            updatePinch(pinch)
        }
        onPinchFinished: {
            updatePinch(pinch)
        }

        MouseArea {
            anchors.fill: parent

            propagateComposedEvents: true

            property point startPoint

            function updateView(mouse) {
                basicCamera.pan((startPoint.x - mouse.x) * sensitivity * basicCamera.fieldOfView / width, Qt.vector3d(0.0, 0.0, 1.0))
                basicCamera.tilt((mouse.y - startPoint.y) * sensitivity * basicCamera.fieldOfView / height)
                startPoint = Qt.point(mouse.x, mouse.y)
            }

            onPressed: {
                startPoint = Qt.point(mouse.x, mouse.y)
            }
            onPositionChanged: {
                updateView(mouse)
            }
            onReleased: {
                updateView(mouse)
            }
        }
    }
    Zoomer {
        id: zoomer

        fovMax: parent.fovMax
        defaultFov: parent.defaultFov
        fovMin: parent.fovMin

        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 45

        onFovChanged: {
            pinchArea.updateFov(fov);
        }
    }

    Shortcut {
        context: Qt.WindowShortcut
        enabled: scene3d.visible

        sequence: StandardKey.Save

        onActivated: {
            panoEntity.pano.dir = basicCamera.viewCenter
            panoEntity.pano.up = basicCamera.upVector
            panoEntity.pano.version = 7
            if (!panoEntity.updatePanorama()) {
                console.log("Unable to update panorama %1".arg(panorama))
            } else if (previewImage && Utility.fileExists(previewImage.source)) {
                scene3d.grabToImage(function(grabResult) {
                    if (!grabResult.saveToFile(Utility.toLocalFile(previewImage.source))) {
                        console.log("Unable save preview to file: %1".arg(previewImage.source))
                    }
                }, Qt.size(512, 512))
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.