0027919: Visualization - support multiple transformation persistence groups within... IR-2021-07-23 WEEK-29
authornds <nds@opencascade.com>
Mon, 19 Jul 2021 10:31:05 +0000 (13:31 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 23 Jul 2021 15:31:51 +0000 (18:31 +0300)
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().

27 files changed:
src/Graphic3d/Graphic3d_CStructure.cxx
src/Graphic3d/Graphic3d_CStructure.hxx
src/Graphic3d/Graphic3d_Group.cxx
src/Graphic3d/Graphic3d_Group.hxx
src/Graphic3d/Graphic3d_Layer.cxx
src/Graphic3d/Graphic3d_Structure.cxx
src/Graphic3d/Graphic3d_TransformPers.hxx
src/Graphic3d/Graphic3d_TransformUtils.hxx
src/NCollection/NCollection_Mat3.hxx
src/NCollection/NCollection_Mat4.hxx
src/OpenGl/OpenGl_Structure.cxx
src/OpenGl/OpenGl_Structure.hxx
src/Prs3d/Prs3d_ArrowAspect.cxx
src/Prs3d/Prs3d_ArrowAspect.hxx
src/PrsDim/PrsDim_AngleDimension.cxx
src/PrsDim/PrsDim_Dimension.cxx
src/Select3D/Select3D_SensitiveEntity.cxx
src/Select3D/Select3D_SensitiveEntity.hxx
src/SelectMgr/SelectMgr_SelectableObjectSet.cxx
src/SelectMgr/SelectMgr_SelectableObjectSet.hxx
src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx
src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx
src/SelectMgr/SelectMgr_ViewerSelector.cxx
src/SelectMgr/SelectMgr_ViewerSelector.hxx
src/ViewerTest/ViewerTest_RelationCommands.cxx
src/gp/gp_GTrsf.hxx
tests/v3d/dimensions/bug27919 [new file with mode: 0644]

index 7da948f..e60815d 100644 (file)
@@ -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();
 }
index 3cbd249..1210025 100644 (file)
@@ -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;
 
 };
 
index 9ea7a7d..ad202ca 100644 (file)
@@ -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)
 
index e13fc5b..c8462b9 100644 (file)
@@ -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
index 6b723c8..f5870fe 100644 (file)
@@ -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;
index a3f1e4e..cfe5ff8 100644 (file)
@@ -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;
index 1ef3286..53b7592 100644 (file)
@@ -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<class T>
   void Apply (const Handle(Graphic3d_Camera)& theCamera,
               const NCollection_Mat4<T>& theProjection,
               NCollection_Mat4<T>& 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<T>& theProjection,
                                      NCollection_Mat4<T>& 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<Standard_Real> 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
index 85fc7d3..68b829a 100644 (file)
@@ -121,7 +121,12 @@ namespace Graphic3d_TransformUtils
 
   //! Returns scaling factor from 3x3 affine matrix.
   template<class T>
-  static Standard_Real ScaleFactor (const typename MatrixType<T>::Mat4& theMatrix);
+  static Standard_Real ScaleFactor (const NCollection_Mat4<T>& theMatrix)
+  {
+    // The determinant of the matrix should give the scale factor (cubed).
+    const T aDeterminant = theMatrix.DeterminantMat3();
+    return Pow (static_cast<Standard_Real> (aDeterminant), 1.0 / 3.0);
+  }
 }
 
 // =======================================================================
@@ -486,22 +491,4 @@ static Standard_Boolean Graphic3d_TransformUtils::UnProject (const T
   return Standard_True;
 }
 
-// =======================================================================
-// function : ScaleFactor
-// purpose  :
-// =======================================================================
-template<class T>
-static Standard_Real Graphic3d_TransformUtils::ScaleFactor (const typename MatrixType<T>::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<Standard_Real> (aDeterminant), 1.0 / 3.0);
-}
-
 #endif // _Graphic3d_TransformUtils_HeaderFile
index 578edd8..79d745c 100644 (file)
@@ -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
   {
index d55f928..141a7de 100755 (executable)
@@ -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<Element_t> Adjoint() const
   {
index ded5c09..0134e2f 100644 (file)
@@ -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<Standard_ShortReal> (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  : 
index e603e30..64f1c3e 100644 (file)
@@ -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;
index 130d868..aac00a7 100644 (file)
@@ -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)
 {
   //
 }
index f63e59a..e652596 100644 (file)
@@ -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;
 
 };
 
index a58af9c..2c80cfe 100644 (file)
@@ -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();
index deba152..514cbed 100644 (file)
@@ -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
index 97bc6a3..d63246c 100644 (file)
@@ -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());
 
index 1d74523..d153d77 100644 (file)
@@ -27,6 +27,7 @@
 #include <SelectMgr_SelectingVolumeManager.hxx>
 #include <TopLoc_Location.hxx>
 
+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;
 
 };
index 15be832..8739f8c 100644 (file)
@@ -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<Standard_Real, 3>();
   myBVH[BVHSubset_3dPersistent] = new BVH_Tree<Standard_Real, 3>();
@@ -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())
 }
index 2925e42..9570170 100644 (file)
@@ -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<BVH_Tree<Standard_Real, 3> >           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;
 };
 
index bad281a..209d9f9 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <SelectMgr_SensitiveEntitySet.hxx>
 
+#include <Graphic3d_TransformPers.hxx>
 #include <Select3D_SensitiveEntity.hxx>
 #include <SelectMgr_SensitiveEntity.hxx>
 
@@ -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<Handle(SelectMgr_SensitiveEntity)>::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();
 }
 
 //=======================================================================
index 61f8d84..49d59a0 100644 (file)
@@ -28,8 +28,8 @@
 typedef NCollection_IndexedMap<Handle(SelectMgr_SensitiveEntity)> SelectMgr_IndexedMapOfHSensitive;
 typedef NCollection_DataMap<Handle(SelectMgr_EntityOwner), Standard_Integer> 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
index 4d4cdab..1ebf8c1 100644 (file)
@@ -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<BVH_Tree<Standard_Real, 3> >& 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);
   }
 }
 
index d98277a..fc8ea81 100644 (file)
@@ -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
index 3f634c9..86f7b55 100644 (file)
@@ -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"
index 1971143..1363b84 100644 (file)
@@ -287,6 +287,24 @@ public:
     theMat.SetValue (3, 3, static_cast<T> (1));
   }
 
+  //! Convert transformation from 4x4 matrix.
+  template<class T>
+  void SetMat4 (const NCollection_Mat4<T>& 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 (file)
index 0000000..f437c69
--- /dev/null
@@ -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