Zoom Qt3D 的相机

4
如何为 Qt3D 相机的FOV实现双指捏合手势处理?
FirstPersonCameraControllerOrbitCameraController相机控制器来处理鼠标/触摸板事件。后者甚至具有zoomLimit属性,但是它的含义不是我需要缩放场景(从立方体贴图内部,相机位置固定为(0,0,0))。我使用前者。它可以正确处理鼠标拖动和单指触摸事件,但无法处理双指类似于捏合手势的事件。
我能否简单地自定义PinchAreaQt3D相机进行交互?或者说Qt Quick的API在这方面与Qt3D的API不相关?
2个回答

1

使用PinchArea的pinchUpdated事件来查找有关Pinch的信息:根据文档

pinch参数提供有关Pinch手势的信息,包括Pinch的比例、中心和角度。这些值仅反映当前手势开始后的变化,因此不受pinch属性中最小和最大限制的限制。

因此,您应该能够执行以下操作:

Camera {
    id: myCamera
}

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

这可以在任何具有Pinch和Camera访问权限的自定义QML中完成。如果它是一个自定义脚本,你可以将相机作为属性传递。
property Camera myCamera

1

我最终使用了PinchAreaMouseArea的组合:

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))
            }
        }
    }
}

PanoEntity是什么?是用来创建全景图的吗?它是开源的吗? - Aleksey Kontsevich
它是开源的。如果你找到了,你可以直接从Stackoverflow上复制粘贴。 - Tomilov Anatoliy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接