From: nds Date: Mon, 19 Jul 2021 10:31:05 +0000 (+0300) Subject: 0027919: Visualization - support multiple transformation persistence groups within... X-Git-Tag: V7_6_0_beta~79 X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=refs%2Fheads%2FIR-2021-07-23;p=occt.git 0027919: Visualization - support multiple transformation persistence groups within single presentation Added transform persistence property to Graphic3d_Group and Select3D_SensitiveEntity. SelectMgr_ViewerSelector, Graphic3d_Layer and OpenGl_Structure have been updated to process per-group transform persistence within picking, ZFit and rendering. Added zoomable state to Prs3d_ArrowAspect supported by PrsDim_Dimension. Added gp_GTrsf::SetMat4(), opposite to gp_GTrsf::GetMat4(). --- diff --git a/src/Graphic3d/Graphic3d_CStructure.cxx b/src/Graphic3d/Graphic3d_CStructure.cxx index 7da948ff3e..e60815de53 100644 --- a/src/Graphic3d/Graphic3d_CStructure.cxx +++ b/src/Graphic3d/Graphic3d_CStructure.cxx @@ -27,10 +27,16 @@ IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_CStructure,Standard_Transient) //purpose : //============================================================================= Graphic3d_CStructure::Graphic3d_CStructure (const Handle(Graphic3d_StructureManager)& theManager) -: myZLayer (Graphic3d_ZLayerId_Default), - Priority (Structure_MAX_PRIORITY / 2), +: Priority (Structure_MAX_PRIORITY / 2), PreviousPriority (Structure_MAX_PRIORITY / 2), ContainsFacet (0), + // + myGraphicDriver (theManager->GraphicDriver()), + myZLayer (Graphic3d_ZLayerId_Default), + myIsCulled (Standard_True), + myBndBoxClipCheck(Standard_True), + myHasGroupTrsf (Standard_False), + // IsInfinite (0), stick (0), highlight (0), @@ -38,10 +44,7 @@ Graphic3d_CStructure::Graphic3d_CStructure (const Handle(Graphic3d_StructureMana HLRValidation (0), IsForHighlight (Standard_False), IsMutable (Standard_False), - Is2dText (Standard_False), - myGraphicDriver (theManager->GraphicDriver()), - myIsCulled (Standard_True), - myBndBoxClipCheck(Standard_True) + Is2dText (Standard_False) { Id = myGraphicDriver->NewIdentification(); } diff --git a/src/Graphic3d/Graphic3d_CStructure.hxx b/src/Graphic3d/Graphic3d_CStructure.hxx index 3cbd249a66..1210025d75 100644 --- a/src/Graphic3d/Graphic3d_CStructure.hxx +++ b/src/Graphic3d/Graphic3d_CStructure.hxx @@ -33,6 +33,7 @@ class Graphic3d_StructureManager; //! Low-level graphic structure interface class Graphic3d_CStructure : public Standard_Transient { + DEFINE_STANDARD_RTTIEXT(Graphic3d_CStructure, Standard_Transient) protected: //! Auxiliary wrapper to iterate through structure list. @@ -89,6 +90,12 @@ public: //! Set transformation persistence. virtual void SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers) { myTrsfPers = theTrsfPers; } + //! Return TRUE if some groups might have transform persistence; FALSE by default. + bool HasGroupTransformPersistence() const { return myHasGroupTrsf; } + + //! Set if some groups might have transform persistence. + void SetGroupTransformPersistence (bool theValue) { myHasGroupTrsf = theValue; } + //! @return associated clip planes const Handle(Graphic3d_SequenceOfHClipPlane)& ClipPlanes() const { @@ -198,23 +205,13 @@ public: public: - int Id; - Graphic3d_ZLayerId myZLayer; - int Priority; - int PreviousPriority; - - int ContainsFacet; - Handle(Graphic3d_ViewAffinity) ViewAffinity; //!< view affinity mask - unsigned IsInfinite : 1; - unsigned stick : 1; //!< displaying state - should be set when structure has been added to scene graph (but can be in hidden state) - unsigned highlight : 1; - unsigned visible : 1; //!< visibility flag - can be used to suppress structure while leaving it in the scene graph - unsigned HLRValidation : 1; - unsigned IsForHighlight : 1; - unsigned IsMutable : 1; - unsigned Is2dText : 1; + Standard_Integer Id; + Standard_Integer Priority; + Standard_Integer PreviousPriority; + + Standard_Integer ContainsFacet; protected: @@ -231,12 +228,23 @@ protected: Handle(Graphic3d_SequenceOfHClipPlane) myClipPlanes; Handle(Graphic3d_PresentationAttributes) myHighlightStyle; //! Current highlight style; is set only if highlight flag is true + Graphic3d_ZLayerId myZLayer; + mutable Standard_Boolean myIsCulled; //!< A status specifying is structure needs to be rendered after BVH tree traverse Standard_Boolean myBndBoxClipCheck; //!< Flag responsible for checking of bounding box clipping before drawing of object + Standard_Boolean myHasGroupTrsf; //!< flag specifying that some groups might have transform persistence + public: - DEFINE_STANDARD_RTTIEXT(Graphic3d_CStructure,Standard_Transient) // Type definition + unsigned IsInfinite : 1; + unsigned stick : 1; //!< displaying state - should be set when structure has been added to scene graph (but can be in hidden state) + unsigned highlight : 1; + unsigned visible : 1; //!< visibility flag - can be used to suppress structure while leaving it in the scene graph + unsigned HLRValidation : 1; + unsigned IsForHighlight : 1; + unsigned IsMutable : 1; + unsigned Is2dText : 1; }; diff --git a/src/Graphic3d/Graphic3d_Group.cxx b/src/Graphic3d/Graphic3d_Group.cxx index 9ea7a7d29b..ad202ca899 100644 --- a/src/Graphic3d/Graphic3d_Group.cxx +++ b/src/Graphic3d/Graphic3d_Group.cxx @@ -140,6 +140,23 @@ Standard_Boolean Graphic3d_Group::IsEmpty() const && !myBounds.IsValid(); } +// ======================================================================= +// function : SetTransformPersistence +// purpose : +// ======================================================================= +void Graphic3d_Group::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers) +{ + if (myTrsfPers != theTrsfPers) + { + myTrsfPers = theTrsfPers; + if (!IsDeleted() + && !theTrsfPers.IsNull()) + { + myStructure->CStructure()->SetGroupTransformPersistence (true); + } + } +} + // ======================================================================= // function : SetMinMaxValues // purpose : @@ -458,6 +475,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 e13fc5b674..c8462b90c7 100644 --- a/src/Graphic3d/Graphic3d_Group.hxx +++ b/src/Graphic3d/Graphic3d_Group.hxx @@ -38,6 +38,7 @@ class Graphic3d_Structure; class Graphic3d_ArrayOfPrimitives; class Graphic3d_Text; +class Graphic3d_TransformPers; //! This class allows the definition of groups //! of primitives inside of graphic objects (presentations). @@ -133,6 +134,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. + Standard_EXPORT virtual void SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers); + //! Returns true if the group contains Polygons, Triangles or Quadrangles. bool ContainsFacet() const { return myContainsFacet; } @@ -290,6 +297,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..f5870fec8c 100644 --- a/src/Graphic3d/Graphic3d_Layer.cxx +++ b/src/Graphic3d/Graphic3d_Layer.cxx @@ -171,6 +171,18 @@ inline bool isInfiniteBndBox (const Graphic3d_BndBox3d& theBndBox) || Abs (theBndBox.CornerMin().z()) >= ShortRealLast(); } +//! Extend bounding box with another box. +static void addBox3dToBndBox (Bnd_Box& theResBox, + const Graphic3d_BndBox3d& theBox) +{ + // skip too big boxes to prevent float overflow at camera parameters calculation + 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 : @@ -222,6 +234,22 @@ Bnd_Box Graphic3d_Layer::BoundingBox (Standard_Integer theViewId, } } + if (!theToIncludeAuxiliary + && aStructure->HasGroupTransformPersistence()) + { + // add per-group transform-persistence point in a bounding box + for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aStructure->Groups()); aGroupIter.More(); aGroupIter.Next()) + { + const Handle(Graphic3d_Group)& aGroup = aGroupIter.Value(); + if (!aGroup->TransformPersistence().IsNull() + && aGroup->TransformPersistence()->IsZoomOrRotate()) + { + const gp_Pnt anAnchor = aGroup->TransformPersistence()->AnchorPoint(); + myBoundingBox[aBoxId].Add (anAnchor); + } + } + } + Graphic3d_BndBox3d aBox = aStructure->BoundingBox(); if (!aBox.IsValid()) { @@ -239,14 +267,7 @@ Bnd_Box Graphic3d_Layer::BoundingBox (Standard_Integer theViewId, { aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox); } - - // skip too big boxes to prevent float overflow at camera parameters calculation - if (aBox.IsValid() - && !isInfiniteBndBox (aBox)) - { - myBoundingBox[aBoxId].Add (gp_Pnt (aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z())); - myBoundingBox[aBoxId].Add (gp_Pnt (aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z())); - } + addBox3dToBndBox (myBoundingBox[aBoxId], aBox); } } @@ -268,25 +289,38 @@ Bnd_Box Graphic3d_Layer::BoundingBox (Standard_Integer theViewId, { continue; } - else if (aStructure->TransformPersistence().IsNull() - || !aStructure->TransformPersistence()->IsTrihedronOr2d()) + + // handle per-group transformation persistence specifically + if (aStructure->HasGroupTransformPersistence()) { - continue; + for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aStructure->Groups()); aGroupIter.More(); aGroupIter.Next()) + { + const Handle(Graphic3d_Group)& aGroup = aGroupIter.Value(); + const Graphic3d_BndBox4f& aBoxF = aGroup->BoundingBox(); + if (aGroup->TransformPersistence().IsNull() + || !aBoxF.IsValid()) + { + continue; + } + + Graphic3d_BndBox3d aBoxCopy (Graphic3d_Vec3d (aBoxF.CornerMin().xyz()), + Graphic3d_Vec3d (aBoxF.CornerMax().xyz())); + aGroup->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBoxCopy); + addBox3dToBndBox (aResBox, aBoxCopy); + } } - Graphic3d_BndBox3d aBox = aStructure->BoundingBox(); - if (!aBox.IsValid()) + const Graphic3d_BndBox3d& aStructBox = aStructure->BoundingBox(); + if (!aStructBox.IsValid() + || 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 aBoxCopy = aStructBox; + aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBoxCopy); + addBox3dToBndBox (aResBox, aBoxCopy); } return aResBox; diff --git a/src/Graphic3d/Graphic3d_Structure.cxx b/src/Graphic3d/Graphic3d_Structure.cxx index a3f1e4e4d4..cfe5ff8ecc 100644 --- a/src/Graphic3d/Graphic3d_Structure.cxx +++ b/src/Graphic3d/Graphic3d_Structure.cxx @@ -86,6 +86,7 @@ void Graphic3d_Structure::clear (const Standard_Boolean theWithDestruction) GraphicClear (theWithDestruction); myCStructure->ContainsFacet = 0; + myCStructure->SetGroupTransformPersistence (false); myStructureManager->Clear (this, theWithDestruction); Update (true); @@ -802,6 +803,11 @@ 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; // should be translated to current view orientation to make sense + } + aBnd.Combine (aGroupIter.Value()->BoundingBox()); } return aBnd; diff --git a/src/Graphic3d/Graphic3d_TransformPers.hxx b/src/Graphic3d/Graphic3d_TransformPers.hxx index 1ef328614a..53b7592056 100644 --- a/src/Graphic3d/Graphic3d_TransformPers.hxx +++ b/src/Graphic3d/Graphic3d_TransformPers.hxx @@ -293,12 +293,14 @@ public: //! @param theWorldView world-view matrix to modify //! @param theViewportWidth viewport width //! @param theViewportHeight viewport height + //! @param theAnchor if not NULL, overrides anchor point template void Apply (const Handle(Graphic3d_Camera)& theCamera, const NCollection_Mat4& theProjection, NCollection_Mat4& theWorldView, const Standard_Integer theViewportWidth, - const Standard_Integer theViewportHeight) const; + const Standard_Integer theViewportHeight, + const gp_Pnt* theAnchor = NULL) const; //! Dumps the content of me into the stream Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const; @@ -347,7 +349,8 @@ void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, const NCollection_Mat4& theProjection, NCollection_Mat4& theWorldView, const Standard_Integer theViewportWidth, - const Standard_Integer theViewportHeight) const + const Standard_Integer theViewportHeight, + const gp_Pnt* theAnchor) const { (void )theViewportWidth; (void )theProjection; @@ -453,7 +456,15 @@ void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, { // Compute reference point for transformation in untransformed projection space. NCollection_Mat4 aWorldView = theCamera->OrientationMatrix(); - Graphic3d_TransformUtils::Translate (aWorldView, myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ); + if (theAnchor != NULL) + { + Graphic3d_TransformUtils::Translate (aWorldView, theAnchor->X(), theAnchor->Y(), theAnchor->Z()); + } + else + { + Graphic3d_TransformUtils::Translate (aWorldView, myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ); + } + if ((myMode & Graphic3d_TMF_RotatePers) != 0) { // lock rotation by nullifying rotation component diff --git a/src/Graphic3d/Graphic3d_TransformUtils.hxx b/src/Graphic3d/Graphic3d_TransformUtils.hxx index 85fc7d3283..68b829a1d5 100644 --- a/src/Graphic3d/Graphic3d_TransformUtils.hxx +++ b/src/Graphic3d/Graphic3d_TransformUtils.hxx @@ -121,7 +121,12 @@ namespace Graphic3d_TransformUtils //! Returns scaling factor from 3x3 affine matrix. template - static Standard_Real ScaleFactor (const typename MatrixType::Mat4& theMatrix); + static Standard_Real ScaleFactor (const NCollection_Mat4& theMatrix) + { + // The determinant of the matrix should give the scale factor (cubed). + const T aDeterminant = theMatrix.DeterminantMat3(); + return Pow (static_cast (aDeterminant), 1.0 / 3.0); + } } // ======================================================================= @@ -486,22 +491,4 @@ static Standard_Boolean Graphic3d_TransformUtils::UnProject (const T return Standard_True; } -// ======================================================================= -// function : ScaleFactor -// purpose : -// ======================================================================= -template -static Standard_Real Graphic3d_TransformUtils::ScaleFactor (const typename MatrixType::Mat4& theMatrix) -{ - // The determinant of the matrix should give the scale factor (cubed). - const T aDeterminant = (theMatrix.GetValue (0, 0) * theMatrix.GetValue (1, 1) * theMatrix.GetValue (2, 2) + - theMatrix.GetValue (0, 1) * theMatrix.GetValue (1, 2) * theMatrix.GetValue (2, 0) + - theMatrix.GetValue (0, 2) * theMatrix.GetValue (1, 0) * theMatrix.GetValue (2, 1)) - - (theMatrix.GetValue (0, 2) * theMatrix.GetValue (1, 1) * theMatrix.GetValue (2, 0) + - theMatrix.GetValue (0, 0) * theMatrix.GetValue (1, 2) * theMatrix.GetValue (2, 1) + - theMatrix.GetValue (0, 1) * theMatrix.GetValue (1, 0) * theMatrix.GetValue (2, 2)); - - return Pow (static_cast (aDeterminant), 1.0 / 3.0); -} - #endif // _Graphic3d_TransformUtils_HeaderFile diff --git a/src/NCollection/NCollection_Mat3.hxx b/src/NCollection/NCollection_Mat3.hxx index 578edd83ca..79d745cb5a 100644 --- a/src/NCollection/NCollection_Mat3.hxx +++ b/src/NCollection/NCollection_Mat3.hxx @@ -408,6 +408,17 @@ public: *this = Transposed(); } + //! Return determinant of the matrix. + Element_t Determinant() const + { + return (GetValue (0, 0) * GetValue (1, 1) * GetValue (2, 2) + + GetValue (0, 1) * GetValue (1, 2) * GetValue (2, 0) + + GetValue (0, 2) * GetValue (1, 0) * GetValue (2, 1)) + - (GetValue (0, 2) * GetValue (1, 1) * GetValue (2, 0) + + GetValue (0, 0) * GetValue (1, 2) * GetValue (2, 1) + + GetValue (0, 1) * GetValue (1, 0) * GetValue (2, 2)); + } + //! Return adjoint (adjugate matrix, e.g. conjugate transpose). Standard_NODISCARD NCollection_Mat3 Adjoint() const { diff --git a/src/NCollection/NCollection_Mat4.hxx b/src/NCollection/NCollection_Mat4.hxx index d55f928ed7..141a7de93d 100755 --- a/src/NCollection/NCollection_Mat4.hxx +++ b/src/NCollection/NCollection_Mat4.hxx @@ -597,6 +597,17 @@ public: return anInv; } + //! Return determinant of the 3x3 sub-matrix. + Element_t DeterminantMat3() const + { + return (GetValue (0, 0) * GetValue (1, 1) * GetValue (2, 2) + + GetValue (0, 1) * GetValue (1, 2) * GetValue (2, 0) + + GetValue (0, 2) * GetValue (1, 0) * GetValue (2, 1)) + - (GetValue (0, 2) * GetValue (1, 1) * GetValue (2, 0) + + GetValue (0, 0) * GetValue (1, 2) * GetValue (2, 1) + + GetValue (0, 1) * GetValue (1, 0) * GetValue (2, 2)); + } + //! Return adjoint (adjugate matrix, e.g. conjugate transpose). Standard_NODISCARD NCollection_Mat4 Adjoint() const { diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index ded5c09c4a..0134e2f368 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -394,10 +394,27 @@ void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorksp myInstancedStructure->renderGeometry (theWorkspace, theHasClosed); } + bool anOldCastShadows = false; + const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next()) { - theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed(); - aGroupIter.Value()->Render (theWorkspace); + const OpenGl_Group* aGroup = aGroupIter.Value(); + + const Handle(Graphic3d_TransformPers)& aTrsfPers = aGroup->TransformPersistence(); + if (!aTrsfPers.IsNull()) + { + applyPersistence (aCtx, aTrsfPers, true, anOldCastShadows); + aCtx->ApplyModelViewMatrix(); + } + + theHasClosed = theHasClosed || aGroup->IsClosed(); + aGroup->Render (theWorkspace); + + if (!aTrsfPers.IsNull()) + { + revertPersistence (aCtx, aTrsfPers, true, anOldCastShadows); + aCtx->ApplyModelViewMatrix(); + } } } @@ -446,26 +463,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, false, anOldCastShadows); #ifdef GL_DEPTH_CLAMP if (myTrsfPers->Mode() == Graphic3d_TMF_CameraPers @@ -623,8 +621,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con if (!myTrsfPers.IsNull()) { - aCtx->WorldViewState.Pop(); - aCtx->ShaderManager()->SetCastShadows (anOldCastShadows); + revertPersistence (aCtx, myTrsfPers, false, anOldCastShadows); #ifdef GL_DEPTH_CLAMP if (toRestoreDepthClamp) { aCtx->core11fwd->glDisable (GL_DEPTH_CLAMP); } #endif @@ -666,6 +663,77 @@ 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)& theCtx, + const Handle(Graphic3d_TransformPers)& theTrsfPers, + const Standard_Boolean theIsLocal, + Standard_Boolean& theOldCastShadows) const +{ + // temporarily disable shadows on non-3d objects + theOldCastShadows = theCtx->ShaderManager()->SetCastShadows (false); + + theCtx->WorldViewState.Push(); + OpenGl_Mat4& aWorldView = theCtx->WorldViewState.ChangeCurrent(); + + if (theIsLocal + && theTrsfPers->IsZoomOrRotate()) + { + // move anchor point to presentation location + theCtx->ModelWorldState.Push(); + OpenGl_Mat4& aModelWorld = theCtx->ModelWorldState.ChangeCurrent(); + gp_Pnt aStartPnt = theTrsfPers->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)); // reset translation part + aStartPnt.SetCoord (anAnchorPoint.x(), anAnchorPoint.y(), anAnchorPoint.z()); + + theTrsfPers->Apply (theCtx->Camera(), + theCtx->ProjectionState.Current(), aWorldView, + theCtx->VirtualViewport()[2], theCtx->VirtualViewport()[3], + &aStartPnt); + } + else + { + theTrsfPers->Apply (theCtx->Camera(), + theCtx->ProjectionState.Current(), aWorldView, + theCtx->VirtualViewport()[2], theCtx->VirtualViewport()[3]); + } + +#if !defined(GL_ES_VERSION_2_0) + if (!theCtx->IsGlNormalizeEnabled() + && theCtx->core11ffp != NULL) + { + const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor (aWorldView); + if (Abs (aScale - 1.0) > Precision::Confusion()) + { + theCtx->SetGlNormalizeEnabled (true); + } + } +#endif +} + +// ======================================================================= +// function : revertPersistence +// purpose : +// ======================================================================= +void OpenGl_Structure::revertPersistence (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_TransformPers)& theTrsfPers, + const Standard_Boolean theIsLocal, + const Standard_Boolean theOldCastShadows) const +{ + if (theIsLocal + && theTrsfPers->IsZoomOrRotate()) + { + theCtx->ModelWorldState.Pop(); + } + theCtx->WorldViewState.Pop(); + theCtx->ShaderManager()->SetCastShadows (theOldCastShadows); +} + //======================================================================= //function : DumpJson //purpose : diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx index e603e30973..64f1c3e547 100644 --- a/src/OpenGl/OpenGl_Structure.hxx +++ b/src/OpenGl/OpenGl_Structure.hxx @@ -146,6 +146,27 @@ 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 otherwise. + //! @param[in] theCtx current context + //! @param[in] theTrsfPers transform persistence + //! @param[in] theIsLocal specifies if transform persistence is defined locally or to entire presentation + //! @param[out] theOldCastShadows state of the previous cast shadows state + Standard_EXPORT void applyPersistence (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_TransformPers)& theTrsfPersistence, + const Standard_Boolean theIsLocal, + Standard_Boolean& theOldCastShadows) const; + + //! Restore context from transform persistence changes. + //! @param[in] theCtx current context + //! @param[in] theTrsfPers transform persistence + //! @param[in] theIsLocal specifies if transform persistence is defined locally or to entire presentation + //! @param[in] theOldCastShadows state of the previous cast shadows state + Standard_EXPORT void revertPersistence (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_TransformPers)& theTrsfPersistence, + const Standard_Boolean theIsLocal, + const Standard_Boolean theOldCastShadows) 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..e652596b0d 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; TRUE by default. + bool IsZoomable() 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..2c80cfe95c 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()->IsZoomable()) + { + 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..514cbede47 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()->IsZoomable(); 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()->IsZoomable()) + { + 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 1d745239a1..d153d7706d 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..8739f8c289 100644 --- a/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx +++ b/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx @@ -114,8 +114,7 @@ namespace const Handle(Graphic3d_Camera)& theCamera, const Graphic3d_Mat4d& theProjectionMat, const Graphic3d_Mat4d& theWorldViewMat, - const Standard_Integer theWidth, - const Standard_Integer theHeight) + const Graphic3d_Vec2i& theWinSize) : myObjects (theObjects) { myBoundings.ReSize (myObjects.Size()); @@ -125,15 +124,51 @@ 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, + theWinSize.x(), theWinSize.y(), + aBoundingBox); + } + + // processing presentations with own transform persistence + for (PrsMgr_Presentations::Iterator aPrsIter (anObject->Presentations()); aPrsIter.More(); aPrsIter.Next()) + { + const Handle(PrsMgr_Presentation)& aPrs3d = aPrsIter.Value(); + if (!aPrs3d->CStructure()->HasGroupTransformPersistence()) + { + continue; + } + + for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aPrs3d->Groups()); aGroupIter.More(); aGroupIter.Next()) + { + const Handle(Graphic3d_Group)& aGroup = aGroupIter.Value(); + const Graphic3d_BndBox4f& aBndBox = aGroup->BoundingBox(); + if (aGroup->TransformPersistence().IsNull() + || !aBndBox.IsValid()) + { + continue; + } + + Bnd_Box aGroupBox; + aGroupBox.Update (aBndBox.CornerMin().x(), aBndBox.CornerMin().y(), aBndBox.CornerMin().z(), + aBndBox.CornerMax().x(), aBndBox.CornerMax().y(), aBndBox.CornerMax().z()); + aGroup->TransformPersistence()->Apply (theCamera, + theProjectionMat, theWorldViewMat, + theWinSize.x(), theWinSize.y(), + aGroupBox); + aBoundingBox.Add (aGroupBox); + } + } + + 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()), @@ -205,8 +240,6 @@ namespace // Purpose : //============================================================================= SelectMgr_SelectableObjectSet::SelectMgr_SelectableObjectSet() -: myLastWidth (0), - myLastHeight (0) { myBVH[BVHSubset_2dPersistent] = new BVH_Tree(); myBVH[BVHSubset_3dPersistent] = new BVH_Tree(); @@ -311,12 +344,8 @@ void SelectMgr_SelectableObjectSet::ChangeSubset (const Handle(SelectMgr_Selecta // Function: UpdateBVH // Purpose : //============================================================================= -void SelectMgr_SelectableObjectSet::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) +void SelectMgr_SelectableObjectSet::UpdateBVH (const Handle(Graphic3d_Camera)& theCam, + const Graphic3d_Vec2i& theWinSize) { // ----------------------------------------- // check and update 3D BVH tree if necessary @@ -333,20 +362,24 @@ void SelectMgr_SelectableObjectSet::UpdateBVH (const Handle(Graphic3d_Camera)& t myIsDirty[BVHSubset_3d] = Standard_False; } - if (!theCamera.IsNull()) + if (!theCam.IsNull()) { - const Standard_Boolean isWindowSizeChanged = - (myLastHeight != theViewportHeight) || (myLastWidth != theViewportWidth); + const Standard_Boolean isWinSizeChanged = myLastWinSize != theWinSize; + const Graphic3d_Mat4d& aProjMat = theCam->ProjectionMatrix(); + const Graphic3d_Mat4d& aWorldViewMat = theCam->OrientationMatrix(); + const Graphic3d_WorldViewProjState& aViewState = theCam->WorldViewProjState(); // ----------------------------------------------------- // check and update 3D persistence BVH tree if necessary // ----------------------------------------------------- - if (!IsEmpty (BVHSubset_3dPersistent) && - (myIsDirty[BVHSubset_3dPersistent] || myLastViewState.IsChanged (theViewState) || isWindowSizeChanged)) + if (!IsEmpty (BVHSubset_3dPersistent) + && (myIsDirty[BVHSubset_3dPersistent] + || myLastViewState.IsChanged (aViewState) + || isWinSizeChanged)) { // construct adaptor over private fields to provide direct access for the BVH builder BVHBuilderAdaptorPersistent anAdaptor (myObjects[BVHSubset_3dPersistent], - theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight); + theCam, aProjMat, aWorldViewMat, theWinSize); // update corresponding BVH tree data structure myBuilder[BVHSubset_3dPersistent]->Build (&anAdaptor, myBVH[BVHSubset_3dPersistent].get(), anAdaptor.Box()); @@ -355,12 +388,14 @@ void SelectMgr_SelectableObjectSet::UpdateBVH (const Handle(Graphic3d_Camera)& t // ----------------------------------------------------- // check and update 2D persistence BVH tree if necessary // ----------------------------------------------------- - if (!IsEmpty (BVHSubset_2dPersistent) && - (myIsDirty[BVHSubset_2dPersistent] || myLastViewState.IsProjectionChanged (theViewState) || isWindowSizeChanged)) + if (!IsEmpty (BVHSubset_2dPersistent) + && (myIsDirty[BVHSubset_2dPersistent] + || myLastViewState.IsProjectionChanged (aViewState) + || isWinSizeChanged)) { // construct adaptor over private fields to provide direct access for the BVH builder BVHBuilderAdaptorPersistent anAdaptor (myObjects[BVHSubset_2dPersistent], - theCamera, theProjectionMat, SelectMgr_SelectableObjectSet_THE_IDENTITY_MAT, theViewportWidth, theViewportHeight); + theCam, aProjMat, SelectMgr_SelectableObjectSet_THE_IDENTITY_MAT, theWinSize); // update corresponding BVH tree data structure myBuilder[BVHSubset_2dPersistent]->Build (&anAdaptor, myBVH[BVHSubset_2dPersistent].get(), anAdaptor.Box()); @@ -371,12 +406,11 @@ void SelectMgr_SelectableObjectSet::UpdateBVH (const Handle(Graphic3d_Camera)& t myIsDirty[BVHSubset_2dPersistent] = Standard_False; // keep last view state - myLastViewState = theViewState; + myLastViewState = aViewState; } // keep last window state - myLastWidth = theViewportWidth; - myLastHeight = theViewportHeight; + myLastWinSize = theWinSize; } //============================================================================= @@ -412,6 +446,6 @@ void SelectMgr_SelectableObjectSet::DumpJson (Standard_OStream& theOStream, Stan TCollection_AsciiString separator; OCCT_DUMP_FIELD_VALUE_STRING (theOStream, separator) } - OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLastWidth) - OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLastHeight) + OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLastWinSize.x()) + OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLastWinSize.y()) } diff --git a/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx b/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx index 2925e42b42..95701702f7 100644 --- a/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx +++ b/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx @@ -134,12 +134,8 @@ public: //! 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); + Standard_EXPORT void UpdateBVH (const Handle(Graphic3d_Camera)& theCam, + const Graphic3d_Vec2i& theWinSize); //! Marks every BVH subset for update. Standard_EXPORT void MarkDirty(); @@ -190,6 +186,15 @@ private: { if (theObject->TransformPersistence().IsNull()) { + const PrsMgr_Presentations& aPresentations = theObject->Presentations(); + for (PrsMgr_Presentations::Iterator aPrsIter (aPresentations); aPrsIter.More(); aPrsIter.Next()) + { + const Handle(PrsMgr_Presentation)& aPrs3d = aPrsIter.ChangeValue(); + if (aPrs3d->CStructure()->HasGroupTransformPersistence()) + { + return SelectMgr_SelectableObjectSet::BVHSubset_3dPersistent; + } + } return SelectMgr_SelectableObjectSet::BVHSubset_3d; } else if (theObject->TransformPersistence()->Mode() == Graphic3d_TMF_2d) @@ -221,9 +226,8 @@ private: opencascade::handle > myBVH[BVHSubsetNb]; //!< BVH tree computed for each subset Handle(Select3D_BVHBuilder3d) myBuilder[BVHSubsetNb]; //!< Builder allocated for each subset Standard_Boolean myIsDirty[BVHSubsetNb]; //!< Dirty flag for each subset - Graphic3d_WorldViewProjState myLastViewState; //!< Last view-projection state used for construction of BVH - Standard_Integer myLastWidth; //!< Last viewport's (window's) width used for construction of BVH - Standard_Integer myLastHeight; //!< Last viewport's (window's) height used for construction of BVH + Graphic3d_WorldViewProjState myLastViewState; //!< Last view-projection state used for construction of BVH + Graphic3d_Vec2i myLastWinSize; //!< Last viewport's (window's) width used for construction of BVH friend class Iterator; }; diff --git a/src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx b/src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx index bad281a5e1..209d9f9b55 100644 --- a/src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx +++ b/src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx @@ -15,6 +15,7 @@ #include +#include #include #include @@ -47,6 +48,10 @@ void SelectMgr_SensitiveEntitySet::Append (const Handle(SelectMgr_SensitiveEntit { addOwner (theEntity->BaseSensitive()->OwnerId()); } + if (!theEntity->BaseSensitive()->TransformPersistence().IsNull()) + { + myHasEntityWithPersistence = Standard_True; + } MarkDirty(); } @@ -59,16 +64,21 @@ void SelectMgr_SensitiveEntitySet::Append (const Handle(SelectMgr_Selection)& th { for (NCollection_Vector::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next()) { - if (!aSelEntIter.Value()->BaseSensitive()->IsKind (STANDARD_TYPE(Select3D_SensitiveEntity))) + const Handle(SelectMgr_SensitiveEntity)& aSensEnt = aSelEntIter.Value(); + if (!aSensEnt->BaseSensitive()->IsKind (STANDARD_TYPE(Select3D_SensitiveEntity))) { - aSelEntIter.Value()->ResetSelectionActiveStatus(); + aSensEnt->ResetSelectionActiveStatus(); continue; } const Standard_Integer anExtent = mySensitives.Extent(); - if (mySensitives.Add (aSelEntIter.Value()) > anExtent) + if (mySensitives.Add (aSensEnt) > anExtent) + { + addOwner (aSensEnt->BaseSensitive()->OwnerId()); + } + if (!aSensEnt->BaseSensitive()->TransformPersistence().IsNull()) { - addOwner (aSelEntIter.Value()->BaseSensitive()->OwnerId()); + myHasEntityWithPersistence = Standard_True; } } MarkDirty(); @@ -107,7 +117,13 @@ 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()) + { + return Select3D_BndBox3d(); + } + + return aSensitive->BoundingBox(); } //======================================================================= diff --git a/src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx b/src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx index 61f8d84f92..49d59a00f4 100644 --- a/src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx +++ b/src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx @@ -28,8 +28,8 @@ typedef NCollection_IndexedMap SelectMgr_IndexedMapOfHSensitive; typedef NCollection_DataMap SelectMgr_MapOfOwners; -//! This class is used to store all calculated sensitive entites of one selectable -//! object. It provides an interface for building BVH tree which is used to speed-up +//! This class is used to store all calculated sensitive entities of one selectable object. +//! It provides an interface for building BVH tree which is used to speed-up //! the performance of searching for overlap among sensitives of one selectable object class SelectMgr_SensitiveEntitySet : public BVH_PrimitiveSet3d { @@ -79,6 +79,9 @@ public: //! Returns map of owners. const SelectMgr_MapOfOwners& Owners() const { return myOwnersMap; } + //! Returns map of entities. + Standard_Boolean HasEntityWithPersistence() const { return myHasEntityWithPersistence; } + protected: //! Adds entity owner to the map of owners (or increases its counter if it is already there). @@ -89,8 +92,9 @@ protected: 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 + 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 + 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 4d4cdab540..1ebf8c1604 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx @@ -356,8 +356,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable const Handle(Graphic3d_Camera)& theCamera, const Graphic3d_Mat4d& theProjectionMat, const Graphic3d_Mat4d& theWorldViewMat, - const Standard_Integer theViewportWidth, - const Standard_Integer theViewportHeight) + const Graphic3d_Vec2i& theWinSize) { Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject); if (anEntitySet->Size() == 0) @@ -365,6 +364,8 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable return; } + const bool hasEntityTrsfPers = anEntitySet->HasEntityWithPersistence() + && !theCamera.IsNull(); const opencascade::handle >& aSensitivesTree = anEntitySet->BVH(); gp_GTrsf aInversedTrsf; if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull()) @@ -379,20 +380,12 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable { return; } - gp_GTrsf aTPers; - Graphic3d_Mat4d aMat = theObject->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))); + const Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, + theProjectionMat, theWorldViewMat, + theWinSize.x(), theWinSize.y()); + gp_GTrsf aTPers; + aTPers.SetMat4 (aMat); aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted(); } } @@ -400,7 +393,8 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL) : theMgr; - if (!aMgr.OverlapsBox (aSensitivesTree->MinPoint (0), + if (!hasEntityTrsfPers + && !aMgr.OverlapsBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0))) { return; @@ -482,12 +476,14 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable { const Standard_Integer aLeftChildIdx = aSensitivesTree->Child<0> (aNode); const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode); - const Standard_Boolean isLeftChildIn = aMgr.OverlapsBox (aSensitivesTree->MinPoint (aLeftChildIdx), - aSensitivesTree->MaxPoint (aLeftChildIdx)); - const Standard_Boolean isRightChildIn = aMgr.OverlapsBox (aSensitivesTree->MinPoint (aRightChildIdx), + const Standard_Boolean isLeftChildIn = hasEntityTrsfPers + || aMgr.OverlapsBox (aSensitivesTree->MinPoint (aLeftChildIdx), + aSensitivesTree->MaxPoint (aLeftChildIdx)); + const Standard_Boolean isRightChildIn = hasEntityTrsfPers + || aMgr.OverlapsBox (aSensitivesTree->MinPoint (aRightChildIdx), aSensitivesTree->MaxPoint (aRightChildIdx)); if (isLeftChildIn - && isRightChildIn) + && isRightChildIn) { aNode = aLeftChildIdx; ++aHead; @@ -544,17 +540,35 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable } if (!aClipped) { - Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode); - Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode); + const Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode); + const Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode); for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx) { const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx); - if (aSensitive->IsActiveForSelection()) + if (!aSensitive->IsActiveForSelection()) + { + continue; + } + + const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive(); + + gp_GTrsf aInvSensTrsf = aInversedTrsf; + if (!anEnt->TransformPersistence().IsNull()) { - const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive(); - computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr); - checkOverlap (anEnt, aInversedTrsf, aTmpMgr); + if (theCamera.IsNull()) + { + continue; + } + const Graphic3d_Mat4d aMat = anEnt->TransformPersistence()->Compute (theCamera, + theProjectionMat, theWorldViewMat, + theWinSize.x(), theWinSize.y()); + gp_GTrsf aTPers; + aTPers.SetMat4 (aMat); + aInvSensTrsf = (aTPers * gp_GTrsf(theObject->Transformation())).Inverted(); } + + computeFrustum (anEnt, theMgr, aMgr, aInvSensTrsf, aScaledTrnsfFrustums, aTmpMgr); + checkOverlap (anEnt, aInvSensTrsf, aTmpMgr); } } if (aHead < 0) @@ -599,9 +613,8 @@ void SelectMgr_ViewerSelector::TraverseSensitives() mystored.Clear(); - Standard_Integer aWidth = 0; - Standard_Integer aHeight = 0; - mySelectingVolumeMgr.WindowSize (aWidth, aHeight); + Graphic3d_Vec2i aWinSize; + mySelectingVolumeMgr.WindowSize (aWinSize.x(), aWinSize.y()); const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera(); Graphic3d_Mat4d aProjectionMat, aWorldViewMat; @@ -617,10 +630,10 @@ void SelectMgr_ViewerSelector::TraverseSensitives() myCameraScale = aCamera->IsOrthographic() ? aCamera->Scale() : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0); - const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight); + const double aPixelSize = Max (1.0 / aWinSize.x(), 1.0 / aWinSize.y()); myCameraScale *= aPixelSize; } - mySelectableObjects.UpdateBVH (aCamera, aProjectionMat, aWorldViewMat, aViewState, aWidth, aHeight); + mySelectableObjects.UpdateBVH (aCamera, aWinSize); for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt) { @@ -664,7 +677,7 @@ void SelectMgr_ViewerSelector::TraverseSensitives() aWorldViewMat = aNewCamera->OrientationMatrix(); // should be identity matrix aProjectionMat = aNewCamera->ProjectionMatrix(); // should be the same to aProjectionMat aBuilder->SetCamera (aNewCamera); - aBuilder->SetWindowSize (aWidth, aHeight); + aBuilder->SetWindowSize (aWinSize.x(), aWinSize.y()); aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder); } else @@ -724,7 +737,7 @@ void SelectMgr_ViewerSelector::TraverseSensitives() const Handle(SelectMgr_SelectableObject)& aSelectableObject = mySelectableObjects.GetObjectById (aBVHSubset, anIdx); - traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight); + traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWinSize); } if (aHead < 0) { @@ -998,20 +1011,9 @@ void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsF if (theIsForce) { - Standard_Integer aViewportWidth, aViewportHeight; - mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight); - - Standard_Integer aWidth; - Standard_Integer aHeight; - mySelectingVolumeMgr.WindowSize (aWidth, aHeight); - const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera(); - const Graphic3d_Mat4d& aProjMat = !aCamera.IsNull() ? aCamera->ProjectionMatrix() - : SelectMgr_ViewerSelector_THE_IDENTITY_MAT; - const Graphic3d_Mat4d& anOrientMat = !aCamera.IsNull() ? aCamera->OrientationMatrix() - : SelectMgr_ViewerSelector_THE_IDENTITY_MAT; - Graphic3d_WorldViewProjState aViewState = !aCamera.IsNull() ? aCamera->WorldViewProjState() - : Graphic3d_WorldViewProjState(); - mySelectableObjects.UpdateBVH (aCamera, aProjMat, anOrientMat, aViewState, aWidth, aHeight); + Graphic3d_Vec2i aWinSize; + mySelectingVolumeMgr.WindowSize (aWinSize.x(), aWinSize.y()); + mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(), aWinSize); } } diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.hxx b/src/SelectMgr/SelectMgr_ViewerSelector.hxx index d98277aab8..fc8ea81b8f 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.hxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.hxx @@ -281,8 +281,7 @@ protected: const Handle(Graphic3d_Camera)& theCamera, const Graphic3d_Mat4d& theProjectionMat, const Graphic3d_Mat4d& theWorldViewMat, - const Standard_Integer theViewportWidth, - const Standard_Integer theViewportHeight); + const Graphic3d_Vec2i& theWinSize); //! Internal function that checks if a particular sensitive //! entity theEntity overlaps current selecting volume precisely diff --git a/src/ViewerTest/ViewerTest_RelationCommands.cxx b/src/ViewerTest/ViewerTest_RelationCommands.cxx index 3f634c91e6..86f7b557e9 100644 --- a/src/ViewerTest/ViewerTest_RelationCommands.cxx +++ b/src/ViewerTest/ViewerTest_RelationCommands.cxx @@ -377,6 +377,17 @@ 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]); + Standard_Boolean isZoomableArrow = Standard_True; + if (!Draw::ParseOnOff (aValue.ToCString(), isZoomableArrow)) + { + Message::SendFail() << "Error: zoomable arrow value should be 0 or 1."; + return 1; + } + theAspect->ArrowAspect()->SetZoomable (isZoomableArrow); + } else if (aParam.IsEqual ("-arrowlength") || aParam.IsEqual ("-arlen")) { TCollection_AsciiString aValue (theArgVec[++anIt]); @@ -1926,6 +1937,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]\n" "[{-arrowlength|-arlen} RealArrowLength]\n" "[{-arrowangle|-arangle} ArrowAngle(degrees)]\n" "[-plane xoy|yoz|zox]\n" @@ -1961,6 +1973,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/src/gp/gp_GTrsf.hxx b/src/gp/gp_GTrsf.hxx index 1971143d53..1363b84d29 100644 --- a/src/gp/gp_GTrsf.hxx +++ b/src/gp/gp_GTrsf.hxx @@ -287,6 +287,24 @@ public: theMat.SetValue (3, 3, static_cast (1)); } + //! Convert transformation from 4x4 matrix. + template + void SetMat4 (const NCollection_Mat4& theMat) + { + shape = gp_Other; + scale = 0.0; + matrix.SetValue (1, 1, theMat.GetValue (0, 0)); + matrix.SetValue (1, 2, theMat.GetValue (0, 1)); + matrix.SetValue (1, 3, theMat.GetValue (0, 2)); + matrix.SetValue (2, 1, theMat.GetValue (1, 0)); + matrix.SetValue (2, 2, theMat.GetValue (1, 1)); + matrix.SetValue (2, 3, theMat.GetValue (1, 2)); + matrix.SetValue (3, 1, theMat.GetValue (2, 0)); + matrix.SetValue (3, 2, theMat.GetValue (2, 1)); + matrix.SetValue (3, 3, theMat.GetValue (2, 2)); + loc.SetCoord (theMat.GetValue (0, 3), theMat.GetValue (1, 3), theMat.GetValue (2, 3)); + } + //! Dumps the content of me into the stream Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const; diff --git a/tests/v3d/dimensions/bug27919 b/tests/v3d/dimensions/bug27919 new file mode 100644 index 0000000000..f437c69bc3 --- /dev/null +++ b/tests/v3d/dimensions/bug27919 @@ -0,0 +1,37 @@ +puts "=============" +puts "0027919: Visualization - support multiple transformation persistence groups within single presentation" +puts "=============" + +pload VISUALIZATION + +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}_def.png +vseldump $imagedir/${casename}_def_selowner.png -type owner + +vlocation angle -reset -setlocation 10 0 0 -rotate 0 0 0 1 0 0 40 +vdump $imagedir/${casename}_rot1.png +vseldump $imagedir/${casename}_rot1_selowner.png -type owner + +vzoom 0.25 +vlocation angle -reset -setlocation 30 0 0 -rotate 0 0 0 1 0 0 40 +vdump $imagedir/${casename}_rot2.png +vseldump $imagedir/${casename}_rot2_selowner.png -type owner