mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-06-14 08:41:58 +02:00
[ui] Viewer3D: DefaultCameraController + better double click handling
* add DefaultCameraController: * mouse-only navigation * keyboard modifiers fallbacks for view re-centering (Ctrl+LeftClick) and fast zooming (Alt+RightClick) * improved double click handling for 3D Object Picking * moved logic/Timer to the CameraController * always use TrianglePicking but only activate the ObjectPicker when necessary
This commit is contained in:
parent
886ded7f19
commit
ecc376e3b6
3 changed files with 172 additions and 27 deletions
140
meshroom/ui/qml/Viewer/DefaultCameraController.qml
Normal file
140
meshroom/ui/qml/Viewer/DefaultCameraController.qml
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import Qt3D.Core 2.1
|
||||||
|
import Qt3D.Render 2.1
|
||||||
|
import Qt3D.Input 2.1
|
||||||
|
import Qt3D.Logic 2.0
|
||||||
|
import QtQml 2.2
|
||||||
|
|
||||||
|
Entity {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property Camera camera
|
||||||
|
property real translateSpeed: 75.0
|
||||||
|
property real tiltSpeed: 500.0
|
||||||
|
property real panSpeed: 500.0
|
||||||
|
property bool moving: pressed || actionAlt.active
|
||||||
|
readonly property alias controlPressed: actionControl.active
|
||||||
|
|
||||||
|
readonly property alias pressed: mouseHandler._pressed
|
||||||
|
signal mousePressed(var mouse)
|
||||||
|
signal mouseReleased(var mouse)
|
||||||
|
signal mouseClicked(var mouse)
|
||||||
|
signal mouseWheeled(var wheel)
|
||||||
|
signal mouseDoubleClicked(var mouse)
|
||||||
|
|
||||||
|
KeyboardDevice { id: keyboardSourceDevice }
|
||||||
|
MouseDevice { id: mouseSourceDevice }
|
||||||
|
|
||||||
|
MouseHandler {
|
||||||
|
id: mouseHandler
|
||||||
|
property bool _pressed
|
||||||
|
sourceDevice: mouseSourceDevice
|
||||||
|
onPressed: { _pressed = true; mousePressed(mouse) }
|
||||||
|
onReleased: { _pressed = false; mouseReleased(mouse) }
|
||||||
|
onClicked: mouseClicked(mouse)
|
||||||
|
onDoubleClicked: mouseDoubleClicked(mouse)
|
||||||
|
onWheel: {
|
||||||
|
var d = (root.camera.viewCenter.minus(root.camera.position)).length() * 0.2;
|
||||||
|
var tz = (wheel.angleDelta.y / 120) * d;
|
||||||
|
root.camera.translate(Qt.vector3d(0, 0, tz), Camera.DontTranslateViewCenter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogicalDevice {
|
||||||
|
id: cameraControlDevice
|
||||||
|
actions: [
|
||||||
|
Action {
|
||||||
|
id: actionLMB
|
||||||
|
inputs: [
|
||||||
|
ActionInput {
|
||||||
|
sourceDevice: mouseSourceDevice
|
||||||
|
buttons: [MouseEvent.LeftButton]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Action {
|
||||||
|
id: actionRMB
|
||||||
|
inputs: [
|
||||||
|
ActionInput {
|
||||||
|
sourceDevice: mouseSourceDevice
|
||||||
|
buttons: [MouseEvent.RightButton]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Action {
|
||||||
|
id: actionMMB
|
||||||
|
inputs: [
|
||||||
|
ActionInput {
|
||||||
|
sourceDevice: mouseSourceDevice
|
||||||
|
buttons: [MouseEvent.MiddleButton]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Action {
|
||||||
|
id: actionControl
|
||||||
|
inputs: [
|
||||||
|
ActionInput {
|
||||||
|
sourceDevice: keyboardSourceDevice
|
||||||
|
buttons: [Qt.Key_Control]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Action {
|
||||||
|
id: actionAlt
|
||||||
|
inputs: [
|
||||||
|
ActionInput {
|
||||||
|
sourceDevice: keyboardSourceDevice
|
||||||
|
buttons: [Qt.Key_Alt]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
axes: [
|
||||||
|
Axis {
|
||||||
|
id: axisMX
|
||||||
|
inputs: [
|
||||||
|
AnalogAxisInput {
|
||||||
|
sourceDevice: mouseSourceDevice
|
||||||
|
axis: MouseDevice.X
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Axis {
|
||||||
|
id: axisMY
|
||||||
|
inputs: [
|
||||||
|
AnalogAxisInput {
|
||||||
|
sourceDevice: mouseSourceDevice
|
||||||
|
axis: MouseDevice.Y
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
components: [
|
||||||
|
FrameAction {
|
||||||
|
onTriggered: {
|
||||||
|
if(actionLMB.active) { // rotate
|
||||||
|
var rx = -axisMX.value;
|
||||||
|
var ry = -axisMY.value;
|
||||||
|
root.camera.panAboutViewCenter(root.panSpeed * rx * dt, Qt.vector3d(0,1,0))
|
||||||
|
root.camera.tiltAboutViewCenter(root.tiltSpeed * ry * dt)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(actionMMB.active) { // translate
|
||||||
|
var d = (root.camera.viewCenter.minus(root.camera.position)).length() * 0.03;
|
||||||
|
var tx = axisMX.value * root.translateSpeed * d;
|
||||||
|
var ty = axisMY.value * root.translateSpeed * d;
|
||||||
|
root.camera.translate(Qt.vector3d(-tx, -ty, 0).times(dt))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(actionAlt.active && actionRMB.active) { // zoom with alt + RMD
|
||||||
|
var d = (root.camera.viewCenter.minus(root.camera.position)).length() * 0.1;
|
||||||
|
var tz = axisMX.value * root.translateSpeed * d;
|
||||||
|
root.camera.translate(Qt.vector3d(0, 0, tz).times(dt), Camera.DontTranslateViewCenter)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -98,32 +98,42 @@ FocusScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MayaCameraController {
|
DefaultCameraController {
|
||||||
id: cameraController
|
id: cameraController
|
||||||
camera: mainCamera
|
camera: mainCamera
|
||||||
onMousePressed: {
|
onMousePressed: {
|
||||||
mouse.accepted = false
|
|
||||||
scene3D.forceActiveFocus()
|
scene3D.forceActiveFocus()
|
||||||
|
if(mouse.button == Qt.LeftButton)
|
||||||
|
{
|
||||||
|
if(!doubleClickTimer.running)
|
||||||
|
doubleClickTimer.restart()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
doubleClickTimer.stop()
|
||||||
}
|
}
|
||||||
onMouseReleased: {
|
onMouseReleased: {
|
||||||
if(moving)
|
if(moving)
|
||||||
return;
|
return
|
||||||
switch(mouse.button) {
|
if(mouse.button == Qt.RightButton)
|
||||||
case Qt.LeftButton:
|
{
|
||||||
break;
|
contextMenu.popup()
|
||||||
case Qt.RightButton:
|
|
||||||
contextMenu.x = mouse.x;
|
|
||||||
contextMenu.y = mouse.y;
|
|
||||||
contextMenu.open();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Manually handle double click to activate object picking
|
||||||
|
// for camera re-centering only during a short amount of time
|
||||||
|
Timer {
|
||||||
|
id: doubleClickTimer
|
||||||
|
running: false
|
||||||
|
interval: 300
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
components: [
|
components: [
|
||||||
RenderSettings {
|
RenderSettings {
|
||||||
// To avoid performance drop, only pick triangles when not moving the camera
|
// To avoid performance drops, picking is only enabled under certain circumstances (see ObjectPicker below)
|
||||||
pickingSettings.pickMethod: cameraController.moving ? PickingSettings.BoundingVolumePicking : PickingSettings.TrianglePicking
|
pickingSettings.pickMethod: PickingSettings.TrianglePicking
|
||||||
|
pickingSettings.pickResultMode: PickingSettings.NearestPick
|
||||||
renderPolicy: RenderSettings.Always
|
renderPolicy: RenderSettings.Always
|
||||||
activeFrameGraph: Viewport {
|
activeFrameGraph: Viewport {
|
||||||
normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0)
|
normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0)
|
||||||
|
@ -156,23 +166,17 @@ FocusScope {
|
||||||
|
|
||||||
components: [scene, transform, picker]
|
components: [scene, transform, picker]
|
||||||
|
|
||||||
|
// ObjectPicker used for view re-centering
|
||||||
ObjectPicker {
|
ObjectPicker {
|
||||||
id: picker
|
id: picker
|
||||||
|
// Triangle picking is expensive
|
||||||
|
// Only activate it when a double click may happen or when the 'Control' key is pressed
|
||||||
|
enabled: cameraController.controlPressed || doubleClickTimer.running
|
||||||
hoverEnabled: false
|
hoverEnabled: false
|
||||||
onPressed: {
|
onPressed: {
|
||||||
if(Qt.LeftButton & pick.buttons)
|
if(pick.button == Qt.LeftButton)
|
||||||
{
|
mainCamera.viewCenter = pick.worldIntersection
|
||||||
if(!doubleClickTimer.running)
|
doubleClickTimer.stop()
|
||||||
doubleClickTimer.start()
|
|
||||||
else
|
|
||||||
mainCamera.viewCenter = pick.worldIntersection
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: doubleClickTimer
|
|
||||||
running: false
|
|
||||||
interval: 400
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +243,7 @@ FocusScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// menus
|
// Menu
|
||||||
Menu {
|
Menu {
|
||||||
id: contextMenu
|
id: contextMenu
|
||||||
MenuItem {
|
MenuItem {
|
||||||
|
|
|
@ -2,6 +2,7 @@ module Viewer
|
||||||
|
|
||||||
Viewer2D 1.0 Viewer2D.qml
|
Viewer2D 1.0 Viewer2D.qml
|
||||||
Viewer3D 1.0 Viewer3D.qml
|
Viewer3D 1.0 Viewer3D.qml
|
||||||
|
DefaultCameraController 1.0 DefaultCameraController.qml
|
||||||
MayaCameraController 1.0 MayaCameraController.qml
|
MayaCameraController 1.0 MayaCameraController.qml
|
||||||
Locator3D 1.0 Locator3D.qml
|
Locator3D 1.0 Locator3D.qml
|
||||||
Grid3D 1.0 Grid3D.qml
|
Grid3D 1.0 Grid3D.qml
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue