mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-08-02 00:08:29 +02:00
[ui] Viewer3D: TransformGizmo - ready to be set with absolute values
- Now, we can set the transformation with a position vector, Euler angles and a scale vector.
This commit is contained in:
parent
da765a5f98
commit
d0a78d96ab
4 changed files with 70 additions and 17 deletions
|
@ -188,6 +188,29 @@ class Transformations3DHelper(QObject):
|
||||||
|
|
||||||
return { "position": posMat, "rotation": rotMat, "scale": scaleMat, "quaternion": decomposition.get("quaternion") }
|
return { "position": posMat, "rotation": rotMat, "scale": scaleMat, "quaternion": decomposition.get("quaternion") }
|
||||||
|
|
||||||
|
@Slot(QVector3D, QVector3D, QVector3D, result=QMatrix4x4)
|
||||||
|
def computeModelMatrixWithEuler(self, translation, rotation, scale):
|
||||||
|
""" Compute a model matrix from three Vector3D.
|
||||||
|
Args:
|
||||||
|
translation (QVector3D): position in space (x, y, z)
|
||||||
|
rotation (QVector3D): Euler angles in degrees (x, y, z)
|
||||||
|
scale (QVector3D): scale of the object (x, y, z)
|
||||||
|
Returns:
|
||||||
|
QMatrix4x4: corresponding model matrix
|
||||||
|
"""
|
||||||
|
posMat = QMatrix4x4()
|
||||||
|
posMat.translate(translation)
|
||||||
|
|
||||||
|
quaternion = QQuaternion.fromEulerAngles(rotation)
|
||||||
|
rotMat = self.quaternionToRotationMatrix(quaternion)
|
||||||
|
|
||||||
|
scaleMat = QMatrix4x4()
|
||||||
|
scaleMat.scale(scale)
|
||||||
|
|
||||||
|
modelMat = posMat * rotMat * scaleMat
|
||||||
|
|
||||||
|
return modelMat
|
||||||
|
|
||||||
|
|
||||||
#---------- "Private" Methods ----------#
|
#---------- "Private" Methods ----------#
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,10 @@ Entity {
|
||||||
readonly property Camera camera : cameraController.camera
|
readonly property Camera camera : cameraController.camera
|
||||||
readonly property var windowSize: cameraController.windowSize
|
readonly property var windowSize: cameraController.windowSize
|
||||||
readonly property alias objectTransform : transformGizmo.objectTransform // The Transform the object should use
|
readonly property alias objectTransform : transformGizmo.objectTransform // The Transform the object should use
|
||||||
|
readonly property alias updateTransformations: transformGizmo.updateTransformations // Function to update the transformations
|
||||||
|
|
||||||
signal pickedChanged(bool pressed)
|
signal pickedChanged(bool pressed)
|
||||||
|
signal gizmoChanged(var translation, var rotation, var scale)
|
||||||
|
|
||||||
onPickedChanged: {
|
onPickedChanged: {
|
||||||
cameraController.loseMouseFocus = pressed // Notify the camera if the transform takes/releases the focus
|
cameraController.loseMouseFocus = pressed // Notify the camera if the transform takes/releases the focus
|
||||||
|
@ -30,5 +32,8 @@ Entity {
|
||||||
onPickedChanged: {
|
onPickedChanged: {
|
||||||
root.pickedChanged(pressed)
|
root.pickedChanged(pressed)
|
||||||
}
|
}
|
||||||
|
onGizmoChanged: {
|
||||||
|
root.gizmoChanged(translation, rotation, scale)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,9 +14,29 @@ Entity {
|
||||||
property var windowSize
|
property var windowSize
|
||||||
property var frontLayerComponent
|
property var frontLayerComponent
|
||||||
property var window
|
property var window
|
||||||
readonly property Transform objectTransform : Transform {}
|
|
||||||
|
readonly property Transform objectTransform : Transform {
|
||||||
|
translation: gizmoDisplayTransform.translation
|
||||||
|
rotation: gizmoDisplayTransform.rotation
|
||||||
|
scale3D: Qt.vector3d(1,1,1)
|
||||||
|
}
|
||||||
|
readonly property var updateTransformations: function updateTransformations(translation, rotation, scale) {
|
||||||
|
const gizmoModelMat = Transformations3DHelper.computeModelMatrixWithEuler(translation, rotation, Qt.vector3d(1,1,1))
|
||||||
|
gizmoDisplayTransform.setMatrix(gizmoModelMat) // Update gizmo matrix and translation/rotation of the object (with binding)
|
||||||
|
objectTransform.scale3D = scale // Update the scale of the object
|
||||||
|
}
|
||||||
|
|
||||||
signal pickedChanged(bool pressed)
|
signal pickedChanged(bool pressed)
|
||||||
|
signal gizmoChanged(var translation, var rotation, var scale)
|
||||||
|
|
||||||
|
function emitGizmoChanged() {
|
||||||
|
const translation = gizmoDisplayTransform.translation // Position in space
|
||||||
|
const rotation = Qt.vector3d(gizmoDisplayTransform.rotationX, gizmoDisplayTransform.rotationY, gizmoDisplayTransform.rotationZ) // Euler angles
|
||||||
|
const scale = objectTransform.scale3D // Scale of the object
|
||||||
|
|
||||||
|
updateTransformations(translation, rotation, scale) // Optional: just to make sure the absolute values work well
|
||||||
|
gizmoChanged(translation, rotation, scale)
|
||||||
|
}
|
||||||
|
|
||||||
components: [gizmoDisplayTransform, mouseHandler, frontLayerComponent]
|
components: [gizmoDisplayTransform, mouseHandler, frontLayerComponent]
|
||||||
|
|
||||||
|
@ -38,31 +58,27 @@ Entity {
|
||||||
/***** TRANSFORMATIONS (using local vars) *****/
|
/***** TRANSFORMATIONS (using local vars) *****/
|
||||||
|
|
||||||
function doRelativeTranslation(initialModelMatrix, translateVec) {
|
function doRelativeTranslation(initialModelMatrix, translateVec) {
|
||||||
Transformations3DHelper.relativeLocalTranslate(gizmoDisplayTransform, initialModelMatrix.position, initialModelMatrix.rotation, initialModelMatrix.scale, translateVec) // Update gizmo matrix
|
Transformations3DHelper.relativeLocalTranslate(gizmoDisplayTransform, initialModelMatrix.position, initialModelMatrix.rotation, initialModelMatrix.scale, translateVec) // Update gizmo matrix and object matrix with binding
|
||||||
Transformations3DHelper.relativeLocalTranslate(objectTransform, initialModelMatrix.position, initialModelMatrix.rotation, initialModelMatrix.scale, translateVec) // Update object matrix
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function doRelativeRotation(initialModelMatrix, axis, degree) {
|
function doRelativeRotation(initialModelMatrix, axis, degree) {
|
||||||
Transformations3DHelper.relativeLocalRotate(gizmoDisplayTransform, initialModelMatrix.position, initialModelMatrix.quaternion, initialModelMatrix.scale, axis, degree) // Update gizmo matrix
|
Transformations3DHelper.relativeLocalRotate(gizmoDisplayTransform, initialModelMatrix.position, initialModelMatrix.quaternion, initialModelMatrix.scale, axis, degree) // Update gizmo matrix and object matrix with binding
|
||||||
Transformations3DHelper.relativeLocalRotate(objectTransform, initialModelMatrix.position, initialModelMatrix.quaternion, initialModelMatrix.scale, axis, degree) // Update object matrix
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function doRelativeScale(initialModelMatrix, scaleVec) {
|
function doRelativeScale(initialModelMatrix, scaleVec) {
|
||||||
Transformations3DHelper.relativeLocalScale(objectTransform, initialModelMatrix.position, initialModelMatrix.rotation, initialModelMatrix.scale, scaleVec) // Update object matrix
|
Transformations3DHelper.relativeLocalScale(objectTransform, initialModelMatrix.position, initialModelMatrix.rotation, initialModelMatrix.scale, scaleVec) // Update only object matrix
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetTranslation() {
|
function resetTranslation() {
|
||||||
gizmoDisplayTransform.translation = Qt.vector3d(0,0,0)
|
gizmoDisplayTransform.translation = Qt.vector3d(0,0,0) // Reset gizmo matrix and object matrix with binding
|
||||||
objectTransform.translation = Qt.vector3d(0,0,0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetRotation() {
|
function resetRotation() {
|
||||||
gizmoDisplayTransform.rotation = Qt.quaternion(1,0,0,0)
|
gizmoDisplayTransform.rotation = Qt.quaternion(1,0,0,0) // Reset gizmo matrix and object matrix with binding
|
||||||
objectTransform.rotation = Qt.quaternion(1,0,0,0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetScale() {
|
function resetScale() {
|
||||||
objectTransform.scale3D = Qt.vector3d(1,1,1)
|
objectTransform.scale3D = Qt.vector3d(1,1,1) // Reset only object matrix
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetATransformType(transformType) {
|
function resetATransformType(transformType) {
|
||||||
|
@ -71,6 +87,7 @@ Entity {
|
||||||
case TransformGizmo.Type.ROTATION: resetRotation(); break
|
case TransformGizmo.Type.ROTATION: resetRotation(); break
|
||||||
case TransformGizmo.Type.SCALE: resetScale(); break
|
case TransformGizmo.Type.SCALE: resetScale(); break
|
||||||
}
|
}
|
||||||
|
emitGizmoChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** DEVICES *****/
|
/***** DEVICES *****/
|
||||||
|
@ -84,7 +101,7 @@ Entity {
|
||||||
property bool enabled: false
|
property bool enabled: false
|
||||||
|
|
||||||
onPositionChanged: {
|
onPositionChanged: {
|
||||||
if (objectPicker) {
|
if (objectPicker && objectPicker.button === Qt.LeftButton) {
|
||||||
// Get the selected axis
|
// Get the selected axis
|
||||||
let pickedAxis
|
let pickedAxis
|
||||||
switch(objectPicker.gizmoAxis) {
|
switch(objectPicker.gizmoAxis) {
|
||||||
|
@ -137,7 +154,8 @@ Entity {
|
||||||
const gizmoToCameraVector = camera.position.toVector4d().minus(gizmoCenterPoint)
|
const gizmoToCameraVector = camera.position.toVector4d().minus(gizmoCenterPoint)
|
||||||
const orientation = gizmoLocalAxisVector.dotProduct(gizmoToCameraVector) > 0 ? 1 : -1
|
const orientation = gizmoLocalAxisVector.dotProduct(gizmoToCameraVector) > 0 ? 1 : -1
|
||||||
|
|
||||||
if (angle !== 0) doRelativeRotation(objectPicker.modelMatrix, pickedAxis, angle*orientation)
|
if (angle !== 0) doRelativeRotation(objectPicker.modelMatrix, pickedAxis, angle*orientation) // Do a rotation from the initial Object Model Matrix when we picked the gizmo
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,18 +174,23 @@ Entity {
|
||||||
let offset = (mouseVector.length() - scaleUnit) * sensibility
|
let offset = (mouseVector.length() - scaleUnit) * sensibility
|
||||||
offset = (offset < 0) ? offset * 3 : offset // Used to make it more sensible when we want to reduce the scale (because the action field is shorter)
|
offset = (offset < 0) ? offset * 3 : offset // Used to make it more sensible when we want to reduce the scale (because the action field is shorter)
|
||||||
|
|
||||||
if (offset) doRelativeScale(objectPicker.modelMatrix, pickedAxis.times(offset))
|
if (offset) doRelativeScale(objectPicker.modelMatrix, pickedAxis.times(offset)) // Do a scale from the initial Object Model Matrix when we picked the gizmo
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
onReleased: {
|
if(objectPicker && objectPicker.button === Qt.RightButton) {
|
||||||
if(objectPicker && mouse.button === Qt.RightButton) {
|
|
||||||
resetMenu.updateTypeBeforePopup(objectPicker.gizmoType)
|
resetMenu.updateTypeBeforePopup(objectPicker.gizmoType)
|
||||||
resetMenu.popup(window)
|
resetMenu.popup(window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onReleased: {
|
||||||
|
if(objectPicker && mouse.button === Qt.LeftButton) {
|
||||||
|
emitGizmoChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu {
|
Menu {
|
||||||
|
|
|
@ -15,6 +15,7 @@ ObjectPicker {
|
||||||
property int gizmoType
|
property int gizmoType
|
||||||
property point screenPoint
|
property point screenPoint
|
||||||
property var modelMatrix
|
property var modelMatrix
|
||||||
|
property int button
|
||||||
|
|
||||||
signal pickedChanged(var picker)
|
signal pickedChanged(var picker)
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ ObjectPicker {
|
||||||
mouseController.objectPicker = this
|
mouseController.objectPicker = this
|
||||||
root.isPressed = true
|
root.isPressed = true
|
||||||
screenPoint = pick.position
|
screenPoint = pick.position
|
||||||
|
button = pick.button
|
||||||
pickedChanged(this)
|
pickedChanged(this)
|
||||||
}
|
}
|
||||||
onEntered: {
|
onEntered: {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue