[ui] Viewer3D: new Trackball camera manipulator

This commit is contained in:
Yann Lanthony 2018-12-07 18:22:57 +01:00
parent 6836f7fd93
commit 87d5a62846
6 changed files with 148 additions and 24 deletions

View file

@ -15,6 +15,9 @@ Entity {
property bool moving: pressed || (actionAlt.active && keyboardHandler._pressed)
property alias focus: keyboardHandler.focus
readonly property bool pickingActive: actionControl.active && keyboardHandler._pressed
property real rotationSpeed: 2.0
property size windowSize
property real trackballSize: 1.0
readonly property alias pressed: mouseHandler._pressed
signal mousePressed(var mouse)
@ -29,10 +32,20 @@ Entity {
MouseHandler {
id: mouseHandler
property bool _pressed
property point lastPosition
property point currentPosition
sourceDevice: mouseSourceDevice
onPressed: { _pressed = true; mousePressed(mouse) }
onReleased: { _pressed = false; mouseReleased(mouse) }
onPressed: {
_pressed = true;
currentPosition = lastPosition = Qt.point(mouse.x, mouse.y);
mousePressed(mouse);
}
onReleased: {
_pressed = false;
mouseReleased(mouse);
}
onClicked: mouseClicked(mouse)
onPositionChanged: { currentPosition = Qt.point(mouse.x, mouse.y) }
onDoubleClicked: mouseDoubleClicked(mouse)
onWheel: {
var d = (root.camera.viewCenter.minus(root.camera.position)).length() * 0.2;
@ -135,6 +148,36 @@ Entity {
]
}
// Based on the C++ version from https://github.com/cjmdaixi/Qt3DTrackball
function projectToTrackball(screenCoords)
{
var sx = screenCoords.x, sy = windowSize.height - screenCoords.y;
var p2d = Qt.vector2d(sx / windowSize.width - 0.5, sy / windowSize.height - 0.5);
var z = 0.0;
var r2 = trackballSize * trackballSize;
var lengthSquared = p2d.length() * p2d.length();
if(lengthSquared <= r2 * 0.5)
z = Math.sqrt(r2 - lengthSquared);
else
z = r2 * 0.5 / p2d.length();
return Qt.vector3d(p2d.x, p2d.y, z);
}
function clamp(x)
{
return Math.max(-1, Math.min(x, 1));
}
function createRotation(firstPoint, nextPoint)
{
var lastPos3D = projectToTrackball(firstPoint).normalized();
var currentPos3D = projectToTrackball(nextPoint).normalized();
var obj = {};
obj.angle = Math.acos(clamp(currentPos3D.dotProduct(lastPos3D)));
obj.dir = currentPos3D.crossProduct(lastPos3D);
return obj;
}
components: [
FrameAction {
onTriggered: {
@ -145,11 +188,14 @@ Entity {
root.camera.translate(Qt.vector3d(-tx, -ty, 0).times(dt))
return;
}
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)
if(actionLMB.active){ // trackball rotation
var res = createRotation(mouseHandler.lastPosition, mouseHandler.currentPosition);
var transform = root.camera.components[1]; // transform is camera first component
var currentRotation = transform.rotation;
var rotatedAxis = Scene3DHelper.rotatedVector(transform.rotation, res.dir);
res.angle *= rotationSpeed * dt;
root.camera.rotateAboutViewCenter(transform.fromAxisAndAngle(rotatedAxis, res.angle * Math.PI * 180));
mouseHandler.lastPosition = mouseHandler.currentPosition;
return;
}
if(actionAlt.active && actionRMB.active) { // zoom with alt + RMD