diff options
author | Candice Bentéjac <candice.bentejac@gmail.com> | 2022-11-10 19:58:24 +0300 |
---|---|---|
committer | Candice Bentéjac <candice.bentejac@gmail.com> | 2022-11-10 19:58:24 +0300 |
commit | 1bfc7cd08328ff90340d07919ae3245311dcb646 (patch) | |
tree | 77e71b645d445fa5ee9aee92c43b226dcc220dbc | |
parent | d9c330eba8bbe4cb6fff830947d976e3af22bb8a (diff) | |
parent | c4d44aa55022d36024f3799107d340b5ca695d67 (diff) |
Merge branch 'develop' into dev/qt6-migrationdev/qt6-migration
-rw-r--r-- | bin/ion_start_meshroom.sh | 2 | ||||
-rw-r--r-- | meshroom/ui/app.py | 5 | ||||
-rw-r--r-- | meshroom/ui/components/scene3D.py | 114 | ||||
-rwxr-xr-x | meshroom/ui/qml/GraphEditor/GraphEditor.qml | 42 | ||||
-rw-r--r-- | meshroom/ui/qml/Viewer/PanoramaViewer.qml | 57 | ||||
-rw-r--r-- | meshroom/ui/qml/Viewer/Viewer2D.qml | 60 | ||||
-rw-r--r-- | meshroom/ui/qml/Viewer3D/MeshingBoundingBox.qml | 50 | ||||
-rwxr-xr-x | meshroom/ui/qml/main.qml | 13 |
8 files changed, 282 insertions, 61 deletions
diff --git a/bin/ion_start_meshroom.sh b/bin/ion_start_meshroom.sh index 5215e054..54de022e 100644 --- a/bin/ion_start_meshroom.sh +++ b/bin/ion_start_meshroom.sh @@ -1,3 +1,4 @@ +#!/bin/bash PATH_QML=${ION_CONTAINER_ROOT}/base/qml/QtQuick PATH_QML_TRUE=`readlink -f $PATH_QML`/../ @@ -6,6 +7,5 @@ PATH_PLUGIN_TRUE=`readlink -f $PATH_PLUGIN`/../ export QML2_IMPORT_PATH=$PATH_QML_TRUE:$QML2_IMPORT_PATH export QT_PLUGIN_PATH=$PATH_PLUGIN_TRUE:$QT_PLUGIN_PATH -export ALICEVISION_ROOT=${ION_CONTAINER_ROOT}/base python ${ION_CONTAINER_ROOT}/base/meshroom/meshroom/ui diff --git a/meshroom/ui/app.py b/meshroom/ui/app.py index 5e06a92a..fe910a09 100644 --- a/meshroom/ui/app.py +++ b/meshroom/ui/app.py @@ -343,8 +343,13 @@ class MeshroomApp(QApplication): } ] + def _default8bitViewerEnabled(self): + return bool(os.environ.get("MESHROOM_USE_8BIT_VIEWER", False)) + + licensesModel = Property("QVariantList", _licensesModel, constant=True) pipelineTemplateFilesChanged = Signal() recentProjectFilesChanged = Signal() pipelineTemplateFiles = Property("QVariantList", _pipelineTemplateFiles, notify=pipelineTemplateFilesChanged) recentProjectFiles = Property("QVariantList", _recentProjectFiles, notify=recentProjectFilesChanged) + default8bitViewerEnabled = Property(bool, _default8bitViewerEnabled, constant=True) diff --git a/meshroom/ui/components/scene3D.py b/meshroom/ui/components/scene3D.py index b7c04d85..ad03464e 100644 --- a/meshroom/ui/components/scene3D.py +++ b/meshroom/ui/components/scene3D.py @@ -1,4 +1,4 @@ -from math import acos, pi, sqrt +from math import acos, pi, sqrt, atan2, cos, sin, asin from PySide6.QtCore import QObject, Slot, QSize, Signal, QPointF from PySide6.Qt3DCore import Qt3DCore @@ -110,6 +110,101 @@ class Transformations3DHelper(QObject): # ---------- Exposed to QML ---------- # + @Slot(QVector3D, QVector3D, result=QQuaternion) + def rotationBetweenAandB(self, A, B): + + A = A/A.length() + B = B/B.length() + + # Get rotation matrix between 2 vectors + v = QVector3D.crossProduct(A, B) + s = v.length() + c = QVector3D.dotProduct(A, B) + return QQuaternion.fromAxisAndAngle(v / s, atan2(s, c) * 180 / pi) + + @Slot(QVector3D, result=QVector3D) + def fromEquirectangular(self, vector): + return QVector3D(cos(vector.x()) * sin(vector.y()), sin(vector.x()), cos(vector.x()) * cos(vector.y())) + + @Slot(QVector3D, result=QVector3D) + def toEquirectangular(self, vector): + return QVector3D(asin(vector.y()), atan2(vector.x(), vector.z()), 0) + + @Slot(QVector3D, QVector2D, QVector2D, result=QVector3D) + def updatePanorama(self, euler, ptStart, ptEnd): + + delta = 1e-3 + + #Get initial rotation + qStart = QQuaternion.fromEulerAngles(euler.y(), euler.x(), euler.z()) + + #Convert input to points on unit sphere + vStart = self.fromEquirectangular(QVector3D(ptStart)) + vStartdY = self.fromEquirectangular(QVector3D(ptStart.x(), ptStart.y() + delta, 0)) + vEnd = self.fromEquirectangular(QVector3D(ptEnd)) + + qAdd = QQuaternion.rotationTo(vStart, vEnd) + + + #Get the 3D point on unit sphere which would correspond to the no rotation +X + vCurrent = qAdd.rotatedVector(vStartdY) + vIdeal = self.fromEquirectangular(QVector3D(ptEnd.x(), ptEnd.y() + delta, 0)) + + #project on rotation plane + lambdaEnd = 1 / QVector3D.dotProduct(vEnd, vCurrent) + lambdaIdeal = 1 / QVector3D.dotProduct(vEnd, vIdeal) + vPlaneCurrent = lambdaEnd * vCurrent + vPlaneIdeal = lambdaIdeal * vIdeal + + #Get the directions + rotStart = (vPlaneCurrent - vEnd).normalized() + rotEnd = (vPlaneIdeal - vEnd).normalized() + + # Get rotation matrix between 2 vectors + v = QVector3D.crossProduct(rotEnd, rotStart) + s = QVector3D.dotProduct(v, vEnd) + c = QVector3D.dotProduct(rotStart, rotEnd) + angle = atan2(s, c) * 180 / pi + + qImage = QQuaternion.fromAxisAndAngle(vEnd, -angle) + + return (qImage * qAdd * qStart).toEulerAngles() + + @Slot(QVector3D, QVector2D, QVector2D, result=QVector3D) + def updatePanoramaInPlane(self, euler, ptStart, ptEnd): + + delta = 1e-3 + + #Get initial rotation + qStart = QQuaternion.fromEulerAngles(euler.y(), euler.x(), euler.z()) + + #Convert input to points on unit sphere + vStart = self.fromEquirectangular(QVector3D(ptStart)) + vEnd = self.fromEquirectangular(QVector3D(ptEnd)) + + #Get the 3D point on unit sphere which would correspond to the no rotation +X + vIdeal = self.fromEquirectangular(QVector3D(ptStart.x(), ptStart.y() + delta, 0)) + + #project on rotation plane + lambdaEnd = 1 / QVector3D.dotProduct(vStart, vEnd) + lambdaIdeal = 1 / QVector3D.dotProduct(vStart, vIdeal) + vPlaneEnd = lambdaEnd * vEnd + vPlaneIdeal = lambdaIdeal * vIdeal + + #Get the directions + rotStart = (vPlaneEnd - vStart).normalized() + rotEnd = (vPlaneIdeal - vStart).normalized() + + # Get rotation matrix between 2 vectors + v = QVector3D.crossProduct(rotEnd, rotStart) + s = QVector3D.dotProduct(v, vStart) + c = QVector3D.dotProduct(rotStart, rotEnd) + angle = atan2(s, c) * 180 / pi + + qAdd = QQuaternion.fromAxisAndAngle(vStart, angle) + + return (qAdd * qStart).toEulerAngles() + @Slot(QVector4D, Qt3DRender.QCamera, QSize, result=QVector2D) def pointFromWorldToScreen(self, point, camera, windowSize): """ Compute the Screen point corresponding to a World Point. @@ -124,7 +219,7 @@ class Transformations3DHelper(QObject): viewMatrix = camera.transform().matrix().inverted() projectedPoint = (camera.projectionMatrix() * viewMatrix[0]).map(point) projectedPoint2D = QVector2D( - projectedPoint.x()/projectedPoint.w(), + projectedPoint.x()/projectedPoint.w(), projectedPoint.y()/projectedPoint.w() ) @@ -146,7 +241,7 @@ class Transformations3DHelper(QObject): initialScaleMat (QMatrix4x4): initial scale matrix translateVec (QVector3D): vector used for the local translation """ - # Compute the translation transformation matrix + # Compute the translation transformation matrix translationMat = QMatrix4x4() translationMat.translate(translateVec) @@ -246,6 +341,19 @@ class Transformations3DHelper(QObject): return modelMat + @Slot(QVector3D, result=QVector3D) + def convertRotationFromCV2GL(self, rotation): + """ Convert rotation (euler angles) from Computer Vision + to Computer Graphics coordinate system (like opengl). + """ + M = QQuaternion.fromAxisAndAngle(QVector3D(1, 0, 0), 180.0) + + quaternion = QQuaternion.fromEulerAngles(rotation) + + U = M * quaternion * M + + return U.toEulerAngles() + @Slot(QVector3D, QMatrix4x4, Qt3DRender.QCamera, QSize, result=float) def computeScaleUnitFromModelMatrix(self, axis, modelMat, camera, windowSize): """ Compute the length of the screen projected vector axis unit transformed by the model matrix. diff --git a/meshroom/ui/qml/GraphEditor/GraphEditor.qml b/meshroom/ui/qml/GraphEditor/GraphEditor.qml index 19683cda..6c105930 100755 --- a/meshroom/ui/qml/GraphEditor/GraphEditor.qml +++ b/meshroom/ui/qml/GraphEditor/GraphEditor.qml @@ -117,20 +117,34 @@ Item { return mapToItem(draggable, mouseArea.width / 2, mouseArea.height / 2) } - Keys.onPressed: function (event) { - if (event.key === Qt.Key_F) - fit() - if (event.key === Qt.Key_Delete) - if (event.modifiers == Qt.AltModifier) - uigraph.removeNodesFrom(uigraph.selectedNodes) - else - uigraph.removeNodes(uigraph.selectedNodes) - if (event.key === Qt.Key_D) - duplicateNode(event.modifiers == Qt.AltModifier) - if (event.key === Qt.Key_C && event.modifiers == Qt.ControlModifier) - copyNodes() - if (event.key === Qt.Key_V && event.modifiers == Qt.ControlModifier) - pasteNodes() + Keys.onPressed: { + if (event.key === Qt.Key_F) { + fit(); + } + else if (event.key === Qt.Key_Delete) { + if (event.modifiers == Qt.AltModifier) { + uigraph.removeNodesFrom(uigraph.selectedNodes); + } + else { + uigraph.removeNodes(uigraph.selectedNodes); + } + } + else if (event.key === Qt.Key_D) { + duplicateNode(event.modifiers == Qt.AltModifier); + } + else if (event.key === Qt.Key_C && event.modifiers == Qt.ControlModifier) { + copyNodes(); + } + else if (event.key === Qt.Key_V && event.modifiers == Qt.ControlModifier) { + pasteNodes(); + } + else if (event.key == Qt.Key_Tab) { + event.accepted = true; + if (mouseArea.containsMouse) { + newNodeMenu.spawnPosition = mouseArea.mapToItem(draggable, mouseArea.mouseX, mouseArea.mouseY); + newNodeMenu.popup(); + } + } } MouseArea { diff --git a/meshroom/ui/qml/Viewer/PanoramaViewer.qml b/meshroom/ui/qml/Viewer/PanoramaViewer.qml index d2439902..157eb2e3 100644 --- a/meshroom/ui/qml/Viewer/PanoramaViewer.qml +++ b/meshroom/ui/qml/Viewer/PanoramaViewer.qml @@ -59,6 +59,10 @@ AliceVision.PanoramaViewer { property var xStart : 0 property var yStart : 0 + property var previous_yaw: 0; + property var previous_pitch: 0; + property var previous_roll: 0; + property double yaw: 0; property double pitch: 0; property double roll: 0; @@ -132,18 +136,43 @@ AliceVision.PanoramaViewer { // Rotate Panorama if (isRotating && isEditable) { - var xoffset = mouse.x - lastX; - var yoffset = mouse.y - lastY; - lastX = mouse.x; - lastY = mouse.y; - - // Update Euler Angles - if (mouse.modifiers & Qt.AltModifier) { - root.roll = limitAngle(root.roll + toDegrees((xoffset / width) * mouseMultiplier)) - } - else { - root.yaw = limitAngle(root.yaw + toDegrees((xoffset / width) * mouseMultiplier)) - root.pitch = limitPitch(root.pitch + toDegrees(-(yoffset / height) * mouseMultiplier)) + + var nx = Math.max(0, mouse.x) + var nx = Math.min(width - 1, mouse.x) + var ny = Math.max(0, mouse.y) + var ny = Math.min(height - 1, mouse.y) + + var xoffset = nx - lastX; + var yoffset = ny - lastY; + + if (xoffset != 0 || yoffset !=0) + { + var latitude_start = (yStart / height) * Math.PI - (Math.PI / 2); + var longitude_start = ((xStart / width) * 2 * Math.PI) - Math.PI; + var latitude_end = (ny / height) * Math.PI - ( Math.PI / 2); + var longitude_end = ((nx / width) * 2 * Math.PI) - Math.PI; + + var start_pt = Qt.vector2d(latitude_start, longitude_start) + var end_pt = Qt.vector2d(latitude_end, longitude_end) + + var previous_euler = Qt.vector3d(previous_yaw, previous_pitch, previous_roll) + + if (mouse.modifiers & Qt.ControlModifier) + { + var result = Transformations3DHelper.updatePanoramaInPlane(previous_euler, start_pt, end_pt) + root.pitch = result.x + root.yaw = result.y + root.roll = result.z + } + else + { + var result = Transformations3DHelper.updatePanorama(previous_euler, start_pt, end_pt) + root.pitch = result.x + root.yaw = result.y + root.roll = result.z + } + + } _reconstruction.setAttribute(activeNode.attribute("manualTransform.manualRotation.x"), Math.round(root.pitch)); @@ -160,6 +189,10 @@ AliceVision.PanoramaViewer { xStart = mouse.x; yStart = mouse.y; + + previous_yaw = yaw; + previous_pitch = pitch; + previous_roll = roll; } onReleased: function (mouse) { diff --git a/meshroom/ui/qml/Viewer/Viewer2D.qml b/meshroom/ui/qml/Viewer/Viewer2D.qml index d8d043da..7efa2e35 100644 --- a/meshroom/ui/qml/Viewer/Viewer2D.qml +++ b/meshroom/ui/qml/Viewer/Viewer2D.qml @@ -20,12 +20,13 @@ FocusScope { property Component floatViewerComp: Qt.createComponent("FloatImage.qml") property Component panoramaViewerComp: Qt.createComponent("PanoramaViewer.qml") - property alias useFloatImageViewer: displayHDR.checked + property var useFloatImageViewer: displayHDR.checked property alias useLensDistortionViewer: displayLensDistortionViewer.checked property alias usePanoramaViewer: displayPanoramaViewer.checked property var activeNodeFisheye: _reconstruction.activeNodes.get("PanoramaInit").node property bool cropFisheye : activeNodeFisheye ? activeNodeFisheye.attribute("useFisheye").value : false + property bool enable8bitViewer: MeshroomApp.default8bitViewerEnabled QtObject { id: m @@ -62,8 +63,10 @@ FocusScope { readonly property bool oiioPluginAvailable: oiioPluginLoader.status === Component.Ready Component.onCompleted: { - if(!aliceVisionPluginAvailable) + if(!aliceVisionPluginAvailable) { console.warn("Missing plugin qtAliceVision.") + displayHDR.checked = false + } if(!oiioPluginAvailable) console.warn("Missing plugin qtOIIO.") } @@ -96,7 +99,7 @@ FocusScope { } if(msfmDataLoader.status === Loader.Ready && msfmDataLoader.item) { - if(msfmDataLoader.item.status === MSfMData.Loading) + if(msfmDataLoader.item != null && msfmDataLoader.item.status === MSfMData.Loading) { res += " SfMData"; } @@ -370,12 +373,35 @@ FocusScope { active: root.aliceVisionPluginAvailable && (root.useFloatImageViewer || root.useLensDistortionViewer) && !panoramaViewerLoader.active visible: (floatImageViewerLoader.status === Loader.Ready) && active anchors.centerIn: parent + property var fittedOnce: false + property var previousWidth: 0 + property var previousHeight: 0 + onHeightChanged: { + /* Image size is not updated through a single signal with the floatImage viewer, unlike + * the simple QML image viewer: instead of updating straight away the width and height to x and + * y, the emitted signals look like: + * - width = -1, height = -1 + * - width = x, height = -1 + * - width = x, height = y + * We want to do the auto-fit on the first display of an image from the group, and then keep its + * scale when displaying another image from the group, so we need to know if an image in the + * group has already been auto-fitted. If we change the group of images (when another project is + * opened, for example, and the images have a different size), then another auto-fit needs to be + * performed */ + if ((!fittedOnce && imgContainer.image.status == Image.Ready && imgContainer.image.height > 0) || + (fittedOnce && ((width > 1 && previousWidth != width) || (height > 1 && previousHeight != height)))) { + fit(); + fittedOnce = true; + previousWidth = width; + previousHeight = height; + } + } // handle rotation/position based on available metadata rotation: { var orientation = m.imgMetadata ? m.imgMetadata["Orientation"] : 0 - switch(orientation) { + switch (orientation) { case "6": return 90; case "8": return -90; default: return 0; @@ -383,7 +409,7 @@ FocusScope { } onActiveChanged: { - if(active) { + if (active) { // instantiate and initialize a FeaturesViewer component dynamically using Loader.setSource // Note: It does not work to use previously created component, so we re-create it with setSource. // floatViewerComp.createObject(floatImageViewerLoader, { @@ -398,7 +424,7 @@ FocusScope { 'surface.gridColor' : Qt.binding(function(){ return lensDistortionImageToolbar.color;}), 'surface.subdivisions' : Qt.binding(function(){ return root.useFloatImageViewer ? 1 : lensDistortionImageToolbar.subdivisionsValue;}), 'viewerTypeString': Qt.binding(function(){ return displayLensDistortionViewer.checked ? "distortion" : "hdr";}), - 'surface.msfmData': Qt.binding(function() { return (msfmDataLoader.status === Loader.Ready && msfmDataLoader.item && msfmDataLoader.item.status === 2) ? msfmDataLoader.item : null; }), + 'surface.msfmData': Qt.binding(function() { return (msfmDataLoader.status === Loader.Ready && msfmDataLoader.item != null && msfmDataLoader.item.status === 2) ? msfmDataLoader.item : null; }), 'canBeHovered': false, 'idView': Qt.binding(function() { return _reconstruction.selectedViewId; }), 'cropFisheye': false @@ -406,6 +432,7 @@ FocusScope { } else { // Force the unload (instead of using Component.onCompleted to load it once and for all) is necessary since Qt 5.14 setSource("", {}) + fittedOnce = false } } @@ -474,7 +501,6 @@ FocusScope { } } - property var image: { if (floatImageViewerLoader.active) floatImageViewerLoader.item @@ -483,8 +509,8 @@ FocusScope { else qtImageViewerLoader.item } - width: image ? image.width : 1 - height: image ? image.height : 1 + width: image ? (image.width > 0 ? image.width : 1) : 1 + height: image ? (image.height > 0 ? image.height : 1) : 1 scale: 1.0 // FeatureViewer: display view extracted feature points @@ -953,12 +979,14 @@ FocusScope { padding: 0 Layout.minimumWidth: 0 checkable: true - checked: false + checked: root.aliceVisionPluginAvailable enabled: root.aliceVisionPluginAvailable + visible: root.enable8bitViewer onCheckedChanged : { - if(displayLensDistortionViewer.checked && checked){ + if (displayLensDistortionViewer.checked && checked) { displayLensDistortionViewer.checked = false; } + root.useFloatImageViewer = !root.useFloatImageViewer } } MaterialToolButton { @@ -989,9 +1017,11 @@ FocusScope { checked: false enabled: activeNode && isComputed onCheckedChanged : { - if((displayHDR.checked || displayPanoramaViewer.checked) && checked){ + if ((displayHDR.checked || displayPanoramaViewer.checked) && checked) { displayHDR.checked = false; displayPanoramaViewer.checked = false; + } else if (!checked) { + displayHDR.checked = true; } } } @@ -1021,15 +1051,15 @@ FocusScope { checked: false enabled: activeNode && isComputed onCheckedChanged : { - if(displayLensDistortionViewer.checked && checked){ + if (displayLensDistortionViewer.checked && checked) { displayLensDistortionViewer.checked = false; } - if(displayFisheyeCircleLoader.checked && checked){ + if (displayFisheyeCircleLoader.checked && checked) { displayFisheyeCircleLoader.checked = false; } } onEnabledChanged : { - if(!enabled){ + if (!enabled) { checked = false; } } diff --git a/meshroom/ui/qml/Viewer3D/MeshingBoundingBox.qml b/meshroom/ui/qml/Viewer3D/MeshingBoundingBox.qml index 92769efb..f0842f78 100644 --- a/meshroom/ui/qml/Viewer3D/MeshingBoundingBox.qml +++ b/meshroom/ui/qml/Viewer3D/MeshingBoundingBox.qml @@ -24,18 +24,22 @@ Entity { // Update node meshing slider values when the gizmo has changed: translation, rotation, scale, type transformGizmo.onGizmoChanged: { + + var rotationEuler_cv = Qt.vector3d(rotation.x, rotation.y, rotation.z) + var rotation_gl = Transformations3DHelper.convertRotationFromCV2GL(rotationEuler_cv) + switch(type) { case TransformGizmo.Type.TRANSLATION: { _reconstruction.setAttribute( root.currentMeshingNode.attribute("boundingBox.bboxTranslation"), - JSON.stringify([translation.x, translation.y, translation.z]) + JSON.stringify([translation.x, -translation.y, -translation.z]) ) break } case TransformGizmo.Type.ROTATION: { _reconstruction.setAttribute( root.currentMeshingNode.attribute("boundingBox.bboxRotation"), - JSON.stringify([rotation.x, rotation.y, rotation.z]) + JSON.stringify([rotation_gl.x, rotation_gl.y, rotation_gl.z]) ) break } @@ -50,8 +54,8 @@ Entity { _reconstruction.setAttribute( root.currentMeshingNode.attribute("boundingBox"), JSON.stringify([ - [translation.x, translation.y, translation.z], - [rotation.x, rotation.y, rotation.z], + [translation.x, -translation.y, -translation.z], + [rotation_gl.x, rotation_gl.y, rotation_gl.z], [scale.x, scale.y, scale.z] ]) ) @@ -63,13 +67,41 @@ Entity { // Translation values from node (vector3d because this is the type of QTransform.translation) property var nodeTranslation : Qt.vector3d( root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxTranslation.x").value : 0, - root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxTranslation.y").value : 0, - root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxTranslation.z").value : 0 + root.currentMeshingNode ? -root.currentMeshingNode.attribute("boundingBox.bboxTranslation.y").value : 0, + root.currentMeshingNode ? -root.currentMeshingNode.attribute("boundingBox.bboxTranslation.z").value : 0 ) + // Rotation values from node (3 separated values because QTransform stores Euler angles like this) - property var nodeRotationX: root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxRotation.x").value : 0 - property var nodeRotationY: root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxRotation.y").value : 0 - property var nodeRotationZ: root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxRotation.z").value : 0 + property var nodeRotationX: { + var rx = root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxRotation.x").value : 0 + var ry = root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxRotation.y").value : 0 + var rz = root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxRotation.z").value : 0 + + var rotationEuler_cv = Qt.vector3d(rx, ry, rz) + var rotation_gl = Transformations3DHelper.convertRotationFromCV2GL(rotationEuler_cv) + return rotation_gl.x + } + + property var nodeRotationY: { + var rx = root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxRotation.x").value : 0 + var ry = root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxRotation.y").value : 0 + var rz = root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxRotation.z").value : 0 + + var rotationEuler_cv = Qt.vector3d(rx, ry, rz) + var rotation_gl = Transformations3DHelper.convertRotationFromCV2GL(rotationEuler_cv) + return rotation_gl.y + } + + property var nodeRotationZ: { + var rx = root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxRotation.x").value : 0 + var ry = root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxRotation.y").value : 0 + var rz = root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxRotation.z").value : 0 + + var rotationEuler_cv = Qt.vector3d(rx, ry, rz) + var rotation_gl = Transformations3DHelper.convertRotationFromCV2GL(rotationEuler_cv) + return rotation_gl.z + } + // Scale values from node (vector3d because this is the type of QTransform.scale3D) property var nodeScale: Qt.vector3d( root.currentMeshingNode ? root.currentMeshingNode.attribute("boundingBox.bboxScale.x").value : 1, diff --git a/meshroom/ui/qml/main.qml b/meshroom/ui/qml/main.qml index 0923f352..a119ce4d 100755 --- a/meshroom/ui/qml/main.qml +++ b/meshroom/ui/qml/main.qml @@ -322,13 +322,12 @@ ApplicationWindow { } FileDialog { - id: importFilesDialog + id: importImagesDialog title: "Import Images" fileMode: FileDialog.OpenFiles nameFilters: [] onAccepted: { - console.warn("importFilesDialog selectedFiles: " + importFilesDialog.selectedFiles) - _reconstruction.importImagesUrls(importFilesDialog.selectedFiles) + _reconstruction.importImagesUrls(importImagesDialog.selectedFiles) } } @@ -588,17 +587,17 @@ ApplicationWindow { } } Action { - id: importActionItem + id: importImagesAction text: "Import Images" shortcut: "Ctrl+I" onTriggered: { - initFileDialogFolder(importFilesDialog); - importFilesDialog.open(); + initFileDialogFolder(importImagesDialog); + importImagesDialog.open(); } } Action { - id: clearActionItem + id: clearImagesAction text: "Clear Images" onTriggered: { //Loop through all the camera inits |