From 5969df37f4bd278798c13e2910acb8b96965a4a2 Mon Sep 17 00:00:00 2001 From: Florian Foinant-Willig Date: Mon, 18 Nov 2024 23:09:20 +0100 Subject: [PATCH] Sketcher infinite axes --- src/Gui/View3DInventorViewer.cpp | 73 +++++++++++++++++++- src/Gui/View3DInventorViewer.h | 7 ++ src/Mod/Sketcher/Gui/EditModeCoinManager.cpp | 24 +++---- src/Mod/Sketcher/Gui/EditModeCoinManager.h | 8 ++- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 32 ++++++++- src/Mod/Sketcher/Gui/ViewProviderSketch.h | 3 +- 6 files changed, 124 insertions(+), 23 deletions(-) diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 66b68c3abd..3a4b9cea2f 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -91,6 +91,7 @@ #include #include #include +#include #include #include @@ -2657,8 +2658,76 @@ SbVec2f View3DInventorViewer::getNormalizedPosition(const SbVec2s& pnt) const return {pX, pY}; } -SbVec3f View3DInventorViewer::getPointOnXYPlaneOfPlacement(const SbVec2s& pnt, - const Base::Placement& plc) const +Base::BoundBox2d View3DInventorViewer::getViewportOnXYPlaneOfPlacement(Base::Placement plc) const +{ + auto projBBox = Base::BoundBox3d(); + projBBox.SetVoid(); + + SoCamera* pCam = this->getSoRenderManager()->getCamera(); + + if (!pCam) { + // Return empty box. + return Base::BoundBox2d(0, 0, 0, 0); + } + + Base::Vector3d pos = plc.getPosition(); + Base::Rotation rot = plc.getRotation(); + + // Transform the plane LCS into the global one. + Base::Vector3d zAxis(0, 0, 1); + rot.multVec(zAxis, zAxis); + + // Get the position and convert Base::Vector3d to SbVec3f + SbVec3f planeNormal(zAxis.x, zAxis.y, zAxis.z); + SbVec3f planePosition(pos.x, pos.y, pos.z); + SbPlane xyPlane(planeNormal, planePosition); + + const SbViewportRegion& vp = this->getSoRenderManager()->getViewportRegion(); + SbViewVolume vol = pCam->getViewVolume(); + + float fRatio = vp.getViewportAspectRatio(); + float dX, dY; + vp.getViewportSize().getValue(dX, dY); + + // Projects a pair of normalized coordinates on the XY plane. + auto projectPoint = + [&](float x, float y) { + if (fRatio > 1.f) { + x = (x - 0.5f * dX) * fRatio + 0.5f * dX; + } + else if (fRatio < 1.f) { + y = (y - 0.5f * dY) / fRatio + 0.5f * dY; + } + + SbLine line; + vol.projectPointToLine(SbVec2f(x, y), line); + + SbVec3f pt; + // Intersection point on the XY plane. + if (!xyPlane.intersect(line, pt)) { + return; + } + + projBBox.Add(Base::convertTo(pt)); + }; + + // Project the four corners of the viewport plane. + projectPoint(0.f, 0.f); + projectPoint(1.f, 0.f); + projectPoint(0.f, 1.f); + projectPoint(1.f, 1.f); + + if (!projBBox.IsValid()) { + // Return empty box. + return Base::BoundBox2d(0, 0, 0, 0); + } + + plc.invert(); + Base::ViewOrthoProjMatrix proj(plc.toMatrix()); + return projBBox.ProjectBox(&proj); +} + +SbVec3f View3DInventorViewer::getPointOnXYPlaneOfPlacement(const SbVec2s& pnt, const Base::Placement& plc) const { SbVec2f pnt2d = getNormalizedPosition(pnt); SoCamera* pCam = this->getSoRenderManager()->getCamera(); diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index dfa91ca3de..1a520e616c 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -67,6 +67,10 @@ class SoClipPlane; namespace Quarter = SIM::Coin3D::Quarter; +namespace Base { + class BoundBox2d; +} + namespace Gui { class ViewProvider; @@ -311,6 +315,9 @@ public: /** Returns the 3d point on the XY plane of a placement to the given 2d point. */ SbVec3f getPointOnXYPlaneOfPlacement(const SbVec2s&, const Base::Placement&) const; + /** Returns the bounding box on the XY plane of a placement to the given 2d point. */ + Base::BoundBox2d getViewportOnXYPlaneOfPlacement(Base::Placement plc) const; + /** Returns the 2d coordinates on the viewport to the given 3d point. */ SbVec2s getPointOnViewport(const SbVec3f&) const; diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp index e29026c9dd..28660f5b64 100644 --- a/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp @@ -808,8 +808,6 @@ void EditModeCoinManager::processGeometryConstraintsInformationOverlay( processGeometryInformationOverlay(geolistfacade); - updateAxesLength(); - pEditModeConstraintCoinManager->processConstraints(geolistfacade); } @@ -852,22 +850,18 @@ void EditModeCoinManager::processGeometryInformationOverlay(const GeoListFacade& overlayParameters.visibleInformationChanged = false; // just updated } -void EditModeCoinManager::updateAxesLength() +void EditModeCoinManager::updateAxesLength(const Base::BoundBox2d& bb) { auto zCrossH = ViewProviderSketchCoinAttorney::getViewOrientationFactor(viewProvider) * drawingParameters.zCross; - editModeScenegraphNodes.RootCrossCoordinate->point.set1Value( - 0, - SbVec3f(-analysisResults.boundingBoxMagnitudeOrder, 0.0f, zCrossH)); - editModeScenegraphNodes.RootCrossCoordinate->point.set1Value( - 1, - SbVec3f(analysisResults.boundingBoxMagnitudeOrder, 0.0f, zCrossH)); - editModeScenegraphNodes.RootCrossCoordinate->point.set1Value( - 2, - SbVec3f(0.0f, -analysisResults.boundingBoxMagnitudeOrder, zCrossH)); - editModeScenegraphNodes.RootCrossCoordinate->point.set1Value( - 3, - SbVec3f(0.0f, analysisResults.boundingBoxMagnitudeOrder, zCrossH)); + editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(0, + SbVec3f(bb.MinX, 0.0f, zCrossH)); + editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(1, + SbVec3f(bb.MaxX, 0.0f, zCrossH)); + editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(2, + SbVec3f(0.0f, bb.MinY, zCrossH)); + editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(3, + SbVec3f(0.0f, bb.MaxY, zCrossH)); } void EditModeCoinManager::updateColor() diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManager.h b/src/Mod/Sketcher/Gui/EditModeCoinManager.h index 338d983452..2d06a995a6 100644 --- a/src/Mod/Sketcher/Gui/EditModeCoinManager.h +++ b/src/Mod/Sketcher/Gui/EditModeCoinManager.h @@ -44,6 +44,8 @@ class Vector3; class Vector2d; +class BoundBox2d; + class Placement; } // namespace Base @@ -256,6 +258,9 @@ public: void setConstraintSelectability(bool enabled = true); //@} + // Updates the Axes extension to span the specified area. + void updateAxesLength(const Base::BoundBox2d& bb); + private: // This function populates the coin nodes with the information of the current geometry void processGeometry(const GeoListFacade& geolistfacade); @@ -265,9 +270,6 @@ private: // parallel. void processGeometryInformationOverlay(const GeoListFacade& geolistfacade); - // updates the Axes length to extend beyond the calculated bounding box magnitude - void updateAxesLength(); - // updates the parameters to be used for the Overlay information layer void updateOverlayParameters(); diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index d70834bb13..55a91adafa 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -3459,8 +3459,10 @@ void ViewProviderSketch::setEditViewer(Gui::View3DInventorViewer* viewer, int Mo viewer->setupEditingRoot(); - cameraSensor.setData(new VPRender {this, viewer->getSoRenderManager()}); - cameraSensor.attach(viewer->getSoRenderManager()->getSceneGraph()); + auto *camSensorData = new VPRender {this, viewer->getSoRenderManager()}; + cameraSensor.setData(camSensorData); + cameraSensor.setDeleteCallback(&ViewProviderSketch::camSensDeleteCB, camSensorData); + cameraSensor.attach(viewer->getCamera()); } void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer) @@ -3468,6 +3470,7 @@ void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer) auto dataPtr = static_cast(cameraSensor.getData()); delete dataPtr; cameraSensor.setData(nullptr); + cameraSensor.setDeleteCallback(nullptr, nullptr); cameraSensor.detach(); viewer->removeGraphicsItem(rubberband.get()); @@ -3475,6 +3478,22 @@ void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer) viewer->setSelectionEnabled(true); } +void ViewProviderSketch::camSensDeleteCB(void* data, SoSensor *s) +{ + auto *proxyVPrdr = static_cast(data); + if (!proxyVPrdr) + return; + + // The camera object the observer was attached to is gone, try to re-attach the sensor + // to the new camera. + // This happens i.e. when the user switches the camera type from orthographic to + // perspective. + SoCamera *camera = proxyVPrdr->renderMgr->getCamera(); + if (camera) { + static_cast(s)->attach(camera); + } +} + void ViewProviderSketch::camSensCB(void* data, SoSensor*) { VPRender* proxyVPrdr = static_cast(data); @@ -3516,6 +3535,15 @@ void ViewProviderSketch::onCameraChanged(SoCamera* cam) Base::Interpreter().runStringObject(cmdStr.toLatin1()); } + // Stretch the axes to cover the whole viewport. + Gui::View3DInventor* view = qobject_cast(this->getActiveView()); + if (view) { + Base::Placement plc = getEditingPlacement(); + const Base::BoundBox2d vpBBox = view->getViewer() + ->getViewportOnXYPlaneOfPlacement(plc); + editCoinManager->updateAxesLength(vpBBox); + } + drawGrid(true); } diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index ae5b272690..0ceb339efd 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -717,7 +717,8 @@ protected: void unsetEdit(int ModNum) override; void setEditViewer(Gui::View3DInventorViewer*, int ModNum) override; void unsetEditViewer(Gui::View3DInventorViewer*) override; - static void camSensCB(void* data, SoSensor*); // camera sensor callback + static void camSensCB(void* data, SoSensor*); // camera sensor callback + static void camSensDeleteCB(void* data, SoSensor*); // camera sensor callback void onCameraChanged(SoCamera* cam); //@}