From: Natalia Ermolaeva Date: Sat, 26 Jun 2021 07:36:40 +0000 (+0300) Subject: 0027919: Visualization - support multiple transformation persistence groups within... X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=db2f23ffcab2648e2e191ce22ed7210249f66183;p=occt-copy.git 0027919: Visualization - support multiple transformation persistence groups within single presentation (cherry picked from commit 57f02cff1af4c6a62a586c96dcdb53c6fba5b370) # Conflicts: # src/SelectMgr/SelectMgr_ViewerSelector.cxx --- diff --git a/src/Graphic3d/Graphic3d_Group.cxx b/src/Graphic3d/Graphic3d_Group.cxx index 9ea7a7d29b..687dcf4d60 100644 --- a/src/Graphic3d/Graphic3d_Group.cxx +++ b/src/Graphic3d/Graphic3d_Group.cxx @@ -458,6 +458,8 @@ void Graphic3d_Group::DumpJson (Standard_OStream& theOStream, Standard_Integer t OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, this) + OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myTrsfPers.get()) + OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myStructure) OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myBounds) diff --git a/src/Graphic3d/Graphic3d_Group.hxx b/src/Graphic3d/Graphic3d_Group.hxx index e26516f351..69a1e3a67b 100644 --- a/src/Graphic3d/Graphic3d_Group.hxx +++ b/src/Graphic3d/Graphic3d_Group.hxx @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -137,6 +138,12 @@ public: //! sets the flipping to theIsEnabled state. Standard_EXPORT virtual void SetFlippingOptions (const Standard_Boolean theIsEnabled, const gp_Ax2& theRefPlane) = 0; + //! Return transformation persistence. + const Handle(Graphic3d_TransformPers)& TransformPersistence() const { return myTrsfPers; } + + //! Set transformation persistence. + virtual void SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers) { myTrsfPers = theTrsfPers; } + //! Returns true if the group contains Polygons, Triangles or Quadrangles. bool ContainsFacet() const { return myContainsFacet; } @@ -294,6 +301,7 @@ protected: protected: + Handle(Graphic3d_TransformPers) myTrsfPers; //!< current transform persistence Graphic3d_Structure* myStructure; //!< pointer to the parent structure Graphic3d_BndBox4f myBounds; //!< bounding box bool myIsClosed; //!< flag indicating closed volume diff --git a/src/Graphic3d/Graphic3d_Layer.cxx b/src/Graphic3d/Graphic3d_Layer.cxx index 6b723c8f31..84ec9c1ecb 100644 --- a/src/Graphic3d/Graphic3d_Layer.cxx +++ b/src/Graphic3d/Graphic3d_Layer.cxx @@ -171,6 +171,37 @@ inline bool isInfiniteBndBox (const Graphic3d_BndBox3d& theBndBox) || Abs (theBndBox.CornerMin().z()) >= ShortRealLast(); } +// ======================================================================= +// function : updateBoundingBox +// purpose : +// ======================================================================= +void updateBoundingBox (const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& aProjectionMat, + const Graphic3d_Mat4d& aWorldViewMat, + Standard_Integer theWindowWidth, + Standard_Integer theWindowHeight, + const Handle(Graphic3d_TransformPers)& theTrsfPers, + Graphic3d_BndBox3d& theBox, + Bnd_Box& theResBox) +{ + if (theTrsfPers.IsNull()) + { + return; + } + + if (!theBox.IsValid()) + { + return; + } + + theTrsfPers->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, theBox); + if (theBox.IsValid() && !isInfiniteBndBox (theBox)) + { + theResBox.Add (gp_Pnt (theBox.CornerMin().x(), theBox.CornerMin().y(), theBox.CornerMin().z())); + theResBox.Add (gp_Pnt (theBox.CornerMax().x(), theBox.CornerMax().y(), theBox.CornerMax().z())); + } +} + // ======================================================================= // function : BoundingBox // purpose : @@ -268,25 +299,34 @@ Bnd_Box Graphic3d_Layer::BoundingBox (Standard_Integer theViewId, { continue; } - else if (aStructure->TransformPersistence().IsNull() - || !aStructure->TransformPersistence()->IsTrihedronOr2d()) + for (Graphic3d_SequenceOfGroup::Iterator aGroupIter(aStructure->Groups()); aGroupIter.More(); aGroupIter.Next()) { - continue; + const Handle(Graphic3d_Group)& aGroup = aGroupIter.Value(); + if (aGroup->TransformPersistence().IsNull()) + { + continue; + } + + const Graphic3d_BndBox4f& aBoxF = aGroup->BoundingBox(); + Graphic3d_BndBox3d aBox = Graphic3d_BndBox3d (Graphic3d_Vec3d ((Standard_Real)aBoxF.CornerMin().x(), + (Standard_Real)aBoxF.CornerMin().y(), + (Standard_Real)aBoxF.CornerMin().z()), + Graphic3d_Vec3d ((Standard_Real)aBoxF.CornerMax().x(), + (Standard_Real)aBoxF.CornerMax().y(), + (Standard_Real)aBoxF.CornerMax().z())); + updateBoundingBox (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, + aGroup->TransformPersistence(), aBox, aResBox); } - Graphic3d_BndBox3d aBox = aStructure->BoundingBox(); - if (!aBox.IsValid()) + if (aStructure->TransformPersistence().IsNull() + || !aStructure->TransformPersistence()->IsTrihedronOr2d()) { continue; } - aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox); - if (aBox.IsValid() - && !isInfiniteBndBox (aBox)) - { - aResBox.Add (gp_Pnt (aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z())); - aResBox.Add (gp_Pnt (aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z())); - } + Graphic3d_BndBox3d aBox = aStructure->BoundingBox(); + updateBoundingBox (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, + aStructure->TransformPersistence(), aBox, aResBox); } return aResBox; diff --git a/src/Graphic3d/Graphic3d_Structure.cxx b/src/Graphic3d/Graphic3d_Structure.cxx index a3f1e4e4d4..16a56f4024 100644 --- a/src/Graphic3d/Graphic3d_Structure.cxx +++ b/src/Graphic3d/Graphic3d_Structure.cxx @@ -802,6 +802,10 @@ Graphic3d_BndBox4f Graphic3d_Structure::minMaxCoord() const Graphic3d_BndBox4f aBnd; for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myCStructure->Groups()); aGroupIter.More(); aGroupIter.Next()) { + if (!aGroupIter.Value()->TransformPersistence().IsNull()) + { + continue; + } aBnd.Combine (aGroupIter.Value()->BoundingBox()); } return aBnd; diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index ded5c09c4a..6d26cd51bf 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -394,10 +394,42 @@ void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorksp myInstancedStructure->renderGeometry (theWorkspace, theHasClosed); } + const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next()) { + const Handle(Graphic3d_TransformPers)& aTrsfPersistence = aGroupIter.Value()->TransformPersistence(); + Standard_Boolean anOldCastShadows; + gp_Pnt aStartPnt; + + if (!aTrsfPersistence.IsNull()) + { + if (aTrsfPersistence->IsZoomOrRotate()) + { + aCtx->ModelWorldState.Push(); + OpenGl_Mat4& aModelWorld = aCtx->ModelWorldState.ChangeCurrent(); + aStartPnt = aTrsfPersistence->AnchorPoint(); + Graphic3d_Vec4 anAnchorPoint = aModelWorld * Graphic3d_Vec4 ((Standard_ShortReal)aStartPnt.X(), + (Standard_ShortReal)aStartPnt.Y(), (Standard_ShortReal)aStartPnt.Z(), 1.0f); + aModelWorld.SetColumn (3, Graphic3d_Vec4 (Graphic3d_Vec3 (0.0), 1.0)); + aTrsfPersistence->SetAnchorPoint (gp_Pnt (anAnchorPoint.x(), anAnchorPoint.y(), anAnchorPoint.z())); + } + applyPersistence (aCtx, aTrsfPersistence, anOldCastShadows, Standard_True); + aCtx->ApplyModelViewMatrix(); + } + theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed(); aGroupIter.Value()->Render (theWorkspace); + + if (!aTrsfPersistence.IsNull()) + { + if (aTrsfPersistence->IsZoomOrRotate()) + { + aTrsfPersistence->SetAnchorPoint (aStartPnt); + aCtx->ModelWorldState.Pop(); + } + applyPersistence (aCtx, aTrsfPersistence, anOldCastShadows, Standard_False); + aCtx->ApplyModelViewMatrix(); + } } } @@ -446,26 +478,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con #endif if (!myTrsfPers.IsNull()) { - // temporarily disable shadows on non-3d objects - anOldCastShadows = aCtx->ShaderManager()->SetCastShadows (false); - - aCtx->WorldViewState.Push(); - OpenGl_Mat4& aWorldView = aCtx->WorldViewState.ChangeCurrent(); - myTrsfPers->Apply (aCtx->Camera(), - aCtx->ProjectionState.Current(), aWorldView, - aCtx->VirtualViewport()[2], aCtx->VirtualViewport()[3]); - - #if !defined(GL_ES_VERSION_2_0) - if (!aCtx->IsGlNormalizeEnabled() - && aCtx->core11ffp != NULL) - { - const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor (aWorldView); - if (Abs (aScale - 1.0) > Precision::Confusion()) - { - aCtx->SetGlNormalizeEnabled (Standard_True); - } - } - #endif + applyPersistence (aCtx, myTrsfPers, anOldCastShadows, Standard_True); #ifdef GL_DEPTH_CLAMP if (myTrsfPers->Mode() == Graphic3d_TMF_CameraPers @@ -623,7 +636,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con if (!myTrsfPers.IsNull()) { - aCtx->WorldViewState.Pop(); + applyPersistence (aCtx, myTrsfPers, anOldCastShadows, Standard_False); aCtx->ShaderManager()->SetCastShadows (anOldCastShadows); #ifdef GL_DEPTH_CLAMP if (toRestoreDepthClamp) { aCtx->core11fwd->glDisable (GL_DEPTH_CLAMP); } @@ -666,6 +679,46 @@ Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3 return new OpenGl_StructureShadow (theManager, this); } +// ======================================================================= +// function : applyPersistence +// purpose : +// ======================================================================= +void OpenGl_Structure::applyPersistence (const Handle(OpenGl_Context)& theContext, + const Handle(Graphic3d_TransformPers)& theTrsfPersistence, + Standard_Boolean& theOldCastShadows, + const Standard_Boolean toEnable) const +{ + if (toEnable) + { + // temporarily disable shadows on non-3d objects + theOldCastShadows = theContext->ShaderManager()->SetCastShadows (false); + + theContext->WorldViewState.Push(); + OpenGl_Mat4& aWorldView = theContext->WorldViewState.ChangeCurrent(); + theTrsfPersistence->Apply (theContext->Camera(), + theContext->ProjectionState.Current(), aWorldView, + theContext->VirtualViewport()[2], theContext->VirtualViewport()[3]); + + #if !defined(GL_ES_VERSION_2_0) + if (!theContext->IsGlNormalizeEnabled() + && theContext->core11ffp != NULL) + { + const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor (aWorldView); + if (Abs (aScale - 1.0) > Precision::Confusion()) + { + theContext->SetGlNormalizeEnabled (Standard_True); + } + } + #endif + } + else + { + theContext->WorldViewState.Pop(); + theContext->ShaderManager()->SetCastShadows (theOldCastShadows); + theContext->ApplyModelViewMatrix(); + } +} + //======================================================================= //function : DumpJson //purpose : diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx index e603e30973..48aa3f3641 100644 --- a/src/OpenGl/OpenGl_Structure.hxx +++ b/src/OpenGl/OpenGl_Structure.hxx @@ -146,6 +146,18 @@ protected: //! Render the bounding box. Standard_EXPORT void renderBoundingBox(const Handle(OpenGl_Workspace)& theWorkspace) const; + + //! Apply transform persistence into context. + //! It disables shadows on non - 3d objects when toEnable is true and restores overwise. + //! @param theWorkspace current workspace + //! @param theTrsfPersistence transform persistence + //! @param theOldCastShadows state of the the previous cast shadows state + //! @param toEnable flag to switch ON/OFF persistence + Standard_EXPORT void applyPersistence (const Handle(OpenGl_Context)& theContext, + const Handle(Graphic3d_TransformPers)& theTrsfPersistence, + Standard_Boolean& theOldCastShadows, + const Standard_Boolean toEnable) const; + protected: OpenGl_Structure* myInstancedStructure; diff --git a/src/Prs3d/Prs3d_ArrowAspect.cxx b/src/Prs3d/Prs3d_ArrowAspect.cxx index 130d868900..aac00a74ef 100644 --- a/src/Prs3d/Prs3d_ArrowAspect.cxx +++ b/src/Prs3d/Prs3d_ArrowAspect.cxx @@ -26,7 +26,8 @@ IMPLEMENT_STANDARD_RTTIEXT(Prs3d_ArrowAspect, Prs3d_BasicAspect) Prs3d_ArrowAspect::Prs3d_ArrowAspect() : myArrowAspect (new Graphic3d_AspectLine3d (Quantity_Color(Quantity_NOC_WHITE), Aspect_TOL_SOLID, 1.0)), myAngle (M_PI / 180.0 * 10.0), - myLength(1.0) + myLength (1.0), + myIsZoomable (Standard_True) { // } diff --git a/src/Prs3d/Prs3d_ArrowAspect.hxx b/src/Prs3d/Prs3d_ArrowAspect.hxx index f63e59a417..0c9276f061 100644 --- a/src/Prs3d/Prs3d_ArrowAspect.hxx +++ b/src/Prs3d/Prs3d_ArrowAspect.hxx @@ -51,6 +51,12 @@ public: //! Returns the current value of the length used when drawing an arrow. Standard_Real Length() const { return myLength; } + //! Turns usage of arrow zoomable on/off + void SetZoomable (bool theIsZoomable) { myIsZoomable = theIsZoomable; } + + //! Returns TRUE when the Arrow Zoomable is on. + bool Zoomable() const { return myIsZoomable; } + void SetColor (const Quantity_Color& theColor) { myArrowAspect->SetColor (theColor); } const Handle(Graphic3d_AspectLine3d)& Aspect() const { return myArrowAspect; } @@ -65,6 +71,7 @@ protected: Handle(Graphic3d_AspectLine3d) myArrowAspect; Standard_Real myAngle; Standard_Real myLength; + Standard_Boolean myIsZoomable; }; diff --git a/src/PrsDim/PrsDim_AngleDimension.cxx b/src/PrsDim/PrsDim_AngleDimension.cxx index a58af9cc21..7fdb93b518 100644 --- a/src/PrsDim/PrsDim_AngleDimension.cxx +++ b/src/PrsDim/PrsDim_AngleDimension.cxx @@ -691,8 +691,14 @@ void PrsDim_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager)& , aFirstArrowBegin = aFirstAttach; aSecondArrowBegin = aSecondAttach; - aFirstArrowEnd = aFirstAttach.Translated (-aFirstArrowVec); - aSecondArrowEnd = aSecondAttach.Translated (-aSecondArrowVec); + aFirstArrowEnd = aFirstAttach; + aSecondArrowEnd = aSecondAttach; + + if (aDimensionAspect->ArrowAspect()->Zoomable()) + { + aFirstArrowEnd.Translate (-aFirstArrowVec); + aSecondArrowEnd.Translate (-aSecondArrowVec); + } // Group1: stenciling text and the angle dimension arc thePresentation->NewGroup(); diff --git a/src/PrsDim/PrsDim_Dimension.cxx b/src/PrsDim/PrsDim_Dimension.cxx index deba152a40..9bb67a0784 100644 --- a/src/PrsDim/PrsDim_Dimension.cxx +++ b/src/PrsDim/PrsDim_Dimension.cxx @@ -363,6 +363,7 @@ void PrsDim_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentat Standard_Real aLength = myDrawer->DimensionAspect()->ArrowAspect()->Length(); Standard_Real anAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle(); + Standard_Boolean isZoomable = myDrawer->DimensionAspect()->ArrowAspect()->Zoomable(); if (myDrawer->DimensionAspect()->IsArrows3d()) { @@ -375,16 +376,17 @@ void PrsDim_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentat } else { + gp_Pnt aLocation = isZoomable ? theLocation : gp::Origin(); gp_Pnt aLeftPoint (gp::Origin()); gp_Pnt aRightPoint (gp::Origin()); const gp_Dir& aPlane = GetPlane().Axis().Direction(); - PointsForArrow (theLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint); + PointsForArrow (aLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint); Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3); anArrow->AddVertex (aLeftPoint); - anArrow->AddVertex (theLocation); + anArrow->AddVertex (aLocation); anArrow->AddVertex (aRightPoint); // Set aspect for arrow triangles @@ -400,6 +402,10 @@ void PrsDim_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentat aGroup->SetPrimitivesAspect (aShadingStyle); aGroup->AddPrimitiveArray (anArrow); + if (!isZoomable) + { + aGroup->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_ZoomPers, theLocation)); + } } SelectionGeometry::Arrow& aSensitiveArrow = mySelectionGeom.NewArrow(); @@ -707,10 +713,16 @@ void PrsDim_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& th aFirstArrowBegin = aLineBegPoint; aSecondArrowBegin = aLineEndPoint; - aFirstArrowEnd = aLineBegPoint.Translated (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength)); - aSecondArrowEnd = aLineEndPoint.Translated (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength)); + aFirstArrowEnd = aLineBegPoint; + aSecondArrowEnd = aLineEndPoint; + + if (aDimensionAspect->ArrowAspect()->Zoomable()) + { + aFirstArrowEnd.Translate (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength)); + aSecondArrowEnd.Translate (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength)); + } - gp_Pnt aCenterLineBegin = isArrowsExternal + gp_Pnt aCenterLineBegin = isArrowsExternal ? aLineBegPoint : aFirstArrowEnd; gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide diff --git a/src/Select3D/Select3D_SensitiveEntity.cxx b/src/Select3D/Select3D_SensitiveEntity.cxx index 97bc6a3684..d63246c9e3 100644 --- a/src/Select3D/Select3D_SensitiveEntity.cxx +++ b/src/Select3D/Select3D_SensitiveEntity.cxx @@ -40,7 +40,8 @@ void Select3D_SensitiveEntity::DumpJson (Standard_OStream& theOStream, Standard_ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myOwnerId.get()) - OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mySFactor) + OCCT_DUMP_FIELD_VALUES_DUMPED(theOStream, theDepth, myTrsfPers.get()) + OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, mySFactor) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, NbSubElements()); diff --git a/src/Select3D/Select3D_SensitiveEntity.hxx b/src/Select3D/Select3D_SensitiveEntity.hxx index 3015a14d5b..9abc398b47 100644 --- a/src/Select3D/Select3D_SensitiveEntity.hxx +++ b/src/Select3D/Select3D_SensitiveEntity.hxx @@ -27,6 +27,7 @@ #include #include +class Graphic3d_TransformPers; class SelectMgr_EntityOwner; //! Abstract framework to define 3D sensitive entities. @@ -93,6 +94,12 @@ public: //! Otherwise, returns identity matrix. virtual gp_GTrsf InvInitLocation() const { return gp_GTrsf(); } + //! Return transformation persistence. + const Handle(Graphic3d_TransformPers)& TransformPersistence() const { return myTrsfPers; } + + //! Set transformation persistence. + virtual void SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers) { myTrsfPers = theTrsfPers; } + //! Dumps the content of me into the stream Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const; @@ -103,6 +110,7 @@ protected: protected: Handle(SelectMgr_EntityOwner) myOwnerId; + Handle(Graphic3d_TransformPers) myTrsfPers; Standard_Integer mySFactor; }; diff --git a/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx b/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx index 15be832ffd..4c343b573c 100644 --- a/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx +++ b/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx @@ -125,15 +125,40 @@ namespace Bnd_Box aBoundingBox; anObject->BoundingBox (aBoundingBox); - if (aBoundingBox.IsVoid() - || anObject->TransformPersistence().IsNull()) + if (!aBoundingBox.IsVoid() + && !anObject->TransformPersistence().IsNull()) + { + anObject->TransformPersistence()->Apply (theCamera, theProjectionMat, theWorldViewMat, theWidth, theHeight, aBoundingBox); + } + // processing presentations with own transform persistence + PrsMgr_Presentations& aPresentations = anObject->Presentations(); + for (PrsMgr_Presentations::Iterator aPrsIter (aPresentations); aPrsIter.More(); aPrsIter.Next()) + { + const Handle(PrsMgr_Presentation)& aPrs3d = aPrsIter.ChangeValue(); + for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aPrs3d->Groups()); aGroupIter.More(); aGroupIter.Next()) + { + if (!aGroupIter.Value()->TransformPersistence().IsNull()) + { + const Graphic3d_BndBox4f& aBndBox = aGroupIter.Value()->BoundingBox(); + if (!aBndBox.IsValid()) + { + continue; + } + Bnd_Box aGroupBoundingBox; + aGroupBoundingBox.Update (aBndBox.CornerMin().x(), aBndBox.CornerMin().y(), aBndBox.CornerMin().z(), + aBndBox.CornerMax().x(), aBndBox.CornerMax().y(), aBndBox.CornerMax().z()); + aGroupIter.Value()->TransformPersistence()->Apply (theCamera, theProjectionMat, theWorldViewMat, theWidth, theHeight, aGroupBoundingBox); + aBoundingBox.Add (aGroupBoundingBox); + } + } + } + + if (aBoundingBox.IsVoid()) { myBoundings.Add (new Select3D_HBndBox3d()); } else { - anObject->TransformPersistence()->Apply (theCamera, theProjectionMat, theWorldViewMat, theWidth, theHeight, aBoundingBox); - const gp_Pnt aMin = aBoundingBox.CornerMin(); const gp_Pnt aMax = aBoundingBox.CornerMax(); myBoundings.Add (new Select3D_HBndBox3d (Select3D_Vec3 (aMin.X(), aMin.Y(), aMin.Z()), diff --git a/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx b/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx index 2925e42b42..51dea02574 100644 --- a/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx +++ b/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx @@ -190,6 +190,18 @@ private: { if (theObject->TransformPersistence().IsNull()) { + PrsMgr_Presentations& aPresentations = theObject->Presentations(); + for (PrsMgr_Presentations::Iterator aPrsIter (aPresentations); aPrsIter.More(); aPrsIter.Next()) + { + const Handle(PrsMgr_Presentation)& aPrs3d = aPrsIter.ChangeValue(); + for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aPrs3d->Groups()); aGroupIter.More(); aGroupIter.Next()) + { + if (!aGroupIter.Value()->TransformPersistence().IsNull()) + { + return SelectMgr_SelectableObjectSet::BVHSubset_3dPersistent; + } + } + } return SelectMgr_SelectableObjectSet::BVHSubset_3d; } else if (theObject->TransformPersistence()->Mode() == Graphic3d_TMF_2d) diff --git a/src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx b/src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx index bad281a5e1..bf50591a63 100644 --- a/src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx +++ b/src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx @@ -15,11 +15,45 @@ #include +#include #include #include IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_SensitiveEntitySet, BVH_PrimitiveSet3d) +class SelectMgr_AdaptorPersistent : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(SelectMgr_AdaptorPersistent, Standard_Transient) +public: + SelectMgr_AdaptorPersistent (const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& theProjectionMat, + const Graphic3d_Mat4d& theWorldViewMat, + const Graphic3d_WorldViewProjState& theViewState, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight) + : myCamera (theCamera), myProjectionMat (theProjectionMat), + myWorldViewMat (theWorldViewMat), myViewState (theViewState), + myViewportWidth (theViewportWidth), myViewportHeight (theViewportHeight) {} + + const Handle(Graphic3d_Camera)& Camera() const { return myCamera; } + const Graphic3d_Mat4d& ProjectionMat() const { return myProjectionMat; } + const Graphic3d_Mat4d& WorldViewMat() const { return myWorldViewMat; } + const Graphic3d_WorldViewProjState& ViewState() const { return myViewState; } + Standard_Integer ViewportWidth() const { return myViewportWidth; } + Standard_Integer ViewportHeight() const { return myViewportHeight; } + +private: + Handle(Graphic3d_Camera) myCamera; + Graphic3d_Mat4d myProjectionMat; + Graphic3d_Mat4d myWorldViewMat; + Graphic3d_WorldViewProjState myViewState; + Standard_Integer myViewportWidth; + Standard_Integer myViewportHeight; +}; + +DEFINE_STANDARD_HANDLE(SelectMgr_AdaptorPersistent, Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_AdaptorPersistent, Standard_Transient) + //======================================================================= // function : SelectMgr_SensitiveEntitySet // purpose : @@ -47,6 +81,11 @@ void SelectMgr_SensitiveEntitySet::Append (const Handle(SelectMgr_SensitiveEntit { addOwner (theEntity->BaseSensitive()->OwnerId()); } + mySensitives.Add (theEntity); + if (!theEntity->BaseSensitive()->TransformPersistence().IsNull()) + { + myHasEntityWithPersistence = Standard_True; + } MarkDirty(); } @@ -70,6 +109,11 @@ void SelectMgr_SensitiveEntitySet::Append (const Handle(SelectMgr_Selection)& th { addOwner (aSelEntIter.Value()->BaseSensitive()->OwnerId()); } + mySensitives.Add (aSelEntIter.Value()); + if (!aSelEntIter.Value()->BaseSensitive()->TransformPersistence().IsNull()) + { + myHasEntityWithPersistence = Standard_True; + } } MarkDirty(); } @@ -96,6 +140,7 @@ void SelectMgr_SensitiveEntitySet::Remove (const Handle(SelectMgr_Selection)& th mySensitives.RemoveLast(); removeOwner (aSelEntIter.Value()->BaseSensitive()->OwnerId()); + // TODO: update myHasEntityWithPersistence state, clear myAdaptorPersistent if false } MarkDirty(); @@ -107,7 +152,31 @@ void SelectMgr_SensitiveEntitySet::Remove (const Handle(SelectMgr_Selection)& th //======================================================================= Select3D_BndBox3d SelectMgr_SensitiveEntitySet::Box (const Standard_Integer theIndex) const { - return GetSensitiveById (theIndex)->BaseSensitive()->BoundingBox(); + const Handle(Select3D_SensitiveEntity)& aSensitive = GetSensitiveById (theIndex)->BaseSensitive(); + if (aSensitive->TransformPersistence().IsNull() || myAdaptorPersistent.IsNull()) + { + return GetSensitiveById (theIndex)->BaseSensitive()->BoundingBox(); + } + + Select3D_BndBox3d aSensitiveBndBox = GetSensitiveById (theIndex)->BaseSensitive()->BoundingBox(); + Select3D_BndBox3d aBndBoxInPersistence; + + Bnd_Box aBndBox ( + gp_Pnt (aSensitiveBndBox.CornerMin().x(), aSensitiveBndBox.CornerMin().y(), aSensitiveBndBox.CornerMin().z()), + gp_Pnt (aSensitiveBndBox.CornerMax().x(), aSensitiveBndBox.CornerMin().y(), aSensitiveBndBox.CornerMin().z())); + + aSensitive->TransformPersistence()->Apply ( + myAdaptorPersistent->Camera(), + myAdaptorPersistent->ProjectionMat(), + myAdaptorPersistent->WorldViewMat(), + myAdaptorPersistent->ViewportWidth(), + myAdaptorPersistent->ViewportHeight(), + aBndBox); + + gp_Pnt aBndBoxMin = aBndBox.CornerMin(); + gp_Pnt aBndBoxMax = aBndBox.CornerMax(); + return Select3D_BndBox3d (SelectMgr_Vec3 (aBndBoxMin.X(), aBndBoxMin.Y(), aBndBoxMin.Z()), + SelectMgr_Vec3 (aBndBoxMax.X(), aBndBoxMax.Y(), aBndBoxMax.Z())); } //======================================================================= @@ -189,3 +258,29 @@ void SelectMgr_SensitiveEntitySet::removeOwner (const Handle(SelectMgr_EntityOwn } } } + +//======================================================================= +// function : UpdateBVH +// purpose : +//======================================================================= +void SelectMgr_SensitiveEntitySet::UpdateBVH (const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& theProjectionMat, + const Graphic3d_Mat4d& theWorldViewMat, + const Graphic3d_WorldViewProjState& theViewState, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight) +{ + if (!myHasEntityWithPersistence) + { + return; + } + myAdaptorPersistent = new SelectMgr_AdaptorPersistent(theCamera, theProjectionMat, + theWorldViewMat, + theViewState, + theViewportWidth, + theViewportHeight); + + MarkDirty(); + BVH(); + myAdaptorPersistent.Nullify(); +} diff --git a/src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx b/src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx index 61f8d84f92..7a8b3e593e 100644 --- a/src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx +++ b/src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx @@ -25,6 +25,8 @@ #include #include +class SelectMgr_AdaptorPersistent; + typedef NCollection_IndexedMap SelectMgr_IndexedMapOfHSensitive; typedef NCollection_DataMap SelectMgr_MapOfOwners; @@ -79,6 +81,18 @@ public: //! Returns map of owners. const SelectMgr_MapOfOwners& Owners() const { return myOwnersMap; } + //! Returns map of entities. + Standard_EXPORT Standard_Boolean HasEntityWithPersistence() const { return myHasEntityWithPersistence; } + + //! Updates outdated BVH trees and remembers the last state of the + //! camera view-projection matrices and viewport (window) dimensions. + Standard_EXPORT void UpdateBVH (const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& theProjectionMat, + const Graphic3d_Mat4d& theWorldViewMat, + const Graphic3d_WorldViewProjState& theViewState, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight); + protected: //! Adds entity owner to the map of owners (or increases its counter if it is already there). @@ -91,6 +105,8 @@ private: SelectMgr_IndexedMapOfHSensitive mySensitives; //!< Map of entities and its corresponding index in BVH SelectMgr_MapOfOwners myOwnersMap; //!< Map of entity owners and its corresponding number of sensitives + Handle(SelectMgr_AdaptorPersistent) myAdaptorPersistent; //!< camera parameters to apply transform persistence + Standard_Boolean myHasEntityWithPersistence; //!< flag if some of sensitive entity has own transform persistence }; #endif // _SelectMgr_SensitiveEntitySet_HeaderFile diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx index 30805b3e38..2f9cb907d8 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx @@ -369,6 +369,17 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable return; } + if (anEntitySet->HasEntityWithPersistence()) + { + Standard_Integer aWidth; + Standard_Integer aHeight; + mySelectingVolumeMgr.WindowSize (aWidth, aHeight); + anEntitySet->UpdateBVH (mySelectingVolumeMgr.Camera(), + mySelectingVolumeMgr.Camera()->ProjectionMatrix(), + mySelectingVolumeMgr.Camera()->OrientationMatrix(), + mySelectingVolumeMgr.Camera()->WorldViewProjState(), + aWidth, aHeight); + } const opencascade::handle >& aSensitivesTree = anEntitySet->BVH(); gp_GTrsf aInversedTrsf; if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull()) @@ -400,7 +411,8 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL) : theMgr; - if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0), + if (!anEntitySet->HasEntityWithPersistence() + && !aMgr.Overlaps (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0))) { return; @@ -551,9 +563,33 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx); if (aSensitive->IsActiveForSelection()) { + gp_GTrsf aInversedSensitiveTrsf; + if (aSensitive->BaseSensitive()->TransformPersistence().IsNull()) + { + aInversedSensitiveTrsf = aInversedTrsf; + } + else + { + gp_GTrsf aTPers; + Graphic3d_Mat4d aMat = aSensitive->BaseSensitive()->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight); + + aTPers.SetValue (1, 1, aMat.GetValue (0, 0)); + aTPers.SetValue (1, 2, aMat.GetValue (0, 1)); + aTPers.SetValue (1, 3, aMat.GetValue (0, 2)); + aTPers.SetValue (2, 1, aMat.GetValue (1, 0)); + aTPers.SetValue (2, 2, aMat.GetValue (1, 1)); + aTPers.SetValue (2, 3, aMat.GetValue (1, 2)); + aTPers.SetValue (3, 1, aMat.GetValue (2, 0)); + aTPers.SetValue (3, 2, aMat.GetValue (2, 1)); + aTPers.SetValue (3, 3, aMat.GetValue (2, 2)); + aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3))); + + aInversedSensitiveTrsf = (aTPers * gp_GTrsf(theObject->Transformation())).Inverted(); + } + const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive(); - computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr); - checkOverlap (anEnt, aInversedTrsf, aTmpMgr); + computeFrustum (anEnt, theMgr, aMgr, aInversedSensitiveTrsf, aScaledTrnsfFrustums, aTmpMgr); + checkOverlap (anEnt, aInversedSensitiveTrsf, aTmpMgr); } } } diff --git a/src/ViewerTest/ViewerTest_RelationCommands.cxx b/src/ViewerTest/ViewerTest_RelationCommands.cxx index 2c85248e1e..cf799e2059 100644 --- a/src/ViewerTest/ViewerTest_RelationCommands.cxx +++ b/src/ViewerTest/ViewerTest_RelationCommands.cxx @@ -377,6 +377,16 @@ static int ParseDimensionParams (Standard_Integer theArgNum, if (aLocalParam == "internal") { theAspect->SetArrowOrientation (Prs3d_DAO_Internal); } if (aLocalParam == "fit") { theAspect->SetArrowOrientation (Prs3d_DAO_Fit); } } + else if (aParam.IsEqual ("-zoomablearrow")) + { + TCollection_AsciiString aValue (theArgVec[++anIt]); + if (!aValue.IsIntegerValue()) + { + Message::SendFail() << "Error: zoomable arrow value should be 0 or 1."; + return 1; + } + theAspect->ArrowAspect()->SetZoomable (Draw::Atoi (aValue.ToCString()) != 0); + } else if (aParam.IsEqual ("-arrowlength") || aParam.IsEqual ("-arlen")) { TCollection_AsciiString aValue (theArgVec[++anIt]); @@ -1936,6 +1946,7 @@ void ViewerTest::RelationCommands(Draw_Interpretor& theCommands) "[-font FontName]\n" "[-label left|right|hcenter|hfit top|bottom|vcenter|vfit]\n" "[-arrow external|internal|fit]\n" + "[-zoomablearrow 0|1]\n" "[{-arrowlength|-arlen} RealArrowLength]\n" "[{-arrowangle|-arangle} ArrowAngle(degrees)]\n" "[-plane xoy|yoz|zox]\n" @@ -1971,6 +1982,7 @@ void ViewerTest::RelationCommands(Draw_Interpretor& theCommands) "[-font FontName]\n" "[-label left|right|hcenter|hfit top|bottom|vcenter|vfit]\n" "[-arrow external|internal|fit]\n" + "[-zoomablearrow 0|1]\n" "[{-arrowlength|-arlen} RealArrowLength]\n" "[{-arrowangle|-arangle} ArrowAngle(degrees)]\n" "[-plane xoy|yoz|zox]\n" diff --git a/tests/bugs/vis/bug27919 b/tests/bugs/vis/bug27919 new file mode 100644 index 0000000000..038837c841 --- /dev/null +++ b/tests/bugs/vis/bug27919 @@ -0,0 +1,25 @@ +puts "=============" +puts "0027919: Visualization - support multiple transformation persistence groups within single presentation" +puts "=============" + +vinit +vtrihedron t1 + +vpoint p11 -25 50 0 +vpoint p12 25 50 0 +vdimension dim -length -plane xoy -shapes p11 p12 +vdimparam dim -flyout 1 -arrowlength 30 -arrow internal -label hcenter -zoomablearrow 0 + +vpoint p21 -100 0 0 +vpoint p22 0 0 0 +vpoint p23 100 0 0 +vdimension angle -angle -shapes p21 p22 p23 -arrowlength 30 -zoomablearrow 0 + +vtop +vfit +vzoom 1.5 + +if {[vreadpixel 182 119 rgb name] != "BLACK"} { puts "ERROR: the arrow of the dimension should not be zoomable" } +if {[vreadpixel 149 195 rgb name] != "BLACK"} { puts "ERROR: the arrow of the angle dimension should not be zoomable" } + +vdump $imagedir/${casename}.png