From 50af71b41bd80b828d9c15005595698a272d41e1 Mon Sep 17 00:00:00 2001 From: Jere Tuliniemi Date: Fri, 1 Mar 2019 14:50:42 +0200 Subject: Implement local/global manipulator toggle behavior Manipulators now should be able to manipulate the object in global space. Plane scaling works differently than in the old runtime in this patch as the logic of that is unclear at the moment. Task-number: QT3DS-3010 Change-Id: Ie6961727b32c530d55e41ed84f102526f018ace9 Reviewed-by: Miikka Heikkinen --- .../Studio/Render/Q3DSManipulationWidget.cpp | 9 +- .../Studio/Render/Q3DSManipulationWidget.h | 2 +- src/Authoring/Studio/Render/Q3DSTranslation.cpp | 165 ++++++++++++++++----- src/Authoring/Studio/Render/Q3DSTranslation.h | 6 +- 4 files changed, 137 insertions(+), 45 deletions(-) diff --git a/src/Authoring/Studio/Render/Q3DSManipulationWidget.cpp b/src/Authoring/Studio/Render/Q3DSManipulationWidget.cpp index 70a0505c..87232aa7 100644 --- a/src/Authoring/Studio/Render/Q3DSManipulationWidget.cpp +++ b/src/Authoring/Studio/Render/Q3DSManipulationWidget.cpp @@ -299,13 +299,16 @@ void Q3DSManipulationWidget::destroyManipulators() } void applyNodeProperties(Q3DSNode *node, Q3DSCameraNode *camera, Q3DSLayerNode *layer, - Q3DSModelNode *model, const QVector3D &modelScale) { + Q3DSModelNode *model, const QVector3D &modelScale, bool globalSpace) { QVector3D position; QVector3D rotation; QVector3D dummyScale; calculateGlobalProperties(node, position, rotation, dummyScale); + if (globalSpace) + rotation = QVector3D(0, 0, 0); + Q3DSPropertyChangeList list; list.append(model->setPosition(position)); list.append(model->setRotation(rotation)); @@ -340,7 +343,7 @@ void applyNodeProperties(Q3DSNode *node, Q3DSCameraNode *camera, Q3DSLayerNode * } void Q3DSManipulationWidget::applyProperties(Q3DSGraphObject *node, Q3DSCameraNode *camera, - Q3DSLayerNode *layer) + Q3DSLayerNode *layer, bool globalSpace) { for (int i = 0; i < m_manipulators.size(); ++i) { if (node->type() == Q3DSGraphObject::Model @@ -351,7 +354,7 @@ void Q3DSManipulationWidget::applyProperties(Q3DSGraphObject *node, Q3DSCameraNo || node->type() == Q3DSGraphObject::Text || node->type() == Q3DSGraphObject::Component) { applyNodeProperties(static_cast(node), camera, layer, m_manipulators[i], - m_manipulatorScales[i]); + m_manipulatorScales[i], globalSpace); } } diff --git a/src/Authoring/Studio/Render/Q3DSManipulationWidget.h b/src/Authoring/Studio/Render/Q3DSManipulationWidget.h index 76a0bb11..daa8c65b 100644 --- a/src/Authoring/Studio/Render/Q3DSManipulationWidget.h +++ b/src/Authoring/Studio/Render/Q3DSManipulationWidget.h @@ -67,7 +67,7 @@ public: void destroyManipulators(); void applyProperties(Q3DSGraphObject *node, Q3DSCameraNode *camera, - Q3DSLayerNode *layer); + Q3DSLayerNode *layer, bool globalSpace); private: ManipulationWidgetType m_type = ManipulationWidgetType::Translation; diff --git a/src/Authoring/Studio/Render/Q3DSTranslation.cpp b/src/Authoring/Studio/Render/Q3DSTranslation.cpp index 01ce52fd..14436ead 100644 --- a/src/Authoring/Studio/Render/Q3DSTranslation.cpp +++ b/src/Authoring/Studio/Render/Q3DSTranslation.cpp @@ -454,13 +454,18 @@ void Q3DSTranslation::recompileShadersIfRequired(Q3DSGraphObjectTranslator *tran // If either dragPlane or arrowDir are null, both are extracted from drag widget. QVector4D Q3DSTranslation::calculateWidgetArrowDrag(const QPoint &mousePos, const QVector3D &dragPlane, - const QVector3D &arrowDir) + const QVector3D &arrowDir, + Q3DSNode *node) { - Q3DSNode *node = m_dragTranslator->graphObject(); + QVector3D beginStatePos = m_beginDragState.t; + if (!node) + node = m_dragTranslator->graphObject(); + else + beginStatePos = m_beginWidgetPos; Q3DSNode *parentNode = static_cast(node->parent()); Q3DSNodeAttached *parentAttached = parentNode->attached(); QMatrix4x4 parentMatrix = parentAttached->globalTransform; - QVector3D nodePos = m_beginDragState.t; + QVector3D nodePos = beginStatePos; flipZTranslation(nodePos); QVector3D globalNodePos = parentMatrix * nodePos; Q3DSCameraAttached *cameraAttached = m_dragCamera->attached(); @@ -503,7 +508,7 @@ QVector4D Q3DSTranslation::calculateWidgetArrowDrag(const QPoint &mousePos, } QVector3D globalIntersection = mousePointToPlaneIntersection( - mousePos, m_dragCamera, node, m_beginDragState.t, planeNormal, true); + mousePos, m_dragCamera, node, beginStatePos, planeNormal, true); float distance = globalNodePos.distanceToPlane(globalIntersection, direction); direction *= distance; @@ -515,6 +520,50 @@ QVector4D Q3DSTranslation::calculateWidgetArrowDrag(const QPoint &mousePos, return QVector4D(localNodePos, distance * distanceMultiplier); } +QVector3D Q3DSTranslation::calculateWidgetDragScale(const QPoint &mousePos, const Q3DSNode *node, + float scaleRatio, const QVector3D &planeNormal, + const QVector3D &axis) +{ + Q3DSNode *widgetNode = static_cast(m_pickedWidget); + QVector4D drag = calculateWidgetArrowDrag(mousePos, planeNormal, axis, widgetNode); + float distance = drag.w(); + + QVector3D direction = (drag.toVector3D() - m_beginWidgetPos).normalized(); + + float scaleAmount = distance / scaleRatio; + + QVector3D dummyPosition; + QVector3D rotation; + QVector3D dummyScale; + calculateGlobalProperties(node, dummyPosition, rotation, dummyScale); + + auto rotX = QQuaternion::fromAxisAndAngle(QVector3D(-1, 0, 0), rotation.x()); + auto rotY = QQuaternion::fromAxisAndAngle(QVector3D(0, -1, 0), rotation.y()); + auto rotZ = QQuaternion::fromAxisAndAngle(QVector3D(0, 0, 1), rotation.z()); + QQuaternion quat = rotZ * rotX * rotY; + + QVector3D nodeDirection = quat * direction; + + float maxAxis = qMax(qMax(qAbs(nodeDirection.x()), qAbs(nodeDirection.y())), + qAbs(nodeDirection.z())); + if (qFuzzyIsNull(nodeDirection.x())) + nodeDirection.setX(0); + else + nodeDirection.setX(maxAxis); + + if (qFuzzyIsNull(nodeDirection.y())) + nodeDirection.setY(0); + else + nodeDirection.setY(maxAxis); + + if (qFuzzyIsNull(nodeDirection.z())) + nodeDirection.setZ(0); + else + nodeDirection.setZ(maxAxis); + + return scaleAmount * nodeDirection; +} + void Q3DSTranslation::markPropertyDirty(qt3dsdm::Qt3DSDMInstanceHandle instance, qt3dsdm::Qt3DSDMPropertyHandle property) { @@ -1563,8 +1612,10 @@ void Q3DSTranslation::updateWidgetProperties() if (m_foregroundPickingCamera) { const auto camera = cameraForNode(m_selectedObject, true); const auto layer = layerForNode(m_selectedObject); - if (camera && layer) - m_manipulationWidget.applyProperties(m_selectedObject, camera, layer); + if (camera && layer) { + m_manipulationWidget.applyProperties(m_selectedObject, camera, layer, + g_StudioApp.GetManipulationMode() == StudioManipulationModes::Global); + } } } @@ -1608,6 +1659,8 @@ void Q3DSTranslation::prepareDrag(const QPoint &mousePos, Q3DSGraphObjectTransla selected->enableAutoUpdates(false); Q3DSNode &node = static_cast(m_dragTranslator->graphObject()); Q3DSNodeAttached *nodeAttached = node.attached(); + if (m_pickedWidget) + nodeAttached = m_pickedWidget->attached(); m_dragNodeGlobalTransform = nodeAttached->globalTransform; m_beginDragState.t = node.position(); m_beginDragState.s = node.scale(); @@ -1615,6 +1668,8 @@ void Q3DSTranslation::prepareDrag(const QPoint &mousePos, Q3DSGraphObjectTransla m_currentDragState = m_beginDragState; m_dragCamera = cameraForNode(&node, true); m_dragStartMousePos = mousePos; + if (m_pickedWidget) + m_beginWidgetPos = static_cast(m_pickedWidget)->position(); // Find out the diff between node position and initial mouse click to avoid having the dragged // object initially jump a bit @@ -1634,10 +1689,11 @@ void Q3DSTranslation::prepareWidgetDrag(const QPoint &mousePos, Q3DSGraphObject return; } } - prepareDrag(mousePos); m_pickedWidget = obj; m_manipulationWidget.setColor(m_pickedWidget, Qt::yellow); + + prepareDrag(mousePos); } void Q3DSTranslation::endDrag(bool dragReset, CUpdateableDocumentEditor &inEditor) @@ -1853,45 +1909,74 @@ void Q3DSTranslation::scaleAlongWidget(const QPoint &inOriginalCoords, const QPo float distance = calculateWidgetArrowDrag(mousePos).w(); float scaleAmount = distance / scaleRatio; float magnitude = 1.f + scaleAmount; - if (m_manipulationWidget.isXAxis(m_pickedWidget)) - scaleVec = QVector3D(magnitude, 1.f, 1.f); - else if (m_manipulationWidget.isYAxis(m_pickedWidget)) - scaleVec = QVector3D(1.f, magnitude, 1.f); - else if (m_manipulationWidget.isZAxis(m_pickedWidget)) - scaleVec = QVector3D(1.f, 1.f, magnitude); + if (g_StudioApp.GetManipulationMode() == StudioManipulationModes::Local) { + if (m_manipulationWidget.isXAxis(m_pickedWidget)) + scaleVec = QVector3D(magnitude, 1.f, 1.f); + else if (m_manipulationWidget.isYAxis(m_pickedWidget)) + scaleVec = QVector3D(1.f, magnitude, 1.f); + else if (m_manipulationWidget.isZAxis(m_pickedWidget)) + scaleVec = QVector3D(1.f, 1.f, magnitude); + } else { + scaleVec = QVector3D(1, 1, 1) + calculateWidgetDragScale(mousePos, node, scaleRatio); + } } else { float xScale = 1.f; float yScale = 1.f; float zScale = 1.f; QVector3D planeNormal; - if (m_manipulationWidget.isXYPlane(m_pickedWidget)) { - planeNormal = getZAxis(m_dragNodeGlobalTransform); - xScale = 1.f + calculateWidgetArrowDrag( - mousePos, planeNormal, getXAxis(m_dragNodeGlobalTransform)).w() - / -scaleRatio; - yScale = 1.f + calculateWidgetArrowDrag( - mousePos, planeNormal, getYAxis(m_dragNodeGlobalTransform)).w() - / -scaleRatio; - scaleVec = QVector3D(xScale, yScale, 1.f); - } else if (m_manipulationWidget.isYZPlane(m_pickedWidget)) { - planeNormal = getXAxis(m_dragNodeGlobalTransform); - yScale = 1.f + calculateWidgetArrowDrag( - mousePos, planeNormal, getYAxis(m_dragNodeGlobalTransform)).w() - / -scaleRatio; - zScale = 1.f + calculateWidgetArrowDrag( - mousePos, planeNormal, getZAxis(m_dragNodeGlobalTransform)).w() - / scaleRatio; - scaleVec = QVector3D(1.f, yScale, zScale); - } else if (m_manipulationWidget.isZXPlane(m_pickedWidget)) { - planeNormal = getYAxis(m_dragNodeGlobalTransform); - xScale = 1.f + calculateWidgetArrowDrag( - mousePos, planeNormal, getXAxis(m_dragNodeGlobalTransform)).w() - / -scaleRatio; - zScale = 1.f + calculateWidgetArrowDrag( - mousePos, planeNormal, getZAxis(m_dragNodeGlobalTransform)).w() - / scaleRatio; - scaleVec = QVector3D(xScale, 1.f, zScale); + if (g_StudioApp.GetManipulationMode() == StudioManipulationModes::Local) { + if (m_manipulationWidget.isXYPlane(m_pickedWidget)) { + planeNormal = getZAxis(m_dragNodeGlobalTransform); + xScale = 1.f + calculateWidgetArrowDrag( + mousePos, planeNormal, getXAxis(m_dragNodeGlobalTransform)).w() + / -scaleRatio; + yScale = 1.f + calculateWidgetArrowDrag( + mousePos, planeNormal, getYAxis(m_dragNodeGlobalTransform)).w() + / -scaleRatio; + scaleVec = QVector3D(xScale, yScale, 1.f); + } else if (m_manipulationWidget.isYZPlane(m_pickedWidget)) { + planeNormal = getXAxis(m_dragNodeGlobalTransform); + yScale = 1.f + calculateWidgetArrowDrag( + mousePos, planeNormal, getYAxis(m_dragNodeGlobalTransform)).w() + / -scaleRatio; + zScale = 1.f + calculateWidgetArrowDrag( + mousePos, planeNormal, getZAxis(m_dragNodeGlobalTransform)).w() + / scaleRatio; + scaleVec = QVector3D(1.f, yScale, zScale); + } else if (m_manipulationWidget.isZXPlane(m_pickedWidget)) { + planeNormal = getYAxis(m_dragNodeGlobalTransform); + xScale = 1.f + calculateWidgetArrowDrag( + mousePos, planeNormal, getXAxis(m_dragNodeGlobalTransform)).w() + / -scaleRatio; + zScale = 1.f + calculateWidgetArrowDrag( + mousePos, planeNormal, getZAxis(m_dragNodeGlobalTransform)).w() + / scaleRatio; + scaleVec = QVector3D(xScale, 1.f, zScale); + } + } else { + if (m_manipulationWidget.isXYPlane(m_pickedWidget)) { + planeNormal = getZAxis(m_dragNodeGlobalTransform); + scaleVec = QVector3D(1, 1, 1) + + calculateWidgetDragScale(mousePos, node, scaleRatio, planeNormal, + -getXAxis(m_dragNodeGlobalTransform)) + + calculateWidgetDragScale(mousePos, node, scaleRatio, planeNormal, + -getYAxis(m_dragNodeGlobalTransform)); + } else if (m_manipulationWidget.isYZPlane(m_pickedWidget)) { + planeNormal = getXAxis(m_dragNodeGlobalTransform); + scaleVec = QVector3D(1, 1, 1) + + calculateWidgetDragScale(mousePos, node, scaleRatio, planeNormal, + -getYAxis(m_dragNodeGlobalTransform)) + + calculateWidgetDragScale(mousePos, node, scaleRatio, planeNormal, + getZAxis(m_dragNodeGlobalTransform)); + } else if (m_manipulationWidget.isZXPlane(m_pickedWidget)) { + planeNormal = getYAxis(m_dragNodeGlobalTransform); + scaleVec = QVector3D(1, 1, 1) + + calculateWidgetDragScale(mousePos, node, scaleRatio, planeNormal, + -getXAxis(m_dragNodeGlobalTransform)) + + calculateWidgetDragScale(mousePos, node, scaleRatio, planeNormal, + getZAxis(m_dragNodeGlobalTransform)); + } } } diff --git a/src/Authoring/Studio/Render/Q3DSTranslation.h b/src/Authoring/Studio/Render/Q3DSTranslation.h index 671deb7e..1c7ea328 100644 --- a/src/Authoring/Studio/Render/Q3DSTranslation.h +++ b/src/Authoring/Studio/Render/Q3DSTranslation.h @@ -160,7 +160,10 @@ private: qt3dsdm::Qt3DSDMPropertyHandle property); QVector4D calculateWidgetArrowDrag(const QPoint &mousePos, const QVector3D &dragPlane = {}, - const QVector3D &arrowDir = {}); + const QVector3D &arrowDir = {}, Q3DSNode *node = nullptr); + QVector3D calculateWidgetDragScale(const QPoint &mousePos, const Q3DSNode *node, + float scaleRatio, const QVector3D &planeNormal = {}, + const QVector3D &axis = {}); Q3DStudioRenderer &m_studioRenderer; @@ -233,6 +236,7 @@ private: DragState m_beginDragState; DragState m_currentDragState; + QVector3D m_beginWidgetPos; public: qt3dsdm::SComposerObjectDefinitions &objectDefinitions() const -- cgit v1.2.3