From 3fe9ce0edd41c58bc0321f59b0fd147124d27e71 Mon Sep 17 00:00:00 2001 From: kgv Date: Tue, 23 Aug 2016 17:11:49 +0300 Subject: [PATCH] 0027793: Visualization - object drifts at zoom within Graphic3d_TMF_TriedronPers applied Graphic3d_TransformPers now takes Graphic3d_Camera definition as argument for methods applying transformation. Graphic3d_TransformPers::Apply() now computes Graphic3d_TMF_TriedronPers transformation in the following way: - The object is moved onto Z focus distance. - The object is expected to be defined in pixels. - The Z coordinate on anchor point is used as offset from the view corner in pixels. - It is now possible to define not only corners of the view, but also middle of the side. - Graphic3d_TMF_TriedronPers now works with perspective projection. OpenGl_LayerList::ChangeLayer() - fixed removing of the element in old ZLayer. OpenGl_Layer::BoundingBox() now takes into account bounding box of Graphic3d_TMF_TriedronPers presentations for Z-fit operation. --- dox/dev_guides/upgrade/upgrade.md | 6 + src/Graphic3d/Graphic3d_CStructure.hxx | 8 + src/Graphic3d/Graphic3d_CView.cxx | 24 +- src/Graphic3d/Graphic3d_CView.hxx | 22 +- src/Graphic3d/Graphic3d_Camera.cxx | 8 +- src/Graphic3d/Graphic3d_Camera.hxx | 11 +- src/Graphic3d/Graphic3d_TransformPers.hxx | 125 +++++---- .../OpenGl_BVHClipPrimitiveTrsfPersSet.cxx | 5 +- .../OpenGl_BVHClipPrimitiveTrsfPersSet.hxx | 3 +- src/OpenGl/OpenGl_BVHTreeSelector.cxx | 1 + src/OpenGl/OpenGl_BVHTreeSelector.hxx | 5 + src/OpenGl/OpenGl_GraduatedTrihedron.cxx | 2 +- src/OpenGl/OpenGl_Layer.cxx | 251 +++++++++++------- src/OpenGl/OpenGl_Layer.hxx | 25 +- src/OpenGl/OpenGl_LayerList.cxx | 2 +- src/OpenGl/OpenGl_Structure.cxx | 2 +- src/OpenGl/OpenGl_View.cxx | 10 +- src/OpenGl/OpenGl_View.hxx | 13 +- src/SelectMgr/SelectMgr_BaseFrustum.cxx | 2 + src/SelectMgr/SelectMgr_BaseFrustum.hxx | 4 + .../SelectMgr_SelectableObjectTrsfPersSet.cxx | 5 +- .../SelectMgr_SelectableObjectTrsfPersSet.hxx | 3 +- .../SelectMgr_SelectingVolumeManager.hxx | 3 + src/SelectMgr/SelectMgr_ViewerSelector.cxx | 6 +- src/V3d/V3d_View.cxx | 2 +- src/ViewerTest/ViewerTest.cxx | 2 +- tests/bugs/vis/bug26344 | 67 ++--- tests/bugs/vis/bug27793 | 21 ++ 28 files changed, 401 insertions(+), 237 deletions(-) create mode 100644 tests/bugs/vis/bug27793 diff --git a/dox/dev_guides/upgrade/upgrade.md b/dox/dev_guides/upgrade/upgrade.md index aa5655b3aa..b433110f35 100644 --- a/dox/dev_guides/upgrade/upgrade.md +++ b/dox/dev_guides/upgrade/upgrade.md @@ -1031,6 +1031,12 @@ Applications should explicitly enable deprecated functionality by setting OpenGl but being aware that this functionality is likely to be removed in a next OCCT release. Thus the recommended way to generate vector image of a 3D model or scene is to use application-level solution independent from OpenGL. +@subsection upgrade_710_trsfpers Transformation persistence + +The behavior of transformation persistence flags Graphic3d_TMF_ZoomPers and Graphic3d_TMF_TriedronPers have been changed to be consistent with textured fixed-size 2D text. +Object with these flags is considered to be defined in pixel units, and presentation is no more scaled depending on view height. +Applications that need to scale such objects depending on viewport size should update them manually. + @subsection upgrade_710_removed Removed features The following obsolete features have been removed: diff --git a/src/Graphic3d/Graphic3d_CStructure.hxx b/src/Graphic3d/Graphic3d_CStructure.hxx index 5040ac5ce3..2c914e1f7f 100644 --- a/src/Graphic3d/Graphic3d_CStructure.hxx +++ b/src/Graphic3d/Graphic3d_CStructure.hxx @@ -71,6 +71,14 @@ public: //! Return structure visibility flag bool IsVisible() const { return visible != 0; } + //! Return structure visibility considering both View Affinity and global visibility state. + bool IsVisible (const Standard_Integer theViewId) const + { + return visible != 0 + && (ViewAffinity.IsNull() + || ViewAffinity->IsVisible (theViewId)); + } + //! Set z layer ID to display the structure in specified layer void SetZLayer (const Graphic3d_ZLayerId theLayerIndex) { myZLayer = theLayerIndex; } diff --git a/src/Graphic3d/Graphic3d_CView.cxx b/src/Graphic3d/Graphic3d_CView.cxx index 4fcf838ea2..fe40e846d1 100644 --- a/src/Graphic3d/Graphic3d_CView.cxx +++ b/src/Graphic3d/Graphic3d_CView.cxx @@ -432,7 +432,7 @@ void Graphic3d_CView::DisplayedStructures (Graphic3d_MapOfStructure& theStructur // function : MinMaxValues // purpose : // ======================================================================= -Bnd_Box Graphic3d_CView::MinMaxValues (const Standard_Boolean theToIgnoreInfiniteFlag) const +Bnd_Box Graphic3d_CView::MinMaxValues (const Standard_Boolean theToIncludeAuxiliary) const { Bnd_Box aResult; @@ -453,14 +453,18 @@ Bnd_Box Graphic3d_CView::MinMaxValues (const Standard_Boolean theToIgnoreInfinit aCamera, aWinWidth, aWinHeight, - theToIgnoreInfiniteFlag); + theToIncludeAuxiliary); combineBox (aResult, aBox); } Standard_Integer aMaxZLayer = ZLayerMax(); for (Standard_Integer aLayerId = Graphic3d_ZLayerId_Default; aLayerId <= aMaxZLayer; ++aLayerId) { - Graphic3d_BndBox4f aBox = ZLayerBoundingBox (aLayerId, aCamera, aWinWidth, aWinHeight, theToIgnoreInfiniteFlag); + Graphic3d_BndBox4f aBox = ZLayerBoundingBox (aLayerId, + aCamera, + aWinWidth, + aWinHeight, + theToIncludeAuxiliary); combineBox (aResult, aBox); } @@ -487,12 +491,12 @@ Standard_Real Graphic3d_CView::ConsiderZoomPersistenceObjects() Standard_Real aMaxCoef = 1.0; for (Standard_Integer aLayer = 0; aLayer < THE_NB_DEFAULT_LAYERS; ++aLayer) { - aMaxCoef = Max (aMaxCoef, considerZoomPersistenceObjects (THE_DEFAULT_LAYERS[aLayer], aCamera, aWinWidth, aWinHeight, Standard_False)); + aMaxCoef = Max (aMaxCoef, considerZoomPersistenceObjects (THE_DEFAULT_LAYERS[aLayer], aCamera, aWinWidth, aWinHeight)); } for (Standard_Integer aLayer = Graphic3d_ZLayerId_Default; aLayer <= ZLayerMax(); ++aLayer) { - aMaxCoef = Max (aMaxCoef, considerZoomPersistenceObjects (aLayer, aCamera, aWinWidth, aWinHeight, Standard_False)); + aMaxCoef = Max (aMaxCoef, considerZoomPersistenceObjects (aLayer, aCamera, aWinWidth, aWinHeight)); } return aMaxCoef; @@ -519,12 +523,8 @@ Bnd_Box Graphic3d_CView::MinMaxValues (const Graphic3d_MapOfStructure& theSet, for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (theSet); aStructIter.More(); aStructIter.Next()) { const Handle(Graphic3d_Structure)& aStructure = aStructIter.Key(); - if (!aStructure->IsVisible() || aStructure->IsEmpty()) - { - continue; - } - else if (!aStructure->CStructure()->ViewAffinity.IsNull() - && !aStructure->CStructure()->ViewAffinity->IsVisible (aViewId)) + if (aStructure->IsEmpty() + || !aStructure->CStructure()->IsVisible (aViewId)) { continue; } @@ -554,7 +554,7 @@ Bnd_Box Graphic3d_CView::MinMaxValues (const Graphic3d_MapOfStructure& theSet, { const Graphic3d_Mat4d& aProjectionMat = aCamera->ProjectionMatrix(); const Graphic3d_Mat4d& aWorldViewMat = aCamera->OrientationMatrix(); - aStructure->TransformPersistence().Apply (aProjectionMat, aWorldViewMat, aWinWidth, aWinHeight, aBox); + aStructure->TransformPersistence().Apply (aCamera, aProjectionMat, aWorldViewMat, aWinWidth, aWinHeight, aBox); } // To prevent float overflow at camera parameters calculation and further diff --git a/src/Graphic3d/Graphic3d_CView.hxx b/src/Graphic3d/Graphic3d_CView.hxx index 089af325d2..b9e768fae6 100644 --- a/src/Graphic3d/Graphic3d_CView.hxx +++ b/src/Graphic3d/Graphic3d_CView.hxx @@ -135,17 +135,18 @@ public: Handle(Graphic3d_Structure)& theComputedStruct) const; //! Returns the bounding box of all structures displayed in the view. - //! If is TRUE, then the boundary box - //! also includes minimum and maximum limits of graphical elements - //! forming parts of infinite structures. - Standard_EXPORT Bnd_Box MinMaxValues (const Standard_Boolean theToIgnoreInfiniteFlag = Standard_False) const; + //! If theToIncludeAuxiliary is TRUE, then the boundary box also includes minimum and maximum limits + //! of graphical elements forming parts of infinite and other auxiliary structures. + //! @param theToIncludeAuxiliary consider also auxiliary presentations (with infinite flag or with trihedron transformation persistence) + //! @return computed bounding box + Standard_EXPORT Bnd_Box MinMaxValues (const Standard_Boolean theToIncludeAuxiliary = Standard_False) const; //! Returns the coordinates of the boundary box of all structures in the set . //! If is TRUE, then the boundary box //! also includes minimum and maximum limits of graphical elements //! forming parts of infinite structures. Standard_EXPORT Bnd_Box MinMaxValues (const Graphic3d_MapOfStructure& theSet, - const Standard_Boolean theToIgnoreInfiniteFlag = Standard_False) const; + const Standard_Boolean theToIncludeAuxiliary = Standard_False) const; //! Returns the structure manager handle which manage structures associated with this view. const Handle(Graphic3d_StructureManager)& StructureManager() const { return myStructureManager; } @@ -322,11 +323,17 @@ public: virtual void InvalidateZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId) const = 0; //! Returns the bounding box of all structures displayed in the Z layer. + //! @param theLayerId layer identifier + //! @param theCamera camera definition + //! @param theWindowWidth viewport width (for applying transformation-persistence) + //! @param theWindowHeight viewport height (for applying transformation-persistence) + //! @param theToIncludeAuxiliary consider also auxiliary presentations (with infinite flag or with trihedron transformation persistence) + //! @return computed bounding box virtual Graphic3d_BndBox4f ZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId, const Handle(Graphic3d_Camera)& theCamera, const Standard_Integer theWindowWidth, const Standard_Integer theWindowHeight, - const Standard_Boolean theToIgnoreInfiniteFlag) const = 0; + const Standard_Boolean theToIncludeAuxiliary) const = 0; //! Remove Z layer from the specified view. All structures //! displayed at the moment in layer will be displayed in default layer @@ -473,8 +480,7 @@ private: virtual Standard_Real considerZoomPersistenceObjects (const Graphic3d_ZLayerId theLayerId, const Handle(Graphic3d_Camera)& theCamera, const Standard_Integer theWindowWidth, - const Standard_Integer theWindowHeight, - const Standard_Boolean theToIgnoreInfiniteFlag) const = 0; + const Standard_Integer theWindowHeight) const = 0; protected: diff --git a/src/Graphic3d/Graphic3d_Camera.cxx b/src/Graphic3d/Graphic3d_Camera.cxx index 5696abc622..2288278062 100644 --- a/src/Graphic3d/Graphic3d_Camera.cxx +++ b/src/Graphic3d/Graphic3d_Camera.cxx @@ -270,7 +270,7 @@ void Graphic3d_Camera::SetScale (const Standard_Real theScale) case Projection_MonoLeftEye : case Projection_MonoRightEye : { - Standard_Real aDistance = theScale * 0.5 / Tan(myFOVy * M_PI / 360.0); + Standard_Real aDistance = theScale * 0.5 / Tan(DTR_HALF * myFOVy); SetDistance (aDistance); } @@ -297,7 +297,7 @@ Standard_Real Graphic3d_Camera::Scale() const // case Projection_MonoLeftEye : // case Projection_MonoRightEye : default : - return Distance() * 2.0 * Tan (myFOVy * M_PI / 360.0); + return Distance() * 2.0 * Tan (DTR_HALF * myFOVy); } } @@ -627,10 +627,10 @@ gp_Pnt Graphic3d_Camera::ConvertView2World (const gp_Pnt& thePnt) const // function : ViewDimensions // purpose : // ======================================================================= -gp_XYZ Graphic3d_Camera::ViewDimensions() const +gp_XYZ Graphic3d_Camera::ViewDimensions (const Standard_Real theZValue) const { // view plane dimensions - Standard_Real aSize = IsOrthographic() ? myScale : (2.0 * Distance() * Tan (DTR_HALF * myFOVy)); + Standard_Real aSize = IsOrthographic() ? myScale : (2.0 * theZValue * Tan (DTR_HALF * myFOVy)); Standard_Real aSizeX, aSizeY; if (myAspect > 1.0) { diff --git a/src/Graphic3d/Graphic3d_Camera.hxx b/src/Graphic3d/Graphic3d_Camera.hxx index ca9180196d..dfb90bbce4 100644 --- a/src/Graphic3d/Graphic3d_Camera.hxx +++ b/src/Graphic3d/Graphic3d_Camera.hxx @@ -386,7 +386,16 @@ public: //! Calculate view plane size at center (target) point //! and distance between ZFar and ZNear planes. //! @return values in form of gp_Pnt (Width, Height, Depth). - Standard_EXPORT gp_XYZ ViewDimensions() const; + gp_XYZ ViewDimensions() const + { + return ViewDimensions (Distance()); + } + + //! Calculate view plane size at center point with specified Z offset + //! and distance between ZFar and ZNear planes. + //! @param theZValue [in] the distance from the eye in eye-to-center direction + //! @return values in form of gp_Pnt (Width, Height, Depth). + Standard_EXPORT gp_XYZ ViewDimensions (const Standard_Real theZValue) const; //! Calculate WCS frustum planes for the camera projection volume. //! Frustum is a convex volume determined by six planes directing diff --git a/src/Graphic3d/Graphic3d_TransformPers.hxx b/src/Graphic3d/Graphic3d_TransformPers.hxx index f64417d58b..f2f620b12f 100644 --- a/src/Graphic3d/Graphic3d_TransformPers.hxx +++ b/src/Graphic3d/Graphic3d_TransformPers.hxx @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -44,26 +45,30 @@ public: public: //! Apply transformation to bounding box of presentation. + //! @param theCamera [in] camera definition //! @param theProjection [in] the projection transformation matrix. //! @param theWorldView [in] the world view transformation matrix. //! @param theViewportWidth [in] the width of viewport (for 2d persistence). //! @param theViewportHeight [in] the height of viewport (for 2d persistence). //! @param theBoundingBox [in/out] the bounding box to transform. template - void Apply (const NCollection_Mat4& theProjection, + void Apply (const Handle(Graphic3d_Camera)& theCamera, + const NCollection_Mat4& theProjection, const NCollection_Mat4& theWorldView, const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight, Bnd_Box& theBoundingBox) const; //! Apply transformation to bounding box of presentation + //! @param theCamera [in] camera definition //! @param theProjection [in] the projection transformation matrix. //! @param theWorldView [in] the world view transformation matrix. //! @param theViewportWidth [in] the width of viewport (for 2d persistence). //! @param theViewportHeight [in] the height of viewport (for 2d persistence). //! @param theBoundingBox [in/out] the bounding box to transform. template - void Apply (const NCollection_Mat4& theProjection, + void Apply (const Handle(Graphic3d_Camera)& theCamera, + const NCollection_Mat4& theProjection, const NCollection_Mat4& theWorldView, const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight, @@ -72,19 +77,22 @@ public: //! Compute transformation. //! Computed matrix can be applied to model world transformation //! of an object to implement effect of transformation persistence. + //! @param theCamera [in] camera definition //! @param theProjection [in] the projection transformation matrix. //! @param theWorldView [in] the world view transformation matrix. //! @param theViewportWidth [in] the width of viewport (for 2d persistence). //! @param theViewportHeight [in] the height of viewport (for 2d persistence). //! @return transformation matrix to be applied to model world transformation of an object. template - NCollection_Mat4 Compute (const NCollection_Mat4& theProjection, + NCollection_Mat4 Compute (const Handle(Graphic3d_Camera)& theCamera, + const NCollection_Mat4& theProjection, const NCollection_Mat4& theWorldView, const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight) const; template - void Apply (NCollection_Mat4& theProjection, + void Apply (const Handle(Graphic3d_Camera)& theCamera, + NCollection_Mat4& theProjection, NCollection_Mat4& theWorldView, const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight) const; @@ -95,7 +103,8 @@ public: // purpose : Apply transformation to world view and projection matrices. // ======================================================================= template -void Graphic3d_TransformPers::Apply (NCollection_Mat4& theProjection, +void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, + NCollection_Mat4& theProjection, NCollection_Mat4& theWorldView, const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight) const @@ -105,6 +114,53 @@ void Graphic3d_TransformPers::Apply (NCollection_Mat4& theProjection, return; } + if (Flags == Graphic3d_TMF_TriedronPers) + { + // reset Z focus for trihedron persistence + const Standard_Real aFocus = theCamera->IsOrthographic() + ? theCamera->Distance() + : (theCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative + ? Standard_Real(theCamera->ZFocus() * theCamera->Distance()) + : Standard_Real(theCamera->ZFocus())); + + // scale factor to pixels + const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus); + const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(theViewportHeight); + + // offset from the corner + const Standard_Real anOffset = Point.z() * aScale; + + const gp_Dir aForward (theCamera->Center().XYZ() - theCamera->Eye().XYZ()); + gp_XYZ aCenter = theCamera->Center().XYZ() + aForward.XYZ() * (aFocus - theCamera->Distance()); + if (Point.x() != 0.0) + { + const gp_Dir aSide = aForward.Crossed (theCamera->Up()); + if (Point.x() > 0.0) + { + aCenter += aSide.XYZ() * (Abs(aViewDim.X()) * 0.5 - anOffset); + } + else + { + aCenter -= aSide.XYZ() * (Abs(aViewDim.X()) * 0.5 - anOffset); + } + } + if (Point.y() != 0.0) + { + if (Point.y() > 0.0) + { + aCenter += theCamera->Up().XYZ() * (Abs(aViewDim.Y()) * 0.5 - anOffset); + } + else + { + aCenter -= theCamera->Up().XYZ() * (Abs(aViewDim.Y()) * 0.5 - anOffset); + } + } + + Graphic3d_TransformUtils::Translate (theWorldView, T(aCenter.X()), T(aCenter.Y()), T(aCenter.Z())); + Graphic3d_TransformUtils::Scale (theWorldView, T(aScale), T(aScale), T(aScale)); + return; + } + if (Flags & Graphic3d_TMF_2d) { T aLeft = -static_cast (theViewportWidth / 2); @@ -158,8 +214,7 @@ void Graphic3d_TransformPers::Apply (NCollection_Mat4& theProjection, } // Prevent zooming. - if ((Flags == Graphic3d_TMF_TriedronPers) - || (Flags & Graphic3d_TMF_ZoomPers)) + if ((Flags & Graphic3d_TMF_ZoomPers) != 0) { const T aSize = static_cast (1.0); const Standard_Integer aViewport[4] = { 0, 0, theViewportHeight, theViewportHeight }; @@ -189,7 +244,7 @@ void Graphic3d_TransformPers::Apply (NCollection_Mat4& theProjection, } // Prevent translation by nullifying translation component. - if ((Flags & Graphic3d_TMF_PanPers) || Flags == Graphic3d_TMF_TriedronPers) + if ((Flags & Graphic3d_TMF_PanPers) != 0) { theWorldView .SetValue (0, 3, static_cast (0.0)); theWorldView .SetValue (1, 3, static_cast (0.0)); @@ -215,35 +270,7 @@ void Graphic3d_TransformPers::Apply (NCollection_Mat4& theProjection, theWorldView.SetValue (2, 2, static_cast (1.0)); } - if (Flags == Graphic3d_TMF_TriedronPers) - { - if (Point.x() != 0.0 && Point.y() != 0.0) - { - NCollection_Mat4 anUnviewMat; - - if (!(theProjection).Inverted (anUnviewMat)) - { - Standard_ProgramError::Raise ("Graphic3d_TransformPers::Apply, can not inverse projection matrix."); - } - - NCollection_Vec4 aProjMax (static_cast ( 1.0), static_cast ( 1.0), static_cast (0.0), static_cast (1.0)); - NCollection_Vec4 aProjMin (static_cast (-1.0), static_cast (-1.0), static_cast (0.0), static_cast (1.0)); - NCollection_Vec4 aViewMax = anUnviewMat * aProjMax; - NCollection_Vec4 aViewMin = anUnviewMat * aProjMin; - - aViewMax /= aViewMax.w(); - aViewMin /= aViewMin.w(); - - T aMoveX = static_cast (0.5) * (aViewMax.x() - aViewMin.x() - static_cast (Point.z())); - T aMoveY = static_cast (0.5) * (aViewMax.y() - aViewMin.y() - static_cast (Point.z())); - - aMoveX = (Point.x() > 0.0) ? aMoveX : -aMoveX; - aMoveY = (Point.y() > 0.0) ? aMoveY : -aMoveY; - - Graphic3d_TransformUtils::Translate (theProjection, aMoveX, aMoveY, static_cast (0.0)); - } - } - else if ((Flags & Graphic3d_TMF_PanPers) != Graphic3d_TMF_PanPers) + if ((Flags & Graphic3d_TMF_PanPers) != Graphic3d_TMF_PanPers) { NCollection_Mat4 anUnviewMat; @@ -266,12 +293,18 @@ void Graphic3d_TransformPers::Apply (NCollection_Mat4& theProjection, // purpose : Apply transformation to bounding box of presentation. // ======================================================================= template -void Graphic3d_TransformPers::Apply (const NCollection_Mat4& theProjection, +void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, + const NCollection_Mat4& theProjection, const NCollection_Mat4& theWorldView, const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight, Bnd_Box& theBoundingBox) const { + if (theBoundingBox.IsVoid()) + { + return; + } + T aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; theBoundingBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); @@ -280,7 +313,7 @@ void Graphic3d_TransformPers::Apply (const NCollection_Mat4& theProjection, typename BVH_Box::BVH_VecNt aMax (aXmax, aYmax, aZmax, static_cast (1.0)); BVH_Box aBBox (aMin, aMax); - Apply (theProjection, theWorldView, theViewportWidth, theViewportHeight, aBBox); + Apply (theCamera, theProjection, theWorldView, theViewportWidth, theViewportHeight, aBBox); theBoundingBox = Bnd_Box(); theBoundingBox.Update (aBBox.CornerMin().x(), aBBox.CornerMin().y(), aBBox.CornerMin().z(), @@ -292,15 +325,16 @@ void Graphic3d_TransformPers::Apply (const NCollection_Mat4& theProjection, // purpose : Apply transformation to bounding box of presentation. // ======================================================================= template -void Graphic3d_TransformPers::Apply (const NCollection_Mat4& theProjection, +void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, + const NCollection_Mat4& theProjection, const NCollection_Mat4& theWorldView, const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight, BVH_Box& theBoundingBox) const { - NCollection_Mat4 aTPers = Compute (theProjection, theWorldView, theViewportWidth, theViewportHeight); - - if (aTPers.IsIdentity()) + NCollection_Mat4 aTPers = Compute (theCamera, theProjection, theWorldView, theViewportWidth, theViewportHeight); + if (aTPers.IsIdentity() + || !theBoundingBox.IsValid()) { return; } @@ -333,7 +367,8 @@ void Graphic3d_TransformPers::Apply (const NCollection_Mat4& theProjection, // purpose : Compute transformation. // ======================================================================= template -NCollection_Mat4 Graphic3d_TransformPers::Compute (const NCollection_Mat4& theProjection, +NCollection_Mat4 Graphic3d_TransformPers::Compute (const Handle(Graphic3d_Camera)& theCamera, + const NCollection_Mat4& theProjection, const NCollection_Mat4& theWorldView, const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight) const @@ -353,7 +388,7 @@ NCollection_Mat4 Graphic3d_TransformPers::Compute (const NCollection_Mat4& NCollection_Mat4 aProjection (theProjection); NCollection_Mat4 aWorldView (theWorldView); - Apply (aProjection, aWorldView, theViewportWidth, theViewportHeight); + Apply (theCamera, aProjection, aWorldView, theViewportWidth, theViewportHeight); return anUnviewMat * (aProjection * aWorldView); } diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.cxx b/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.cxx index e351367c43..c1c880a37a 100644 --- a/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.cxx +++ b/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.cxx @@ -133,7 +133,8 @@ const OpenGl_Structure* OpenGl_BVHClipPrimitiveTrsfPersSet::GetStructureById (St // purpose : //======================================================================= const NCollection_Handle >& - OpenGl_BVHClipPrimitiveTrsfPersSet::BVH (const OpenGl_Mat4& theProjectionMatrix, + OpenGl_BVHClipPrimitiveTrsfPersSet::BVH (const Handle(Graphic3d_Camera)& theCamera, + const OpenGl_Mat4& theProjectionMatrix, const OpenGl_Mat4& theWorldViewMatrix, const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight, @@ -154,7 +155,7 @@ const NCollection_Handle >& HBndBox4f aBoundingBox = new Graphic3d_BndBox4f; *aBoundingBox = aStructure->BoundingBox(); - aStructure->TransformPersistence.Apply (theProjectionMatrix, theWorldViewMatrix, theViewportWidth, theViewportHeight, *aBoundingBox); + aStructure->TransformPersistence.Apply (theCamera, theProjectionMatrix, theWorldViewMatrix, theViewportWidth, theViewportHeight, *aBoundingBox); myStructBoxes.Add (aBoundingBox); } diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.hxx b/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.hxx index d838a0e42c..c800e4c592 100644 --- a/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.hxx +++ b/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.hxx @@ -76,7 +76,8 @@ public: } //! Returns BVH tree for the given world view projection (builds it if necessary). - const NCollection_Handle >& BVH (const OpenGl_Mat4& theProjectionMatrix, + const NCollection_Handle >& BVH (const Handle(Graphic3d_Camera)& theCamera, + const OpenGl_Mat4& theProjectionMatrix, const OpenGl_Mat4& theWorldViewMatrix, const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight, diff --git a/src/OpenGl/OpenGl_BVHTreeSelector.cxx b/src/OpenGl/OpenGl_BVHTreeSelector.cxx index 0699286700..66492f39e0 100644 --- a/src/OpenGl/OpenGl_BVHTreeSelector.cxx +++ b/src/OpenGl/OpenGl_BVHTreeSelector.cxx @@ -40,6 +40,7 @@ void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theC myIsProjectionParallel = theCamera->IsOrthographic(); + myCamera = theCamera; myProjectionMat = theCamera->ProjectionMatrixF(); myWorldViewMat = theCamera->OrientationMatrixF(); myWorldViewProjState = theCamera->WorldViewProjState(); diff --git a/src/OpenGl/OpenGl_BVHTreeSelector.hxx b/src/OpenGl/OpenGl_BVHTreeSelector.hxx index 4824ddadc4..39824c9ecb 100644 --- a/src/OpenGl/OpenGl_BVHTreeSelector.hxx +++ b/src/OpenGl/OpenGl_BVHTreeSelector.hxx @@ -46,6 +46,9 @@ public: //! Must be called at the beginning of each BVH tree traverse loop. Standard_EXPORT void CacheClipPtsProjections(); + //! Return the camera definition. + const Handle(Graphic3d_Camera)& Camera() const { return myCamera; } + //! Returns current projection matrix. const OpenGl_Mat4& ProjectionMatrix() const { @@ -115,6 +118,8 @@ protected: OpenGl_Vec4 myClipPlanes[PlanesNB]; //!< Plane equations OpenGl_Vec4 myClipVerts[ClipVerticesNB]; //!< Vertices + Handle(Graphic3d_Camera) myCamera; //!< camera definition + // for caching clip points projections onto viewing area normals once per traverse // ORDER: TOP, BOTTOM, LEFT, RIGHT, NEAR, FAR Standard_ShortReal myMaxClipProjectionPts[PlanesNB]; //!< Max view volume's vertices projections onto its normals diff --git a/src/OpenGl/OpenGl_GraduatedTrihedron.cxx b/src/OpenGl/OpenGl_GraduatedTrihedron.cxx index 94dd4cbf75..cd12dfb418 100755 --- a/src/OpenGl/OpenGl_GraduatedTrihedron.cxx +++ b/src/OpenGl/OpenGl_GraduatedTrihedron.cxx @@ -424,7 +424,7 @@ void OpenGl_GraduatedTrihedron::renderAxis (const Handle(OpenGl_Workspace)& theW const Standard_Integer aHeight = theWorkspace->Height(); // Take into account Transform Persistence - aContext->ModelWorldState.SetCurrent (aTransMode.Compute (aProjection, aWorldView, aWidth, aHeight)); + aContext->ModelWorldState.SetCurrent (aTransMode.Compute (theWorkspace->View()->Camera(), aProjection, aWorldView, aWidth, aHeight)); aContext->ApplyModelViewMatrix(); anAxis.Arrow.Render (theWorkspace); diff --git a/src/OpenGl/OpenGl_Layer.cxx b/src/OpenGl/OpenGl_Layer.cxx index bc624cf59f..330ce25391 100644 --- a/src/OpenGl/OpenGl_Layer.cxx +++ b/src/OpenGl/OpenGl_Layer.cxx @@ -61,6 +61,10 @@ void OpenGl_Layer::Add (const OpenGl_Structure* theStruct, if (theStruct->IsAlwaysRendered()) { theStruct->MarkAsNotCulled(); + if (!isForChangePriority) + { + myAlwaysRenderedMap.Add (theStruct); + } } else if (!isForChangePriority) { @@ -101,12 +105,23 @@ bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct, aStructures.Swap (anIndex, aStructures.Size()); aStructures.RemoveLast(); - if (!theStruct->IsAlwaysRendered() - && !isForChangePriority) + if (!isForChangePriority) { - if (!myBVHPrimitives.Remove (theStruct)) + if (theStruct->IsAlwaysRendered()) { - myBVHPrimitivesTrsfPers.Remove (theStruct); + const Standard_Integer anIndex2 = myAlwaysRenderedMap.FindIndex (theStruct); + if (anIndex2 != 0) + { + myAlwaysRenderedMap.Swap (myAlwaysRenderedMap.Size(), anIndex2); + myAlwaysRenderedMap.RemoveLast(); + } + } + else + { + if (!myBVHPrimitives.Remove (theStruct)) + { + myBVHPrimitivesTrsfPers.Remove (theStruct); + } } } --myNbStructures; @@ -128,18 +143,40 @@ void OpenGl_Layer::InvalidateBVHData() const myIsBVHPrimitivesNeedsReset = Standard_True; } +//! Calculate a finite bounding box of infinite object as its middle point. +inline Graphic3d_BndBox4f centerOfinfiniteBndBox (const Graphic3d_BndBox4f& theBndBox) +{ + // bounding borders of infinite line has been calculated as own point in center of this line + const Graphic3d_Vec4 aDiagVec = theBndBox.CornerMax() - theBndBox.CornerMin(); + return aDiagVec.xyz().SquareModulus() >= 500000.0f * 500000.0f + ? Graphic3d_BndBox4f ((theBndBox.CornerMin() + theBndBox.CornerMax()) * 0.5f) + : Graphic3d_BndBox4f(); +} + +//! Return true if at least one vertex coordinate out of float range. +inline bool isInfiniteBndBox (const Graphic3d_BndBox4f& theBndBox) +{ + return Abs (theBndBox.CornerMax().x()) >= ShortRealLast() + || Abs (theBndBox.CornerMax().y()) >= ShortRealLast() + || Abs (theBndBox.CornerMax().z()) >= ShortRealLast() + || Abs (theBndBox.CornerMin().x()) >= ShortRealLast() + || Abs (theBndBox.CornerMin().y()) >= ShortRealLast() + || Abs (theBndBox.CornerMin().z()) >= ShortRealLast(); +} + // ======================================================================= // function : BoundingBox // purpose : // ======================================================================= -const Graphic3d_BndBox4f& OpenGl_Layer::BoundingBox (const Standard_Integer theViewId, - const Handle(Graphic3d_Camera)& theCamera, - const Standard_Integer theWindowWidth, - const Standard_Integer theWindowHeight, - const Standard_Boolean theToIgnoreInfiniteFlag) const +Graphic3d_BndBox4f OpenGl_Layer::BoundingBox (const Standard_Integer theViewId, + const Handle(Graphic3d_Camera)& theCamera, + const Standard_Integer theWindowWidth, + const Standard_Integer theWindowHeight, + const Standard_Boolean theToIncludeAuxiliary) const { - const Standard_Integer aBoxId = theToIgnoreInfiniteFlag == 0 ? 0 : 1; - + const Standard_Integer aBoxId = !theToIncludeAuxiliary ? 0 : 1; + const Graphic3d_Mat4& aProjectionMat = theCamera->ProjectionMatrixF(); + const Graphic3d_Mat4& aWorldViewMat = theCamera->OrientationMatrixF(); if (myIsBoundingBoxNeedsReset[aBoxId]) { // Recompute layer bounding box @@ -152,12 +189,7 @@ const Graphic3d_BndBox4f& OpenGl_Layer::BoundingBox (const Standard_Integer for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx) { const OpenGl_Structure* aStructure = aStructures.FindKey (aStructIdx); - if (!aStructure->IsVisible()) - { - continue; - } - else if (!aStructure->ViewAffinity.IsNull() - && !aStructure->ViewAffinity->IsVisible (theViewId)) + if (!aStructure->IsVisible (theViewId)) { continue; } @@ -166,7 +198,8 @@ const Graphic3d_BndBox4f& OpenGl_Layer::BoundingBox (const Standard_Integer // but adds transform persistence point in a bounding box of layer (only zoom pers. objects). if (aStructure->TransformPersistence.Flags != Graphic3d_TMF_None) { - if (!theToIgnoreInfiniteFlag && (aStructure->TransformPersistence.Flags & Graphic3d_TMF_ZoomPers)) + if (!theToIncludeAuxiliary + && (aStructure->TransformPersistence.Flags & Graphic3d_TMF_ZoomPers) != 0) { BVH_Vec4f aTPPoint (static_cast (aStructure->TransformPersistence.Point.x()), static_cast (aStructure->TransformPersistence.Point.y()), @@ -178,66 +211,86 @@ const Graphic3d_BndBox4f& OpenGl_Layer::BoundingBox (const Standard_Integer } // Panning and 2d persistence apply changes to projection or/and its translation components. // It makes them incompatible with z-fitting algorithm. Ignored by now. - else if (!theToIgnoreInfiniteFlag - || (aStructure->TransformPersistence.Flags & Graphic3d_TMF_2d) - || (aStructure->TransformPersistence.Flags & Graphic3d_TMF_PanPers) - || (aStructure->TransformPersistence.Flags & Graphic3d_TMF_TriedronPers)) + else if (!theToIncludeAuxiliary + || (aStructure->TransformPersistence.Flags & (Graphic3d_TMF_2d | Graphic3d_TMF_PanPers | Graphic3d_TMF_TriedronPers)) != 0) { continue; } } Graphic3d_BndBox4f aBox = aStructure->BoundingBox(); + if (!aBox.IsValid()) + { + continue; + } if (aStructure->IsInfinite - && !theToIgnoreInfiniteFlag) + && !theToIncludeAuxiliary) { - const Graphic3d_Vec4 aDiagVec = aBox.CornerMax() - aBox.CornerMin(); - if (aDiagVec.xyz().SquareModulus() >= 500000.0f * 500000.0f) - { - // bounding borders of infinite line has been calculated as own point in center of this line - aBox = Graphic3d_BndBox4f ((aBox.CornerMin() + aBox.CornerMax()) * 0.5f); - } - else - { - aBox = Graphic3d_BndBox4f (Graphic3d_Vec4 (ShortRealFirst(), ShortRealFirst(), ShortRealFirst(), 1.0f), - Graphic3d_Vec4 (ShortRealLast(), ShortRealLast(), ShortRealLast(), 1.0f)); - } + // include center of infinite object + aBox = centerOfinfiniteBndBox (aBox); } if (aStructure->TransformPersistence.Flags != Graphic3d_TMF_None) { - const Graphic3d_Mat4& aProjectionMat = theCamera->ProjectionMatrixF(); - const Graphic3d_Mat4& aWorldViewMat = theCamera->OrientationMatrixF(); - - aStructure->TransformPersistence.Apply (aProjectionMat, + aStructure->TransformPersistence.Apply (theCamera, + aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox); } - // To prevent float overflow at camera parameters calculation and further - // rendering, bounding boxes with at least one vertex coordinate out of - // float range are skipped by view fit algorithms - if (Abs (aBox.CornerMax().x()) >= ShortRealLast() - || Abs (aBox.CornerMax().y()) >= ShortRealLast() - || Abs (aBox.CornerMax().z()) >= ShortRealLast() - || Abs (aBox.CornerMin().x()) >= ShortRealLast() - || Abs (aBox.CornerMin().y()) >= ShortRealLast() - || Abs (aBox.CornerMin().z()) >= ShortRealLast()) + // skip too big boxes to prevent float overflow at camera parameters calculation + if (!isInfiniteBndBox (aBox)) { - continue; + myBoundingBox[aBoxId].Combine (aBox); } - - myBoundingBox[aBoxId].Combine (aBox); } } myIsBoundingBoxNeedsReset[aBoxId] = false; } - return myBoundingBox[aBoxId]; + if (!theToIncludeAuxiliary + || myAlwaysRenderedMap.IsEmpty()) + { + return myBoundingBox[aBoxId]; + } + + // add transformation-persistent objects which depend on camera position (and thus can not be cached) for operations like Z-fit + Graphic3d_BndBox4f aResBox = myBoundingBox[aBoxId]; + for (NCollection_IndexedMap::Iterator aStructIter (myAlwaysRenderedMap); aStructIter.More(); aStructIter.Next()) + { + const OpenGl_Structure* aStructure = aStructIter.Value(); + if (!aStructure->IsVisible (theViewId)) + { + continue; + } + else if ((aStructure->TransformPersistence.Flags & Graphic3d_TMF_TriedronPers) == 0) + { + continue; + } + + Graphic3d_BndBox4f aBox = aStructure->BoundingBox(); + if (!aBox.IsValid()) + { + continue; + } + + aStructure->TransformPersistence.Apply (theCamera, + aProjectionMat, + aWorldViewMat, + theWindowWidth, + theWindowHeight, + aBox); + if (!isInfiniteBndBox (aBox)) + { + aResBox.Combine (aBox); + } + } + + return aResBox; } // ======================================================================= @@ -247,8 +300,7 @@ const Graphic3d_BndBox4f& OpenGl_Layer::BoundingBox (const Standard_Integer Standard_Real OpenGl_Layer::considerZoomPersistenceObjects (const Standard_Integer theViewId, const Handle(Graphic3d_Camera)& theCamera, Standard_Integer theWindowWidth, - Standard_Integer theWindowHeight, - Standard_Boolean /*theToIgnoreInfiniteFlag*/) const + Standard_Integer theWindowHeight) const { if (NbOfTransformPersistenceObjects() == 0) { @@ -266,23 +318,19 @@ Standard_Real OpenGl_Layer::considerZoomPersistenceObjects (const Standard_Integ for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx) { OpenGl_Structure* aStructure = const_cast (aStructures.FindKey (aStructIdx)); - if (!aStructure->IsVisible()) - { - continue; - } - else if (!aStructure->ViewAffinity.IsNull() - && !aStructure->ViewAffinity->IsVisible (theViewId)) - { - continue; - } - - if (!(aStructure->TransformPersistence.Flags & Graphic3d_TMF_ZoomPers)) + if (!aStructure->IsVisible (theViewId) + || (aStructure->TransformPersistence.Flags & Graphic3d_TMF_ZoomPers) == 0) { continue; } Graphic3d_BndBox4f aBox = aStructure->BoundingBox(); - aStructure->TransformPersistence.Apply (aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox); + if (!aBox.IsValid()) + { + continue; + } + + aStructure->TransformPersistence.Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox); const BVH_Vec4f& aCornerMin = aBox.CornerMin(); const BVH_Vec4f& aCornerMax = aBox.CornerMax(); @@ -398,37 +446,49 @@ void OpenGl_Layer::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) cons } } +// ======================================================================= +// function : updateBVH +// purpose : +// ======================================================================= +void OpenGl_Layer::updateBVH() const +{ + if (!myIsBVHPrimitivesNeedsReset) + { + return; + } + + myBVHPrimitives.Clear(); + myBVHPrimitivesTrsfPers.Clear(); + myIsBVHPrimitivesNeedsReset = Standard_False; + for (Standard_Integer aPriorityIdx = 0, aNbPriorities = myArray.Length(); aPriorityIdx < aNbPriorities; ++aPriorityIdx) + { + for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (myArray (aPriorityIdx)); aStructIter.More(); aStructIter.Next()) + { + const OpenGl_Structure* aStruct = aStructIter.Value(); + if (aStruct->IsAlwaysRendered()) + { + continue; + } + + if (aStruct->TransformPersistence.Flags == Graphic3d_TMF_None) + { + myBVHPrimitives.Add (aStruct); + } + else + { + myBVHPrimitivesTrsfPers.Add (aStruct); + } + } + } +} + // ======================================================================= // function : renderTraverse // purpose : // ======================================================================= void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const { - if (myIsBVHPrimitivesNeedsReset) - { - myBVHPrimitives.Clear(); - myBVHPrimitivesTrsfPers.Clear(); - myIsBVHPrimitivesNeedsReset = Standard_False; - for (Standard_Integer aPriorityIdx = 0, aNbPriorities = myArray.Length(); aPriorityIdx < aNbPriorities; ++aPriorityIdx) - { - for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (myArray (aPriorityIdx)); aStructIter.More(); aStructIter.Next()) - { - const OpenGl_Structure* aStruct = aStructIter.Value(); - - if (aStruct->IsAlwaysRendered()) - continue; - - if (aStruct->TransformPersistence.Flags == Graphic3d_TMF_None) - { - myBVHPrimitives.Add (aStruct); - } - else - { - myBVHPrimitivesTrsfPers.Add (aStruct); - } - } - } - } + updateBVH(); OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector(); traverse (aSelector); @@ -441,13 +501,8 @@ void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx) { const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx); - if (!aStruct->IsVisible() - || aStruct->IsCulled()) - { - continue; - } - else if (!aStruct->ViewAffinity.IsNull() - && !aStruct->ViewAffinity->IsVisible (aViewId)) + if (aStruct->IsCulled() + || !aStruct->IsVisible (aViewId)) { continue; } @@ -487,7 +542,7 @@ void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const const Standard_Integer aViewportWidth = theSelector.ViewportWidth(); const Standard_Integer aViewportHeight = theSelector.ViewportHeight(); - aBVHTree = myBVHPrimitivesTrsfPers.BVH (aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState); + aBVHTree = myBVHPrimitivesTrsfPers.BVH (theSelector.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState); } else { diff --git a/src/OpenGl/OpenGl_Layer.hxx b/src/OpenGl/OpenGl_Layer.hxx index 09d8b16416..78eeb6e449 100644 --- a/src/OpenGl/OpenGl_Layer.hxx +++ b/src/OpenGl/OpenGl_Layer.hxx @@ -99,18 +99,23 @@ public: } //! Returns layer bounding box. - const Graphic3d_BndBox4f& BoundingBox (const Standard_Integer theViewId, - const Handle(Graphic3d_Camera)& theCamera, - const Standard_Integer theWindowWidth, - const Standard_Integer theWindowHeight, - const Standard_Boolean theToIgnoreInfiniteFlag) const; + //! @param theViewId view index to consider View Affinity in structure + //! @param theCamera camera definition + //! @param theWindowWidth viewport width (for applying transformation-persistence) + //! @param theWindowHeight viewport height (for applying transformation-persistence) + //! @param theToIncludeAuxiliary consider also auxiliary presentations (with infinite flag or with trihedron transformation persistence) + //! @return computed bounding box + Graphic3d_BndBox4f BoundingBox (const Standard_Integer theViewId, + const Handle(Graphic3d_Camera)& theCamera, + const Standard_Integer theWindowWidth, + const Standard_Integer theWindowHeight, + const Standard_Boolean theToIncludeAuxiliary) const; //! Returns zoom-scale factor. Standard_Real considerZoomPersistenceObjects (const Standard_Integer theViewId, const Handle(Graphic3d_Camera)& theCamera, const Standard_Integer theWindowWidth, - const Standard_Integer theWindowHeight, - const Standard_Boolean theToIgnoreInfiniteFlag) const; + const Standard_Integer theWindowHeight) const; // Render all structures. void Render (const Handle(OpenGl_Workspace)& theWorkspace, @@ -124,6 +129,9 @@ public: protected: + //! Updates BVH trees if their state has been invalidated. + void updateBVH() const; + //! Traverses through BVH tree to determine which structures are in view volume. void traverse (OpenGl_BVHTreeSelector& theSelector) const; @@ -150,6 +158,9 @@ private: //! Set of transform persistent OpenGl_Structures for building BVH tree. mutable OpenGl_BVHClipPrimitiveTrsfPersSet myBVHPrimitivesTrsfPers; + //! Indexed map of always rendered structures. + NCollection_IndexedMap myAlwaysRenderedMap; + //! Is needed for implementation of stochastic order of BVH traverse. mutable Standard_Boolean myBVHIsLeftChildQueuedFirst; diff --git a/src/OpenGl/OpenGl_LayerList.cxx b/src/OpenGl/OpenGl_LayerList.cxx index cc4024149a..3735e322b0 100644 --- a/src/OpenGl/OpenGl_LayerList.cxx +++ b/src/OpenGl/OpenGl_LayerList.cxx @@ -242,7 +242,7 @@ void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure* theStructure, // take priority and remove structure from list found by // if the structure is not found there, scan through all other layers - if (aLayer.Remove (theStructure, aPriority, Standard_True)) + if (aLayer.Remove (theStructure, aPriority, Standard_False)) { --myNbStructures; if (aLayer.LayerSettings().IsImmediate) diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index f710c4e26c..1355473699 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -475,7 +475,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con { OpenGl_Mat4 aProjection = aCtx->ProjectionState.Current(); OpenGl_Mat4 aWorldView = aCtx->WorldViewState.Current(); - TransformPersistence.Apply (aProjection, aWorldView, theWorkspace->Width(), theWorkspace->Height()); + TransformPersistence.Apply (theWorkspace->View()->Camera(), aProjection, aWorldView, theWorkspace->Width(), theWorkspace->Height()); aCtx->ProjectionState.Push(); aCtx->WorldViewState.Push(); diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index 42dec5a9a4..4c23086713 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -548,7 +548,7 @@ Graphic3d_BndBox4f OpenGl_View::ZLayerBoundingBox (const Graphic3d_ZLayerId const Handle(Graphic3d_Camera)& theCamera, const Standard_Integer theWindowWidth, const Standard_Integer theWindowHeight, - const Standard_Boolean theToIgnoreInfiniteFlag) const + const Standard_Boolean theToIncludeAuxiliary) const { if (myZLayers.LayerIDs().IsBound (theLayerId)) { @@ -556,7 +556,7 @@ Graphic3d_BndBox4f OpenGl_View::ZLayerBoundingBox (const Graphic3d_ZLayerId theCamera, theWindowWidth, theWindowHeight, - theToIgnoreInfiniteFlag); + theToIncludeAuxiliary); } return Graphic3d_BndBox4f(); @@ -569,16 +569,14 @@ Graphic3d_BndBox4f OpenGl_View::ZLayerBoundingBox (const Graphic3d_ZLayerId Standard_Real OpenGl_View::considerZoomPersistenceObjects (const Graphic3d_ZLayerId theLayerId, const Handle(Graphic3d_Camera)& theCamera, const Standard_Integer theWindowWidth, - const Standard_Integer theWindowHeight, - const Standard_Boolean theToIgnoreInfiniteFlag) const + const Standard_Integer theWindowHeight) const { if (myZLayers.LayerIDs().IsBound (theLayerId)) { return myZLayers.Layer (theLayerId).considerZoomPersistenceObjects (Identification(), theCamera, theWindowWidth, - theWindowHeight, - theToIgnoreInfiniteFlag); + theWindowHeight); } return 1.0; diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx index 7be010328c..7cdfdd4963 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -197,12 +197,18 @@ public: Standard_EXPORT virtual void InvalidateZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId) const Standard_OVERRIDE; //! Returns the bounding box of all structures displayed in the Z layer. - //! Never fails. If Z layer does not exist the empty box is returned. + //! If Z layer does not exist the empty box is returned. + //! @param theLayerId layer identifier + //! @param theCamera camera definition + //! @param theWindowWidth viewport width (for applying transformation-persistence) + //! @param theWindowHeight viewport height (for applying transformation-persistence) + //! @param theToIncludeAuxiliary consider also auxiliary presentations (with infinite flag or with trihedron transformation persistence) + //! @return computed bounding box Standard_EXPORT virtual Graphic3d_BndBox4f ZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId, const Handle(Graphic3d_Camera)& theCamera, const Standard_Integer theWindowWidth, const Standard_Integer theWindowHeight, - const Standard_Boolean theToIgnoreInfiniteFlag) const Standard_OVERRIDE; + const Standard_Boolean theToIncludeAuxiliary) const Standard_OVERRIDE; //! Returns pointer to an assigned framebuffer object. Standard_EXPORT virtual Handle(Standard_Transient) FBO() const Standard_OVERRIDE; @@ -439,8 +445,7 @@ private: Standard_EXPORT virtual Standard_Real considerZoomPersistenceObjects (const Graphic3d_ZLayerId theLayerId, const Handle(Graphic3d_Camera)& theCamera, const Standard_Integer theWindowWidth, - const Standard_Integer theWindowHeight, - const Standard_Boolean theToIgnoreInfiniteFlag) const Standard_OVERRIDE; + const Standard_Integer theWindowHeight) const Standard_OVERRIDE; private: diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.cxx b/src/SelectMgr/SelectMgr_BaseFrustum.cxx index cf1066390f..2d8d8baea2 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.cxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.cxx @@ -35,6 +35,7 @@ SelectMgr_BaseFrustum::SelectMgr_BaseFrustum() //======================================================================= void SelectMgr_BaseFrustum::SetCamera (const Handle(Graphic3d_Camera)& theCamera) { + myCamera = theCamera; myBuilder->SetWorldViewMatrix (theCamera->OrientationMatrix()); myBuilder->SetProjectionMatrix (theCamera->ProjectionMatrix()); myBuilder->SetWorldViewProjState (theCamera->WorldViewProjState()); @@ -51,6 +52,7 @@ void SelectMgr_BaseFrustum::SetCamera (const Graphic3d_Mat4d& theProjection, const Standard_Integer theIsOrthographic, const Graphic3d_WorldViewProjState& theWVPState) { + myCamera.Nullify(); myBuilder->SetWorldViewMatrix (theWorldView); myBuilder->SetProjectionMatrix (theProjection); myBuilder->SetWorldViewProjState (theWVPState); diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.hxx b/src/SelectMgr/SelectMgr_BaseFrustum.hxx index 5855c6db1e..740a9b540b 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.hxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.hxx @@ -48,6 +48,9 @@ public: virtual ~SelectMgr_BaseFrustum() {} + //! Return camera definition. + const Handle(Graphic3d_Camera)& Camera() const { return myCamera; } + //! Passes camera projection and orientation matrices to builder Standard_EXPORT void SetCamera (const Handle(Graphic3d_Camera)& theCamera); @@ -173,6 +176,7 @@ protected: Standard_Boolean myIsOrthographic; //!< Defines if current camera is orthographic Handle(SelectMgr_FrustumBuilder) myBuilder; //!< A tool implementing methods for volume build + Handle(Graphic3d_Camera) myCamera; //!< camera definition }; #endif // _SelectMgr_BaseFrustum_HeaderFile diff --git a/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.cxx b/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.cxx index 47faa725df..ef3825592b 100644 --- a/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.cxx +++ b/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.cxx @@ -117,7 +117,8 @@ Standard_Boolean SelectMgr_SelectableObjectTrsfPersSet::Remove (const Handle(Sel // purpose : //======================================================================= const NCollection_Handle >& - SelectMgr_SelectableObjectTrsfPersSet::BVH (const Graphic3d_Mat4d& theProjectionMatrix, + SelectMgr_SelectableObjectTrsfPersSet::BVH (const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& theProjectionMatrix, const Graphic3d_Mat4d& theWorldViewMatrix, const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight, @@ -141,7 +142,7 @@ const NCollection_Handle >& anObject->BoundingBox (aBoundingBox); if (!aBoundingBox.IsVoid()) { - anObject->TransformPersistence().Apply (theProjectionMatrix, theWorldViewMatrix, theViewportWidth, theViewportHeight, aBoundingBox); + anObject->TransformPersistence().Apply (theCamera, theProjectionMatrix, theWorldViewMatrix, theViewportWidth, theViewportHeight, aBoundingBox); } } diff --git a/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.hxx b/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.hxx index 94ccfc9e6d..86580c294f 100644 --- a/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.hxx +++ b/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.hxx @@ -85,7 +85,8 @@ public: } //! Returns BVH tree for the given world view projection (builds it if necessary). - Standard_EXPORT const NCollection_Handle >& BVH (const Graphic3d_Mat4d& theProjectionMatrix, + Standard_EXPORT const NCollection_Handle >& BVH (const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& theProjectionMatrix, const Graphic3d_Mat4d& theWorldViewMatrix, const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight, diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx index 9321864a8c..4d1b8feb8b 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx @@ -53,6 +53,9 @@ public: Standard_EXPORT void SetActiveSelectionType (const SelectionType& theType); + //! Returns current camera definition. + const Handle(Graphic3d_Camera)& Camera() const { return mySelectingVolumes[Frustum]->Camera(); } + //! Updates camera projection and orientation matrices in all selecting volumes Standard_EXPORT void SetCamera (const Handle(Graphic3d_Camera) theCamera); diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx index 16e34ccfc7..3243627944 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx @@ -333,7 +333,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight); gp_GTrsf aTPers; - Graphic3d_Mat4d aMat = theObject->TransformPersistence().Compute (aProjection, aWorldView, aViewportWidth, aViewportHeight); + Graphic3d_Mat4d aMat = theObject->TransformPersistence().Compute (mySelectingVolumeMgr.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight); aTPers.SetValue (1, 1, aMat.GetValue (0, 0)); aTPers.SetValue (1, 2, aMat.GetValue (0, 1)); aTPers.SetValue (1, 3, aMat.GetValue (0, 2)); @@ -449,7 +449,7 @@ void SelectMgr_ViewerSelector::TraverseSensitives() Standard_Integer aViewportWidth; Standard_Integer aViewportHeight; mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight); - aBVHTree = mySelectableObjectsTrsfPers.BVH (aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState); + aBVHTree = mySelectableObjectsTrsfPers.BVH (mySelectingVolumeMgr.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState); } else { @@ -888,7 +888,7 @@ void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsF mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight); mySelectableObjects.BVH(); - mySelectableObjectsTrsfPers.BVH (aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState); + mySelectableObjectsTrsfPers.BVH (mySelectingVolumeMgr.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState); } } diff --git a/src/V3d/V3d_View.cxx b/src/V3d/V3d_View.cxx index d0c815c945..dd5263df7c 100644 --- a/src/V3d/V3d_View.cxx +++ b/src/V3d/V3d_View.cxx @@ -2224,7 +2224,7 @@ void V3d_View::Gravity (Standard_Real& theX, if (aNbPoints == 0) { // fallback - just use bounding box of entire scene - Bnd_Box aBox = myView->MinMaxValues (Standard_True); + Bnd_Box aBox = myView->MinMaxValues(); if (!aBox.IsVoid()) { aBox.Get (Xmin, Ymin, Zmin, diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index fc05e2762b..69d747e45c 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -4460,7 +4460,7 @@ static Standard_Integer VState (Draw_Interpretor& theDI, Standard_Integer aViewportHeight = 0; aMgr.WindowSize (aViewportWidth, aViewportHeight); - Graphic3d_Mat4d aMat = anObj->TransformPersistence().Compute (aProjection, aWorldView, aViewportWidth, aViewportHeight); + Graphic3d_Mat4d aMat = anObj->TransformPersistence().Compute (aMgr.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight); anInvTrsf.SetValue (1, 1, aMat.GetValue (0, 0)); anInvTrsf.SetValue (1, 2, aMat.GetValue (0, 1)); diff --git a/tests/bugs/vis/bug26344 b/tests/bugs/vis/bug26344 index f7cc40e450..7ea8a20e0c 100644 --- a/tests/bugs/vis/bug26344 +++ b/tests/bugs/vis/bug26344 @@ -7,6 +7,8 @@ puts "" puts "Visualization - provide a support of zoom persistent selection" ########################################################################################## +vclear +vclose ALL vinit View1 w=409 h=409 vtrihedron tri vpan 50 50 @@ -20,60 +22,49 @@ box b5 100 100 100 # 1) Zoom persistence vpoint p1 200 200 200 -vdisplay b1 -trsfPers zoom -trsfPersPos 200 200 200 -vdisplay b2 -trsfPers zoom -trsfPersPos 200 200 200 +vdisplay b1 -dispMode 1 -highMode 1 -trsfPers zoom -trsfPersPos 200 200 200 +vdisplay b2 -dispMode 1 -highMode 1 -trsfPers zoom -trsfPersPos 200 200 200 vsetlocation b2 -25 -25 -25 -vmoveto 387 77 -if { ![checkcolor 387 77 0 1 1] } { - puts "Error picking zoom persistence object" -} - -vmoveto 352 96 -if { ![checkcolor 352 96 0 1 1] } { - puts "Error picking zoom persistent object with location" -} +vselect 0 0 +vselect 387 77 +if { [vreadpixel 387 77 rgb name] != "GRAY66" } { puts "Error picking zoom persistence object(s)" } +vselect 0 0 vselect 330 120 400 50 +if { [vreadpixel 387 77 rgb name] != "GRAY66" || [vreadpixel 352 96 rgb name] != "GRAY66" } { puts "Error selecting zoom persistence object(s)" } -if { ![checkcolor 387 77 0.8 0.8 0.8] || ![checkcolor 352 96 0.8 0.8 0.8] } { - puts "Error selecting zoom persistence object(s)" -} # 2) Rotate persistence -vdisplay b3 -trsfPers rotate -trsfPersPos -200 -200 -200 -vmoveto 160 200 -if { ![checkcolor 160 180 0 1 1] } { - puts "Error picking rotate persistence object" -} +vdisplay b3 -dispMode 1 -highMode 1 -trsfPers rotate -trsfPersPos -200 -200 -200 +vsetmaterial b3 PLASTIC +vselect 0 0 +vselect 160 200 +if { [vreadpixel 160 180 rgb name] != "WHITE" } { puts "Error picking rotate persistence object" } + +vselect 0 0 vselect 130 230 190 170 -if { ![checkcolor 160 180 0.8 0.8 0.8] } { - puts "Error selecting rotate persistence object" -} +if { [vreadpixel 160 180 rgb name] != "WHITE" } { puts "Error selecting rotate persistence object" } # 3) Pan persistence -vdisplay b4 -trsfPers pan -vmoveto 233 188 -if { ![checkcolor 233 188 0 1 1] } { - puts "Error picking pan persistence object" -} +vdisplay b4 -dispMode 1 -highMode 1 -trsfPers pan +vselect 0 0 +vselect 233 188 +if { [vreadpixel 233 188 rgb name] != "GRAY66" } { puts "Error picking pan persistence object" } +vselect 0 0 vselect 200 230 270 140 -if { ![checkcolor 233 188 0.8 0.8 0.8] } { - puts "Error selecting pan persistence object" -} +if { [vreadpixel 233 188 rgb name] != "GRAY66" } { puts "Error selecting pan persistence object" } # 4) Trihedron persistence -vdisplay b5 -trsfPers trihedron -trsfPersPos -1 -1 300 -vmoveto 132 300 -if { ![checkcolor 132 300 0 1 1] } { - puts "Error picking trihedron persistence object" -} +vdisplay b5 -dispMode 1 -highMode 1 -trsfPers trihedron -trsfPersPos -1 -1 62 +vselect 0 0 +vselect 132 300 +if { [vreadpixel 132 300 rgb name] != "GRAY66" } { puts "Error picking trihedron persistence object" } +vselect 0 0 vselect 50 223 235 395 -if { ![checkcolor 132 300 0.8 0.8 0.8] } { - puts "Error selecting trihedron persistence object" -} +if { [vreadpixel 132 300 rgb name] != "GRAY66" } { puts "Error selecting trihedron persistence object" } vselect 50 380 400 50 diff --git a/tests/bugs/vis/bug27793 b/tests/bugs/vis/bug27793 new file mode 100644 index 0000000000..f39ba45738 --- /dev/null +++ b/tests/bugs/vis/bug27793 @@ -0,0 +1,21 @@ +puts "========" +puts "Object drifts at zoom within Graphic3d_TMF_TriedronPers applied" +puts "========" + +pload MODELING VISUALIZATION + +box b 100 200 300 +vclear +vinit View1 +vtrihedron t1 +vtrihedron t2 +vdisplay -dispMode 1 b +vaxo +vdisplay -trsfPers trihedron -trsfPersPos -1 -1 100 t1 +vdisplay -trsfPers trihedron -trsfPersPos 1 1 100 t2 +vsetlocation t2 0 0 -50 +vcamera -persp +vstereo anaglyph +vfit +vzoom 0.05 +vdump $imagedir/${casename}.png -stereo blend