0024307: TKOpenGl - efficient culling of large number of presentations
authorvpa <vpa@opencascade.com>
Fri, 20 Jun 2014 07:26:14 +0000 (11:26 +0400)
committerapn <apn@opencascade.com>
Thu, 26 Jun 2014 08:57:26 +0000 (12:57 +0400)
Implement SAT intersection tests and frustum culling algorithm using BVH trees.

New Draw command vfrustumculling to manage frustum culling.
Add test cases bugs/vis/bug24307_1 and bugs/vis/bug24307_2.
Remove CALL_DEF_BOUNDBOX and CALL_DEF_BOUNDS.

53 files changed:
src/BVH/BVH_PrimitiveSet.hxx
src/Graphic3d/FILES
src/Graphic3d/Graphic3d.cdl
src/Graphic3d/Graphic3d_BndBox4d.hxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_BndBox4f.hxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_CBounds.hxx [deleted file]
src/Graphic3d/Graphic3d_CStructure.cxx
src/Graphic3d/Graphic3d_CStructure.hxx
src/Graphic3d/Graphic3d_CView.hxx
src/Graphic3d/Graphic3d_GraphicDriver.cdl
src/Graphic3d/Graphic3d_Group.cdl
src/Graphic3d/Graphic3d_Group.cxx
src/Graphic3d/Graphic3d_Structure.cdl
src/Graphic3d/Graphic3d_Structure.cxx
src/InterfaceGraphic/InterfaceGraphic_Graphic3d.hxx
src/NCollection/NCollection_Vec4.hxx
src/OpenGl/FILES
src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx [new file with mode: 0644]
src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_BVHTreeSelector.cxx [new file with mode: 0644]
src/OpenGl/OpenGl_BVHTreeSelector.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_GraphicDriver.hxx
src/OpenGl/OpenGl_GraphicDriver_4.cxx
src/OpenGl/OpenGl_GraphicDriver_7.cxx
src/OpenGl/OpenGl_LayerList.cxx
src/OpenGl/OpenGl_LayerList.hxx
src/OpenGl/OpenGl_PriorityList.cxx
src/OpenGl/OpenGl_PriorityList.hxx
src/OpenGl/OpenGl_SceneGeometry.cxx
src/OpenGl/OpenGl_SceneGeometry.hxx
src/OpenGl/OpenGl_Structure.cxx
src/OpenGl/OpenGl_Structure.hxx
src/OpenGl/OpenGl_View.hxx
src/OpenGl/OpenGl_View_2.cxx
src/OpenGl/OpenGl_Workspace.cxx
src/OpenGl/OpenGl_Workspace.hxx
src/OpenGl/OpenGl_Workspace_Raytrace.cxx
src/Prs3d/Prs3d_Presentation.cdl
src/Prs3d/Prs3d_Presentation.cxx
src/PrsMgr/PrsMgr_PresentableObject.cdl
src/PrsMgr/PrsMgr_PresentableObject.cxx
src/PrsMgr/PrsMgr_Presentation.cxx
src/Standard/Standard_Real.hxx
src/V3d/V3d_View.cdl
src/V3d/V3d_View.cxx
src/ViewerTest/ViewerTest.cxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx
src/ViewerTest/ViewerTest_OpenGlCommands.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
src/Visual3d/Visual3d_View.cdl
src/Visual3d/Visual3d_View.cxx
tests/bugs/vis/bug24307_1 [new file with mode: 0644]
tests/bugs/vis/bug24307_2 [new file with mode: 0644]

index ec414b2..a1e7f4c 100644 (file)
@@ -23,6 +23,8 @@
 template<class T, int N>
 class BVH_PrimitiveSet : public BVH_Object<T, N>, public BVH_Set<T, N>
 {
+protected:
+
   using BVH_Set<T, N>::Box;
 
 public:
index 84af421..96a87af 100755 (executable)
@@ -1,3 +1,5 @@
+Graphic3d_BndBox4d.hxx
+Graphic3d_BndBox4f.hxx
 Graphic3d_Buffer.hxx
 Graphic3d_Buffer_Handle.hxx
 Graphic3d_BoundBuffer.hxx
@@ -18,7 +20,6 @@ Graphic3d_CBitFields4.hxx
 Graphic3d_CTexture.hxx
 Graphic3d_CLight.hxx
 Graphic3d_CPick.hxx
-Graphic3d_CBounds.hxx
 Graphic3d_CUserDraw.hxx
 Graphic3d_CView.hxx
 Graphic3d_CGraduatedTrihedron.hxx
index f1bf523..ab80315 100644 (file)
@@ -347,6 +347,9 @@ is
     -- Category: Imported types
     ---------------------------
 
+    imported BndBox4f;
+    ---Purpose: Redefines BVH_Box<Standard_ShortReal, 4> for AABB representation
+    ---Category: Imported types
     imported Buffer;
     imported Buffer_Handle;
     imported BoundBuffer;
@@ -354,6 +357,7 @@ is
     imported IndexBuffer;
     imported IndexBuffer_Handle;
 
+    imported BndBox4d;
     imported BufferType;
 
     imported CBitFields20;
@@ -389,9 +393,6 @@ is
     imported CPlane;
     ---Category: Imported types
 
-    imported CBounds;
-    ---Category: Imported types
-
     imported CUserDraw;
     ---Category: Imported types
 
diff --git a/src/Graphic3d/Graphic3d_BndBox4d.hxx b/src/Graphic3d/Graphic3d_BndBox4d.hxx
new file mode 100644 (file)
index 0000000..90ec6fe
--- /dev/null
@@ -0,0 +1,23 @@
+// Created on: 2014-04-09
+// Created by: Varvara POSKONINA
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Graphic3d_BndBox4d_HeaderFile
+#define _Graphic3d_BndBox4d_HeaderFile
+
+#include <BVH_Box.hxx>
+
+typedef BVH_Box<Standard_Real, 4> Graphic3d_BndBox4d;
+
+#endif // _Graphic3d_BndBox4d_HeaderFile
diff --git a/src/Graphic3d/Graphic3d_BndBox4f.hxx b/src/Graphic3d/Graphic3d_BndBox4f.hxx
new file mode 100644 (file)
index 0000000..7a86c2a
--- /dev/null
@@ -0,0 +1,23 @@
+// Created on: 2014-04-09
+// Created by: Varvara POSKONINA
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Graphic3d_BndBox4f_HeaderFile
+#define _Graphic3d_BndBox4f_HeaderFile
+
+#include <BVH_Box.hxx>
+
+typedef BVH_Box<Standard_ShortReal, 4> Graphic3d_BndBox4f;
+
+#endif // _Graphic3d_BndBox4f_HeaderFile
diff --git a/src/Graphic3d/Graphic3d_CBounds.hxx b/src/Graphic3d/Graphic3d_CBounds.hxx
deleted file mode 100644 (file)
index f3b5cb8..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 1999-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-/*============================================================================*/
-/*==== Titre: Graphic3d_CBounds.hxx                                          */
-/*==== Role : The header file of primitive type "CBounds" from Graphic3d      */
-/*====                                                                       */
-/*==== Implementation:  This is a primitive type implemented with typedef     */
-/*============================================================================*/
-
-#ifndef _Graphic3d_CBounds_HeaderFile
-#define _Graphic3d_CBounds_HeaderFile
-
-#include <InterfaceGraphic_Graphic3d.hxx>
-typedef CALL_DEF_BOUNDS Graphic3d_CBounds;
-
-#endif /*Graphic3d_CBounds_HeaderFile*/
index 7b4262c..5f71832 100644 (file)
@@ -37,6 +37,9 @@ Graphic3d_CStructure::Graphic3d_CStructure (const Handle(Graphic3d_StructureMana
   visible          (1),
   pick             (1),
   HLRValidation    (0),
+  IsForHighlight   (Standard_False),
+  IsMutable        (Standard_False),
+  Is2dText         (Standard_False),
   myGraphicDriver  (theManager->GraphicDriver())
 {
   for (Standard_Integer i = 0; i <= 3; ++i)
index de97997..92fd2ff 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef _Graphic3d_CStructure_HeaderFile
 #define _Graphic3d_CStructure_HeaderFile
 
+#include <Graphic3d_BndBox4f.hxx>
 #include <Graphic3d_CStructure_Handle.hxx>
 #include <Graphic3d_Group.hxx>
 #include <Graphic3d_SequenceOfGroup.hxx>
@@ -53,6 +54,19 @@ public:
   //! Pass clip planes to the associated graphic driver structure
   void SetClipPlanes (const Graphic3d_SequenceOfHClipPlane& thePlanes) { myClipPlanes = thePlanes; }
 
+  //! @return bounding box of this presentation
+  const Graphic3d_BndBox4f& BoundingBox() const
+  {
+    return myBndBox;
+  }
+
+  //! @return bounding box of this presentation
+  //! without transformation matrix applied
+  Graphic3d_BndBox4f& ChangeBoundingBox()
+  {
+    return myBndBox;
+  }
+
 public:
 
   //! Update structure visibility state
@@ -101,19 +115,22 @@ public:
   CALL_DEF_CONTEXTMARKER   ContextMarker;
   CALL_DEF_CONTEXTTEXT     ContextText;
 
-  CALL_DEF_BOUNDBOX BoundBox;
+  CALL_DEF_COLOR HighlightColor;
 
   float Transformation[4][4];
   Graphic3d_TypeOfComposition Composition;
 
   int   ContainsFacet;
 
-  unsigned IsInfinite    : 1;
-  unsigned stick         : 1;
-  unsigned highlight     : 1;
-  unsigned visible       : 1;
-  unsigned pick          : 1;
-  unsigned HLRValidation : 1;
+  unsigned IsInfinite     : 1;
+  unsigned stick          : 1;
+  unsigned highlight      : 1;
+  unsigned visible        : 1;
+  unsigned pick           : 1;
+  unsigned HLRValidation  : 1;
+  unsigned IsForHighlight : 1;
+  unsigned IsMutable      : 1;
+  unsigned Is2dText       : 1;
 
   CALL_DEF_TRANSFORM_PERSISTENCE TransformPersistence;
 
@@ -126,6 +143,7 @@ protected:
 
   Handle(Graphic3d_GraphicDriver) myGraphicDriver;
   Graphic3d_SequenceOfGroup       myGroups;
+  Graphic3d_BndBox4f              myBndBox;
   Graphic3d_SequenceOfHClipPlane  myClipPlanes;
 
 public:
index e8d9e73..f329e76 100644 (file)
@@ -93,13 +93,14 @@ public:
     ptrUnderLayer (NULL),
     ptrOverLayer  (NULL),
     Backfacing  (0),
-         GContext (NULL),
+    GContext (NULL),
     GDisplayCB  (NULL),
     GClientData (NULL),
     ptrFBO (NULL),
-    WasRedrawnGL (0)
+    WasRedrawnGL (0),
+    IsCullingEnabled (Standard_True)
   {
-         memset(&DefWindow,0,sizeof(DefWindow));
+    memset (&DefWindow, 0, sizeof(DefWindow));
   }
 
 public:
@@ -134,6 +135,9 @@ public:
   //! Specifies rendering parameters and effects.
   Graphic3d_RenderingParams RenderParams;
 
+  //! Enables/disables frustum culling.
+  Standard_Boolean IsCullingEnabled;
+
 };
 
 #endif // Graphic3d_CView_HeaderFile
index 140d92e..c656e50 100644 (file)
@@ -643,6 +643,13 @@ is
     -- In contrast to Bitmaps, Vector graphics is scalable (so you may got quality benefits on printing to laser printer).
     -- Notice however that results may differ a lot and do not contain some elements.
 
+    InvalidateBVHData( me         : mutable;
+                       theCView   : out CView from Graphic3d;
+                       theLayerId : Integer from Standard )
+    is deferred;
+    ---Purpose:
+    -- Marks BVH tree and the set of BVH primitives of correspondent priority list with id theLayerId as outdated.
+
     AddZLayer( me         : mutable;
                theCView   : CView from Graphic3d;
                theLayerId : Integer from Standard )
@@ -696,6 +703,14 @@ is
         is deferred;
         ---Purpose:  Sets the settings for a single Z layer of specified view.
 
+    ChangePriority( me             : mutable;
+                    theCStructure  : CStructure from Graphic3d;
+                    theCView       : CView from Graphic3d;
+                    theNewPriority : Integer from Standard )
+        is deferred;
+        ---Purpose: Changes the priority of a structure within its Z layer
+        -- in the specified view.
+
     -----------------------------
     -- Category: Internal methods
     -----------------------------
index 19bee13..10b640a 100644 (file)
@@ -90,7 +90,7 @@ deferred class Group from Graphic3d inherits TShared
         Buffer_Handle               from Graphic3d,
         BoundBuffer_Handle          from Graphic3d,
         TransModeFlags              from Graphic3d,
-        CBounds                     from Graphic3d,
+        BndBox4f                    from Graphic3d,
         Ax2                         from gp
     
     raises
@@ -480,6 +480,22 @@ deferred class Group from Graphic3d inherits TShared
         --      XMin = YMin = ZMin = RealFirst ().
         --      XMax = YMax = ZMax = RealLast ().
         ---Category: Inquire methods
+
+        BoundingBox ( me )
+            returns BndBox4f from Graphic3d
+            is static;
+        ---Level: Public
+        ---Purpose: Returns boundary box of the group <me> without transformation applied,
+        ---if it is specified for the structure.
+        ---C++: return const &
+
+        ChangeBoundingBox ( me : mutable )
+            returns BndBox4f from Graphic3d
+            is static;
+        ---Level: Public
+        ---Purpose: Returns non-const boundary box of the group <me> without transformation applied,
+        ---if it is specified for the structure.
+        ---C++: return &
     
         Structure ( me )
             returns Structure from Graphic3d
@@ -534,7 +550,7 @@ deferred class Group from Graphic3d inherits TShared
   myStructure    : StructurePtr from Graphic3d is protected;
 
   -- the min-max
-  myBounds       : CBounds from Graphic3d is protected;
+  myBounds        : BndBox4f from Graphic3d is protected;
 
   -- Identifies group forming closed volume. Used to filter groups for back face culling and capping algorithms.
   myIsClosed  : Boolean from Standard is protected;
index 3547817..1c64878 100644 (file)
 Graphic3d_Group::Graphic3d_Group (const Handle(Graphic3d_Structure)& theStruct)
 : myIsClosed (Standard_False)
 {
-  myBounds.XMin  = ShortRealLast();
-  myBounds.YMin  = ShortRealLast();
-  myBounds.ZMin  = ShortRealLast();
-  myBounds.XMax  = ShortRealFirst();
-  myBounds.YMax  = ShortRealFirst();
-  myBounds.ZMax  = ShortRealFirst();
-
-  //
   // A small commentary on the usage of This!
   //
   // Graphic3d_Group is created in a structure. Graphic3d_Structure is a
@@ -95,12 +87,7 @@ void Graphic3d_Group::Clear (Standard_Boolean theUpdateStructureMgr)
   ContextMarker.IsDef   = 0,
   ContextFillArea.IsDef = 0;
 
-  myBounds.XMin = ShortRealLast();
-  myBounds.YMin = ShortRealLast();
-  myBounds.ZMin = ShortRealLast();
-  myBounds.XMax = ShortRealFirst();
-  myBounds.YMax = ShortRealFirst();
-  myBounds.ZMax = ShortRealFirst();
+  myBounds.Clear();
 
   if (MyContainsFacet)
   {
@@ -148,12 +135,7 @@ void Graphic3d_Group::Remove()
 
   Update();
 
-  myBounds.XMin = ShortRealLast();
-  myBounds.YMin = ShortRealLast();
-  myBounds.ZMin = ShortRealLast();
-  myBounds.XMax = ShortRealFirst();
-  myBounds.YMax = ShortRealFirst();
-  myBounds.ZMax = ShortRealFirst();
+  myBounds.Clear();
 
   MyIsEmpty = Standard_True;
 }
@@ -188,11 +170,7 @@ Standard_Boolean Graphic3d_Group::IsEmpty() const
     return Standard_True;
   }
 
-  const Standard_ShortReal RL = ShortRealLast();
-  const Standard_ShortReal RF = ShortRealFirst();
-  const Standard_Boolean isEmpty = ((myBounds.XMin == RL) && (myBounds.YMin == RL)
-                                 && (myBounds.ZMin == RL) && (myBounds.XMax == RF)
-                                 && (myBounds.YMax == RF) && (myBounds.ZMax == RF));
+  const Standard_Boolean isEmpty = myStructure->IsInfinite() ? Standard_False : !myBounds.IsValid();
   if (isEmpty != MyIsEmpty)
   {
     ::Message::DefaultMessenger()->Send ("Graphic3d_Group: MyIsEmpty != IsEmpty()", Message_Trace);
@@ -207,12 +185,14 @@ Standard_Boolean Graphic3d_Group::IsEmpty() const
 void Graphic3d_Group::SetMinMaxValues (const Standard_Real theXMin, const Standard_Real theYMin, const Standard_Real theZMin,
                                        const Standard_Real theXMax, const Standard_Real theYMax, const Standard_Real theZMax)
 {
-  myBounds.XMin = Standard_ShortReal (theXMin);
-  myBounds.YMin = Standard_ShortReal (theYMin);
-  myBounds.ZMin = Standard_ShortReal (theZMin);
-  myBounds.XMax = Standard_ShortReal (theXMax);
-  myBounds.YMax = Standard_ShortReal (theYMax);
-  myBounds.ZMax = Standard_ShortReal (theZMax);
+  myBounds.CornerMin() = Graphic3d_Vec4 (static_cast<Standard_ShortReal> (theXMin),
+                                         static_cast<Standard_ShortReal> (theYMin),
+                                         static_cast<Standard_ShortReal> (theZMin),
+                                         1.0f);
+  myBounds.CornerMax() = Graphic3d_Vec4 (static_cast<Standard_ShortReal> (theXMax),
+                                         static_cast<Standard_ShortReal> (theYMax),
+                                         static_cast<Standard_ShortReal> (theZMax),
+                                         1.0f);
 }
 
 // =======================================================================
@@ -248,14 +228,22 @@ void Graphic3d_Group::MinMaxCoord (Standard_Real& theXMin, Standard_Real& theYMi
     theXMin = theYMin = theZMin = ShortRealFirst();
     theXMax = theYMax = theZMax = ShortRealLast();
   }
+  else if (myBounds.IsValid())
+  {
+    const Graphic3d_Vec4& aMinPt = myBounds.CornerMin();
+    const Graphic3d_Vec4& aMaxPt = myBounds.CornerMax();
+    theXMin = Standard_Real (aMinPt.x());
+    theYMin = Standard_Real (aMinPt.y());
+    theZMin = Standard_Real (aMinPt.z());
+    theXMax = Standard_Real (aMaxPt.x());
+    theYMax = Standard_Real (aMaxPt.y());
+    theZMax = Standard_Real (aMaxPt.z());
+  }
   else
   {
-    theXMin = Standard_Real (myBounds.XMin);
-    theYMin = Standard_Real (myBounds.YMin);
-    theZMin = Standard_Real (myBounds.ZMin);
-    theXMax = Standard_Real (myBounds.XMax);
-    theYMax = Standard_Real (myBounds.YMax);
-    theZMax = Standard_Real (myBounds.ZMax);
+    // for consistency with old API
+    theXMin = theYMin = theZMin = ShortRealLast();
+    theXMax = theYMax = theZMax = ShortRealFirst();
   }
 }
 
@@ -1039,10 +1027,7 @@ void Graphic3d_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray th
           for (Standard_Integer aVertIter = 0; aVertIter < aNbVerts; ++aVertIter)
           {
             const Graphic3d_Vec2& aVert = *reinterpret_cast<const Graphic3d_Vec2* >(theAttribs->value (aVertIter) + anOffset);
-            if (aVert.x() < myBounds.XMin) myBounds.XMin = aVert.x();
-            if (aVert.y() < myBounds.YMin) myBounds.YMin = aVert.y();
-            if (aVert.x() > myBounds.XMax) myBounds.XMax = aVert.x();
-            if (aVert.y() > myBounds.YMax) myBounds.YMax = aVert.y();
+            myBounds.Add (Graphic3d_Vec4 (aVert.x(), aVert.y(), 0.0f, 1.0f));
           }
           break;
         }
@@ -1052,12 +1037,7 @@ void Graphic3d_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray th
           for (Standard_Integer aVertIter = 0; aVertIter < aNbVerts; ++aVertIter)
           {
             const Graphic3d_Vec3& aVert = *reinterpret_cast<const Graphic3d_Vec3* >(theAttribs->value (aVertIter) + anOffset);
-            if (aVert.x() < myBounds.XMin) myBounds.XMin = aVert.x();
-            if (aVert.y() < myBounds.YMin) myBounds.YMin = aVert.y();
-            if (aVert.z() < myBounds.ZMin) myBounds.ZMin = aVert.z();
-            if (aVert.x() > myBounds.XMax) myBounds.XMax = aVert.x();
-            if (aVert.y() > myBounds.YMax) myBounds.YMax = aVert.y();
-            if (aVert.z() > myBounds.ZMax) myBounds.ZMax = aVert.z();
+            myBounds.Add (Graphic3d_Vec4 (aVert.x(), aVert.y(), aVert.z(), 1.0f));
           }
           break;
         }
@@ -1130,12 +1110,11 @@ void Graphic3d_Group::Text (const Standard_CString                  /*theText*/,
   {
     Standard_ShortReal x, y, z;
     thePoint.Coord (x, y, z);
-    if (x < myBounds.XMin) myBounds.XMin = x;
-    if (y < myBounds.YMin) myBounds.YMin = y;
-    if (z < myBounds.ZMin) myBounds.ZMin = z;
-    if (x > myBounds.XMax) myBounds.XMax = x;
-    if (y > myBounds.YMax) myBounds.YMax = y;
-    if (z > myBounds.ZMax) myBounds.ZMax = z;
+    myStructure->CStructure()->Is2dText = Standard_True;
+    myBounds.Add (Graphic3d_Vec4 (static_cast<Standard_ShortReal> (x),
+                                  static_cast<Standard_ShortReal> (y),
+                                  static_cast<Standard_ShortReal> (z),
+                                  1.0f));
   }
   Update();
 }
@@ -1202,3 +1181,21 @@ Standard_Boolean Graphic3d_Group::IsClosed() const
 {
   return myIsClosed;
 }
+
+//=======================================================================
+//function : BoundingBox
+//purpose  :
+//=======================================================================
+const Graphic3d_BndBox4f& Graphic3d_Group::BoundingBox() const
+{
+  return myBounds;
+}
+
+//=======================================================================
+//function : ChangeBoundingBox
+//purpose  :
+//=======================================================================
+Graphic3d_BndBox4f& Graphic3d_Group::ChangeBoundingBox()
+{
+  return myBounds;
+}
index 7134dfc..f0231af 100644 (file)
@@ -71,7 +71,9 @@ uses
        Vertex                  from Graphic3d,
        TransModeFlags          from Graphic3d,
        Pnt                     from gp,
-    SequenceOfHClipPlane from Graphic3d
+    SequenceOfHClipPlane from Graphic3d,
+    BndBox4f from Graphic3d,
+    BndBox4d from Graphic3d
 
 raises
 
@@ -210,6 +212,12 @@ is
        --  Warning: No more graphic operations in <me> after this call.
        --  Category: Methods to modify the class definition
 
+       CalculateBoundBox ( me  : mutable )
+               is static;
+       ---Level:   Public
+       ---Purpose: Computes axis-aligned bounding box of a structure.
+       --  Category: Methods to modify the class definition
+
        SetHighlightColor ( me          : mutable;
                            AColor      : Color from Quantity )
                is static;
@@ -358,6 +366,14 @@ is
        --          <LimitSup> is a negative value.
        raises StructureDefinitionError from Graphic3d is static;
 
+    SetIsForHighlight ( me               : mutable;
+                        isForHighlight   : Boolean from Standard )
+        is static;
+    ---Level: Internal
+    ---Purpose: marks the structure <me> representing wired structure needed for
+    --          highlight only so it won't be added to BVH tree.
+    --  Category: Methods to modify the class definition
+
        UnHighlight ( me        : mutable )
                is static;
        ---Level: Public
@@ -810,6 +826,17 @@ is
        ---Purpose: Get the current point of relative modelling transform persistence
         is static;
 
+  SetMutable ( me           : mutable;
+               theIsMutable : Boolean from Standard )
+  is static;
+  ---Purpose: Sets if the structure location has mutable nature (content or location will be changed regularly).
+
+  IsMutable ( me )
+  returns Boolean from Standard
+  is static;
+  ---Purpose: Returns true if structure has mutable nature (content or location are be changed regularly).
+  -- Mutable structure will be managed in different way than static onces.
+
        ----------------------------
        -- Category: Private methods
        ----------------------------
@@ -878,28 +905,16 @@ is
        ---Purpose: Returns the identification number of the structure <me>.
        ---Category: Private methods
 
-    MinMaxCoord (me;
-                 theXMin, theYMin, theZMin : out Real from Standard;
-                 theXMax, theYMax, theZMax : out Real from Standard)
-    is static private;
-    ---Level: Internal
-    ---Purpose: Returns the extreme coordinates found in the structure <me>.
-    --  Warning: If the structure <me> is empty or infinite then :
-    --    theXMin = theYMin = theZMin = RealFirst().
-    --    theXMax = theYMax = theZMax = RealLast().
-    ---Category: Private methods
+  minMaxCoord (me;
+               theToIgnoreInfiniteFlag : Boolean from Standard = Standard_False)
+    returns BndBox4f from Graphic3d
+  is static private;
+  ---Purpose: Returns the extreme coordinates found in the structure <me> without transformation applied.
 
-    MinMaxCoordWithDescendants (me;
-                                theXMin, theYMin, theZMin : out Real from Standard;
-                                theXMax, theYMax, theZMax : out Real from Standard)
-    is static private;
-    ---Level: Internal
-    ---Purpose: Returns the extreme coordinates found in the structure <me>
-    -- and its descendants with transformation applied.
-    --  Warning: If the structure <me> is empty or infinite then :
-    --    theXMin = theYMin = theZMin = RealFirst().
-    --    theXMax = theYMax = theZMax = RealLast().
-    ---Category: Private methods
+  addTransformed (me;
+                  theBox : out BndBox4d from Graphic3d;
+                  theToIgnoreInfiniteFlag : Boolean from Standard = Standard_False)
+  is static private;
 
        PrintNetwork ( myclass;
                       AStructure       : Structure from Graphic3d;
index 6425246..884967a 100644 (file)
@@ -114,6 +114,32 @@ void Graphic3d_Structure::Clear (const Standard_Boolean theWithDestruction)
   Update();
 }
 
+//=======================================================================
+//function : CalculateBoundBox
+//purpose  : Calculates AABB of a structure.
+//=======================================================================
+void Graphic3d_Structure::CalculateBoundBox()
+{
+  Graphic3d_BndBox4d aBox;
+  addTransformed (aBox, Standard_True);
+  if (aBox.IsValid() && myCStructure->TransformPersistence.Flag == 0)
+  {
+    Graphic3d_Vec4 aMinPt (RealToShortReal (aBox.CornerMin().x()),
+                           RealToShortReal (aBox.CornerMin().y()),
+                           RealToShortReal (aBox.CornerMin().z()),
+                           1.0f);
+    Graphic3d_Vec4 aMaxPt (RealToShortReal (aBox.CornerMax().x()),
+                           RealToShortReal (aBox.CornerMax().y()),
+                           RealToShortReal (aBox.CornerMax().z()),
+                           1.0f);
+    myCStructure->ChangeBoundingBox() = Graphic3d_BndBox4f (aMinPt, aMaxPt);
+  }
+  else
+  {
+    myCStructure->ChangeBoundingBox().Clear();
+  }
+}
+
 //=============================================================================
 //function : Remove
 //purpose  :
@@ -150,8 +176,6 @@ void Graphic3d_Structure::Remove()
     ((Graphic3d_Structure *)(myAncestors.ChangeValue (aStructIter)))->Remove (APtr, Graphic3d_TOC_DESCENDANT);
   }
 
-  myCStructure->ContainsFacet = 0;
-
   // Destruction of me in the graphic library
   const Standard_Integer aStructId = myCStructure->Id;
   myCStructure->GraphicDriver()->RemoveStructure (myCStructure);
@@ -183,6 +207,15 @@ void Graphic3d_Structure::Display()
 }
 
 //=============================================================================
+//function : SetIsForHighlight
+//purpose  :
+//=============================================================================
+void Graphic3d_Structure::SetIsForHighlight (const Standard_Boolean isForHighlight)
+{
+  myCStructure->IsForHighlight = isForHighlight;
+}
+
+//=============================================================================
 //function : Display
 //purpose  :
 //=============================================================================
@@ -1375,6 +1408,7 @@ void Graphic3d_Structure::Connect (const Handle(Graphic3d_Structure)& theStructu
       }
 
       myDescendants.Append (theStructure.operator->());
+      CalculateBoundBox();
       theStructure->Connect (this, Graphic3d_TOC_ANCESTOR);
 
       GraphicConnect (theStructure);
@@ -1395,6 +1429,7 @@ void Graphic3d_Structure::Connect (const Handle(Graphic3d_Structure)& theStructu
       }
 
       myAncestors.Append (theStructure.operator->());
+      CalculateBoundBox();
       theStructure->Connect (this, Graphic3d_TOC_DESCENDANT);
 
       // myGraphicDriver->Connect is called in case if connection between parent and child
@@ -1422,6 +1457,8 @@ void Graphic3d_Structure::Disconnect (const Handle(Graphic3d_Structure)& theStru
       GraphicDisconnect (theStructure);
       myStructureManager->Disconnect (this, theStructure);
 
+      CalculateBoundBox();
+
       Update();
       return;
     }
@@ -1434,6 +1471,7 @@ void Graphic3d_Structure::Disconnect (const Handle(Graphic3d_Structure)& theStru
     {
       myAncestors.Remove (anIter);
       theStructure->Disconnect (this);
+      CalculateBoundBox();
       // no call of myGraphicDriver->Disconnect in case of an ancestor
       return;
     }
@@ -1608,6 +1646,7 @@ void Graphic3d_Structure::Transform (TColStd_Array2OfReal& theMatrix) const
   }
 }
 
+
 //=============================================================================
 //function : MinMaxValues
 //purpose  :
@@ -1620,89 +1659,9 @@ void Graphic3d_Structure::MinMaxValues (Standard_Real& theXMin,
                                         Standard_Real& theZMax,
                                         const Standard_Boolean theToIgnoreInfiniteFlag) const
 {
-  if (IsEmpty())
-  {
-    return;
-  }
-
-  Standard_Real aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
-  MinMaxCoord (aXMin, aYMin, aZMin, aXMax, aYMax, aZMax);
-
-  // Infinite boundaries corresponding to empty structure or
-  // non-empty structure, without any primitives specified
-  if (aXMin == RealFirst() && aYMin == RealFirst() && aZMin == RealFirst() &&
-      aXMax == RealLast()  && aYMax == RealLast()  && aZMax == RealLast())
-  {
-    theXMin = RealFirst();
-    theYMin = RealFirst();
-    theZMin = RealFirst();
-    theXMax = RealLast();
-    theYMax = RealLast();
-    theZMax = RealLast();
-    return;
-  }
-
-  // Handle flag, which specifies that structure should be considered as infinite
-  if (IsInfinite() && !theToIgnoreInfiniteFlag)
-  {
-    Graphic3d_Vertex aVertexMin (aXMin, aYMin, aZMin);
-    Graphic3d_Vertex aVertexMax (aXMax, aYMax, aZMax);
-    const Standard_Real aDistance = aVertexMin.Distance (aVertexMax);
-
-    // Special case for infinite line:
-    // Bounding borders of infinite line has been
-    // calculated as own point in center of this line
-    if (aDistance >= 500000.0)
-    {
-      theXMin = theXMax = 0.5 * (aXMin + aXMax);
-      theYMin = theYMax = 0.5 * (aYMin + aYMax);
-      theZMin = theZMax = 0.5 * (aZMin + aZMax);
-      return;
-    }
-
-    theXMin = RealFirst();
-    theYMin = RealFirst();
-    theZMin = RealFirst();
-    theXMax = RealLast();
-    theYMax = RealLast();
-    theZMax = RealLast();
-    return;
-  }
-
-  // Min-Max values of the descendant structures
-  Standard_Real aDescXMin = RealLast();
-  Standard_Real aDescYMin = RealLast();
-  Standard_Real aDescZMin = RealLast();
-  Standard_Real aDescXMax = RealFirst();
-  Standard_Real aDescYMax = RealFirst();
-  Standard_Real aDescZMax = RealFirst();
-  for (Standard_Integer aStructIt = 1; aStructIt <= myDescendants.Length(); aStructIt++)
-  {
-    Graphic3d_Structure* aStructure = (Graphic3d_Structure*) myDescendants.Value (aStructIt);
-    aStructure->MinMaxValues (aXMin, aYMin, aZMin, aXMax, aYMax, aZMax);
-    aDescXMin = Min (aXMin, aDescXMin);
-    aDescYMin = Min (aYMin, aDescYMin);
-    aDescZMin = Min (aZMin, aDescZMin);
-    aDescXMax = Max (aXMax, aDescXMax);
-    aDescYMax = Max (aYMax, aDescYMax);
-    aDescZMax = Max (aZMax, aDescZMax);
-  }
-
-  if (aDescXMin != RealLast()  || aDescYMin != RealLast()  ||
-      aDescZMin != RealLast()  || aDescXMax != RealFirst() ||
-      aDescYMax != RealFirst() || aDescZMax != RealFirst())
-  {
-    aXMin = Min (aDescXMin, aXMin);
-    aYMin = Min (aDescYMin, aYMin);
-    aZMin = Min (aDescZMin, aZMin);
-    aXMax = Max (aDescXMax, aXMax);
-    aYMax = Max (aDescYMax, aYMax);
-    aZMax = Max (aDescZMax, aZMax);
-  }
-
-  // Case impossible as it would mean that the structure is empty or infinite
-  if (aXMin == RealFirst() && aYMin == RealFirst() && aZMin == RealFirst() &&
-      aXMax == RealLast()  && aYMax == RealLast()  && aZMax == RealLast())
+  Graphic3d_BndBox4d aBox;
+  addTransformed (aBox, theToIgnoreInfiniteFlag);
+  if (!aBox.IsValid())
   {
     theXMin = RealFirst();
     theYMin = RealFirst();
@@ -1713,15 +1672,12 @@ void Graphic3d_Structure::MinMaxValues (Standard_Real& theXMin,
     return;
   }
 
-  TColStd_Array2OfReal aTrsf(0, 3, 0, 3);
-  Transform (aTrsf);
-  TransformBoundaries (aTrsf, aXMin, aYMin, aZMin, aXMax, aYMax, aZMax);
-  theXMin = aXMin;
-  theYMin = aYMin;
-  theZMin = aZMin;
-  theXMax = aXMax;
-  theYMax = aYMax;
-  theZMax = aZMax;
+  theXMin = aBox.CornerMin().x();
+  theYMin = aBox.CornerMin().y();
+  theZMin = aBox.CornerMin().z();
+  theXMax = aBox.CornerMax().x();
+  theYMax = aBox.CornerMax().y();
+  theZMax = aBox.CornerMax().z();
 }
 
 //=============================================================================
@@ -1756,6 +1712,7 @@ void Graphic3d_Structure::SetTransformPersistence (const Graphic3d_TransModeFlag
   myCStructure->TransformPersistence.Point.y = float (thePoint.Y());
   myCStructure->TransformPersistence.Point.z = float (thePoint.Z());
   myCStructure->UpdateAspects();
+  CalculateBoundBox();
 
   myCStructure->TransformPersistence.IsSet = 1;
 }
@@ -1855,154 +1812,79 @@ Handle(Graphic3d_StructureManager) Graphic3d_Structure::StructureManager() const
 }
 
 //=============================================================================
-//function : MinMaxCoord
+//function : minMaxCoord
 //purpose  :
 //=============================================================================
-void Graphic3d_Structure::MinMaxCoord (Standard_Real& theXMin,
-                                       Standard_Real& theYMin,
-                                       Standard_Real& theZMin,
-                                       Standard_Real& theXMax,
-                                       Standard_Real& theYMax,
-                                       Standard_Real& theZMax) const
+Graphic3d_BndBox4f Graphic3d_Structure::minMaxCoord (const Standard_Boolean theToIgnoreInfiniteFlag) const
 {
-  if (IsEmpty())
-  {
-    theXMin = RealFirst();
-    theYMin = RealFirst();
-    theZMin = RealFirst();
-    theXMax = RealLast();
-    theYMax = RealLast();
-    theZMax = RealLast();
-    return;
-  }
-
-  Standard_Real aXMin = RealLast();
-  Standard_Real aYMin = RealLast();
-  Standard_Real aZMin = RealLast();
-  Standard_Real aXMax = RealFirst();
-  Standard_Real aYMax = RealFirst();
-  Standard_Real aZMax = RealFirst();
-  Standard_Real aGroupXMin, aGroupYMin, aGroupZMin, aGroupXMax, aGroupYMax, aGroupZMax;
+  Graphic3d_BndBox4f aBnd;
   for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myCStructure->Groups()); aGroupIter.More(); aGroupIter.Next())
   {
-    const Handle(Graphic3d_Group)& aGroup = aGroupIter.Value();
-    if (aGroup->IsEmpty())
+    if (!theToIgnoreInfiniteFlag)
     {
-      continue;
+      aBnd.Combine (aGroupIter.Value()->BoundingBox());
+    }
+    else
+    {
+      Graphic3d_BndBox4f aValidBnd (aGroupIter.Value()->BoundingBox().CornerMin(),
+                                    aGroupIter.Value()->BoundingBox().CornerMax());
+      aBnd.Combine (aValidBnd);
     }
-
-    aGroup->MinMaxValues (aGroupXMin, aGroupYMin, aGroupZMin, aGroupXMax, aGroupYMax, aGroupZMax);
-    aXMin = Min (aXMin, aGroupXMin);
-    aYMin = Min (aYMin, aGroupYMin);
-    aZMin = Min (aZMin, aGroupZMin);
-    aXMax = Max (aXMax, aGroupXMax);
-    aYMax = Max (aYMax, aGroupYMax);
-    aZMax = Max (aZMax, aGroupZMax);
-  }
-
-  // Case impossible as it would mean that the structure is empty
-  if (aXMin == RealLast()  && aYMin == RealLast()  && aZMin == RealLast() &&
-      aXMax == RealFirst() && aYMax == RealFirst() && aZMax == RealFirst())
-  {
-    theXMin = RealFirst();
-    theYMin = RealFirst();
-    theZMin = RealFirst();
-    theXMax = RealLast();
-    theYMax = RealLast();
-    theZMax = RealLast();
   }
-
-  theXMin = aXMin;
-  theYMin = aYMin;
-  theZMin = aZMin;
-  theXMax = aXMax;
-  theYMax = aYMax;
-  theZMax = aZMax;
+  return aBnd;
 }
 
 //=============================================================================
-//function : MinMaxCoordWithDescendants
+//function : addTransformed
 //purpose  :
 //=============================================================================
-void Graphic3d_Structure::MinMaxCoordWithDescendants (Standard_Real& theXMin,
-                                                      Standard_Real& theYMin,
-                                                      Standard_Real& theZMin,
-                                                      Standard_Real& theXMax,
-                                                      Standard_Real& theYMax,
-                                                      Standard_Real& theZMax) const
+void Graphic3d_Structure::addTransformed (Graphic3d_BndBox4d&    theBox,
+                                          const Standard_Boolean theToIgnoreInfiniteFlag) const
 {
-  if (IsEmpty())
+  Graphic3d_BndBox4d aBox;
+  Graphic3d_BndBox4f aBoxF = minMaxCoord (theToIgnoreInfiniteFlag);
+  if (aBoxF.IsValid())
   {
-    theXMin = RealFirst();
-    theYMin = RealFirst();
-    theZMin = RealFirst();
-    theXMax = RealLast();
-    theYMax = RealLast();
-    theZMax = RealLast();
-    return;
-  }
-
-  Standard_Real aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
-  MinMaxCoord (aXMin, aYMin, aZMin, aXMax, aYMax, aZMax);
-
-  // Min-Max of the descendant structures
-  Standard_Real aDescXMin = RealLast();
-  Standard_Real aDescYMin = RealLast();
-  Standard_Real aDescZMin = RealLast();
-  Standard_Real aDescXMax = RealFirst();
-  Standard_Real aDescYMax = RealFirst();
-  Standard_Real aDescZMax = RealFirst();
-  for (Standard_Integer aStructIt = 1; aStructIt <= myDescendants.Length(); aStructIt++)
-  {
-    Graphic3d_Structure* aStructure = (Graphic3d_Structure*) myDescendants.Value (aStructIt);
-    if (aStructure->IsEmpty())
+    aBox = Graphic3d_BndBox4d (Graphic3d_Vec4d ((Standard_Real )aBoxF.CornerMin().x(),
+                                                (Standard_Real )aBoxF.CornerMin().y(),
+                                                (Standard_Real )aBoxF.CornerMin().z(),
+                                                (Standard_Real )aBoxF.CornerMin().w()),
+                               Graphic3d_Vec4d ((Standard_Real )aBoxF.CornerMax().x(),
+                                                (Standard_Real )aBoxF.CornerMax().y(),
+                                                (Standard_Real )aBoxF.CornerMax().z(),
+                                                (Standard_Real )aBoxF.CornerMax().w()));
+    if (IsInfinite()
+    && !theToIgnoreInfiniteFlag)
     {
-      continue;
+      const Graphic3d_Vec4d aDiagVec = aBox.CornerMax() - aBox.CornerMin();
+      if (aDiagVec.xyz().SquareModulus() >= 500000.0 * 500000.0)
+      {
+        // bounding borders of infinite line has been calculated as own point in center of this line
+        aBox = Graphic3d_BndBox4d ((aBox.CornerMin() + aBox.CornerMax()) * 0.5);
+      }
+      else
+      {
+        theBox = Graphic3d_BndBox4d (Graphic3d_Vec4d (RealFirst(), RealFirst(), RealFirst(), 1.0),
+                                     Graphic3d_Vec4d (RealLast(),  RealLast(),  RealLast(),  1.0));
+        return;
+      }
     }
-
-    aStructure->MinMaxCoordWithDescendants (aXMin, aYMin, aZMin, aXMax, aYMax, aZMax);
-    aDescXMin = Min (aXMin, aDescXMin);
-    aDescYMin = Min (aYMin, aDescYMin);
-    aDescZMin = Min (aZMin, aDescZMin);
-    aDescXMax = Max (aXMax, aDescXMax);
-    aDescYMax = Max (aYMax, aDescYMax);
-    aDescZMax = Max (aZMax, aDescZMax);
   }
 
-  if (aDescXMin != RealLast()  || aDescYMin != RealLast()  ||
-      aDescZMin != RealLast()  || aDescXMax != RealFirst() ||
-      aDescYMax != RealFirst() || aDescZMax != RealFirst())
+  for (Standard_Integer aStructIt = 1; aStructIt <= myDescendants.Length(); ++aStructIt)
   {
-    TColStd_Array2OfReal aTrsf(0, 3, 0, 3);
-    Transform (aTrsf);
-    TransformBoundaries (aTrsf, aDescXMin, aDescYMin, aDescZMin, aDescXMax, aDescYMax, aDescZMax);
-
-    aXMin = Min (aDescXMin, aXMin);
-    aYMin = Min (aDescYMin, aYMin);
-    aZMin = Min (aDescZMin, aZMin);
-    aXMax = Max (aDescXMax, aXMax);
-    aYMax = Max (aDescYMax, aYMax);
-    aZMax = Max (aDescZMax, aZMax);
+    const Graphic3d_Structure* aStruct = (const Graphic3d_Structure* )myDescendants.Value (aStructIt);
+    aStruct->addTransformed (aBox, theToIgnoreInfiniteFlag);
   }
 
-  // Case impossible as it would mean that the structure is empty
-  if (aXMin == RealLast()  && aYMin == RealLast()  && aZMin == RealLast() &&
-      aXMax == RealFirst() && aYMax == RealFirst() && aZMax == RealFirst())
+  if (aBox.IsValid())
   {
-    theXMin = RealFirst();
-    theYMin = RealFirst();
-    theZMin = RealFirst();
-    theXMax = RealLast();
-    theYMax = RealLast();
-    theZMax = RealLast();
+    TColStd_Array2OfReal aTrsf (0, 3, 0, 3);
+    Transform (aTrsf);
+    TransformBoundaries (aTrsf, aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z(),
+                                aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z());
+    theBox.Combine (aBox);
   }
-
-  theXMin = aXMin;
-  theYMin = aYMin;
-  theZMin = aZMin;
-  theXMax = aXMax;
-  theYMax = aYMax;
-  theZMax = aZMax;
 }
 
 //=============================================================================
@@ -2384,27 +2266,10 @@ void Graphic3d_Structure::GraphicHighlight (const Aspect_TypeOfHighlightMethod t
     }
     case Aspect_TOHM_BOUNDBOX:
     {
-      Standard_Real XMin, YMin, ZMin, XMax, YMax, ZMax;
-      if (IsEmpty() || IsInfinite())
-      {
-        // Empty or infinite structure
-        XMin = YMin = ZMin = 0.0;
-        XMax = YMax = ZMax = 0.0;
-      }
-      else
-      {
-        MinMaxCoordWithDescendants (XMin, YMin, ZMin, XMax, YMax, ZMax);
-      }
-      myCStructure->BoundBox.Pmin.x  = float (XMin);
-      myCStructure->BoundBox.Pmin.y  = float (YMin);
-      myCStructure->BoundBox.Pmin.z  = float (ZMin);
-      myCStructure->BoundBox.Pmax.x  = float (XMax);
-      myCStructure->BoundBox.Pmax.y  = float (YMax);
-      myCStructure->BoundBox.Pmax.z  = float (ZMax);
       myHighlightColor.Values (anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB);
-      myCStructure->BoundBox.Color.r = float (anRGB[0]);
-      myCStructure->BoundBox.Color.g = float (anRGB[1]);
-      myCStructure->BoundBox.Color.b = float (anRGB[2]);
+      myCStructure->HighlightColor.r = float (anRGB[0]);
+      myCStructure->HighlightColor.g = float (anRGB[1]);
+      myCStructure->HighlightColor.b = float (anRGB[2]);
       myCStructure->HighlightWithBndBox (this, Standard_True);
       break;
     }
@@ -2531,3 +2396,21 @@ const Graphic3d_SequenceOfHClipPlane& Graphic3d_Structure::GetClipPlanes() const
 {
   return myCStructure->ClipPlanes();
 }
+
+//=======================================================================
+//function : SetMutable
+//purpose  :
+//=======================================================================
+void Graphic3d_Structure::SetMutable (const Standard_Boolean theIsMutable)
+{
+  myCStructure->IsMutable = theIsMutable;
+}
+
+//=======================================================================
+//function : IsMutable
+//purpose  :
+//=======================================================================
+Standard_Boolean Graphic3d_Structure::IsMutable() const
+{
+  return myCStructure->IsMutable;
+}
index 950197a..2e33160 100644 (file)
@@ -16,6 +16,7 @@
 #define InterfaceGraphic_Graphic3dHeader
 
 #include <InterfaceGraphic_telem.hxx>
+#include <Graphic3d_BndBox4f.hxx>
 #include <Standard_Transient.hxx>
 
 /* COULEUR */
@@ -34,18 +35,6 @@ typedef struct {
 
 } CALL_DEF_POINT;
 
-/* BOITE ENGLOBANTE */
-
-typedef struct {
-
-        CALL_DEF_COLOR Color;
-
-        CALL_DEF_POINT Pmin;
-
-        CALL_DEF_POINT Pmax;
-
-} CALL_DEF_BOUNDBOX;
-
 /* MATERIAL */
 
 typedef struct {
@@ -85,26 +74,12 @@ typedef struct
         CALL_DEF_POINT Point;
 } CALL_DEF_TRANSFORM_PERSISTENCE;
 
-/* BOUNDING BOX */
-
-typedef struct {
-
-        float XMin;
-        float YMin;
-        float ZMin;
-
-        float XMax;
-        float YMax;
-        float ZMax;
-
-} CALL_DEF_BOUNDS;
-
 /* USERDRAW DATA */
 
 typedef struct {
 
         void            *Data;
-        CALL_DEF_BOUNDS *Bounds;
+        Graphic3d_BndBox4f  *Bounds;
 
 } CALL_DEF_USERDRAW;
 
index 1758217..45aa2b0 100644 (file)
@@ -315,7 +315,7 @@ public:
   //! Compute per-component division by scale factor.
   NCollection_Vec4 operator/ (const Element_t theInvFactor)
   {
-    NCollection_Vec4 aResult(this);
+    NCollection_Vec4 aResult(*this);
     return aResult /= theInvFactor;
   }
 
index 2a8a56d..3991fff 100755 (executable)
@@ -143,3 +143,7 @@ OpenGl_SceneGeometry.cxx
 OpenGl_Workspace_Raytrace.cxx
 OpenGl_Flipper.hxx
 OpenGl_Flipper.cxx
+OpenGl_BVHTreeSelector.hxx
+OpenGl_BVHTreeSelector.cxx
+OpenGl_BVHClipPrimitiveSet.cxx
+OpenGl_BVHClipPrimitiveSet.hxx
diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx
new file mode 100644 (file)
index 0000000..4f3b9e8
--- /dev/null
@@ -0,0 +1,143 @@
+// Created on: 2013-12-25
+// Created by: Varvara POSKONINA
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <OpenGl_BVHClipPrimitiveSet.hxx>
+
+#include <BVH_BinnedBuilder.hxx>
+
+// =======================================================================
+// function : OpenGl_BVHClipPrimitiveSet
+// purpose  :
+// =======================================================================
+OpenGl_BVHClipPrimitiveSet::OpenGl_BVHClipPrimitiveSet()
+{
+  myBuilder = new BVH_BinnedBuilder<Standard_ShortReal, 4> (1, 32);
+}
+
+// =======================================================================
+// function : Size
+// purpose  :
+// =======================================================================
+Standard_Integer OpenGl_BVHClipPrimitiveSet::Size() const
+{
+  return myStructs.Size();
+}
+
+// =======================================================================
+// function : Box
+// purpose  :
+// =======================================================================
+Graphic3d_BndBox4f OpenGl_BVHClipPrimitiveSet::Box (const Standard_Integer theIdx) const
+{
+  return myStructs (theIdx + 1)->BoundingBox();
+}
+
+// =======================================================================
+// function : Center
+// purpose  :
+// =======================================================================
+Standard_ShortReal OpenGl_BVHClipPrimitiveSet::Center (const Standard_Integer theIdx,
+                                                       const Standard_Integer theAxis) const
+{
+  Graphic3d_BndBox4f aBndBox = myStructs (theIdx + 1)->BoundingBox();
+  Standard_ShortReal aCenter =  theAxis == 0 ? (aBndBox.CornerMin().x() + aBndBox.CornerMax().x()) * 0.5f
+                             : (theAxis == 1 ? (aBndBox.CornerMin().y() + aBndBox.CornerMax().y()) * 0.5f
+                             : (theAxis == 2 ? (aBndBox.CornerMin().z() + aBndBox.CornerMax().z()) * 0.5f
+                             : (aBndBox.CornerMin().w() + aBndBox.CornerMax().w()) * 0.5f));
+  return aCenter;
+}
+
+// =======================================================================
+// function : Swap
+// purpose  :
+// =======================================================================
+void OpenGl_BVHClipPrimitiveSet::Swap (const Standard_Integer theIdx1,
+                                       const Standard_Integer theIdx2)
+{
+  const OpenGl_Structure* aStruct1 = myStructs (theIdx1 + 1);
+  const OpenGl_Structure* aStruct2 = myStructs (theIdx2 + 1);
+  myStructs.ChangeValue (theIdx1 + 1) = aStruct2;
+  myStructs.ChangeValue (theIdx2 + 1) = aStruct1;
+}
+
+// =======================================================================
+// function : Assign
+// purpose  :
+// =======================================================================
+void OpenGl_BVHClipPrimitiveSet::Assign (const OpenGl_ArrayOfStructure& theStructs)
+{
+  myStructs.Clear();
+
+  const Standard_Integer aNbPriorities = theStructs.Length();
+  OpenGl_SequenceOfStructure::Iterator aStructIter;
+  for (Standard_Integer aPriorityIdx = 0; aPriorityIdx < aNbPriorities; ++aPriorityIdx)
+  {
+    const OpenGl_SequenceOfStructure& aSeq = theStructs (aPriorityIdx);
+    for (aStructIter.Init (aSeq); aStructIter.More(); aStructIter.Next())
+    {
+      const OpenGl_Structure* aStruct = aStructIter.Value();
+      if (!aStruct->IsAlwaysRendered())
+        myStructs.Append (aStruct);
+    }
+  }
+
+  MarkDirty();
+}
+
+// =======================================================================
+// function : Add
+// purpose  :
+// =======================================================================
+void OpenGl_BVHClipPrimitiveSet::Add (const OpenGl_Structure* theStruct)
+{
+  myStructs.Append (theStruct);
+  MarkDirty();
+}
+
+// =======================================================================
+// function : Remove
+// purpose  :
+// =======================================================================
+void OpenGl_BVHClipPrimitiveSet::Remove (const OpenGl_Structure* theStruct)
+{
+  for (Standard_Integer anIdx = 1; anIdx <= myStructs.Size(); ++anIdx)
+  {
+    if (myStructs (anIdx) == theStruct)
+    {
+      myStructs.Remove (anIdx);
+      MarkDirty();
+      break;
+    }
+  }
+}
+
+// =======================================================================
+// function : Clear
+// purpose  :
+// =======================================================================
+void OpenGl_BVHClipPrimitiveSet::Clear()
+{
+  myStructs.Clear();
+  MarkDirty();
+}
+
+// =======================================================================
+// function : GetStructureById
+// purpose  :
+// =======================================================================
+const OpenGl_Structure* OpenGl_BVHClipPrimitiveSet::GetStructureById (Standard_Integer theId)
+{
+  return myStructs (theId + 1);
+}
diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx
new file mode 100644 (file)
index 0000000..9a5c18a
--- /dev/null
@@ -0,0 +1,78 @@
+// Created on: 2013-12-25
+// Created by: Varvara POSKONINA
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _OpenGl_BVHClipPrimitiveSet_HeaderFile
+#define _OpenGl_BVHClipPrimitiveSet_HeaderFile
+
+#include <BVH_PrimitiveSet.hxx>
+
+#include <NCollection_Array1.hxx>
+#include <NCollection_Sequence.hxx>
+
+#include <OpenGl_Vec.hxx>
+#include <OpenGl_Structure.hxx>
+
+typedef NCollection_Sequence<const OpenGl_Structure*> OpenGl_SequenceOfStructure;
+typedef NCollection_Array1<OpenGl_SequenceOfStructure> OpenGl_ArrayOfStructure;
+
+//! Set of OpenGl_Structures for building BVH tree.
+class OpenGl_BVHClipPrimitiveSet : public BVH_PrimitiveSet<Standard_ShortReal, 4>
+{
+protected:
+
+  using BVH_PrimitiveSet<Standard_ShortReal, 4>::Box;
+
+public:
+
+  //! Creates an empty primitive set for BVH clipping.
+  OpenGl_BVHClipPrimitiveSet();
+
+  //! Returns total number of structures.
+  virtual Standard_Integer Size() const;
+
+  //! Returns AABB of a structure.
+  virtual Graphic3d_BndBox4f Box (const Standard_Integer theIdx) const;
+
+  //! Calculates center of the AABB projection onto given axis.
+  virtual Standard_ShortReal Center (const Standard_Integer theIdx,
+                                     const Standard_Integer theAxis) const;
+
+  //! Swaps given AABBs.
+  virtual void Swap (const Standard_Integer theIdx1,
+                     const Standard_Integer theIdx2);
+
+  //! Replaces the set by the given array taking into account
+  //! if each structure is cullable or not.
+  void Assign (const OpenGl_ArrayOfStructure& theStructs);
+
+  //! Adds structure theStruct to the set.
+  void Add (const OpenGl_Structure* theStruct);
+
+  //! Removes the given OpenGl_Structure from the set.
+  void Remove (const OpenGl_Structure* theStruct);
+
+  //! Cleans the whole primitive set.
+  void Clear();
+
+  //! Returns the structure corresponding to the given id.
+  const OpenGl_Structure* GetStructureById (Standard_Integer theId);
+
+private:
+
+  NCollection_Sequence<const OpenGl_Structure*> myStructs;    //!< Sequence of structures
+
+};
+
+#endif // _OpenGl_BVHClipPrimitiveSet_HeaderFile
diff --git a/src/OpenGl/OpenGl_BVHTreeSelector.cxx b/src/OpenGl/OpenGl_BVHTreeSelector.cxx
new file mode 100644 (file)
index 0000000..75a60b7
--- /dev/null
@@ -0,0 +1,283 @@
+// Created on: 2013-12-25
+// Created by: Varvara POSKONINA
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <OpenGl_BVHTreeSelector.hxx>
+#include <OpenGl_BVHClipPrimitiveSet.hxx>
+
+#include <vector>
+#include <algorithm>
+
+// =======================================================================
+// function : DotProduct
+// purpose  : Calculates a dot product of 4-dimensional vectors in homogeneous coordinates
+// =======================================================================
+static Standard_ShortReal DotProduct (const OpenGl_Vec4& theA,
+                                      const OpenGl_Vec4& theB)
+{
+  return theA.x() * theB.x() + theA.y() * theB.y() + theA.z() * theB.z();
+}
+
+// =======================================================================
+// function : BinarySign
+// purpose  :
+// =======================================================================
+static OpenGl_Vec4 BinarySign (const OpenGl_Vec4& theVec)
+{
+  return OpenGl_Vec4 (theVec.x() > 0.0f ? 1.0f : 0.0f,
+                      theVec.y() > 0.0f ? 1.0f : 0.0f,
+                      theVec.z() > 0.0f ? 1.0f : 0.0f,
+                      theVec.w() > 0.0f ? 1.0f : 0.0f);
+}
+
+// =======================================================================
+// function : InversedBinarySign
+// purpose  :
+// =======================================================================
+static OpenGl_Vec4 InversedBinarySign (const OpenGl_Vec4& theVec)
+{
+  return OpenGl_Vec4 (theVec.x() > 0.0f ? 0.0f : 1.0f,
+                      theVec.y() > 0.0f ? 0.0f : 1.0f,
+                      theVec.z() > 0.0f ? 0.0f : 1.0f,
+                      theVec.w() > 0.0f ? 0.0f : 1.0f);
+}
+
+// =======================================================================
+// function : OpenGl_BVHTreeSelector
+// purpose  :
+// =======================================================================
+OpenGl_BVHTreeSelector::OpenGl_BVHTreeSelector()
+: myIsProjectionParallel (Standard_True),
+  myProjectionState      (0),
+  myModelViewState       (0)
+{
+  //
+}
+
+// =======================================================================
+// function : SetClipVolume
+// purpose  : Retrieves view volume's planes equations and its vertices from projection and modelview matrices.
+// =======================================================================
+void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theCamera)
+{
+  myIsProjectionParallel = theCamera->IsOrthographic();
+  const OpenGl_Mat4& aProjMat  = theCamera->ProjectionMatrixF();
+  const OpenGl_Mat4& aModelMat = theCamera->OrientationMatrixF();
+
+  Standard_ShortReal nLeft = 0.0f, nRight = 0.0f, nTop = 0.0f, nBottom = 0.0f;
+  Standard_ShortReal fLeft = 0.0f, fRight = 0.0f, fTop = 0.0f, fBottom = 0.0f;
+  Standard_ShortReal aNear = 0.0f, aFar   = 0.0f;
+  if (!myIsProjectionParallel)
+  {
+    // handle perspective projection
+    aNear   = aProjMat.GetValue (2, 3) / (- 1.0f + aProjMat.GetValue (2, 2));
+    aFar    = aProjMat.GetValue (2, 3) / (  1.0f + aProjMat.GetValue (2, 2));
+    // Near plane
+    nLeft   = aNear * (aProjMat.GetValue (0, 2) - 1.0f) / aProjMat.GetValue (0, 0);
+    nRight  = aNear * (aProjMat.GetValue (0, 2) + 1.0f) / aProjMat.GetValue (0, 0);
+    nTop    = aNear * (aProjMat.GetValue (1, 2) + 1.0f) / aProjMat.GetValue (1, 1);
+    nBottom = aNear * (aProjMat.GetValue (1, 2) - 1.0f) / aProjMat.GetValue (1, 1);
+    // Far plane
+    fLeft   = aFar  * (aProjMat.GetValue (0, 2) - 1.0f) / aProjMat.GetValue (0, 0);
+    fRight  = aFar  * (aProjMat.GetValue (0, 2) + 1.0f) / aProjMat.GetValue (0, 0);
+    fTop    = aFar  * (aProjMat.GetValue (1, 2) + 1.0f) / aProjMat.GetValue (1, 1);
+    fBottom = aFar  * (aProjMat.GetValue (1, 2) - 1.0f) / aProjMat.GetValue (1, 1);
+  }
+  else
+  {
+    // handle orthographic projection
+    aNear   = (1.0f / aProjMat.GetValue (2, 2)) * (aProjMat.GetValue (2, 3) + 1.0f);
+    aFar    = (1.0f / aProjMat.GetValue (2, 2)) * (aProjMat.GetValue (2, 3) - 1.0f);
+    // Near plane
+    nLeft   = ( 1.0f + aProjMat.GetValue (0, 3)) / (-aProjMat.GetValue (0, 0));
+    fLeft   = nLeft;
+    nRight  = ( 1.0f - aProjMat.GetValue (0, 3)) /   aProjMat.GetValue (0, 0);
+    fRight  = nRight;
+    nTop    = ( 1.0f - aProjMat.GetValue (1, 3)) /   aProjMat.GetValue (1, 1);
+    fTop    = nTop;
+    nBottom = (-1.0f - aProjMat.GetValue (1, 3)) /   aProjMat.GetValue (1, 1);
+    fBottom = nBottom;
+  }
+
+  OpenGl_Vec4 aLeftTopNear     (nLeft,  nTop,    -aNear, 1.0f), aRightBottomFar (fRight, fBottom, -aFar, 1.0f);
+  OpenGl_Vec4 aLeftBottomNear  (nLeft,  nBottom, -aNear, 1.0f), aRightTopFar    (fRight, fTop,    -aFar, 1.0f);
+  OpenGl_Vec4 aRightBottomNear (nRight, nBottom, -aNear, 1.0f), aLeftTopFar     (fLeft,  fTop,    -aFar, 1.0f);
+  OpenGl_Vec4 aRightTopNear    (nRight, nTop,    -aNear, 1.0f), aLeftBottomFar  (fLeft,  fBottom, -aFar, 1.0f);
+
+  const OpenGl_Mat4 aViewProj = aModelMat * aProjMat;
+  OpenGl_Mat4 anInvModelView;
+  aModelMat.Inverted(anInvModelView);
+
+  myClipVerts[ClipVert_LeftTopNear]     = anInvModelView * aLeftTopNear;
+  myClipVerts[ClipVert_RightBottomFar]  = anInvModelView * aRightBottomFar;
+  myClipVerts[ClipVert_LeftBottomNear]  = anInvModelView * aLeftBottomNear;
+  myClipVerts[ClipVert_RightTopFar]     = anInvModelView * aRightTopFar;
+  myClipVerts[ClipVert_RightBottomNear] = anInvModelView * aRightBottomNear;
+  myClipVerts[ClipVert_LeftTopFar]      = anInvModelView * aLeftTopFar;
+  myClipVerts[ClipVert_RightTopNear]    = anInvModelView * aRightTopNear;
+  myClipVerts[ClipVert_LeftBottomFar]   = anInvModelView * aLeftBottomFar;
+
+  // UNNORMALIZED!
+  myClipPlanes[Plane_Left]   = aViewProj.GetRow (3) + aViewProj.GetRow (0);
+  myClipPlanes[Plane_Right]  = aViewProj.GetRow (3) - aViewProj.GetRow (0);
+  myClipPlanes[Plane_Top]    = aViewProj.GetRow (3) - aViewProj.GetRow (1);
+  myClipPlanes[Plane_Bottom] = aViewProj.GetRow (3) + aViewProj.GetRow (1);
+  myClipPlanes[Plane_Near]   = aViewProj.GetRow (3) + aViewProj.GetRow (2);
+  myClipPlanes[Plane_Far]    = aViewProj.GetRow (3) - aViewProj.GetRow (2);
+
+  gp_Pnt aPtCenter = theCamera->Center();
+  OpenGl_Vec4 aCenter (static_cast<Standard_ShortReal> (aPtCenter.X()),
+                       static_cast<Standard_ShortReal> (aPtCenter.Y()),
+                       static_cast<Standard_ShortReal> (aPtCenter.Z()),
+                       1.0f);
+
+  for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB; ++aPlaneIter)
+  {
+    OpenGl_Vec4 anEq = myClipPlanes[aPlaneIter];
+    if (SignedPlanePointDistance (anEq, aCenter) > 0)
+    {
+      anEq *= -1.0f;
+      myClipPlanes[aPlaneIter] = anEq;
+    }
+  }
+}
+
+// =======================================================================
+// function : SignedPlanePointDistance
+// purpose  :
+// =======================================================================
+Standard_ShortReal OpenGl_BVHTreeSelector::SignedPlanePointDistance (const OpenGl_Vec4& theNormal,
+                                                                     const OpenGl_Vec4& thePnt)
+{
+  const Standard_ShortReal aNormLength = std::sqrt (theNormal.x() * theNormal.x()
+                                                  + theNormal.y() * theNormal.y()
+                                                  + theNormal.z() * theNormal.z());
+  const Standard_ShortReal anInvNormLength = 1.0f / aNormLength;
+  const Standard_ShortReal aD  = theNormal.w() * anInvNormLength;
+  const Standard_ShortReal anA = theNormal.x() * anInvNormLength;
+  const Standard_ShortReal aB  = theNormal.y() * anInvNormLength;
+  const Standard_ShortReal aC  = theNormal.z() * anInvNormLength;
+  return aD + (anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z());
+}
+
+// =======================================================================
+// function : CacheClipPtsProjections
+// purpose  : Caches view volume's vertices projections along its normals and AABBs dimensions
+//            Must be called at the beginning of each BVH tree traverse loop
+// =======================================================================
+void OpenGl_BVHTreeSelector::CacheClipPtsProjections()
+{
+  Standard_ShortReal aProjectedVerts[ClipVerticesNB];
+  for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB; ++aPlaneIter)
+  {
+    const OpenGl_Vec4 aPlane = myClipPlanes[aPlaneIter];
+    for (Standard_Integer aCornerIter = 0; aCornerIter < ClipVerticesNB; ++aCornerIter)
+    {
+      Standard_ShortReal aProjection = DotProduct (aPlane, myClipVerts[aCornerIter]);
+      aProjectedVerts[aCornerIter] = aProjection;
+    }
+    myMaxClipProjectionPts[aPlaneIter] = *std::max_element (aProjectedVerts, aProjectedVerts + ClipVerticesNB);
+    myMinClipProjectionPts[aPlaneIter] = *std::min_element (aProjectedVerts, aProjectedVerts + ClipVerticesNB);
+  }
+
+  OpenGl_Vec4 aDimensions[3] =
+  {
+    OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 1.0f),
+    OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 1.0f),
+    OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 1.0f)
+  };
+
+  for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
+  {
+    for (Standard_Integer aCornerIter = 0; aCornerIter < ClipVerticesNB; ++aCornerIter)
+    {
+      Standard_ShortReal aProjection = DotProduct (aDimensions[aDim], myClipVerts[aCornerIter]);
+      aProjectedVerts[aCornerIter] = aProjection;
+    }
+    myMaxOrthoProjectionPts[aDim] = *std::max_element (aProjectedVerts, aProjectedVerts + ClipVerticesNB);
+    myMinOrthoProjectionPts[aDim] = *std::min_element (aProjectedVerts, aProjectedVerts + ClipVerticesNB);
+  }
+}
+
+// =======================================================================
+// function : Intersect
+// purpose  : Detects if AABB overlaps view volume using separating axis theorem (SAT)
+// =======================================================================
+Standard_Boolean OpenGl_BVHTreeSelector::Intersect (const OpenGl_Vec4& theMinPt,
+                                                    const OpenGl_Vec4& theMaxPt) const
+{
+  //     E1
+  //    |_ E0
+  //   /
+  //    E2
+  const OpenGl_Vec4  aShiftedBoxMax  = theMaxPt - theMinPt;
+  Standard_ShortReal aBoxProjMax     = 0.0f, aBoxProjMin     = 0.0f;
+  Standard_ShortReal aFrustumProjMax = 0.0f, aFrustumProjMin = 0.0f;
+
+  // E0 test
+  aBoxProjMax = aShiftedBoxMax.x();
+  aFrustumProjMax = myMaxOrthoProjectionPts[0] - DotProduct (OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 1.0f), theMinPt);
+  aFrustumProjMin = myMinOrthoProjectionPts[0] - DotProduct (OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 1.0f), theMinPt);
+  if (aBoxProjMin > aFrustumProjMax
+   || aBoxProjMax < aFrustumProjMin)
+  {
+    return Standard_False;
+  }
+
+  // E1 test
+  aBoxProjMax = aShiftedBoxMax.y();
+  aFrustumProjMax = myMaxOrthoProjectionPts[1] - DotProduct (OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 1.0f), theMinPt);
+  aFrustumProjMin = myMinOrthoProjectionPts[1] - DotProduct (OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 1.0f), theMinPt);
+  if (aBoxProjMin > aFrustumProjMax
+   || aBoxProjMax < aFrustumProjMin)
+  {
+    return Standard_False;
+  }
+
+  // E2 test
+  aBoxProjMax = aShiftedBoxMax.z();
+  aFrustumProjMax = myMaxOrthoProjectionPts[2] - DotProduct (OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 1.0f), theMinPt);
+  aFrustumProjMin = myMinOrthoProjectionPts[2] - DotProduct (OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 1.0f), theMinPt);
+  if (aBoxProjMin > aFrustumProjMax
+   || aBoxProjMax < aFrustumProjMin)
+  {
+    return Standard_False;
+  }
+
+  const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1;
+  for (Standard_Integer aPlaneIter = 0; aPlaneIter < 5; aPlaneIter += anIncFactor)
+  {
+    OpenGl_Vec4 aPlane = myClipPlanes[aPlaneIter];
+    OpenGl_Vec4 aPt1 (0.0f), aPt2 (0.0f);
+    aPt1 = BinarySign (aPlane) * aShiftedBoxMax;
+    aBoxProjMax = DotProduct (aPlane, aPt1);
+    aFrustumProjMax = myMaxClipProjectionPts[aPlaneIter] - DotProduct (aPlane, theMinPt);
+    aFrustumProjMin = myMinClipProjectionPts[aPlaneIter] - DotProduct (aPlane, theMinPt);
+    if (aFrustumProjMin < aBoxProjMax
+     && aBoxProjMax < aFrustumProjMax)
+    {
+      continue;
+    }
+
+    aPt2 = InversedBinarySign (aPlane) * aShiftedBoxMax;
+    aBoxProjMin = DotProduct (aPlane, aPt2);
+    if (aBoxProjMin > aFrustumProjMax
+     || aBoxProjMax < aFrustumProjMin)
+    {
+      return Standard_False;
+    }
+  }
+
+  return Standard_True;
+}
diff --git a/src/OpenGl/OpenGl_BVHTreeSelector.hxx b/src/OpenGl/OpenGl_BVHTreeSelector.hxx
new file mode 100644 (file)
index 0000000..96183ce
--- /dev/null
@@ -0,0 +1,117 @@
+// Created on: 2013-12-25
+// Created by: Varvara POSKONINA
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _OpenGl_BVHTreeSelector_HeaderFile
+#define _OpenGl_BVHTreeSelector_HeaderFile
+
+#include <Graphic3d_Camera.hxx>
+
+#include <OpenGl_Vec.hxx>
+
+//! BVHTreeSelector class provides a possibility to store parameters of view volume,
+//! such as its vertices and equations, and contains methods detecting if given AABB overlaps
+//! view volume.
+class OpenGl_BVHTreeSelector
+{
+public:
+
+  //! Creates an empty selector object with parallel projection type by default.
+  Standard_EXPORT OpenGl_BVHTreeSelector();
+
+  //! Retrieves view volume's planes equations and its vertices from projection and modelview matrices.
+  Standard_EXPORT void SetViewVolume (const Handle(Graphic3d_Camera)& theCamera);
+
+  //! Detects if AABB overlaps view volume using separating axis theorem (SAT).
+  //! @param theMinPt [in] maximum point of AABB.
+  //! @param theMaxPt [in] minimum point of AABB.
+  //! @return Standard_True, if AABB is in viewing area, Standard_False otherwise.
+  Standard_EXPORT Standard_Boolean Intersect (const OpenGl_Vec4& theMinPt,
+                                              const OpenGl_Vec4& theMaxPt) const;
+
+  //! Caches view volume's vertices projections along its normals and AABBs dimensions.
+  //! Must be called at the beginning of each BVH tree traverse loop.
+  Standard_EXPORT void CacheClipPtsProjections();
+
+  //! Returnes the state of projection matrix previously saved in selector.
+  Standard_EXPORT const Standard_Size ProjectionState() { return myProjectionState; }
+
+  //! Returnes the link for changing the state of projection matrix.
+  Standard_EXPORT Standard_Size& ChangeProjectionState() { return myProjectionState; }
+
+  //! Returnes the state of model view matrix previously saved in selector.
+  Standard_EXPORT const Standard_Size ModelViewState() { return myModelViewState; }
+
+  //! Returnes the link for changing the state of model view matrix.
+  Standard_EXPORT Standard_Size& ChangeModelViewState() { return myModelViewState; }
+
+protected:
+
+  //! Calculates signed distance from plane to point.
+  //! @param theNormal [in] the plane's normal.
+  //! @param thePnt    [in]
+  Standard_EXPORT Standard_ShortReal SignedPlanePointDistance (const OpenGl_Vec4& theNormal,
+                                                               const OpenGl_Vec4& thePnt);
+
+protected:
+
+  //! Enumerates planes of view volume.
+  enum
+  {
+    Plane_Top,
+    Plane_Bottom,
+    Plane_Left,
+    Plane_Right,
+    Plane_Near,
+    Plane_Far,
+    PlanesNB
+  };
+
+  //! Enumerates vertices of view volume.
+  enum
+  {
+    ClipVert_LeftTopNear,
+    ClipVert_LeftBottomNear,
+    ClipVert_RightTopNear,
+    ClipVert_RightBottomNear,
+    ClipVert_LeftTopFar,
+    ClipVert_LeftBottomFar,
+    ClipVert_RightTopFar,
+    ClipVert_RightBottomFar,
+    ClipVerticesNB
+  };
+
+protected:
+
+  OpenGl_Vec4        myClipPlanes[PlanesNB];           //!< Plane equations
+  OpenGl_Vec4        myClipVerts[ClipVerticesNB];      //!< Vertices
+
+  // for caching clip points projections onto viewing area normals once per traverse
+  // ORDER: TOP, BOTTOM, LEFT, RIGHT, NEAR, FAR
+  Standard_ShortReal myMaxClipProjectionPts[PlanesNB]; //!< Max view volume's vertices projections onto its normals
+  Standard_ShortReal myMinClipProjectionPts[PlanesNB]; //!< Min view volume's vertices projections onto its normals
+
+  // for caching clip points projections onto AABB normals once per traverse
+  // ORDER: E0, E1, E2
+  Standard_ShortReal myMaxOrthoProjectionPts[3];       //!< Max view volume's vertices projections onto normalized dimensions of AABB
+  Standard_ShortReal myMinOrthoProjectionPts[3];       //!< Min view volume's vertices projections onto normalized dimensions of AABB
+
+  Standard_Boolean   myIsProjectionParallel;
+
+  Standard_Size myProjectionState; //! Caches the state of projection matrix to prevent unnecessary updates.
+  Standard_Size myModelViewState;  //! Caches the state of model view matrix to prevent unnecessary updates.
+
+};
+
+#endif // _OpenGl_BVHTreeSelector_HeaderFile
index a82d358..d1828ec 100644 (file)
@@ -279,6 +279,11 @@ public:
                                           const Standard_Integer theLayerId,
                                           const Graphic3d_ZLayerSettings& theSettings);
 
+  //! Changes priority of a structure within its Z layer for the specified view.
+  Standard_EXPORT void ChangePriority (const Graphic3d_CStructure& theCStructure,
+                                       const Graphic3d_CView& theCView,
+                                       const Standard_Integer theNewPriority);
+
 public:
 
   //! @return the visualization options
@@ -315,6 +320,10 @@ public:
   //! Could return NULL-handle if no window created by this driver.
   Standard_EXPORT const Handle(OpenGl_Context)& GetSharedContext() const;
 
+  //! Marks BVH tree for given priority list as dirty and
+  //! marks primitive set for rebuild.
+  Standard_EXPORT void InvalidateBVHData (Graphic3d_CView& theCView, const Standard_Integer theLayerId);
+
 public:
 
   DEFINE_STANDARD_RTTI(OpenGl_GraphicDriver)
index f12cc7a..5e6a015 100644 (file)
@@ -127,3 +127,21 @@ void OpenGl_GraphicDriver::UnsetZLayer (const Standard_Integer theLayerId)
       aStruct->SetZLayer (0);
   }
 }
+
+//=======================================================================
+//function : ChangePriority
+//purpose  :
+//=======================================================================
+void OpenGl_GraphicDriver::ChangePriority (const Graphic3d_CStructure& theCStructure,
+                                           const Graphic3d_CView& theCView,
+                                           const Standard_Integer theNewPriority)
+{
+  const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
+
+  if (!myMapOfStructure.IsBound (theCStructure.Id) || !aCView)
+    return;
+
+  OpenGl_Structure* aStructure = myMapOfStructure.Find (theCStructure.Id);
+
+  aCView->View->ChangePriority (aStructure, theNewPriority);
+}
index 9eabd7f..224813b 100644 (file)
@@ -459,6 +459,19 @@ void OpenGl_GraphicDriver::Transparency (const Graphic3d_CView& ACView, const St
     aCView->WS->UseTransparency(AFlag);
 }
 
+// =======================================================================
+// function : InvalidateBVHData
+// purpose  :
+// =======================================================================
+void OpenGl_GraphicDriver::InvalidateBVHData (Graphic3d_CView& theCView, const Standard_Integer theLayerId)
+{
+  OpenGl_CView *aCView = (OpenGl_CView *)theCView.ptrView;
+  if(aCView)
+  {
+    aCView->View->InvalidateBVHData (theLayerId);
+  }
+}
+
 Standard_Boolean OpenGl_GraphicDriver::View (Graphic3d_CView& theCView)
 {
   if (myMapOfView.IsBound (theCView.ViewId)
index 1392fe4..2d90858 100644 (file)
@@ -156,14 +156,15 @@ void OpenGl_LayerList::RemoveLayer (const Standard_Integer theLayerId)
 
 void OpenGl_LayerList::AddStructure (const OpenGl_Structure *theStructure,
                                      const Standard_Integer  theLayerId,
-                                     const Standard_Integer  thePriority)
+                                     const Standard_Integer  thePriority,
+                                     Standard_Boolean isForChangePriority)
 {
   // add structure to associated layer,
   // if layer doesn't exists, display structure in default layer
   OpenGl_PriorityList& aList = !HasLayer (theLayerId) ? defaultLayer ().PriorityList() :
     myLayers.ChangeValue (myLayerIds.Find (theLayerId)).PriorityList();
 
-  aList.Add (theStructure, thePriority);
+  aList.Add (theStructure, thePriority, isForChangePriority);
   myNbStructures++;
 
   // Note: In ray-tracing mode we don't modify modification
@@ -223,6 +224,20 @@ void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure *theStructure,
 }
 
 //=======================================================================
+//function : InvalidateBVHData
+//purpose  :
+//=======================================================================
+void OpenGl_LayerList::InvalidateBVHData (const Standard_Integer theLayerId)
+{
+  Standard_Integer aSeqPos = !HasLayer (theLayerId) ?
+    1 : myLayerIds.Find (theLayerId);
+
+  OpenGl_PriorityList& aList = myLayers.ChangeValue (aSeqPos).PriorityList();
+
+  aList.InvalidateBVHData();
+}
+
+//=======================================================================
 //function : ChangeLayer
 //purpose  :
 //=======================================================================
@@ -239,10 +254,10 @@ void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure *theStructure,
 
   // take priority and remove structure from list found by <theOldLayerId>
   // if the structure is not found there, scan through all other layers
-  if ((aPriority = aList.Remove (theStructure)) >= 0)
+  if ((aPriority = aList.Remove (theStructure, Standard_True)) >= 0)
   {
     myNbStructures--;
-    AddStructure (theStructure, theNewLayerId, aPriority);
+    AddStructure (theStructure, theNewLayerId, aPriority, Standard_True);
   }
   else
   {
@@ -255,10 +270,47 @@ void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure *theStructure,
         continue;
   
       // try to remove structure and get priority value from this layer
-      if ((aPriority = aList.Remove (theStructure)) >= 0)
+      if ((aPriority = aList.Remove (theStructure, Standard_True)) >= 0)
+      {
+        myNbStructures--;
+        AddStructure (theStructure, theNewLayerId, aPriority, Standard_True);
+        break;
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : ChangePriority
+//purpose  :
+//=======================================================================
+void OpenGl_LayerList::ChangePriority (const OpenGl_Structure *theStructure,
+                                       const Standard_Integer theLayerId,
+                                       const Standard_Integer theNewPriority)
+{
+  Standard_Integer aSeqPos = !HasLayer (theLayerId) ?
+    1 : myLayerIds.Find (theLayerId);
+
+  OpenGl_PriorityList& aList = myLayers.ChangeValue (aSeqPos).PriorityList();
+
+  if (aList.Remove (theStructure, Standard_True) >= 0)
+  {
+    myNbStructures--;
+    AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
+  }
+  else
+  {
+    Standard_Integer aSeqId = 1;
+    OpenGl_SequenceOfLayers::Iterator anIts;
+    for (anIts.Init (myLayers); anIts.More (); anIts.Next (), aSeqId++)
+    {
+      if (aSeqPos == aSeqId)
+        continue;
+
+      if (aList.Remove (theStructure, Standard_True) >= 0)
       {
         myNbStructures--;
-        AddStructure (theStructure, theNewLayerId, aPriority);
+        AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
         break;
       }
     }
index 210ebe2..c979feb 100644 (file)
@@ -60,7 +60,8 @@ class OpenGl_LayerList
   //! to default bottom-level layer.
   void AddStructure (const OpenGl_Structure *theStructure,
                      const Standard_Integer  theLayerId,
-                     const Standard_Integer  thePriority);
+                     const Standard_Integer  thePriority,
+                     Standard_Boolean isForChangePriority = Standard_False);
   
   //! Remove structure from structure list and return its previous priority
   void RemoveStructure (const OpenGl_Structure *theStructure,
@@ -73,6 +74,11 @@ class OpenGl_LayerList
                     const Standard_Integer  theOldLayerId,
                     const Standard_Integer  theNewLayerId);
 
+  //! Changes structure priority within its ZLayer
+  void ChangePriority (const OpenGl_Structure *theStructure,
+                       const Standard_Integer  theLayerId,
+                       const Standard_Integer theNewPriority);
+
   //! Returns reference to the layer with given ID.
   OpenGl_Layer& Layer (const Standard_Integer theLayerId);
 
@@ -85,6 +91,10 @@ class OpenGl_LayerList
   //! Returns the set of OpenGL Z-layers.
   const OpenGl_SequenceOfLayers& Layers() const { return myLayers; }
 
+  //! Marks BVH tree for given priority list as dirty and
+  //! marks primitive set for rebuild.
+  void InvalidateBVHData (const Standard_Integer theLayerId);
+
   //! Returns structure modification state (for ray-tracing).
   Standard_Size ModificationState() const { return myModificationState; }
 
index f721715..e6b8cc4 100644 (file)
 
 #include <OpenGl_PriorityList.hxx>
 
+#include <OpenGl_BVHTreeSelector.hxx>
 #include <OpenGl_Structure.hxx>
+#include <OpenGl_View.hxx>
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : OpenGl_PriorityList
+// purpose  :
+// =======================================================================
+OpenGl_PriorityList::OpenGl_PriorityList (const Standard_Integer theNbPriorities)
+: myArray (0, theNbPriorities - 1),
+  myNbStructures (0),
+  myBVHIsLeftChildQueuedFirst (Standard_True),
+  myIsBVHPrimitivesNeedsReset (Standard_False)
+{
+  //
+}
 
-void OpenGl_PriorityList::Add (const OpenGl_Structure *AStructure,const Standard_Integer APriority)
+// =======================================================================
+// function : ~OpenGl_PriorityList
+// purpose  :
+// =======================================================================
+OpenGl_PriorityList::~OpenGl_PriorityList()
 {
-  Standard_Integer anIndex = APriority;
-  if (anIndex < 0) anIndex = 0;
-  else if (anIndex >= myArray.Length()) anIndex = myArray.Length()-1;
-  myArray(anIndex).Append(AStructure);
-  myNbStructures++;
+  //
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : Add
+// purpose  :
+// =======================================================================
+void OpenGl_PriorityList::Add (const OpenGl_Structure* theStructure,
+                               const Standard_Integer  thePriority,
+                               Standard_Boolean isForChangePriority)
+{
+  const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1);
 
-Standard_Integer OpenGl_PriorityList::Remove (const OpenGl_Structure *AStructure)
+  myArray (anIndex).Append (theStructure);
+  if (theStructure->IsAlwaysRendered())
+  {
+    theStructure->MarkAsNotCulled();
+  }
+  else if (!isForChangePriority)
+  {
+    myBVHPrimitives.Add (theStructure);
+  }
+  ++myNbStructures;
+}
+
+// =======================================================================
+// function : Remove
+// purpose  :
+// =======================================================================
+Standard_Integer OpenGl_PriorityList::Remove (const OpenGl_Structure* theStructure,
+                                              Standard_Boolean isForChangePriority)
 {
-  const Standard_Integer aNbPr = myArray.Length();
-  Standard_Integer i = 0;
-  OpenGl_SequenceOfStructure::Iterator its;
-  for (; i < aNbPr; i++)
+  const Standard_Integer aNbPriorities = myArray.Length();
+  OpenGl_SequenceOfStructure::Iterator aStructIter;
+  for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
   {
-    OpenGl_SequenceOfStructure &aSeq = myArray(i);
-    for (its.Init(aSeq); its.More(); its.Next())
+    OpenGl_SequenceOfStructure& aSeq = myArray (aPriorityIter);
+    for (aStructIter.Init (aSeq); aStructIter.More(); aStructIter.Next())
     {
-      if (its.Value() == AStructure)
+      if (aStructIter.Value() == theStructure)
       {
-        aSeq.Remove(its);
-        myNbStructures--;
-        return i;
+        aSeq.Remove (aStructIter);
+        if (!theStructure->IsAlwaysRendered()
+            && !isForChangePriority)
+        {
+          myBVHPrimitives.Remove (theStructure);
+        }
+        --myNbStructures;
+        return aPriorityIter;
       }
     }
   }
@@ -52,50 +94,177 @@ Standard_Integer OpenGl_PriorityList::Remove (const OpenGl_Structure *AStructure
   return -1;
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : InvalidateBVHData
+// purpose  :
+// =======================================================================
+void OpenGl_PriorityList::InvalidateBVHData()
+{
+  myIsBVHPrimitivesNeedsReset = Standard_True;
+}
 
-void OpenGl_PriorityList::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
+// =======================================================================
+// function : Render
+// purpose  :
+// =======================================================================
+void OpenGl_PriorityList::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
 {
-  const Standard_Integer aNbPr = myArray.Length();
-  Standard_Integer i = 0;
-  OpenGl_SequenceOfStructure::Iterator its;
-  for (; i < aNbPr; i++)
+  theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace);
+}
+
+// =======================================================================
+// function : renderAll
+// purpose  :
+// =======================================================================
+void OpenGl_PriorityList::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const
+{
+  const Standard_Integer aNbPriorities = myArray.Length();
+  OpenGl_SequenceOfStructure::Iterator aStructIter;
+  for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
   {
-    for (its.Init(myArray(i)); its.More(); its.Next())
-      its.Value()->Render(AWorkspace);
+    for (aStructIter.Init (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
+    {
+      aStructIter.Value()->Render (theWorkspace);
+    }
   }
 }
 
-//=======================================================================
-//function : Append
-//purpose  : 
-//=======================================================================
+// =======================================================================
+// function : renderTraverse
+// purpose  :
+// =======================================================================
+void OpenGl_PriorityList::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const
+{
+  if (myIsBVHPrimitivesNeedsReset)
+  {
+    myBVHPrimitives.Assign (myArray);
+    myIsBVHPrimitivesNeedsReset = Standard_False;
+  }
+
+  OpenGl_BVHTreeSelector& aSelector = theWorkspace->ActiveView()->BVHTreeSelector();
+  traverse (aSelector);
+
+  const Standard_Integer aNbPriorities = myArray.Length();
+  OpenGl_SequenceOfStructure::Iterator aStructIter;
+  for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
+  {
+    for (aStructIter.Init (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
+    {
+      if (!aStructIter.Value()->IsCulled())
+      {
+        aStructIter.Value()->Render (theWorkspace);
+        aStructIter.Value()->ResetCullingStatus();
+      }
+    }
+  }
+}
 
+// =======================================================================
+// function : traverse
+// purpose  :
+// =======================================================================
+void OpenGl_PriorityList::traverse (OpenGl_BVHTreeSelector& theSelector) const
+{
+  // handle a case when all objects are infinite
+  if (myBVHPrimitives.Size() == 0)
+    return;
+
+  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVHTree = myBVHPrimitives.BVH();
+
+  Standard_Integer aNode = 0; // a root node
+  theSelector.CacheClipPtsProjections();
+  if (!theSelector.Intersect (aBVHTree->MinPoint (0),
+                              aBVHTree->MaxPoint (0)))
+  {
+    return;
+  }
+
+  Standard_Integer aStack[32];
+  Standard_Integer aHead = -1;
+  for (;;)
+  {
+    if (!aBVHTree->IsOuter (aNode))
+    {
+      const Standard_Integer aLeftChildIdx  = aBVHTree->LeftChild  (aNode);
+      const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
+      const Standard_Boolean isLeftChildIn  = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx),
+                                                                     aBVHTree->MaxPoint (aLeftChildIdx));
+      const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx),
+                                                                     aBVHTree->MaxPoint (aRightChildIdx));
+      if (isLeftChildIn
+       && isRightChildIn)
+      {
+        aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx;
+        ++aHead;
+        aStack[aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx;
+        myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst;
+      }
+      else if (isLeftChildIn
+            || isRightChildIn)
+      {
+        aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
+      }
+      else
+      {
+        if (aHead < 0)
+        {
+          return;
+        }
+
+        aNode = aStack[aHead];
+        --aHead;
+      }
+    }
+    else
+    {
+      if (theSelector.Intersect (aBVHTree->MinPoint (aNode),
+                                 aBVHTree->MaxPoint (aNode)))
+      {
+        Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode);
+        myBVHPrimitives.GetStructureById (aIdx)->MarkAsNotCulled();
+        if (aHead < 0)
+        {
+          return;
+        }
+
+        aNode = aStack[aHead];
+        --aHead;
+      }
+    }
+  }
+}
+
+// =======================================================================
+// function : Append
+// purpose  :
+// =======================================================================
 Standard_Boolean OpenGl_PriorityList::Append (const OpenGl_PriorityList& theOther)
 {
   // the source priority list shouldn't have more priorities
   const Standard_Integer aNbPriorities = theOther.NbPriorities ();
-  if (aNbPriorities > NbPriorities ())
+  if (aNbPriorities > NbPriorities())
+  {
     return Standard_False;
+  }
 
   // add all structures to destination priority list
-  Standard_Integer aIdx = 0;
-  OpenGl_SequenceOfStructure::Iterator anIts;
-  for (; aIdx < aNbPriorities; aIdx++)
+  OpenGl_SequenceOfStructure::Iterator aStructIter;
+  for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
   {
-    const OpenGl_SequenceOfStructure& aSeq = theOther.myArray (aIdx);
-    for (anIts.Init (aSeq); anIts.More (); anIts.Next ())
-      Add (anIts.Value (), aIdx);
+    const OpenGl_SequenceOfStructure& aSeq = theOther.myArray (aPriorityIter);
+    for (aStructIter.Init (aSeq); aStructIter.More(); aStructIter.Next())
+    {
+      Add (aStructIter.Value(), aPriorityIter);
+    }
   }
 
   return Standard_True;
 }
 
-//=======================================================================
-//function : NbPriorities
-//purpose  : 
-//=======================================================================
-
+// =======================================================================
+// function : NbPriorities
+// purpose  :
+// =======================================================================
 Standard_Integer OpenGl_PriorityList::NbPriorities() const
 {
   return myArray.Length();
index cebdb1c..dab5631 100644 (file)
@@ -22,6 +22,8 @@
 #include <InterfaceGraphic_telem.hxx>
 
 #include <Handle_OpenGl_Workspace.hxx>
+#include <OpenGl_BVHClipPrimitiveSet.hxx>
+#include <OpenGl_BVHTreeSelector.hxx>
 
 class OpenGl_Structure;
 
@@ -30,21 +32,27 @@ typedef NCollection_Array1<OpenGl_SequenceOfStructure> OpenGl_ArrayOfStructure;
 
 class OpenGl_PriorityList
 {
- public:
+public:
 
-  OpenGl_PriorityList (const Standard_Integer ANbPriorities = 11) : myArray(0,(ANbPriorities-1)), myNbStructures(0) {}
+  // Empty constructor.
+  OpenGl_PriorityList (const Standard_Integer theNbPriorities = 11);
 
-  virtual ~OpenGl_PriorityList () {}
+  //! Destructor.
+  virtual ~OpenGl_PriorityList();
 
-  void Add (const OpenGl_Structure *AStructure, const Standard_Integer APriority);
+  void Add (const OpenGl_Structure* theStructure,
+            const Standard_Integer  thePriority,
+            Standard_Boolean isForChangePriority = Standard_False);
 
-  //! Remove structure and returns its priority, if the structure is not found,
-  //! method returns negative value
-  Standard_Integer Remove (const OpenGl_Structure *AStructure);
+  //! Remove structure and returns its priority, if the structure is not found, method returns negative value
+  Standard_Integer Remove (const OpenGl_Structure* theStructure,
+                           Standard_Boolean isForChangePriority = Standard_False);
 
-  Standard_Integer NbStructures () const { return myNbStructures; }
+  //! @return the number of structures
+  Standard_Integer NbStructures() const { return myNbStructures; }
 
-  void Render (const Handle(OpenGl_Workspace) &AWorkspace) const;
+  // Render all structures.
+  void Render (const Handle(OpenGl_Workspace)& theWorkspace) const;
 
   //! Returns the number of available priority levels
   Standard_Integer NbPriorities() const;
@@ -56,13 +64,33 @@ class OpenGl_PriorityList
   //! Returns array of OpenGL structures.
   const OpenGl_ArrayOfStructure& ArrayOfStructures() const { return myArray; }
 
- protected:
+  //! Marks BVH tree for given priority list as dirty and
+  //! marks primitive set for rebuild.
+  void InvalidateBVHData();
 
-  OpenGl_ArrayOfStructure myArray;
-  Standard_Integer        myNbStructures;
+protected:
+
+  //! Traverses through BVH tree to determine which structures are in view volume.
+  void traverse (OpenGl_BVHTreeSelector& theSelector) const;
+
+  //! Iterates through the hierarchical list of existing structures and renders them all.
+  void renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const;
+
+  //! Iterates through the hierarchical list of existing structures and renders only overlapping ones.
+  void renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const;
+
+protected:
+
+  OpenGl_ArrayOfStructure            myArray;
+  Standard_Integer                   myNbStructures;
+  mutable OpenGl_BVHClipPrimitiveSet myBVHPrimitives;             //<! Set of OpenGl_Structures for building BVH tree
+  mutable Standard_Boolean           myBVHIsLeftChildQueuedFirst; //<! Is needed for implementation of stochastic order of BVH traverse
+  mutable Standard_Boolean           myIsBVHPrimitivesNeedsReset; //<! Defines if the primitive set for BVH is outdated
+
+public:
 
- public:
   DEFINE_STANDARD_ALLOC
+
 };
 
-#endif //_OpenGl_PriorityList_Header
+#endif // _OpenGl_PriorityList_Header
index 60e69de..627b500 100755 (executable)
@@ -18,9 +18,9 @@
 #ifdef HAVE_TBB
   // On Windows, function TryEnterCriticalSection has appeared in Windows NT
   // and is surrounded by #ifdef in MS VC++ 7.1 headers.
-  // Thus to use it we need to define appropriate macro saying that we wil
+  // Thus to use it we need to define appropriate macro saying that we will
   // run on Windows NT 4.0 at least
-  #if ((defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN32_WINNT))
+  #if defined(_WIN32) && !defined(_WIN32_WINNT)
     #define _WIN32_WINNT 0x0501
   #endif
 
@@ -29,6 +29,9 @@
 
 #include <OpenGl_SceneGeometry.hxx>
 
+#include <OpenGl_PrimitiveArray.hxx>
+#include <OpenGl_Structure.hxx>
+
 //! Use this macro to output BVH profiling info
 //#define BVH_PRINT_INFO
 
index f3af8b1..dea8471 100755 (executable)
 #include <BVH_Geometry.hxx>
 #include <BVH_Triangulation.hxx>
 #include <NCollection_StdAllocator.hxx>
-#include <OpenGl_PrimitiveArray.hxx>
-#include <OpenGl_Structure.hxx>
+
+struct OpenGl_ElementNode;
+class  OpenGl_Group;
+class  OpenGl_Structure;
+class  OpenGl_PrimitiveArray;
 
 namespace OpenGl_Raytrace
 {
index b0d8200..2cb3ddc 100644 (file)
@@ -37,14 +37,15 @@ class OpenGl_BndBoxPrs : public OpenGl_Element
 public:
 
   //! Main constructor
-  OpenGl_BndBoxPrs (const CALL_DEF_BOUNDBOX& theBndBox)
-  {
-    const float Xm = theBndBox.Pmin.x;
-    const float Ym = theBndBox.Pmin.y;
-    const float Zm = theBndBox.Pmin.z;
-    const float XM = theBndBox.Pmax.x;
-    const float YM = theBndBox.Pmax.y;
-    const float ZM = theBndBox.Pmax.z;
+  OpenGl_BndBoxPrs (const Graphic3d_BndBox4f& theBndBox)
+  {
+    const float Xm = theBndBox.CornerMin().x();
+    const float Ym = theBndBox.CornerMin().y();
+    const float Zm = theBndBox.CornerMin().z();
+    const float XM = theBndBox.CornerMax().x();
+    const float YM = theBndBox.CornerMax().y();
+    const float ZM = theBndBox.CornerMax().z();
+
     myVerts[0]  = OpenGl_Vec3 (Xm, Ym, Zm);
     myVerts[1]  = OpenGl_Vec3 (Xm, Ym, ZM);
     myVerts[2]  = OpenGl_Vec3 (Xm, YM, ZM);
@@ -143,7 +144,8 @@ OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& th
   myNamedStatus(0),
   myZLayer(0),
   myIsRaytracable (Standard_False),
-  myModificationState (0)
+  myModificationState (0),
+  myIsCulled (Standard_True)
 {
   UpdateNamedStatus();
 }
@@ -212,6 +214,7 @@ void OpenGl_Structure::SetTransformPersistence(const CALL_DEF_TRANSFORM_PERSISTE
   myTransPers->pointX = ATransPers.Point.x;
   myTransPers->pointY = ATransPers.Point.y;
   myTransPers->pointZ = ATransPers.Point.z;
+  MarkAsNotCulled();
 }
 
 // =======================================================================
@@ -323,12 +326,12 @@ void OpenGl_Structure::HighlightWithBndBox (const Handle(Graphic3d_Structure)& t
 
   CALL_DEF_CONTEXTLINE& aContextLine = myHighlightBox->ChangeContextLine();
   aContextLine.IsDef    = 1;
-  aContextLine.Color    = BoundBox.Color;
+  aContextLine.Color    = HighlightColor;
   aContextLine.LineType = Aspect_TOL_SOLID;
   aContextLine.Width    = 1.0f;
   myHighlightBox->UpdateAspectLine (Standard_True);
 
-  OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (BoundBox);
+  OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
   myHighlightBox->AddElement (aBndBoxPrs);
 }
 
@@ -598,6 +601,9 @@ void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
     UpdateStateWithAncestorStructures();
     UpdateRaytracableWithAncestorStructures();
   }
+
+  Is2dText       = Standard_False;
+  IsForHighlight = Standard_False;
 }
 
 // =======================================================================
@@ -610,6 +616,8 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
   if ( myNamedStatus & OPENGL_NS_HIDE )
     return;
 
+  const Handle(OpenGl_Context)& aCtx = AWorkspace->GetGlContext();
+
   // Render named status
   const Standard_Integer named_status = AWorkspace->NamedStatus;
   AWorkspace->NamedStatus |= myNamedStatus;
@@ -617,8 +625,6 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
   // Is rendering in ADD or IMMEDIATE mode?
   const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & OPENGL_NS_IMMEDIATE) != 0;
 
-  const Handle(OpenGl_Context)& aCtx = AWorkspace->GetGlContext();
-
   // Apply local transformation
   GLint matrix_mode = 0;
   const OpenGl_Matrix *local_trsf = NULL;
@@ -678,12 +684,6 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
   if (myAspectText)
     AWorkspace->SetAspectText(myAspectText);
 
-  // Apply highlight box
-  if (!myHighlightBox.IsNull())
-  {
-    myHighlightBox->Render (AWorkspace);
-  }
-
   // Apply highlight color
   const TEL_COLOUR *highlight_color = AWorkspace->HighlightColor;
   if (myHighlightColor)
@@ -800,6 +800,12 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
     }
   }
 
+  // Apply highlight box
+  if (!myHighlightBox.IsNull())
+  {
+    myHighlightBox->Render (AWorkspace);
+  }
+
   // Restore named status
   AWorkspace->NamedStatus = named_status;
 }
@@ -872,6 +878,7 @@ Standard_Integer OpenGl_Structure::GetZLayer () const
   return myZLayer;
 }
 
+//! Dummy structure which just redirects to groups of another structure.
 class OpenGl_StructureShadow : public OpenGl_Structure
 {
 
@@ -898,6 +905,10 @@ DEFINE_STANDARD_HANDLE(OpenGl_StructureShadow, OpenGl_Structure)
 IMPLEMENT_STANDARD_HANDLE (OpenGl_StructureShadow, OpenGl_Structure)
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_StructureShadow, OpenGl_Structure)
 
+//=======================================================================
+//function : OpenGl_StructureShadow
+//purpose  :
+//=======================================================================
 OpenGl_StructureShadow::OpenGl_StructureShadow (const Handle(Graphic3d_StructureManager)& theManager,
                                                 const Handle(OpenGl_Structure)&           theStructure)
 : OpenGl_Structure (theManager)
index fd7b367..48569ae 100644 (file)
@@ -27,6 +27,8 @@
 #include <OpenGl_Group.hxx>
 #include <OpenGl_Matrix.hxx>
 #include <OpenGl_NamedStatus.hxx>
+#include <OpenGl_Vec.hxx>
+#include <OpenGl_Workspace.hxx>
 
 #include <NCollection_List.hxx>
 #include <InterfaceGraphic_Graphic3d.hxx>
@@ -140,6 +142,34 @@ public:
   virtual void Render  (const Handle(OpenGl_Workspace)& theWorkspace) const;
   virtual void Release (const Handle(OpenGl_Context)&   theGlCtx);
 
+  //! Marks structure as not overlapping view volume (as it is by default).
+  void ResetCullingStatus() const
+  {
+    if (!IsAlwaysRendered())
+    {
+      myIsCulled = Standard_True;
+    }
+  }
+
+  //! Marks structure as overlapping the current view volume one.
+  //! The method is called during traverse of BVH tree.
+  void MarkAsNotCulled() const { myIsCulled = Standard_False; }
+
+  //! Returns Standard_False if the structure hits the current view volume, otherwise
+  //! returns Standard_True. The default value for all structures before each traverse
+  //! of BVH tree is Standard_True.
+  Standard_Boolean IsCulled() const { return myIsCulled; }
+
+  //! Checks if the structure should be included into BVH tree or not.
+  const Standard_Boolean IsAlwaysRendered() const
+  {
+    return IsInfinite
+        || IsForHighlight
+        || IsMutable
+        || Is2dText
+        || TransformPersistence.Flag != 0;
+  }
+
   //! This method releases GL resources without actual elements destruction.
   //! As result structure could be correctly destroyed layer without GL context
   //! (after last window was closed for example).
@@ -212,6 +242,8 @@ protected:
   mutable Standard_Boolean         myIsRaytracable;
   mutable Standard_Size            myModificationState;
 
+  mutable Standard_Boolean         myIsCulled; //!< A status specifying is structure needs to be rendered after BVH tree traverse.
+
 public:
 
   DEFINE_STANDARD_RTTI(OpenGl_Structure) // Type definition
index b1cbe18..b3f2a12 100644 (file)
@@ -37,6 +37,7 @@
 #include <Graphic3d_ZLayerSettings.hxx>
 #include <Visual3d_TypeOfSurfaceDetail.hxx>
 
+#include <OpenGl_BVHTreeSelector.hxx>
 #include <OpenGl_LayerList.hxx>
 #include <OpenGl_Light.hxx>
 #include <OpenGl_LineAttributes.hxx>
@@ -164,6 +165,10 @@ class OpenGl_View : public MMgt_TShared
   void SetZLayerSettings (const Standard_Integer theLayerId,
                           const Graphic3d_ZLayerSettings theSettings);
 
+  //! Changes the priority of a structure within its ZLayer
+  void ChangePriority (const OpenGl_Structure *theStructure,
+                       const Standard_Integer theNewPriority);
+
   void CreateBackgroundTexture (const Standard_CString AFileName, const Aspect_FillMethod AFillStyle);
   void SetBackgroundTextureStyle (const Aspect_FillMethod FillStyle);
   void SetBackgroundGradient (const Quantity_Color& AColor1, const Quantity_Color& AColor2, const Aspect_GradientFillMethod AType);
@@ -190,6 +195,14 @@ class OpenGl_View : public MMgt_TShared
   //! Returns visualization mode for objects in the view.
   Visual3d_TypeOfSurfaceDetail SurfaceDetail() const { return mySurfaceDetail; }
 
+  //! Returns selector for BVH tree, providing a possibility to store information
+  //! about current view volume and to detect which objects are overlapping it.
+  OpenGl_BVHTreeSelector& BVHTreeSelector() { return myBVHSelector; }
+
+  //! Marks BVH tree for given priority list as dirty and
+  //! marks primitive set for rebuild.
+  void InvalidateBVHData (const Standard_Integer theLayerId);
+
   void GetMatrices (TColStd_Array2OfReal&  theMatOrient,
                     TColStd_Array2OfReal&  theMatMapping) const;
 
@@ -273,6 +286,9 @@ protected:
   StateInfo myLastViewMappingState;
   StateInfo myLastLightSourceState;
 
+  //! Is needed for selection of overlapping objects and storage of the current view volume
+  OpenGl_BVHTreeSelector myBVHSelector;
+
   Standard_Size myModificationState;
 
 public:
index 99b2266..59c1dfd 100644 (file)
@@ -383,6 +383,19 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
     }
   }
 
+  Standard_Boolean isProjectionMatUpdateNeeded  = Standard_False;
+  Standard_Boolean isOrientationMatUpdateNeeded = Standard_False;
+  if (myBVHSelector.ProjectionState() != myCamera->ProjectionState())
+  {
+    isProjectionMatUpdateNeeded = Standard_True;
+    myBVHSelector.ChangeProjectionState() = myCamera->ProjectionState();
+  }
+  if (myBVHSelector.ModelViewState() != myCamera->ModelViewState())
+  {
+    isOrientationMatUpdateNeeded = Standard_True;
+    myBVHSelector.ChangeModelViewState() = myCamera->ModelViewState();
+  }
+
   // Set OCCT state uniform variables
   const Handle(OpenGl_ShaderManager) aManager = aContext->ShaderManager();
   if (!aManager->IsEmpty())
@@ -429,6 +442,12 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
     }
   }
 
+  if (isProjectionMatUpdateNeeded
+   || isOrientationMatUpdateNeeded)
+  {
+    myBVHSelector.SetViewVolume (myCamera);
+  }
+
   // ====================================
   //      Step 2: Redraw background
   // ====================================
@@ -643,6 +662,15 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   }
 }
 
+// =======================================================================
+// function : InvalidateBVHData
+// purpose  :
+// =======================================================================
+void OpenGl_View::InvalidateBVHData (const Standard_Integer theLayerId)
+{
+  myZLayers.InvalidateBVHData (theLayerId);
+}
+
 /*----------------------------------------------------------------------*/
 
 //ExecuteViewDisplay
@@ -1033,6 +1061,16 @@ void OpenGl_View::SetZLayerSettings (const Standard_Integer theLayerId,
   myZLayers.Layer (theLayerId).SetLayerSettings (theSettings);
 }
 
+//=======================================================================
+//function : ChangePriority
+//purpose  :
+//=======================================================================
+void OpenGl_View::ChangePriority (const OpenGl_Structure *theStructure,
+                                  const Standard_Integer theNewPriority)
+{
+  Standard_Integer aLayerId = theStructure->GetZLayer();
+  myZLayers.ChangePriority (theStructure, aLayerId, theNewPriority);
+}
 
 //=======================================================================
 //function : RedrawScene
index b6dd166..61e4d13 100644 (file)
@@ -159,6 +159,7 @@ OpenGl_Workspace::OpenGl_Workspace (const Handle(Aspect_DisplayConnection)& theD
   myUseZBuffer (Standard_False),
   myUseDepthTest (Standard_True),
   myUseGLLight (Standard_True),
+  myIsCullingEnabled (Standard_False),
   //
   AspectLine_set (&myDefaultAspectLine),
   AspectLine_applied (NULL),
@@ -560,6 +561,8 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
     return;
   }
 
+  myIsCullingEnabled = theCView.IsCullingEnabled;
+
   // release pending GL resources
   Handle(OpenGl_Context) aGlCtx = GetGlContext();
   aGlCtx->ReleaseDelayed();
index d9f9634..4267949 100755 (executable)
@@ -64,6 +64,7 @@ class OpenGl_AspectMarker;
 class OpenGl_AspectText;
 class OpenGl_FrameBuffer;
 class OpenGl_Structure;
+class OpenGl_TriangleSet;
 class OpenGl_Element;
 class Image_PixMap;
 
@@ -224,6 +225,9 @@ public:
   //! Returns currently applied polygon offset params.
   const TEL_POFFSET_PARAM& AppliedPolygonOffset() { return PolygonOffset_applied; }
 
+  //! @return true if clipping algorithm enabled
+  inline Standard_Boolean IsCullingEnabled() const { return myIsCullingEnabled; }
+
 protected:
 
   //! Copy content of Back buffer to the Front buffer
@@ -599,6 +603,7 @@ protected: //! @name protected fields
   Standard_Boolean       myUseZBuffer;
   Standard_Boolean       myUseDepthTest;
   Standard_Boolean       myUseGLLight;
+  Standard_Boolean       myIsCullingEnabled;     //!< frustum culling flag
 
 protected: //! @name fields related to status
 
index 91792ce..15dae2b 100755 (executable)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
+#include <OpenGl_Workspace.hxx>
+
 #include <NCollection_Mat4.hxx>
 #include <OpenGl_ArbFBO.hxx>
 #include <OpenGl_FrameBuffer.hxx>
+#include <OpenGl_PrimitiveArray.hxx>
 #include <OpenGl_Texture.hxx>
 #include <OpenGl_VertexBuffer.hxx>
 #include <OpenGl_View.hxx>
-#include <OpenGl_Workspace.hxx>
 #include <OSD_File.hxx>
 #include <OSD_Protection.hxx>
 #include <Standard_Assert.hxx>
index 7f7ec9d..4a59f66 100644 (file)
@@ -91,6 +91,12 @@ is
        ---Purpose: displays the whole content of the presentation in the specified color.
     BoundBox(me: mutable) is static;
 
+    SetIsForHighlight (me             : mutable;
+                       isForHighlight : Boolean from Standard)
+        is virtual;
+    ---Purpose: marks the structure <me> representing wired structure needed for
+    --          highlight only so it won't be added to BVH tree.
+
 ---Category: Global modification methods.
     SetShadingAspect(me: mutable; aShadingAspect: ShadingAspect from Prs3d);
     
index 76bce47..a205f09 100644 (file)
@@ -288,6 +288,15 @@ Handle(Graphic3d_Group) Prs3d_Presentation::CurrentGroup () const
 }
 
 //=======================================================================
+//=======================================================================
+//function : SetIsForHighlight
+//purpose  :
+//=======================================================================
+void Prs3d_Presentation::SetIsForHighlight (const Standard_Boolean isForHighlight)
+{
+  Graphic3d_Structure::SetIsForHighlight (isForHighlight);
+}
+
 //function : Compute
 //purpose  : 
 //=======================================================================
index f4457f5..9b88fe5 100644 (file)
@@ -277,6 +277,16 @@ is
    ---Purpose: Get clip planes.
    -- @return set of previously added clip planes for all display mode presentations.
 
+  SetMutable ( me           : mutable;
+               theIsMutable : Boolean from Standard ) is virtual;
+  ---Purpose: Sets if the object has mutable nature (content or location will be changed regularly).
+  -- This method should be called before object displaying to take effect.
+
+  IsMutable (me) returns Boolean from Standard;
+  ---C++: return const
+  ---Purpose: Returns true if object has mutable nature (content or location are be changed regularly).
+  -- Mutable object will be managed in different way than static onces (another optimizations).
+
    UpdateClipping (me : mutable) is virtual protected;
    ---Purpose: General virtual method for internal update of presentation state
    -- when some modifications on list of clip planes occurs. Base 
@@ -287,8 +297,8 @@ fields
     myTypeOfPresentation3d: TypeOfPresentation3d from PrsMgr is protected;
     myLocation  : Location from TopLoc is protected; 
     myClipPlanes : SequenceOfHClipPlane from Graphic3d is protected;
-    --myTransformPersistence  :  TransModeFlags  from  Graphic3d; 
     myTransformPersistence  :  CTransPersStruct  from  Graphic3d;
+    myIsMutable : Boolean from Standard is protected;
 
 friends
     class Presentation        from PrsMgr,
index a392bc5..b1535eb 100644 (file)
 
 //=======================================================================
 //function : PrsMgr_PresentableObject
-//purpose  : 
+//purpose  :
 //=======================================================================
-PrsMgr_PresentableObject::PrsMgr_PresentableObject(const PrsMgr_TypeOfPresentation3d aTypeOfPresentation3d)
-     :myPresentations(),myTypeOfPresentation3d(aTypeOfPresentation3d)
+PrsMgr_PresentableObject::PrsMgr_PresentableObject (const PrsMgr_TypeOfPresentation3d theType)
+: myTypeOfPresentation3d (theType),
+  myIsMutable (Standard_False)
 {
   myTransformPersistence.Flag = 0;
   myTransformPersistence.Point.x = 0.0;
@@ -294,6 +295,7 @@ void PrsMgr_PresentableObject::SetTransformPersistence (const Graphic3d_TransMod
      && !aPrs3d->Presentation().IsNull())
     {
       aPrs3d->Presentation()->SetTransformPersistence (theFlag, thePoint);
+      aPrs3d->Presentation()->ReCompute();
     }
   }
 }
@@ -414,3 +416,37 @@ void PrsMgr_PresentableObject::UpdateClipping()
     aModedPrs.Presentation()->Presentation()->SetClipPlanes (myClipPlanes);
   }
 }
+
+// =======================================================================
+// function : SetMutable
+// purpose  :
+// =======================================================================
+void PrsMgr_PresentableObject::SetMutable (const Standard_Boolean theIsMutable)
+{
+  if (myIsMutable == theIsMutable)
+  {
+    return;
+  }
+
+  myIsMutable = theIsMutable;
+  for (Standard_Integer aPrsIter = 1; aPrsIter <= myPresentations.Length(); ++aPrsIter)
+  {
+    const PrsMgr_ModedPresentation& aModedPrs = myPresentations (aPrsIter);
+    if (aModedPrs.Presentation().IsNull()
+     || aModedPrs.Presentation()->Presentation().IsNull())
+    {
+      continue;
+    }
+
+    aModedPrs.Presentation()->Presentation()->SetMutable (theIsMutable);
+  }
+}
+
+// =======================================================================
+// function : IsMutable
+// purpose  :
+// =======================================================================
+const Standard_Boolean PrsMgr_PresentableObject::IsMutable() const
+{
+  return myIsMutable;
+}
index 11269ef..6343c1a 100644 (file)
@@ -52,6 +52,7 @@ PrsMgr_Presentation::PrsMgr_Presentation (const Handle(PrsMgr_PresentationManage
   myStructure = new PrsMgr_Prs (thePrsMgr->StructureManager(),
                                 this, thePrsObject->TypeOfPresentation3d());
   myStructure->SetOwner (myPresentableObject);
+  myStructure->SetMutable (myPresentableObject->IsMutable());
 }
 
 //=======================================================================
@@ -68,15 +69,17 @@ void PrsMgr_Presentation::Display()
 //function : Display
 //purpose  :
 //=======================================================================
-void PrsMgr_Presentation::Display (const Standard_Boolean /*theIsHighlight*/)
+void PrsMgr_Presentation::Display (const Standard_Boolean theIsHighlight)
 {
   if (!myStructure->IsDisplayed())
   {
+    myStructure->SetIsForHighlight (theIsHighlight);
     myStructure->Display();
   }
   else if (!myStructure->IsVisible())
   {
     SetVisible (Standard_True);
+    myStructure->SetIsForHighlight (theIsHighlight);
   }
 }
 
index 14f425b..b70687c 100644 (file)
@@ -270,6 +270,20 @@ inline  Standard_Integer RealToInt (const Standard_Real Value)
     : (Standard_Integer)Value;
 }
 
+// =======================================================================
+// function : RealToShortReal
+// purpose  : Converts Standard_Real value to the nearest valid
+//            Standard_ShortReal. If input value is out of valid range
+//            for Standard_ShortReal, minimal or maximal
+//            Standard_ShortReal is returned.
+// =======================================================================
+inline Standard_ShortReal RealToShortReal (const Standard_Real theVal)
+{
+  return theVal < -FLT_MAX ? -FLT_MAX
+    : theVal > FLT_MAX ? FLT_MAX
+    : (Standard_ShortReal)theVal;
+}
+
 //-------------------------------------------------------------------
 // Round : Returns the nearest integer of a real
 //-------------------------------------------------------------------
index e90e475..593d008 100644 (file)
@@ -1629,6 +1629,14 @@ is
     ---Level: Public
     ---Purpose: Returns reference to current rendering parameters and effect settings.
 
+        IsCullingEnabled (me) returns Boolean from Standard is static;
+     ---Level: Public
+     ---Purpose: @return flag value of objects culling mechanism
+
+        SetFrustumCulling (me : mutable; theMode : Boolean from Standard) is static;
+     ---Level: Public
+     ---Purpose: Turn on/off automatic culling of objects outside frustrum (ON by default)
+
 fields
 
         myOldMouseX : Real is protected;
index 028e1c8..0d17f6b 100644 (file)
@@ -3392,3 +3392,23 @@ void V3d_View::Translate (const Handle(Graphic3d_Camera)& theCamera,
 
   theCamera->Transform (aPanTrsf);
 }
+
+// =======================================================================
+// function : IsCullingEnabled
+// purpose  :
+// =======================================================================
+Standard_Boolean V3d_View::IsCullingEnabled() const
+{
+  Graphic3d_CView* aView = (Graphic3d_CView* )MyView->CView();
+  return aView->IsCullingEnabled;
+}
+
+// =======================================================================
+// function : SetFrustumCulling
+// purpose  :
+// =======================================================================
+void V3d_View::SetFrustumCulling (const Standard_Boolean theToClip)
+{
+  Graphic3d_CView* aView = (Graphic3d_CView* )MyView->CView();
+  aView->IsCullingEnabled = theToClip;
+}
index 5fed471..7698ebd 100644 (file)
@@ -2028,6 +2028,7 @@ int VRemove (Draw_Interpretor& theDI,
   ViewerTest_RedrawMode aToUpdate     = ViewerTest_RM_Auto;
   Standard_Boolean      isContextOnly = Standard_False;
   Standard_Boolean      toRemoveAll   = Standard_False;
+  Standard_Boolean      toPrintInfo   = Standard_True;
 
   Standard_Integer anArgIter = 1;
   for (; anArgIter < theArgNb; ++anArgIter)
@@ -2042,6 +2043,10 @@ int VRemove (Draw_Interpretor& theDI,
     {
       toRemoveAll = Standard_True;
     }
+    else if (anArg == "-noinfo")
+    {
+      toPrintInfo = Standard_False;
+    }
     else if (!parseRedrawMode (anArg, aToUpdate))
     {
       break;
@@ -2133,11 +2138,13 @@ int VRemove (Draw_Interpretor& theDI,
        anIter.More(); anIter.Next())
   {
     const Handle(AIS_InteractiveObject) anIO  = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anIter.Value()));
-
     if (!anIO.IsNull())
     {
       TheAISContext()->Remove (anIO, Standard_False);
-      theDI << anIter.Value().ToCString() << " was removed\n";
+      if (toPrintInfo)
+      {
+        theDI << anIter.Value().ToCString() << " was removed\n";
+      }
     }
     else
     {
@@ -2145,10 +2152,12 @@ int VRemove (Draw_Interpretor& theDI,
       if (!aNisIO.IsNull())
       {
         TheNISContext()->Remove (aNisIO);
-        theDI << anIter.Value().ToCString() << " was removed\n";
+        if (toPrintInfo)
+        {
+          theDI << anIter.Value().ToCString() << " was removed\n";
+        }
       }
     }
-      
     if (!isContextOnly)
     {
       GetMapOfAIS().UnBind2 (anIter.Value());
@@ -2854,19 +2863,31 @@ static int VDisplay2 (Draw_Interpretor& theDI,
   }
 
   ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
+  Standard_Integer      isMutable = -1;
   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
   {
-    const TCollection_AsciiString aName = theArgVec[anArgIter];
+    const TCollection_AsciiString aName     = theArgVec[anArgIter];
+    TCollection_AsciiString       aNameCase = aName;
+    aNameCase.LowerCase();
     if (parseRedrawMode (aName, aToUpdate))
     {
       continue;
     }
+    else if (aNameCase == "-mutable")
+    {
+      isMutable = 1;
+      continue;
+    }
     else if (!GetMapOfAIS().IsBound2 (aName))
     {
       // create the AIS_Shape from a name
       const Handle(AIS_InteractiveObject) aShape = GetAISShapeFromName (aName.ToCString());
       if (!aShape.IsNull())
       {
+        if (isMutable != -1)
+        {
+          aShape->SetMutable (isMutable == 1);
+        }
         GetMapOfAIS().Bind (aShape, aName);
         aCtx->Display (aShape, Standard_False);
       }
@@ -2877,6 +2898,11 @@ static int VDisplay2 (Draw_Interpretor& theDI,
     if (anObj->IsKind (STANDARD_TYPE (AIS_InteractiveObject)))
     {
       Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anObj);
+      if (isMutable != -1)
+      {
+        aShape->SetMutable (isMutable == 1);
+      }
+
       if (aShape->Type() == AIS_KOI_Datum)
       {
         aCtx->Display (aShape, Standard_False);
@@ -2896,7 +2922,6 @@ static int VDisplay2 (Draw_Interpretor& theDI,
         aCtx->Redisplay (aShape, Standard_False);
         aCtx->Display   (aShape, Standard_False);
       }
-      aShape.Nullify();
     }
     else if (anObj->IsKind (STANDARD_TYPE (NIS_InteractiveObject)))
     {
@@ -3088,14 +3113,19 @@ static int VAnimation (Draw_Interpretor& di, Standard_Integer argc, const char**
   GetMapOfAIS().Bind(myAisCrankArm,"c");
   GetMapOfAIS().Bind(myAisPropeller,"d");
 
-  TheAISContext()->SetColor(myAisCylinderHead, Quantity_NOC_INDIANRED);
-  TheAISContext()->SetColor(myAisEngineBlock , Quantity_NOC_RED);
-  TheAISContext()->SetColor(myAisPropeller   , Quantity_NOC_GREEN);
+  myAisCylinderHead->SetMutable (Standard_True);
+  myAisEngineBlock ->SetMutable (Standard_True);
+  myAisCrankArm    ->SetMutable (Standard_True);
+  myAisPropeller   ->SetMutable (Standard_True);
 
-  TheAISContext()->Display(myAisCylinderHead,Standard_False);
-  TheAISContext()->Display(myAisEngineBlock,Standard_False );
-  TheAISContext()->Display(myAisCrankArm,Standard_False    );
-  TheAISContext()->Display(myAisPropeller,Standard_False);
+  TheAISContext()->SetColor (myAisCylinderHead, Quantity_NOC_INDIANRED);
+  TheAISContext()->SetColor (myAisEngineBlock,  Quantity_NOC_RED);
+  TheAISContext()->SetColor (myAisPropeller,    Quantity_NOC_GREEN);
+
+  TheAISContext()->Display (myAisCylinderHead, Standard_False);
+  TheAISContext()->Display (myAisEngineBlock,  Standard_False);
+  TheAISContext()->Display (myAisCrankArm,     Standard_False);
+  TheAISContext()->Display (myAisPropeller,    Standard_False);
 
   TheAISContext()->Deactivate(myAisCylinderHead);
   TheAISContext()->Deactivate(myAisEngineBlock );
@@ -4215,9 +4245,10 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
                  __FILE__, visos, group);
 
   theCommands.Add("vdisplay",
-                 "vdisplay [-noupdate|-update] name1 [name2] ... [name n]"
+                 "vdisplay [-noupdate|-update] [-mutable] name1 [name2] ... [name n]"
       "\n\t\t: Displays named objects."
       "\n\t\t: Option -noupdate suppresses viewer redraw call."
+      "\n\t\t: Option -mutable enables optimizations for mutable objects."
                  __FILE__,VDisplay2,group);
 
   theCommands.Add ("vupdate",
@@ -4232,12 +4263,13 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
                  __FILE__, VErase, group);
 
   theCommands.Add("vremove",
-    "vremove [-noupdate|-update] [-context] [-all] [name1] ...  [name n]"
+    "vremove [-noupdate|-update] [-context] [-all] [-noinfo] [name1] ...  [name n]"
     "or vremove [-context] -all to remove all objects"
       "\n\t\t: Removes selected or named objects."
       "\n\t\t  If -context is in arguments, the objects are not deleted"
       "\n\t\t  from the map of objects and names."
-      "\n\t\t: Option -noupdate suppresses viewer redraw call.",
+      "\n\t\t: Option -noupdate suppresses viewer redraw call."
+      "\n\t\t: Option -noinfo suppresses displaying the list of removed objects.",
       __FILE__, VRemove, group);
 
   theCommands.Add("vdonly",
index dd23be3..dd08448 100644 (file)
@@ -2923,12 +2923,14 @@ static int VDrawSphere (Draw_Interpretor& /*di*/, Standard_Integer argc, const c
   Standard_Real aCenterY = (argc > 5) ? Draw::Atof (argv[4]) : 0.0;
   Standard_Real aCenterZ = (argc > 5) ? Draw::Atof (argv[5]) : 0.0;
   Standard_Real aRadius =  (argc > 6) ? Draw::Atof (argv[6]) : 100.0;
-  Standard_Boolean toShowEdges =  (argc > 7) ? Draw::Atoi (argv[7]) : Standard_False;
+  Standard_Boolean toShowEdges = (argc > 7) ? Draw::Atoi (argv[7]) == 1 : Standard_False;
+  Standard_Boolean toPrintInfo = (argc > 8) ? Draw::Atoi (argv[8]) == 1 : Standard_True;
 
   // remove AIS object with given name from map
   VDisplayAISObject (aShapeName, Handle(AIS_InteractiveObject)());
 
-  std::cout << "Compute Triangulation...\n";
+  if (toPrintInfo)
+    std::cout << "Compute Triangulation...\n";
   Handle(AIS_Triangulation) aShape
     = new AIS_Triangulation (CalculationOfSphere (aCenterX, aCenterY, aCenterZ,
                                                   aResolution,
@@ -2967,12 +2969,15 @@ static int VDrawSphere (Draw_Interpretor& /*di*/, Standard_Integer argc, const c
   aColorsSize >>= 20;
   aTrianglesSize >>= 20;
   aPolyConnectSize >>= 20;
-  std::cout << "NumberOfPoints:    " << aNumberPoints << "\n"
-            << "NumberOfTriangles: " << aNumberTriangles << "\n"
-            << "Amount of memory required for PolyTriangulation without Normals: " << (aTotalSize - aNormalsSize) << " Mb\n"
-            << "Amount of memory for colors: " << aColorsSize << " Mb\n"
-            << "Amount of memory for PolyConnect: " << aPolyConnectSize << " Mb\n"
-            << "Amount of graphic card memory required: " << aTotalSize << " Mb\n";
+  if (toPrintInfo)
+  {
+    std::cout << "NumberOfPoints:    " << aNumberPoints << "\n"
+      << "NumberOfTriangles: " << aNumberTriangles << "\n"
+      << "Amount of memory required for PolyTriangulation without Normals: " << (aTotalSize - aNormalsSize) << " Mb\n"
+      << "Amount of memory for colors: " << aColorsSize << " Mb\n"
+      << "Amount of memory for PolyConnect: " << aPolyConnectSize << " Mb\n"
+      << "Amount of graphic card memory required: " << aTotalSize << " Mb\n";
+  }
 
   // Setting material properties, very important for desirable visual result!
   Graphic3d_MaterialAspect aMat (Graphic3d_NOM_PLASTIC);
@@ -5283,7 +5288,7 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
     __FILE__,VDrawText,group);
 
   theCommands.Add("vdrawsphere",
-    "vdrawsphere: vdrawsphere shapeName Fineness [X=0.0 Y=0.0 Z=0.0] [Radius=100.0] [ToShowEdges=0]\n",
+    "vdrawsphere: vdrawsphere shapeName Fineness [X=0.0 Y=0.0 Z=0.0] [Radius=100.0] [ToShowEdges=0] [ToPrintInfo=1]\n",
     __FILE__,VDrawSphere,group);
 
   theCommands.Add ("vsetlocation",
index 2682f31..8e3e8f2 100644 (file)
@@ -86,7 +86,7 @@ public:
 
   public:
     Element (const Handle(VUserDrawObj)& theIObj,
-             CALL_DEF_BOUNDS* theBounds)
+             Graphic3d_BndBox4f* theBounds)
     : myIObj( theIObj )
     {
       if (!myIObj.IsNull())
@@ -123,7 +123,7 @@ private:
 
     // Called by VUserDrawElement
     void Render(const Handle(OpenGl_Workspace)& theWorkspace) const;
-    void GetBounds(CALL_DEF_BOUNDS* theBounds);
+    void GetBounds(Graphic3d_BndBox4f* theBounds);
 
     GLfloat myCoords[6];
 
@@ -156,16 +156,21 @@ void VUserDrawObj::ComputeSelection (const Handle(SelectMgr_Selection)& theSelec
   theSelection->Add(aSensitive);
 }
 
-void VUserDrawObj::GetBounds(CALL_DEF_BOUNDS* theBounds)
+void VUserDrawObj::GetBounds(Graphic3d_BndBox4f* theBounds)
 {
   if (theBounds)
   {
-    theBounds->XMin = myCoords[0];
-    theBounds->YMin = myCoords[1];
-    theBounds->ZMin = myCoords[2];
-    theBounds->XMax = myCoords[3];
-    theBounds->YMax = myCoords[4];
-    theBounds->ZMax = myCoords[5];
+    Graphic3d_Vec4 aMinPt (myCoords[0], myCoords[1], myCoords[2], 1.0f);
+    Graphic3d_Vec4 aMaxPt (myCoords[3], myCoords[4], myCoords[5], 1.0f);
+    if (!theBounds->IsValid())
+    {
+      theBounds->Combine (Graphic3d_BndBox4f (aMinPt, aMaxPt));
+    }
+    else
+    {
+      theBounds->CornerMin() = aMinPt;
+      theBounds->CornerMax() = aMaxPt;
+    }
   }
 }
 
index f60b096..f1d0263 100644 (file)
@@ -6604,6 +6604,53 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
 }
 
 //=======================================================================
+//function : VFrustumCulling
+//purpose  : enables/disables view volume's culling.
+//=======================================================================
+static int VFrustumCulling (Draw_Interpretor& theDI,
+                            Standard_Integer  theArgNb,
+                            const char**      theArgVec)
+{
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
+    return 1;
+  }
+
+  if (theArgNb < 2)
+  {
+    theDI << (aView->IsCullingEnabled() ? "on" : "off");
+    return 0;
+  }
+  else if (theArgNb != 2)
+  {
+    std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
+    return 1;
+  }
+
+  TCollection_AsciiString aModeStr (theArgVec[1]);
+  aModeStr.LowerCase();
+  Standard_Boolean toEnable = 0;
+  if (aModeStr == "on")
+  {
+    toEnable = 1;
+  }
+  else if (aModeStr == "off")
+  {
+    toEnable = 0;
+  }
+  else
+  {
+    toEnable = Draw::Atoi (theArgVec[1]) != 0;
+  }
+
+  aView->SetFrustumCulling (toEnable);
+  aView->Redraw();
+  return 0;
+}
+
+//=======================================================================
 //function : ViewerCommands
 //purpose  :
 //=======================================================================
@@ -6968,4 +7015,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n      '-fsaa        on|off'  Enables/disables adaptive anti-aliasing"
     "\n      '-gleam       on|off'  Enables/disables transparency shadow effects",
     __FILE__, VRenderParams, group);
+  theCommands.Add("vfrustumculling",
+    "vfrustumculling [toEnable]: enables/disables objects clipping",
+    __FILE__,VFrustumCulling,group);
 }
index 0e7bbdf..7f919c7 100644 (file)
@@ -297,25 +297,6 @@ is
        ---Purpose: Sets the context <CTX> in the view <me>.
        ---Category: Methods to modify the class definition
 
-       SetTransform ( me       : mutable;
-                      AMatrix  : Array2OfReal from TColStd )
-       ---Level: Internal
-       ---Purpose: Sets the transformation matrix that is applied
-       --          to <MyViewOrientation> field of the view <me>.
-       --
-       --          <AMatrix> is defined as a 4*4 real matrix.
-       --
-       --              -------------------
-       --              | a11 a12 a13  t1 |
-       --              | a21 a22 a23  t2 |
-       --              | a31 a32 a33  t3 |
-       --              |  0   0   0   1  |
-       --              -------------------
-       --
-       --  Category: Methods to modify the class definition
-       --  Warning: Raises TransformError if the matrix isn't a 4x4 matrix.
-       raises TransformError from Visual3d is static;
-
        SetViewMappingDefault ( me      : mutable )
                is static;
        ---Level: Public
index fb4f501..1834df7 100644 (file)
@@ -1189,8 +1189,7 @@ Standard_Integer Index = IsComputed (AStructure);
              << ", " << OldPriority << ", " << NewPriority << ")\n";
         cout << flush;
 #endif
-                MyGraphicDriver->EraseStructure   (MyCView, *(MyCOMPUTEDSequence.Value (Index)->CStructure()));
-                MyGraphicDriver->DisplayStructure (MyCView, *(MyCOMPUTEDSequence.Value (Index)->CStructure()), NewPriority);
+                MyGraphicDriver->ChangePriority (*(MyCOMPUTEDSequence.Value (Index)->CStructure()), MyCView, NewPriority);
         }
         else
         {
@@ -1201,8 +1200,7 @@ Standard_Integer Index = IsComputed (AStructure);
              << ", " << OldPriority << ", " << NewPriority << ")\n";
         cout << flush;
 #endif
-                MyGraphicDriver->EraseStructure   (MyCView, *(AStructure->CStructure()));
-                MyGraphicDriver->DisplayStructure (MyCView, *(AStructure->CStructure()), NewPriority);
+                MyGraphicDriver->ChangePriority (*(AStructure->CStructure()), MyCView, NewPriority);
         }
 
 }
@@ -1381,6 +1379,7 @@ Standard_Integer Index = IsComputed (AStructure);
 
         if (Answer == Visual3d_TOA_YES ) {
                 if (IsDisplayed (AStructure)) return;
+                AStructure->CalculateBoundBox();
                 MyGraphicDriver->DisplayStructure (MyCView, *(AStructure->CStructure()), AStructure->DisplayPriority());
                 MyDisplayedStructure.Add (AStructure);
                 if (AnUpdateMode == Aspect_TOU_ASAP) Update ();
@@ -1628,6 +1627,14 @@ Standard_Integer Index = IsComputed (AStructure);
                     MyCOMPUTEDSequence.Value (Index)->GraphicTransform (ATrsf);
         }
 
+        Standard_Integer aLayerId = AStructure->GetZLayer();
+        if (!AStructure->IsMutable()
+         && !AStructure->CStructure()->IsForHighlight
+         && !AStructure->CStructure()->IsInfinite)
+        {
+          AStructure->CalculateBoundBox();
+          MyGraphicDriver->InvalidateBVHData (MyCView, aLayerId);
+        }
 }
 
 void Visual3d_View::UnHighlight (const Handle(Graphic3d_Structure)& AStructure) {
@@ -2089,6 +2096,13 @@ Graphic3d_SequenceOfStructure FooSequence;
 }
 
 void Visual3d_View::ReCompute (const Handle(Graphic3d_Structure)& AStructure) {
+        if (MyCView.IsCullingEnabled)
+        {
+          AStructure->CalculateBoundBox();
+          Standard_Integer aLayerId = AStructure->DisplayPriority();
+          MyGraphicDriver->InvalidateBVHData(MyCView, aLayerId);
+        }
+
         if (!ComputedMode()) return;
 
         if (IsDeleted ()) return;
diff --git a/tests/bugs/vis/bug24307_1 b/tests/bugs/vis/bug24307_1
new file mode 100644 (file)
index 0000000..114bafe
--- /dev/null
@@ -0,0 +1,82 @@
+puts "========"
+puts "OCC24307 Objects clipping algorithm using BVH performance test: Solid spheres test"
+puts "========"
+
+# define objects' location parameters and their characteristics
+set SPHERES_NUM 10
+set SPERE_RADIUS 100
+set SPHERE_FINENESS 10
+set PERCENT_OF_INNER_SPHERES 30
+
+# window parameters
+set SMALL_WIN_WIDTH 512
+set SMALL_WIN_HEIGHT 512
+
+# other
+array set aSphereNames {}
+
+set aWithoutClippingSnapshot $imagedir/${casename}_without.png
+set aWithClippingSnapshot $imagedir/${casename}_with.png
+set aDiffImage $imagedir/${casename}_diff.png
+
+pload VISUALIZATION MODELING
+vinit name=small_wnd l=32 t=32 w=$SMALL_WIN_WIDTH h=$SMALL_WIN_HEIGHT
+vactivate small_wnd
+vfrustumculling 0
+vautozfit 0
+vviewparams -scale 1.953125 -eye 0.57735026918962573 -0.57735026918962573 0.57735026918962573
+vzrange 1 512
+vclear
+vremove -all -noinfo
+
+puts [vdrawsphere tmp_sph $SPHERE_FINENESS]
+vremove -noinfo tmp_sph
+
+set aInnerSpheresNum [expr $SPHERES_NUM * $PERCENT_OF_INNER_SPHERES / 100]
+puts ""
+set aDebugInfo "Total number of visible objects: "
+append aDebugInfo $aInnerSpheresNum
+puts $aDebugInfo
+puts ""
+
+puts "Start displaying spheres without clipping..."
+set aInnerWidthStep [expr $SMALL_WIN_WIDTH / ($aInnerSpheresNum + 1)]
+set aInnerHeightStep [expr $SMALL_WIN_HEIGHT / ($aInnerSpheresNum + 1)]
+set aOuterStep [expr $SPERE_RADIUS * 3 / ($SPHERES_NUM - $aInnerSpheresNum + 1)]
+for {set i 0} {$i < $aInnerSpheresNum} {incr i} {
+  set aCurrName "inner_sph"
+  append aCurrName $i
+  set aX [expr - $SMALL_WIN_WIDTH / 2 + ($i + 1) * $aInnerWidthStep ]
+  set aY [expr - $SMALL_WIN_HEIGHT / 2 + ($i + 1) * $aInnerHeightStep ]
+  vdrawsphere $aCurrName $SPHERE_FINENESS $aX $aY 0 $SPERE_RADIUS 0 0
+  set aSphereNames($i) $aCurrName
+}
+for {set i $aInnerSpheresNum} {$i < $SPHERES_NUM} {incr i} {
+  set aCurrName "outer_sph"
+  append aCurrName $i
+  set aX [expr - $SMALL_WIN_WIDTH - $SPERE_RADIUS * 3 + ($i - $aInnerSpheresNum + 1) * $aOuterStep ]
+  set aY [expr - $SMALL_WIN_HEIGHT - $SPERE_RADIUS * 3 + ($i - $aInnerSpheresNum + 1) * $aOuterStep ]
+  vdrawsphere $aCurrName $SPHERE_FINENESS $aX $aY 0 $SPERE_RADIUS 0 0
+  set aSphereNames($i) $aCurrName
+}
+puts [vfps]
+vdump $aWithoutClippingSnapshot
+puts "All spheres were displayed."
+puts ""
+
+verase
+
+puts "Start displaying spheres with clipping..."
+vfrustumculling 1
+vdisplayall
+puts [vfps]
+vdump $aWithClippingSnapshot
+puts "All spheres were displayed."
+puts ""
+
+set aDiffImageResult [diffimage $aWithClippingSnapshot $aWithoutClippingSnapshot 0.1 0 0 $aDiffImage]
+if {$aDiffImageResult != 0} {
+  puts "ERROR : Test failed: there is a difference between images rendered with and without clipping"
+}
+
+verase
diff --git a/tests/bugs/vis/bug24307_2 b/tests/bugs/vis/bug24307_2
new file mode 100644 (file)
index 0000000..8e25767
--- /dev/null
@@ -0,0 +1,86 @@
+puts "========"
+puts "OCC24307 Objects clipping algorithm using BVH performance test: Simple boxes test"
+puts "========"
+
+# object characteristics
+set BOXES_NUM 10
+set BOX_SIZE 100
+set PERCENT_OF_INNER_BOXES 30
+
+# window parameters
+set SMALL_WIN_WIDTH 512
+set SMALL_WIN_HEIGHT 512
+
+# other
+array set aBoxNames {}
+
+set aWithoutClippingSnapshot $imagedir/${casename}_without.png
+set aWithClippingSnapshot $imagedir/${casename}_with.png
+set aDiffImage $imagedir/${casename}_diff.png
+
+pload VISUALIZATION MODELING
+vinit name=small_wnd l=32 t=32 w=$SMALL_WIN_WIDTH h=$SMALL_WIN_HEIGHT
+vactivate small_wnd
+vfrustumculling 0
+vautozfit 0
+vviewparams -scale 1.953125 -eye 0.57735026918962573 -0.57735026918962573 0.57735026918962573
+vzrange 1 512
+vclear
+vremove -all -noinfo
+
+set aInnerBoxesNum [expr $BOXES_NUM * $PERCENT_OF_INNER_BOXES / 100]
+puts ""
+set aDebugInfo "Total number of visible objects: "
+append aDebugInfo $aInnerBoxesNum
+puts $aDebugInfo
+puts ""
+
+puts "Start boxes generation..."
+set aInnerWidthStep [expr $SMALL_WIN_WIDTH / (2 * ($aInnerBoxesNum + 1))]
+set aInnerHeightStep [expr $SMALL_WIN_HEIGHT / (2 * ($aInnerBoxesNum + 1))]
+set aOuterStep [expr $BOX_SIZE * 3 / ($BOXES_NUM - $aInnerBoxesNum + 1)]
+for {set i 0} {$i < $aInnerBoxesNum} {incr i} {
+  set aCurrName "inner_box"
+  append aCurrName $i
+  set aX [expr - $SMALL_WIN_WIDTH / 4 + ($i + 1) * $aInnerWidthStep ]
+  set aY [expr - $SMALL_WIN_HEIGHT / 4 + ($i + 1) * $aInnerHeightStep ]
+  box $aCurrName $aX $aY 0 $BOX_SIZE $BOX_SIZE $BOX_SIZE
+  set aBoxNames($i) $aCurrName
+}
+for {set i $aInnerBoxesNum} {$i < $BOXES_NUM} {incr i} {
+  set aCurrName "outer_box"
+  append aCurrName $i
+  set aX [expr - $SMALL_WIN_WIDTH - $BOX_SIZE * 3 + ($i - $aInnerBoxesNum + 1) * $aOuterStep]
+  set aY [expr - $SMALL_WIN_HEIGHT - $BOX_SIZE * 3 + ($i - $aInnerBoxesNum + 1) * $aOuterStep]
+  box $aCurrName $aX $aY 0 $BOX_SIZE $BOX_SIZE $BOX_SIZE
+  set aBoxNames($i) $aCurrName
+}
+puts "$BOXES_NUM boxes generated."
+puts ""
+
+puts "Start displaying boxes without clipping..."
+for {set i 0} {$i < $BOXES_NUM} {incr i} {
+  vdisplay -noupdate $aBoxNames($i)
+}
+puts [vfps]
+vdump $aWithoutClippingSnapshot
+puts "All boxes were displayed."
+puts ""
+
+verase
+
+vfrustumculling 1
+puts "Start displaying boxes with clipping..."
+for {set i 0} {$i < $BOXES_NUM} {incr i} {
+  vdisplay -noupdate $aBoxNames($i)
+}
+puts [vfps]
+vdump $aWithClippingSnapshot
+puts "All boxes were displayed."
+
+set aDiffImageResult [diffimage $aWithClippingSnapshot $aWithoutClippingSnapshot 0.1 0 0 $aDiffImage]
+if {$aDiffImageResult != 0} {
+  puts "ERROR : Test failed: there is a difference between images rendered with and without clipping"
+}
+
+verase