放大Qt3D的相机

时间:2017-10-25 09:31:06

标签: c++ qt qml pinchzoom qt3d

如何为 Qt3D Camera的FOV实现双指捏手势处理?

FirstPersonCameraControllerOrbitCameraController个摄像头控制器可以处理鼠标/触控板事件。后者甚至具有zoomLimit属性,但其含义不是我需要缩放场景(从立方体贴图内部,摄像机位置固定为(0, 0, 0))。我用前者。它可以正确处理鼠标拖动和单指触摸事件,但不会处理双指捏状手势。

我可以用简单的方式自定义PinchArea Qt3D Camera进行互动吗?或 Qt Quick 的API在这个意义上与 Qt3D 的API正交?

2 个答案:

答案 0 :(得分:1)

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

  

pinch参数提供有关捏合手势的信息,   包括夹点的刻度,中心和角度。这些价值观   仅反映自当前手势开始以来的变化,以及   因此不受最小和最大限制的限制   捏财产。

所以你应该能够做到这样的事情:

Camera {
    id: myCamera
}

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

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

property Camera myCamera

答案 1 :(得分:0)

我最终得到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))
            }
        }
    }
}