如何为 Qt3D Camera
的FOV实现双指捏手势处理?
有FirstPersonCameraController
和OrbitCameraController
个摄像头控制器可以处理鼠标/触控板事件。后者甚至具有zoomLimit
属性,但其含义不是我需要缩放场景(从立方体贴图内部,摄像机位置固定为(0, 0, 0)
)。我用前者。它可以正确处理鼠标拖动和单指触摸事件,但不会处理双指捏状手势。
我可以用简单的方式自定义PinchArea
与 Qt3D Camera
进行互动吗?或 Qt Quick 的API在这个意义上与 Qt3D 的API正交?
答案 0 :(得分:1)
使用PinchArea的pinchUpdated事件查找有关Pinch的信息:根据文档
pinch参数提供有关捏合手势的信息, 包括夹点的刻度,中心和角度。这些价值观 仅反映自当前手势开始以来的变化,以及 因此不受最小和最大限制的限制 捏财产。
所以你应该能够做到这样的事情:
Camera {
id: myCamera
}
PinchArea {
onPinchUpdated: {
myCamera.fieldOfView = pinch.scale*someFactor
}
}
这可以在任何有权访问Pinch和相机的自定义QML中完成。 如果是自定义脚本,您可以将相机作为属性传递
property Camera myCamera
答案 1 :(得分:0)
我最终得到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))
}
}
}
}