0027374: Visualization - optimize management of the scene bounding box
authorduv <duv@opencascade.com>
Wed, 25 May 2016 14:00:59 +0000 (17:00 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 27 May 2016 08:57:55 +0000 (11:57 +0300)
OpenGl_View now caches bounding boxes per Z-layer (instead of bounding box of entire scene in Graphic3d_CView).
Redundant invalidation of cached scene bounding box is now avoided in case
when new presentation attributes are assigned to the graphic structure.

Add a new methods ConsiderZoomPersistenceObjects() and considerZoomPersistenceObjects() in the Graphic3d_CView, OpenGl_View and OpenGl_Layer classes.
Call ConsiderZoomPersistenceObjects() in the V3d_View::FitMinMax method.

std::numeric_limits<T>::lowest() fix

13 files changed:
src/Graphic3d/Graphic3d_CView.cxx
src/Graphic3d/Graphic3d_CView.hxx
src/Graphic3d/Graphic3d_Structure.cxx
src/Graphic3d/Graphic3d_Structure.hxx
src/Graphic3d/Graphic3d_StructureManager.cxx
src/Graphic3d/Graphic3d_StructureManager.hxx
src/OpenGl/OpenGl_Layer.cxx
src/OpenGl/OpenGl_Layer.hxx
src/OpenGl/OpenGl_LayerList.hxx
src/OpenGl/OpenGl_View.cxx
src/OpenGl/OpenGl_View.hxx
src/V3d/V3d_View.cxx
tests/bugs/vis/bug27374 [new file with mode: 0644]

index 6b8617e..f9125a7 100644 (file)
 
 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_CView,Graphic3d_DataStructureManager)
 
+namespace
+{
+  static const int THE_DEFAULT_LAYERS[] = { Graphic3d_ZLayerId_Top,
+                                            Graphic3d_ZLayerId_Topmost,
+                                            Graphic3d_ZLayerId_BotOSD,
+                                            Graphic3d_ZLayerId_TopOSD };
+
+  static const int THE_NB_DEFAULT_LAYERS = sizeof(THE_DEFAULT_LAYERS) / sizeof(*THE_DEFAULT_LAYERS);
+
+  void combineBox (Bnd_Box& aCombined, const Graphic3d_BndBox4f& theBox)
+  {
+    if (theBox.IsValid())
+    {
+      aCombined.Add (gp_Pnt (theBox.CornerMin().x(),
+                             theBox.CornerMin().y(),
+                             theBox.CornerMin().z()));
+      aCombined.Add (gp_Pnt (theBox.CornerMax().x(),
+                             theBox.CornerMax().y(),
+                             theBox.CornerMax().z()));
+    }
+  }
+}
+
 //=======================================================================
 //function : Constructor
 //purpose  :
@@ -349,9 +372,11 @@ void Graphic3d_CView::ReCompute (const Handle(Graphic3d_Structure)& theStruct)
 // function : Update
 // purpose  :
 // =======================================================================
-void Graphic3d_CView::Update (const Aspect_TypeOfUpdate theUpdateMode)
+void Graphic3d_CView::Update (const Aspect_TypeOfUpdate theUpdateMode,
+                              const Graphic3d_ZLayerId  theLayerId)
 {
-  myMinMax.Invalidate();
+  InvalidateZLayerBoundingBox (theLayerId);
+
   if (theUpdateMode == Aspect_TOU_ASAP)
   {
     Compute();
@@ -409,13 +434,68 @@ void Graphic3d_CView::DisplayedStructures (Graphic3d_MapOfStructure& theStructur
 // =======================================================================
 Bnd_Box Graphic3d_CView::MinMaxValues (const Standard_Boolean theToIgnoreInfiniteFlag) const
 {
-  if (myMinMax.IsOutdated (theToIgnoreInfiniteFlag))
+  Bnd_Box aResult;
+
+  if (!IsDefined())
+  {
+    return aResult;
+  }
+
+  Handle(Graphic3d_Camera) aCamera = Camera();
+  Standard_Integer aWinWidth  = 0;
+  Standard_Integer aWinHeight = 0;
+
+  Window()->Size (aWinWidth, aWinHeight);
+
+  for (Standard_Integer aLayer = 0; aLayer < THE_NB_DEFAULT_LAYERS; ++aLayer)
+  {
+    Graphic3d_BndBox4f aBox = ZLayerBoundingBox (THE_DEFAULT_LAYERS[aLayer],
+                                                 aCamera,
+                                                 aWinWidth,
+                                                 aWinHeight,
+                                                 theToIgnoreInfiniteFlag);
+    combineBox (aResult, aBox);
+  }
+
+  Standard_Integer aMaxZLayer = ZLayerMax();
+  for (Standard_Integer aLayerId = Graphic3d_ZLayerId_Default; aLayerId <= aMaxZLayer; ++aLayerId)
+  {
+    Graphic3d_BndBox4f aBox = ZLayerBoundingBox (aLayerId, aCamera, aWinWidth, aWinHeight, theToIgnoreInfiniteFlag);
+    combineBox (aResult, aBox);
+  }
+
+  return aResult;
+}
+
+// =======================================================================
+// function : ConsiderZoomPersistenceObjects
+// purpose  :
+// =======================================================================
+Standard_Real Graphic3d_CView::ConsiderZoomPersistenceObjects()
+{
+  if (!IsDefined())
+  {
+    return 1.0;
+  }
+
+  Handle(Graphic3d_Camera) aCamera = Camera();
+  Standard_Integer aWinWidth  = 0;
+  Standard_Integer aWinHeight = 0;
+
+  Window()->Size (aWinWidth, aWinHeight);
+
+  Standard_Real aMaxCoef = 1.0;
+  for (Standard_Integer aLayer = 0; aLayer < THE_NB_DEFAULT_LAYERS; ++aLayer)
+  {
+    aMaxCoef = Max (aMaxCoef, considerZoomPersistenceObjects (THE_DEFAULT_LAYERS[aLayer], aCamera, aWinWidth, aWinHeight, Standard_False));
+  }
+
+  for (Standard_Integer aLayer = Graphic3d_ZLayerId_Default; aLayer <= ZLayerMax(); ++aLayer)
   {
-    myMinMax.BoundingBox (theToIgnoreInfiniteFlag) = MinMaxValues (myStructsDisplayed, theToIgnoreInfiniteFlag);
-    myMinMax.IsOutdated  (theToIgnoreInfiniteFlag) = Standard_False;
+    aMaxCoef = Max (aMaxCoef, considerZoomPersistenceObjects (aLayer, aCamera, aWinWidth, aWinHeight, Standard_False));
   }
 
-  return myMinMax.BoundingBox (theToIgnoreInfiniteFlag);
+  return aMaxCoef;
 }
 
 // =======================================================================
@@ -672,7 +752,7 @@ void Graphic3d_CView::Display (const Handle(Graphic3d_Structure)& theStructure,
 
     theStructure->CalculateBoundBox();
     displayStructure (theStructure->CStructure(), theStructure->DisplayPriority());
-    Update (theUpdateMode);
+    Update (theUpdateMode, theStructure->GetZLayer());
     return;
   }
   else if (anAnswer != Graphic3d_TOA_COMPUTE)
@@ -693,7 +773,7 @@ void Graphic3d_CView::Display (const Handle(Graphic3d_Structure)& theStructure,
       }
 
       displayStructure (anOldStruct->CStructure(), theStructure->DisplayPriority());
-      Update (theUpdateMode);
+      Update (theUpdateMode, anOldStruct->GetZLayer());
       return;
     }
     else
@@ -716,7 +796,7 @@ void Graphic3d_CView::Display (const Handle(Graphic3d_Structure)& theStructure,
         const Handle(Graphic3d_Structure)& aNewStruct = myStructsComputed.Value (aNewIndex);
         myStructsComputed.SetValue (anIndex, aNewStruct);
         displayStructure (aNewStruct->CStructure(), theStructure->DisplayPriority());
-        Update (theUpdateMode);
+        Update (theUpdateMode, aNewStruct->GetZLayer());
         return;
       }
       else
@@ -807,7 +887,7 @@ void Graphic3d_CView::Display (const Handle(Graphic3d_Structure)& theStructure,
   myStructsDisplayed.Add (theStructure);
   displayStructure (aStruct->CStructure(), theStructure->DisplayPriority());
 
-  Update (theUpdateMode);
+  Update (theUpdateMode, aStruct->GetZLayer());
 }
 
 // =======================================================================
@@ -851,7 +931,7 @@ void Graphic3d_CView::Erase (const Handle(Graphic3d_Structure)& theStructure,
     }
   }
   myStructsDisplayed.Remove (theStructure);
-  Update (theUpdateMode);
+  Update (theUpdateMode, theStructure->GetZLayer());
 }
 
 // =======================================================================
index 451b9c3..94913a7 100644 (file)
@@ -108,8 +108,10 @@ public:
   //! Computes the new presentation of the structure  displayed in this view with the type Graphic3d_TOS_COMPUTED.
   Standard_EXPORT void ReCompute (const Handle(Graphic3d_Structure)& theStructure);
 
-  //! Updates screen in function of modifications of the structures.
-  Standard_EXPORT void Update (const Aspect_TypeOfUpdate theUpdateMode);
+  //! Updates screen in function of modifications of the structures
+  //! and invalidates bounding box of specified ZLayerId.
+  Standard_EXPORT void Update (const Aspect_TypeOfUpdate theUpdateMode,
+                               const Graphic3d_ZLayerId  theLayerId = Graphic3d_ZLayerId_UNKNOWN);
 
   //! Returns Standard_True if one of the structures displayed in the view contains Polygons, Triangles or Quadrangles.
   Standard_EXPORT Standard_Boolean ContainsFacet() const;
@@ -134,8 +136,7 @@ public:
   Standard_EXPORT Standard_Boolean IsComputed (const Standard_Integer theStructId,
                                                Handle(Graphic3d_Structure)& theComputedStruct) const;
 
-  //! Returns the coordinates of the boundary box of all
-  //! structures displayed in the view.
+  //! Returns the bounding box of all structures displayed in the view.
   //! If <theToIgnoreInfiniteFlag> is TRUE, then the boundary box
   //! also includes minimum and maximum limits of graphical elements
   //! forming parts of infinite structures.
@@ -336,6 +337,20 @@ public:
   //! ID for the structure.
   virtual void AddZLayer (const Graphic3d_ZLayerId theLayerId) = 0;
 
+  //! Returns the maximum Z layer ID.
+  //! First layer ID is Graphic3d_ZLayerId_Default, last ID is ZLayerMax().
+  virtual Standard_Integer ZLayerMax() const = 0;
+
+  //! Returns the bounding box of all structures displayed in the Z layer.
+  virtual void InvalidateZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId) const = 0;
+
+  //! Returns the bounding box of all structures displayed in the Z layer.
+  virtual Graphic3d_BndBox4f ZLayerBoundingBox (const Graphic3d_ZLayerId        theLayerId,
+                                                const Handle(Graphic3d_Camera)& theCamera,
+                                                const Standard_Integer          theWindowWidth,
+                                                const Standard_Integer          theWindowHeight,
+                                                const Standard_Boolean          theToIgnoreInfiniteFlag) const = 0;
+
   //! Remove Z layer from the specified view. All structures
   //! displayed at the moment in layer will be displayed in default layer
   //! ( the bottom-level z layer ). To unset layer ID from associated
@@ -346,6 +361,9 @@ public:
   virtual void SetZLayerSettings (const Graphic3d_ZLayerId theLayerId,
                                   const Graphic3d_ZLayerSettings& theSettings) = 0;
 
+  //! Returns zoom-scale factor.
+  Standard_EXPORT Standard_Real ConsiderZoomPersistenceObjects();
+
   //! Returns pointer to an assigned framebuffer object.
   virtual Handle(Standard_Transient) FBO() const = 0;
 
@@ -522,29 +540,12 @@ private:
   virtual void changePriority (const Handle(Graphic3d_CStructure)& theCStructure,
                                const Standard_Integer theNewPriority) = 0;
 
-protected:
-
-  struct CachedMinMax
-  {
-    CachedMinMax() { Invalidate(); }
-
-    Bnd_Box& BoundingBox (const Standard_Boolean theToIgnoreInfiniteFlag)
-    {
-      return !theToIgnoreInfiniteFlag ? myBoundingBox[0] : myBoundingBox[1];
-    }
-    Standard_Boolean& IsOutdated (const Standard_Boolean theToIgnoreInfiniteFlag)
-    {
-      return !theToIgnoreInfiniteFlag ? myIsOutdated[0] : myIsOutdated[1];
-    }
-    void Invalidate()
-    {
-      myIsOutdated[0] = Standard_True;
-      myIsOutdated[1] = Standard_True;
-    }
-
-    Standard_Boolean myIsOutdated [2];
-    Bnd_Box          myBoundingBox[2];
-  };
+  //! Returns zoom-scale factor.
+  virtual Standard_Real considerZoomPersistenceObjects (const Graphic3d_ZLayerId        theLayerId,
+                                                        const Handle(Graphic3d_Camera)& theCamera,
+                                                        const Standard_Integer          theWindowWidth,
+                                                        const Standard_Integer          theWindowHeight,
+                                                        const Standard_Boolean          theToIgnoreInfiniteFlag) const = 0;
 
 protected:
 
@@ -559,7 +560,6 @@ protected:
   Standard_Boolean myIsActive;
   Standard_Boolean myIsRemoved;
   Graphic3d_TypeOfVisualization myVisualization;
-  mutable CachedMinMax myMinMax;
 
 private:
 
index 92a95a0..99cf4ed 100644 (file)
@@ -123,7 +123,7 @@ void Graphic3d_Structure::Clear (const Standard_Boolean theWithDestruction)
   myCStructure->ContainsFacet = 0;
   myStructureManager->Clear (this, theWithDestruction);
 
-  Update();
+  Update (true);
 }
 
 //=======================================================================
@@ -363,7 +363,7 @@ void Graphic3d_Structure::SetVisible (const Standard_Boolean theValue)
 
   myCStructure->visible = isVisible;
   myCStructure->OnVisibilityChanged();
-  Update();
+  Update (true);
 }
 
 //=============================================================================
@@ -1385,7 +1385,7 @@ void Graphic3d_Structure::Connect (const Handle(Graphic3d_Structure)& theStructu
     GraphicConnect (theStructure);
     myStructureManager->Connect (this, theStructure);
 
-    Update();
+    Update (true);
   }
   else // Graphic3d_TOC_ANCESTOR
   {
@@ -1422,7 +1422,7 @@ void Graphic3d_Structure::Disconnect (const Handle(Graphic3d_Structure)& theStru
     myStructureManager->Disconnect (this, theStructure);
 
     CalculateBoundBox();
-    Update();
+    Update (true);
   }
   else if (RemoveAncestor (aStructure))
   {
@@ -1562,7 +1562,7 @@ void Graphic3d_Structure::SetTransform (const TColStd_Array2OfReal&       theMat
   myCStructure->UpdateTransformation();
   myStructureManager->SetTransform (this, aNewTrsf);
 
-  Update();
+  Update (true);
 }
 
 //=============================================================================
@@ -1986,14 +1986,15 @@ void Graphic3d_Structure::PrintNetwork (const Handle(Graphic3d_Structure)& theSt
 //function : Update
 //purpose  :
 //=============================================================================
-void Graphic3d_Structure::Update() const
+void Graphic3d_Structure::Update (const bool theUpdateLayer) const
 {
   if (IsDeleted())
   {
     return;
   }
 
-  myStructureManager->Update (myStructureManager->UpdateMode());
+  myStructureManager->Update (myStructureManager->UpdateMode(),
+                              theUpdateLayer ? myCStructure->ZLayer() : Graphic3d_ZLayerId_UNKNOWN);
 }
 
 //=============================================================================
index 6e0b80e..cdad89f 100644 (file)
@@ -532,9 +532,9 @@ private:
   //! Returns the manager to which <me> is associated.
   Standard_EXPORT Handle(Graphic3d_StructureManager) StructureManager() const;
   
-  //! Calls the Update method of the StructureManager which
-  //! contains the Structure <me>.
-  Standard_EXPORT void Update() const;
+  //! Calls the Update method of the StructureManager which contains the Structure <me>.
+  //! If theUpdateLayer is true then invalidates bounding box of ZLayer.
+  Standard_EXPORT void Update (const bool theUpdateLayer = false) const;
   
   //! Updates the c structure associated to <me>.
   Standard_EXPORT void UpdateStructure (const Handle(Graphic3d_AspectLine3d)& CTXL, const Handle(Graphic3d_AspectText3d)& CTXT, const Handle(Graphic3d_AspectMarker3d)& CTXM, const Handle(Graphic3d_AspectFillArea3d)& CTXF);
index a32ab8f..7af7a77 100644 (file)
@@ -83,11 +83,12 @@ Aspect_TypeOfUpdate Graphic3d_StructureManager::UpdateMode() const
 // function : Update
 // purpose  :
 // ========================================================================
-void Graphic3d_StructureManager::Update (const Aspect_TypeOfUpdate theMode) const
+void Graphic3d_StructureManager::Update (const Aspect_TypeOfUpdate theMode,
+                                         const Graphic3d_ZLayerId  theLayerId) const
 {
   for (Graphic3d_IndexedMapOfView::Iterator aViewIt (myDefinedViews); aViewIt.More(); aViewIt.Next())
   {
-    aViewIt.Value()->Update (theMode);
+    aViewIt.Value()->Update (theMode, theLayerId);
   }
 }
 
index a0bf0ba..cba5c98 100644 (file)
@@ -109,8 +109,10 @@ public:
   //! TOU_WAIT on demand (Update)
   Standard_EXPORT Aspect_TypeOfUpdate UpdateMode() const;
 
-  //! Updates screen in function of modifications of the structures.
-  Standard_EXPORT virtual void Update (const Aspect_TypeOfUpdate theMode = Aspect_TOU_ASAP) const;
+  //! Updates screen in function of modifications of the structures
+  //! and invalidates bounding box of specified ZLayerId.
+  Standard_EXPORT virtual void Update (const Aspect_TypeOfUpdate theMode = Aspect_TOU_ASAP,
+                                       const Graphic3d_ZLayerId  theLayerId = Graphic3d_ZLayerId_UNKNOWN) const;
 
   //! Deletes and erases the 3D structure manager.
   Standard_EXPORT virtual void Remove();
index 55a51b8..9a5c2de 100644 (file)
 // purpose  :
 // =======================================================================
 OpenGl_Layer::OpenGl_Layer (const Standard_Integer theNbPriorities)
-: myArray (0, theNbPriorities - 1),
-  myNbStructures (0),
+: myArray                     (0, theNbPriorities - 1),
+  myNbStructures              (0),
   myBVHIsLeftChildQueuedFirst (Standard_True),
   myIsBVHPrimitivesNeedsReset (Standard_False)
 {
-  //
+  myIsBoundingBoxNeedsReset[0] = myIsBoundingBoxNeedsReset[1] = true;
 }
 
 // =======================================================================
@@ -123,12 +123,258 @@ bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct,
 // function : InvalidateBVHData
 // purpose  :
 // =======================================================================
-void OpenGl_Layer::InvalidateBVHData()
+void OpenGl_Layer::InvalidateBVHData() const
 {
   myIsBVHPrimitivesNeedsReset = Standard_True;
 }
 
 // =======================================================================
+// function : BoundingBox
+// purpose  :
+// =======================================================================
+const Graphic3d_BndBox4f& OpenGl_Layer::BoundingBox (const Standard_Integer          theViewId,
+                                                     const Handle(Graphic3d_Camera)& theCamera,
+                                                     const Standard_Integer          theWindowWidth,
+                                                     const Standard_Integer          theWindowHeight,
+                                                     const Standard_Boolean          theToIgnoreInfiniteFlag) const
+{
+  const Standard_Integer aBoxId = theToIgnoreInfiniteFlag == 0 ? 0 : 1;
+
+  if (myIsBoundingBoxNeedsReset[aBoxId])
+  {
+    // Recompute layer bounding box
+    myBoundingBox[aBoxId].Clear();
+
+    const Standard_Integer aNbPriorities = myArray.Length();
+    for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
+    {
+      const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
+      for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
+      {
+        const OpenGl_Structure* aStructure = aStructures.FindKey (aStructIdx);
+        if (!aStructure->IsVisible())
+        {
+          continue;
+        }
+        else if (!aStructure->ViewAffinity.IsNull()
+              && !aStructure->ViewAffinity->IsVisible (theViewId))
+        {
+          continue;
+        }
+
+        // "FitAll" operation ignores object with transform persistence parameter
+        // but adds transform persistence point in a bounding box of layer (only zoom pers. objects).
+        if (aStructure->TransformPersistence.Flags != Graphic3d_TMF_None)
+        {
+          if (!theToIgnoreInfiniteFlag && (aStructure->TransformPersistence.Flags & Graphic3d_TMF_ZoomPers))
+          {
+            if (!theCamera->IsOrthographic())
+            {
+              continue;
+            }
+
+            BVH_Vec4f aTPPoint (static_cast<float> (aStructure->TransformPersistence.Point.x()),
+                                static_cast<float> (aStructure->TransformPersistence.Point.y()),
+                                static_cast<float> (aStructure->TransformPersistence.Point.z()),
+                                1.0f);
+
+            myBoundingBox[aBoxId].Combine (aTPPoint);
+            continue;
+          }
+          // Panning and 2d persistence apply changes to projection or/and its translation components.
+          // It makes them incompatible with z-fitting algorithm. Ignored by now.
+          else if (!theToIgnoreInfiniteFlag
+           || (aStructure->TransformPersistence.Flags & Graphic3d_TMF_2d)
+           || (aStructure->TransformPersistence.Flags & Graphic3d_TMF_PanPers)
+           || (aStructure->TransformPersistence.Flags & Graphic3d_TMF_TriedronPers))
+          {
+            continue;
+          }
+        }
+
+        Graphic3d_BndBox4f aBox = aStructure->BoundingBox();
+
+        if (aStructure->IsInfinite
+        && !theToIgnoreInfiniteFlag)
+        {
+          const Graphic3d_Vec4 aDiagVec = aBox.CornerMax() - aBox.CornerMin();
+          if (aDiagVec.xyz().SquareModulus() >= 500000.0f * 500000.0f)
+          {
+            // bounding borders of infinite line has been calculated as own point in center of this line
+            aBox = Graphic3d_BndBox4f ((aBox.CornerMin() + aBox.CornerMax()) * 0.5f);
+          }
+          else
+          {
+            aBox = Graphic3d_BndBox4f (Graphic3d_Vec4 (ShortRealFirst(), ShortRealFirst(), ShortRealFirst(), 1.0f),
+                                       Graphic3d_Vec4 (ShortRealLast(),  ShortRealLast(),  ShortRealLast(),  1.0f));
+          }
+        }
+
+        if (aStructure->TransformPersistence.Flags != Graphic3d_TMF_None)
+        {
+          const Graphic3d_Mat4& aProjectionMat = theCamera->ProjectionMatrixF();
+          const Graphic3d_Mat4& aWorldViewMat  = theCamera->OrientationMatrixF();
+
+          aStructure->TransformPersistence.Apply (aProjectionMat,
+                                                  aWorldViewMat,
+                                                  theWindowWidth,
+                                                  theWindowHeight,
+                                                  aBox);
+        }
+
+        // To prevent float overflow at camera parameters calculation and further
+        // rendering, bounding boxes with at least one vertex coordinate out of
+        // float range are skipped by view fit algorithms
+        if (Abs (aBox.CornerMax().x()) >= ShortRealLast()
+         || Abs (aBox.CornerMax().y()) >= ShortRealLast()
+         || Abs (aBox.CornerMax().z()) >= ShortRealLast()
+         || Abs (aBox.CornerMin().x()) >= ShortRealLast()
+         || Abs (aBox.CornerMin().y()) >= ShortRealLast()
+         || Abs (aBox.CornerMin().z()) >= ShortRealLast())
+        {
+          continue;
+        }
+
+        myBoundingBox[aBoxId].Combine (aBox);
+      }
+    }
+
+    myIsBoundingBoxNeedsReset[aBoxId] = false;
+  }
+
+  return myBoundingBox[aBoxId];
+}
+
+// =======================================================================
+// function : considerZoomPersistenceObjects
+// purpose  :
+// =======================================================================
+Standard_Real OpenGl_Layer::considerZoomPersistenceObjects (const Standard_Integer          theViewId,
+                                                            const Handle(Graphic3d_Camera)& theCamera,
+                                                            Standard_Integer                theWindowWidth,
+                                                            Standard_Integer                theWindowHeight,
+                                                            Standard_Boolean                /*theToIgnoreInfiniteFlag*/) const
+{
+  if (NbOfTransformPersistenceObjects() == 0)
+  {
+    return 1.0;
+  }
+
+  const Standard_Integer aNbPriorities  = myArray.Length();
+  const Graphic3d_Mat4&  aProjectionMat = theCamera->ProjectionMatrixF();
+  const Graphic3d_Mat4&  aWorldViewMat  = theCamera->OrientationMatrixF();
+  Standard_Real          aMaxCoef       = -std::numeric_limits<double>::max();
+
+  for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
+  {
+    const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
+    for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
+    {
+      OpenGl_Structure* aStructure = const_cast<OpenGl_Structure*> (aStructures.FindKey (aStructIdx));
+      if (!aStructure->IsVisible())
+      {
+        continue;
+      }
+      else if (!aStructure->ViewAffinity.IsNull()
+            && !aStructure->ViewAffinity->IsVisible (theViewId))
+      {
+        continue;
+      }
+
+      if (!(aStructure->TransformPersistence.Flags & Graphic3d_TMF_ZoomPers))
+      {
+        continue;
+      }
+
+      Graphic3d_BndBox4f aBox = aStructure->BoundingBox();
+      aStructure->TransformPersistence.Apply (aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox);
+
+      const BVH_Vec4f&       aCornerMin           = aBox.CornerMin();
+      const BVH_Vec4f&       aCornerMax           = aBox.CornerMax();
+      const Standard_Integer aNbOfPoints          = 8;
+      const gp_Pnt           aPoints[aNbOfPoints] = { gp_Pnt (aCornerMin.x(), aCornerMin.y(), aCornerMin.z()),
+                                                      gp_Pnt (aCornerMin.x(), aCornerMin.y(), aCornerMax.z()),
+                                                      gp_Pnt (aCornerMin.x(), aCornerMax.y(), aCornerMin.z()),
+                                                      gp_Pnt (aCornerMin.x(), aCornerMax.y(), aCornerMax.z()),
+                                                      gp_Pnt (aCornerMax.x(), aCornerMin.y(), aCornerMin.z()),
+                                                      gp_Pnt (aCornerMax.x(), aCornerMin.y(), aCornerMax.z()),
+                                                      gp_Pnt (aCornerMax.x(), aCornerMax.y(), aCornerMin.z()),
+                                                      gp_Pnt (aCornerMax.x(), aCornerMax.y(), aCornerMax.z()) };
+      gp_Pnt aConvertedPoints[aNbOfPoints];
+      Standard_Real aConvertedMinX =  std::numeric_limits<double>::max();
+      Standard_Real aConvertedMaxX = -std::numeric_limits<double>::max();
+      Standard_Real aConvertedMinY =  std::numeric_limits<double>::max();
+      Standard_Real aConvertedMaxY = -std::numeric_limits<double>::max();
+      for (Standard_Integer anIdx = 0; anIdx < aNbOfPoints; ++anIdx)
+      {
+        aConvertedPoints[anIdx] = theCamera->Project (aPoints[anIdx]);
+
+        aConvertedMinX          = Min (aConvertedMinX, aConvertedPoints[anIdx].X());
+        aConvertedMaxX          = Max (aConvertedMaxX, aConvertedPoints[anIdx].X());
+
+        aConvertedMinY          = Min (aConvertedMinY, aConvertedPoints[anIdx].Y());
+        aConvertedMaxY          = Max (aConvertedMaxY, aConvertedPoints[anIdx].Y());
+      }
+
+      const Standard_Boolean isBigObject  = (Abs (aConvertedMaxX - aConvertedMinX) > 2.0)  // width  of zoom pers. object greater than width  of window
+                                         || (Abs (aConvertedMaxY - aConvertedMinY) > 2.0); // height of zoom pers. object greater than height of window
+      const Standard_Boolean isAlreadyInScreen = (aConvertedMinX > -1.0 && aConvertedMinX < 1.0)
+                                              && (aConvertedMaxX > -1.0 && aConvertedMaxX < 1.0)
+                                              && (aConvertedMinY > -1.0 && aConvertedMinY < 1.0)
+                                              && (aConvertedMaxY > -1.0 && aConvertedMaxY < 1.0);
+      if (isBigObject || isAlreadyInScreen)
+      {
+        continue;
+      }
+
+      const gp_Pnt aTPPoint (aStructure->TransformPersistence.Point.x(),
+                             aStructure->TransformPersistence.Point.y(),
+                             aStructure->TransformPersistence.Point.z());
+      gp_Pnt aConvertedTPPoint = theCamera->Project (aTPPoint);
+      aConvertedTPPoint.SetZ (0.0);
+
+      if (aConvertedTPPoint.Coord().Modulus() < Precision::Confusion())
+      {
+        continue;
+      }
+
+      Standard_Real aShiftX = 0.0;
+      if (aConvertedMinX < -1.0)
+      {
+        aShiftX = ((aConvertedMaxX < -1.0) ? (-(1.0 + aConvertedMaxX) + (aConvertedMaxX - aConvertedMinX)) : -(1.0 + aConvertedMinX));
+      }
+      else if (aConvertedMaxX > 1.0)
+      {
+        aShiftX = ((aConvertedMinX > 1.0) ? ((aConvertedMinX - 1.0) + (aConvertedMaxX - aConvertedMinX)) : (aConvertedMaxX - 1.0));
+      }
+
+      Standard_Real aShiftY = 0.0;
+      if (aConvertedMinY < -1.0)
+      {
+        aShiftY = ((aConvertedMaxY < -1.0) ? (-(1.0 + aConvertedMaxY) + (aConvertedMaxY - aConvertedMinY)) : -(1.0 + aConvertedMinY));
+      }
+      else if (aConvertedMaxY > 1.0)
+      {
+        aShiftY = ((aConvertedMinY > 1.0) ? ((aConvertedMinY - 1.0) + (aConvertedMaxY - aConvertedMinY)) : (aConvertedMaxY - 1.0));
+      }
+
+      const Standard_Real aDifX = Abs (aConvertedTPPoint.X()) - aShiftX;
+      const Standard_Real aDifY = Abs (aConvertedTPPoint.Y()) - aShiftY;
+      if (aDifX > Precision::Confusion())
+      {
+        aMaxCoef = Max (aMaxCoef, Abs (aConvertedTPPoint.X()) / aDifX);
+      }
+      if (aDifY > Precision::Confusion())
+      {
+        aMaxCoef = Max (aMaxCoef, Abs (aConvertedTPPoint.Y()) / aDifY);
+      }
+    }
+  }
+
+  return (aMaxCoef > 0.0) ? aMaxCoef : 1.0;
+}
+
+// =======================================================================
 // function : renderAll
 // purpose  :
 // =======================================================================
index eda0572..a6eddd2 100644 (file)
@@ -92,12 +92,38 @@ public:
 
   //! Marks BVH tree for given priority list as dirty and
   //! marks primitive set for rebuild.
-  void InvalidateBVHData();
+  void InvalidateBVHData() const;
+
+  //! Marks cached bounding box as obsolete.
+  void InvalidateBoundingBox() const
+  {
+    myIsBoundingBoxNeedsReset[0] = myIsBoundingBoxNeedsReset[1] = true;
+  }
+
+  //! Returns layer bounding box.
+  const Graphic3d_BndBox4f& BoundingBox (const Standard_Integer          theViewId,
+                                         const Handle(Graphic3d_Camera)& theCamera,
+                                         const Standard_Integer          theWindowWidth,
+                                         const Standard_Integer          theWindowHeight,
+                                         const Standard_Boolean          theToIgnoreInfiniteFlag) const;
+
+  //! Returns zoom-scale factor.
+  Standard_Real considerZoomPersistenceObjects (const Standard_Integer          theViewId,
+                                                const Handle(Graphic3d_Camera)& theCamera,
+                                                const Standard_Integer          theWindowWidth,
+                                                const Standard_Integer          theWindowHeight,
+                                                const Standard_Boolean          theToIgnoreInfiniteFlag) const;
 
   // Render all structures.
   void Render (const Handle(OpenGl_Workspace)&   theWorkspace,
                const OpenGl_GlobalLayerSettings& theDefaultSettings) const;
 
+  //! Returns number of transform persistence objects.
+  Standard_Integer NbOfTransformPersistenceObjects() const
+  {
+    return myBVHPrimitivesTrsfPers.Size();
+  }
+
 protected:
 
   //! Traverses through BVH tree to determine which structures are in view volume.
@@ -132,6 +158,12 @@ private:
   //! Defines if the primitive set for BVH is outdated.
   mutable Standard_Boolean myIsBVHPrimitivesNeedsReset;
 
+  //! Defines if the cached bounding box is outdated.
+  mutable bool myIsBoundingBoxNeedsReset[2];
+
+  //! Cached layer bounding box.
+  mutable Graphic3d_BndBox4f myBoundingBox[2];
+
 public:
 
   DEFINE_STANDARD_ALLOC
index ec05a3e..d54bbe4 100644 (file)
@@ -95,6 +95,9 @@ public:
   //! Returns the set of OpenGL Z-layers.
   const OpenGl_SequenceOfLayers& Layers() const { return myLayers; }
 
+  //! Returns the map of Z-layer IDs to indexes.
+  const OpenGl_LayerSeqIds& LayerIDs() const { return myLayerIds; }
+
   //! Marks BVH tree for given priority list as dirty and
   //! marks primitive set for rebuild.
   void InvalidateBVHData (const Graphic3d_ZLayerId theLayerId);
index 7d2b9b6..3e1a7da 100644 (file)
@@ -522,6 +522,91 @@ void OpenGl_View::SetZLayerSettings (const Graphic3d_ZLayerId        theLayerId,
 }
 
 //=======================================================================
+//function : ZLayerMax
+//purpose  :
+//=======================================================================
+Standard_Integer OpenGl_View::ZLayerMax() const
+{
+  Standard_Integer aLayerMax = Graphic3d_ZLayerId_Default;
+  for (OpenGl_LayerSeqIds::Iterator aMapIt(myZLayers.LayerIDs()); aMapIt.More(); aMapIt.Next())
+  {
+    aLayerMax = Max (aLayerMax, aMapIt.Value());
+  }
+
+  return aLayerMax;
+}
+
+//=======================================================================
+//function : InvalidateZLayerBoundingBox
+//purpose  :
+//=======================================================================
+void OpenGl_View::InvalidateZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId) const
+{
+  if (myZLayers.LayerIDs().IsBound (theLayerId))
+  {
+    myZLayers.Layer (theLayerId).InvalidateBoundingBox();
+  }
+  else
+  {
+    for (Standard_Integer aLayerId = Graphic3d_ZLayerId_Default; aLayerId < ZLayerMax(); ++aLayerId)
+    {
+      if (myZLayers.LayerIDs().IsBound (aLayerId))
+      {
+        const OpenGl_Layer& aLayer = myZLayers.Layer (aLayerId);
+        if (aLayer.NbOfTransformPersistenceObjects() > 0)
+        {
+          aLayer.InvalidateBoundingBox();
+        }
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : ZLayerBoundingBox
+//purpose  :
+//=======================================================================
+Graphic3d_BndBox4f OpenGl_View::ZLayerBoundingBox (const Graphic3d_ZLayerId        theLayerId,
+                                                   const Handle(Graphic3d_Camera)& theCamera,
+                                                   const Standard_Integer          theWindowWidth,
+                                                   const Standard_Integer          theWindowHeight,
+                                                   const Standard_Boolean          theToIgnoreInfiniteFlag) const
+{
+  if (myZLayers.LayerIDs().IsBound (theLayerId))
+  {
+    return myZLayers.Layer (theLayerId).BoundingBox (Identification(),
+                                                     theCamera,
+                                                     theWindowWidth,
+                                                     theWindowHeight,
+                                                     theToIgnoreInfiniteFlag);
+  }
+
+  return Graphic3d_BndBox4f();
+}
+
+//=======================================================================
+//function : considerZoomPersistenceObjects
+//purpose  :
+//=======================================================================
+Standard_Real OpenGl_View::considerZoomPersistenceObjects (const Graphic3d_ZLayerId        theLayerId,
+                                                           const Handle(Graphic3d_Camera)& theCamera,
+                                                           const Standard_Integer          theWindowWidth,
+                                                           const Standard_Integer          theWindowHeight,
+                                                           const Standard_Boolean          theToIgnoreInfiniteFlag) const
+{
+  if (myZLayers.LayerIDs().IsBound (theLayerId) && theCamera->IsOrthographic())
+  {
+    return myZLayers.Layer (theLayerId).considerZoomPersistenceObjects (Identification(),
+                                                                        theCamera,
+                                                                        theWindowWidth,
+                                                                        theWindowHeight,
+                                                                        theToIgnoreInfiniteFlag);
+  }
+
+  return 1.0;
+}
+
+//=======================================================================
 //function : FBO
 //purpose  :
 //=======================================================================
@@ -742,6 +827,8 @@ void OpenGl_View::changeZLayer (const Handle(Graphic3d_CStructure)& theStructure
   const Graphic3d_ZLayerId anOldLayer = theStructure->ZLayer();
   const OpenGl_Structure* aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
   myZLayers.ChangeLayer (aStruct, anOldLayer, theNewLayerId);
+  Update (Aspect_TOU_WAIT, anOldLayer);
+  Update (Aspect_TOU_WAIT, theNewLayerId);
 }
 
 //=======================================================================
index 0b35e2c..efa355a 100644 (file)
@@ -231,6 +231,22 @@ public:
   Standard_EXPORT virtual void SetZLayerSettings (const Graphic3d_ZLayerId theLayerId,
                                                   const Graphic3d_ZLayerSettings& theSettings) Standard_OVERRIDE;
 
+  //! Returns the maximum Z layer ID.
+  //! First layer ID is Graphic3d_ZLayerId_Default, last ID is ZLayerMax().
+  Standard_EXPORT virtual Standard_Integer ZLayerMax() const Standard_OVERRIDE;
+
+  //! Returns the bounding box of all structures displayed in the Z layer.
+  //! Never fails. If Z layer does not exist nothing happens.
+  Standard_EXPORT virtual void InvalidateZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId) const Standard_OVERRIDE;
+
+  //! Returns the bounding box of all structures displayed in the Z layer.
+  //! Never fails. If Z layer does not exist the empty box is returned.
+  Standard_EXPORT virtual Graphic3d_BndBox4f ZLayerBoundingBox (const Graphic3d_ZLayerId        theLayerId,
+                                                                const Handle(Graphic3d_Camera)& theCamera,
+                                                                const Standard_Integer          theWindowWidth,
+                                                                const Standard_Integer          theWindowHeight,
+                                                                const Standard_Boolean          theToIgnoreInfiniteFlag) const Standard_OVERRIDE;
+
   //! Returns pointer to an assigned framebuffer object.
   Standard_EXPORT virtual Handle(Standard_Transient) FBO() const Standard_OVERRIDE;
 
@@ -528,6 +544,13 @@ private:
   Standard_EXPORT virtual void changePriority (const Handle(Graphic3d_CStructure)& theCStructure,
                                                const Standard_Integer theNewPriority) Standard_OVERRIDE;
 
+  //! Returns zoom-scale factor.
+  Standard_EXPORT virtual Standard_Real considerZoomPersistenceObjects (const Graphic3d_ZLayerId        theLayerId,
+                                                                        const Handle(Graphic3d_Camera)& theCamera,
+                                                                        const Standard_Integer          theWindowWidth,
+                                                                        const Standard_Integer          theWindowHeight,
+                                                                        const Standard_Boolean          theToIgnoreInfiniteFlag) const Standard_OVERRIDE;
+
 private:
 
   //! Copy content of Back buffer to the Front buffer.
index 49a9860..9f7bed1 100644 (file)
@@ -3257,7 +3257,11 @@ Standard_Boolean V3d_View::FitMinMax (const Handle(Graphic3d_Camera)& theCamera,
     aViewSizeYv = aViewSizeZv;
   }
 
-  Scale (theCamera, aViewSizeXv * (1.0 + theMargin), aViewSizeYv * (1.0 + theMargin));
+  Scale (theCamera, aViewSizeXv, aViewSizeYv);
+
+  const Standard_Real aZoomCoef = myView->ConsiderZoomPersistenceObjects();
+
+  Scale (theCamera, theCamera->ViewDimensions().X() * (aZoomCoef + theMargin), theCamera->ViewDimensions().Y() * (aZoomCoef + theMargin));
 
   return Standard_True;
 }
diff --git a/tests/bugs/vis/bug27374 b/tests/bugs/vis/bug27374
new file mode 100644 (file)
index 0000000..008e1ce
--- /dev/null
@@ -0,0 +1,20 @@
+puts "========"
+puts "OCC27374"
+puts "========"
+puts ""
+################################################################################
+puts "Visualization - add support zoom persistence objects for FitAll operation"
+################################################################################
+
+vinit
+vclear
+
+box b0 30 0 0 3 3 3
+box b1 -30 -30 30 10 20 30
+box b2 30 0 30 100 100 100
+vdisplay b0
+vdisplay b1 -trsfPers zoom -perspos 10 0 0
+vdisplay b2 -trsfPers zoom -perspos 40 0 30
+vfit
+
+vdump $imagedir/${casename}.png