0029729: Visualization, Graphic3d_ClipPlane - add support of clipping plane chains
authorkgv <kgv@opencascade.com>
Fri, 25 May 2018 07:13:38 +0000 (10:13 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 14 Jun 2018 11:03:02 +0000 (14:03 +0300)
Graphic3d_ClipPlane now can define a Chain of Planes (logical AND).
OpenGl_ShaderManager - added new GLSL sub-programs for clipping plane chains.
Bnd_Range::TrimFrom(), ::TrimTo() - added auxiliary methods for trimming the range.
SelectMgr_ViewClipRange now handles non-continuous clipping range.
Graphic3d_SequenceOfHClipPlane now aggregates NCollection_Sequence instead of inheritance.
OpenGl_CappingPlaneResource - triangulation has been adjusted to make front face following CCW order.

34 files changed:
src/Bnd/Bnd_Range.hxx
src/Graphic3d/FILES
src/Graphic3d/Graphic3d_ClipPlane.cxx
src/Graphic3d/Graphic3d_ClipPlane.hxx
src/Graphic3d/Graphic3d_SequenceOfHClipPlane.cxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_SequenceOfHClipPlane.hxx
src/OpenGl/FILES
src/OpenGl/OpenGl_CappingAlgo.cxx
src/OpenGl/OpenGl_CappingPlaneResource.cxx
src/OpenGl/OpenGl_Clipping.cxx
src/OpenGl/OpenGl_Clipping.hxx
src/OpenGl/OpenGl_ClippingIterator.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Group.cxx
src/OpenGl/OpenGl_SetOfShaderPrograms.hxx
src/OpenGl/OpenGl_ShaderManager.cxx
src/OpenGl/OpenGl_ShaderManager.hxx
src/OpenGl/OpenGl_ShaderProgram.cxx
src/OpenGl/OpenGl_ShaderProgram.hxx
src/OpenGl/OpenGl_Structure.cxx
src/OpenGl/OpenGl_View_Redraw.cxx
src/OpenGl/OpenGl_Workspace.cxx
src/OpenGl/OpenGl_Workspace.hxx
src/Select3D/Select3D_SensitivePrimitiveArray.hxx
src/SelectMgr/SelectMgr_RectangularFrustum.cxx
src/SelectMgr/SelectMgr_RectangularFrustum.hxx
src/SelectMgr/SelectMgr_ViewClipRange.hxx
src/SelectMgr/SelectMgr_ViewerSelector.cxx
src/Shaders/Declarations.glsl
src/Shaders/Shaders_Declarations_glsl.pxx
src/ViewerTest/ViewerTest.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/bugs/vis/bug25052
tests/v3d/glsl/clipping1 [new file with mode: 0644]

index 53fcee6..8873824 100644 (file)
@@ -193,6 +193,26 @@ public:
     }
   }
 
+  //! Trims the First value in range by the given lower limit.
+  //! Marks range as Void if the given Lower value is greater than range Max.
+  void TrimFrom (const Standard_Real theValLower)
+  {
+    if (!IsVoid())
+    {
+      myFirst = Max (myFirst, theValLower);
+    }
+  }
+
+  //! Trim the Last value in range by the given Upper limit.
+  //! Marks range as Void if the given Upper value is smaller than range Max.
+  void TrimTo (const Standard_Real theValUpper)
+  {
+    if (!IsVoid())
+    {
+      myLast = Min (myLast, theValUpper);
+    }
+  }
+
   //! Returns True if the value is out of this range.
   Standard_Boolean IsOut (Standard_Real theValue) const
   {
index 6432321..2c15a0d 100755 (executable)
@@ -83,6 +83,7 @@ Graphic3d_RenderingMode.hxx
 Graphic3d_RenderingParams.hxx
 Graphic3d_RenderTransparentMethod.hxx
 Graphic3d_SequenceOfGroup.hxx
+Graphic3d_SequenceOfHClipPlane.cxx
 Graphic3d_SequenceOfHClipPlane.hxx
 Graphic3d_SequenceOfStructure.hxx
 Graphic3d_ShaderAttribute.cxx
index 1524c94..22ac56c 100755 (executable)
@@ -45,8 +45,11 @@ namespace
 // =======================================================================
 Graphic3d_ClipPlane::Graphic3d_ClipPlane()
 : myAspect     (defaultAspect()),
+  myPrevInChain(NULL),
   myPlane      (0.0, 0.0, 1.0, 0.0),
   myEquation   (0.0, 0.0, 1.0, 0.0),
+  myEquationRev(0.0, 0.0,-1.0, 0.0),
+  myChainLenFwd(1),
   myFlags      (Graphic3d_CappingFlags_None),
   myEquationMod(0),
   myAspectMod  (0),
@@ -60,10 +63,13 @@ Graphic3d_ClipPlane::Graphic3d_ClipPlane()
 // function : Graphic3d_ClipPlane
 // purpose  :
 // =======================================================================
-Graphic3d_ClipPlane::Graphic3d_ClipPlane(const Equation& theEquation)
+Graphic3d_ClipPlane::Graphic3d_ClipPlane (const Graphic3d_Vec4d& theEquation)
 : myAspect     (defaultAspect()),
+  myPrevInChain(NULL),
   myPlane      (theEquation.x(), theEquation.y(), theEquation.z(), theEquation.w()),
   myEquation   (theEquation),
+  myEquationRev(0.0, 0.0,-1.0, 0.0),
+  myChainLenFwd(1),
   myFlags      (Graphic3d_CappingFlags_None),
   myEquationMod(0),
   myAspectMod  (0),
@@ -71,6 +77,7 @@ Graphic3d_ClipPlane::Graphic3d_ClipPlane(const Equation& theEquation)
   myIsCapping  (Standard_False)
 {
   makeId();
+  updateInversedPlane();
 }
 
 // =======================================================================
@@ -80,8 +87,11 @@ Graphic3d_ClipPlane::Graphic3d_ClipPlane(const Equation& theEquation)
 Graphic3d_ClipPlane::Graphic3d_ClipPlane(const Graphic3d_ClipPlane& theOther)
 : Standard_Transient(theOther),
   myAspect     (defaultAspect()),
+  myPrevInChain(NULL),
   myPlane      (theOther.myPlane),
   myEquation   (theOther.myEquation),
+  myEquationRev(theOther.myEquationRev),
+  myChainLenFwd(1),
   myFlags      (theOther.myFlags),
   myEquationMod(0),
   myAspectMod  (0),
@@ -98,7 +108,9 @@ Graphic3d_ClipPlane::Graphic3d_ClipPlane(const Graphic3d_ClipPlane& theOther)
 // =======================================================================
 Graphic3d_ClipPlane::Graphic3d_ClipPlane(const gp_Pln& thePlane)
 : myAspect     (defaultAspect()),
+  myPrevInChain(NULL),
   myPlane      (thePlane),
+  myChainLenFwd(1),
   myFlags      (Graphic3d_CappingFlags_None),
   myEquationMod(0),
   myAspectMod  (0),
@@ -106,6 +118,7 @@ Graphic3d_ClipPlane::Graphic3d_ClipPlane(const gp_Pln& thePlane)
   myIsCapping  (Standard_False)
 {
   thePlane.Coefficients (myEquation[0], myEquation[1], myEquation[2], myEquation[3]);
+  updateInversedPlane();
   makeId();
 }
 
@@ -113,10 +126,11 @@ Graphic3d_ClipPlane::Graphic3d_ClipPlane(const gp_Pln& thePlane)
 // function : SetEquation
 // purpose  :
 // =======================================================================
-void Graphic3d_ClipPlane::SetEquation (const Equation& theEquation)
+void Graphic3d_ClipPlane::SetEquation (const Graphic3d_Vec4d& theEquation)
 {
   myPlane = gp_Pln (theEquation.x(), theEquation.y(), theEquation.z(), theEquation.w());
   myEquation = theEquation;
+  updateInversedPlane();
   myEquationMod++;
 }
 
@@ -127,10 +141,8 @@ void Graphic3d_ClipPlane::SetEquation (const Equation& theEquation)
 void Graphic3d_ClipPlane::SetEquation (const gp_Pln& thePlane)
 {
   myPlane = thePlane;
-  thePlane.Coefficients (myEquation[0],
-                         myEquation[1],
-                         myEquation[2],
-                         myEquation[3]);
+  thePlane.Coefficients (myEquation[0], myEquation[1], myEquation[2], myEquation[3]);
+  updateInversedPlane();
   myEquationMod++;
 }
 
@@ -140,6 +152,10 @@ void Graphic3d_ClipPlane::SetEquation (const gp_Pln& thePlane)
 // =======================================================================
 void Graphic3d_ClipPlane::SetOn (const Standard_Boolean theIsOn)
 {
+  if (myPrevInChain != NULL)
+  {
+    throw Standard_ProgramError ("Graphic3d_ClipPlane::SetOn() - undefined operation for a plane in Union");
+  }
   myIsOn = theIsOn;
 }
 
@@ -276,3 +292,35 @@ void Graphic3d_ClipPlane::makeId()
   myId = TCollection_AsciiString ("Graphic3d_ClipPlane_") //DynamicType()->Name()
        + TCollection_AsciiString (Standard_Atomic_Increment (&THE_CLIP_PLANE_COUNTER));
 }
+
+// =======================================================================
+// function : updateChainLen
+// purpose  :
+// =======================================================================
+void Graphic3d_ClipPlane::updateChainLen()
+{
+  myChainLenFwd = !myNextInChain.IsNull() ? (myNextInChain->myChainLenFwd + 1) : 1;
+  if (myPrevInChain != NULL)
+  {
+    myPrevInChain->updateChainLen();
+  }
+}
+
+// =======================================================================
+// function : SetChainNextPlane
+// purpose  :
+// =======================================================================
+void Graphic3d_ClipPlane::SetChainNextPlane (const Handle(Graphic3d_ClipPlane)& thePlane)
+{
+  ++myEquationMod;
+  if (!myNextInChain.IsNull())
+  {
+    myNextInChain->myPrevInChain = NULL;
+  }
+  myNextInChain = thePlane;
+  if (!myNextInChain.IsNull())
+  {
+    myNextInChain->myPrevInChain = this;
+  }
+  updateChainLen();
+}
index 11058e3..388ae39 100755 (executable)
@@ -19,6 +19,7 @@
 #include <Aspect_HatchStyle.hxx>
 #include <gp_Pln.hxx>
 #include <Graphic3d_AspectFillArea3d.hxx>
+#include <Graphic3d_BndBox3d.hxx>
 #include <Graphic3d_CappingFlags.hxx>
 #include <Graphic3d_TextureMap.hxx>
 #include <NCollection_Vec4.hxx>
 #include <Standard_TypeDef.hxx>
 #include <Standard_Transient.hxx>
 
-//! Container for properties describing graphic driver clipping planes.
-//! It is up to application to create instances of this class and specify its
-//! properties. The instances are passed into graphic driver or other facilities
-//! that implement clipping features (e.g. selection).
-//! Depending on usage context the class can be used to specify:
-//! - Global clipping applied over the whole scene.
-//! - Object-level clipping applied for each particular object.
+//! Clipping state.
+enum Graphic3d_ClipState
+{
+  Graphic3d_ClipState_Out, //!< fully outside (clipped) - should be discarded
+  Graphic3d_ClipState_In,  //!< fully inside  (NOT clipped) - should NOT be discarded
+  Graphic3d_ClipState_On,  //!< on (not clipped / partially clipped) - should NOT be discarded
+};
+
+//! Container for properties describing either a Clipping halfspace (single Clipping Plane),
+//! or a chain of Clipping Planes defining logical AND (conjunction) operation.
 //! The plane equation is specified in "world" coordinate system.
-//! Please note that the set of planes can define convex clipping volume.
-//! Be aware that number of clip planes supported by OpenGl is implementation
-//! dependent: at least 6 planes are available. Thus, take into account
-//! number of clipping planes passed for rendering: the object planes plus
-//! the view defined ones.
 class Graphic3d_ClipPlane : public Standard_Transient
 {
+  DEFINE_STANDARD_RTTIEXT(Graphic3d_ClipPlane,Standard_Transient)
 public:
 
-  typedef NCollection_Vec4<Standard_Real> Equation;
+  //! Type defining XYZW (ABCD) plane equation - left for compatibility with old code using Graphic3d_ClipPlane::Equation type.
+  typedef Graphic3d_Vec4d Equation;
+
+public:
 
   //! Default constructor.
   //! Initializes clip plane container with the following properties:
@@ -63,7 +66,7 @@ public:
   //! Construct clip plane for the passed equation.
   //! By default the plane is on, capping is turned off.
   //! @param theEquation [in] the plane equation.
-  Standard_EXPORT Graphic3d_ClipPlane (const Equation& theEquation);
+  Standard_EXPORT Graphic3d_ClipPlane (const Graphic3d_Vec4d& theEquation);
 
   //! Construct clip plane from the passed geometrical definition.
   //! By default the plane is on, capping is turned off.
@@ -78,14 +81,15 @@ public:
   //! Set 4-component equation vector for clipping plane.
   //! The equation is specified in "world" coordinate system.
   //! @param theEquation [in] the XYZW (or "ABCD") equation vector.
-  Standard_EXPORT void SetEquation (const Equation& theEquation);
+  Standard_EXPORT void SetEquation (const Graphic3d_Vec4d& theEquation);
 
   //! Get 4-component equation vector for clipping plane.
   //! @return clipping plane equation vector.
-  const Equation& GetEquation() const
-  {
-    return myEquation;
-  }
+  const Graphic3d_Vec4d& GetEquation() const { return myEquation; }
+
+  //! Get 4-component equation vector for clipping plane.
+  //! @return clipping plane equation vector.
+  const Graphic3d_Vec4d& ReversedEquation() const { return myEquationRev; }
 
   //! Check that the clipping plane is turned on.
   //! @return boolean flag indicating whether the plane is in on or off state.
@@ -123,6 +127,43 @@ public:
   //! @return new instance of clipping plane with same properties and attributes.
   Standard_EXPORT virtual Handle(Graphic3d_ClipPlane) Clone() const;
 
+public:
+
+  //! Return TRUE if this item defines a conjunction (logical AND) between a set of Planes.
+  //! Graphic3d_ClipPlane item defines either a Clipping halfspace (single Clipping Plane)
+  //! or a Clipping volume defined by a logical AND (conjunction) operation between a set of Planes defined as a Chain
+  //! (so that the volume cuts a space only in case if check fails for ALL Planes in the Chain).
+  //!
+  //! Note that Graphic3d_ClipPlane item cannot:
+  //! - Define a Chain with logical OR (disjunction) operation;
+  //!   this should be done through Graphic3d_SequenceOfHClipPlane.
+  //! - Define nested Chains.
+  //! - Disable Chain items; only entire Chain can be disabled (by disabled a head of Chain).
+  //!
+  //! The head of a Chain defines all visual properties of the Chain,
+  //! so that Graphic3d_ClipPlane of next items in a Chain merely defines only geometrical definition of the plane.
+  Standard_Boolean IsChain() const { return !myNextInChain.IsNull(); }
+
+  //! Return the previous plane in a Chain of Planes defining logical AND operation,
+  //! or NULL if there is no Chain or it is a first element in Chain.
+  //! When clipping is defined by a Chain of Planes,
+  //! it cuts a space only in case if check fails for all Planes in Chain.
+  Handle(Graphic3d_ClipPlane) ChainPreviousPlane() const { return myPrevInChain; }
+
+  //! Return the next plane in a Chain of Planes defining logical AND operation,
+  //! or NULL if there is no chain or it is a last element in chain.
+
+  const Handle(Graphic3d_ClipPlane)& ChainNextPlane() const { return myNextInChain; }
+
+  //! Return the number of chains in forward direction (including this item, so it is always >= 1).
+  //! For a head of Chain - returns the length of entire Chain.
+  Standard_Integer NbChainNextPlanes() const { return myChainLenFwd; }
+
+  //! Set the next plane in a Chain of Planes.
+  //! This operation also updates relationship between chains (Previous/Next items),
+  //! so that the previously set Next plane is cut off.
+  Standard_EXPORT void SetChainNextPlane (const Handle(Graphic3d_ClipPlane)& thePlane);
+
 public: // @name user-defined graphical attributes
 
   //! Set material for rendering capping surface.
@@ -209,6 +250,113 @@ public:
   //! Return true if some fill area aspect properties should be taken from object.
   bool ToUseObjectProperties() const { return myFlags != Graphic3d_CappingFlags_None; }
 
+public:
+
+  //! Check if the given point is outside / inside / on section.
+  Graphic3d_ClipState ProbePoint (const Graphic3d_Vec4d& thePoint) const
+  {
+    for (const Graphic3d_ClipPlane* aPlaneIter = this; aPlaneIter != NULL; aPlaneIter = aPlaneIter->myNextInChain.get())
+    {
+      Graphic3d_ClipState aPlnState = aPlaneIter->ProbePointHalfspace (thePoint);
+      if (aPlnState == Graphic3d_ClipState_On)
+      {
+        return Graphic3d_ClipState_On;
+      }
+      else if (aPlnState == Graphic3d_ClipState_Out
+            && aPlaneIter->myNextInChain.IsNull())
+      {
+        return Graphic3d_ClipState_Out;
+      }
+    }
+    return Graphic3d_ClipState_In;
+  }
+
+  //! Check if the given bounding box is fully outside / fully inside.
+  Graphic3d_ClipState ProbeBox (const Graphic3d_BndBox3d& theBox) const
+  {
+    Graphic3d_ClipState aPrevState = Graphic3d_ClipState_On;
+    for (const Graphic3d_ClipPlane* aPlaneIter = this; aPlaneIter != NULL; aPlaneIter = aPlaneIter->myNextInChain.get())
+    {
+      if (aPlaneIter->IsBoxFullOutHalfspace (theBox))
+      {
+        if (aPlaneIter->myNextInChain.IsNull())
+        {
+          return Graphic3d_ClipState_Out;
+        }
+        else if (aPrevState == Graphic3d_ClipState_In)
+        {
+          return Graphic3d_ClipState_On;
+        }
+        aPrevState = Graphic3d_ClipState_Out;
+      }
+      else if (aPlaneIter->IsBoxFullInHalfspace (theBox))
+      {
+        if (aPlaneIter->myNextInChain.IsNull())
+        {
+          return Graphic3d_ClipState_In;
+        }
+        else if (aPrevState == Graphic3d_ClipState_Out)
+        {
+          return Graphic3d_ClipState_On;
+        }
+        aPrevState = Graphic3d_ClipState_In;
+      }
+      else
+      {
+        return Graphic3d_ClipState_On;
+      }
+    }
+    return Graphic3d_ClipState_On;
+  }
+
+public:
+
+  //! Check if the given point is outside of the half-space (e.g. should be discarded by clipping plane).
+  Graphic3d_ClipState ProbePointHalfspace (const Graphic3d_Vec4d& thePoint) const
+  {
+    const Standard_Real aVal = myEquation.Dot (thePoint);
+    return aVal < 0.0
+         ? Graphic3d_ClipState_Out
+         : (aVal == 0.0
+          ? Graphic3d_ClipState_On
+          : Graphic3d_ClipState_In);
+  }
+
+  //! Check if the given bounding box is fully outside / fully inside the half-space.
+  Graphic3d_ClipState ProbeBoxHalfspace (const Graphic3d_BndBox3d& theBox) const
+  {
+    if (IsBoxFullOutHalfspace (theBox))
+    {
+      return Graphic3d_ClipState_Out;
+    }
+    return IsBoxFullInHalfspace (theBox)
+         ? Graphic3d_ClipState_In
+         : Graphic3d_ClipState_On;
+  }
+
+  //! Check if the given point is outside of the half-space (e.g. should be discarded by clipping plane).
+  bool IsPointOutHalfspace (const Graphic3d_Vec4d& thePoint) const { return ProbePointHalfspace (thePoint) == Graphic3d_ClipState_Out; }
+
+  //! Check if the given bounding box is fully outside of the half-space (e.g. should be discarded by clipping plane).
+  bool IsBoxFullOutHalfspace (const Graphic3d_BndBox3d& theBox) const
+  {
+    const Graphic3d_Vec4d aMaxPnt (myEquation.x() > 0.0 ? theBox.CornerMax().x() : theBox.CornerMin().x(),
+                                   myEquation.y() > 0.0 ? theBox.CornerMax().y() : theBox.CornerMin().y(),
+                                   myEquation.z() > 0.0 ? theBox.CornerMax().z() : theBox.CornerMin().z(),
+                                   1.0);
+    return IsPointOutHalfspace (aMaxPnt);
+  }
+
+  //! Check if the given bounding box is fully inside (or touches from inside) the half-space (e.g. NOT discarded by clipping plane).
+  bool IsBoxFullInHalfspace (const Graphic3d_BndBox3d& theBox) const
+  {
+    const Graphic3d_Vec4d aMinPnt (myEquation.x() > 0.0 ? theBox.CornerMin().x() : theBox.CornerMax().x(),
+                                   myEquation.y() > 0.0 ? theBox.CornerMin().y() : theBox.CornerMax().y(),
+                                   myEquation.z() > 0.0 ? theBox.CornerMin().z() : theBox.CornerMax().z(),
+                                   1.0);
+    return !IsPointOutHalfspace (aMinPnt);
+  }
+
 public: // @name modification counters
 
   //! @return modification counter for equation.
@@ -231,21 +379,33 @@ private:
   //! Set capping flag.
   Standard_EXPORT void setCappingFlag (bool theToUse, int theFlag);
 
+  //! Update chain length in backward direction.
+  void updateChainLen();
+
+  //! Update inversed plane definition from main plane.
+  void updateInversedPlane()
+  {
+    gp_Pln aPlane = myPlane;
+    aPlane.SetAxis (aPlane.Axis().Reversed());
+    aPlane.Coefficients (myEquationRev[0], myEquationRev[1], myEquationRev[2], myEquationRev[3]);
+  }
+
 private:
 
   Handle(Graphic3d_AspectFillArea3d) myAspect;    //!< fill area aspect
+  Handle(Graphic3d_ClipPlane)   myNextInChain;    //!< next     plane in a chain of planes defining logical AND operation
+  Graphic3d_ClipPlane*          myPrevInChain;    //!< previous plane in a chain of planes defining logical AND operation
   TCollection_AsciiString myId;                   //!< resource id
   gp_Pln                  myPlane;                //!< plane definition
-  Equation                myEquation;             //!< plane equation vector
+  Graphic3d_Vec4d         myEquation;             //!< plane equation vector
+  Graphic3d_Vec4d         myEquationRev;          //!< reversed plane equation
+  Standard_Integer        myChainLenFwd;          //!< chain length in forward direction (including this item)
   unsigned int            myFlags;                //!< capping flags
   unsigned int            myEquationMod;          //!< modification counter for equation
   unsigned int            myAspectMod;            //!< modification counter of aspect
   Standard_Boolean        myIsOn;                 //!< state of the clipping plane
   Standard_Boolean        myIsCapping;            //!< state of graphic driver capping
 
-public:
-
-  DEFINE_STANDARD_RTTIEXT(Graphic3d_ClipPlane,Standard_Transient)
 };
 
 DEFINE_STANDARD_HANDLE (Graphic3d_ClipPlane, Standard_Transient)
diff --git a/src/Graphic3d/Graphic3d_SequenceOfHClipPlane.cxx b/src/Graphic3d/Graphic3d_SequenceOfHClipPlane.cxx
new file mode 100644 (file)
index 0000000..e8cb10c
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright (c) 2018 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 <Graphic3d_SequenceOfHClipPlane.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_SequenceOfHClipPlane, Standard_Transient)
+
+// =======================================================================
+// function : Graphic3d_SequenceOfHClipPlane
+// purpose  :
+// =======================================================================
+Graphic3d_SequenceOfHClipPlane::Graphic3d_SequenceOfHClipPlane()
+: myToOverrideGlobal (Standard_False)
+{
+  //
+}
+
+// =======================================================================
+// function : Append
+// purpose  :
+// =======================================================================
+bool Graphic3d_SequenceOfHClipPlane::Append (const Handle(Graphic3d_ClipPlane)& theItem)
+{
+  for (NCollection_Sequence<Handle(Graphic3d_ClipPlane)>::Iterator anItemIter (myItems); anItemIter.More(); anItemIter.Next())
+  {
+    if (anItemIter.Value() == theItem)
+    {
+      return false;
+    }
+  }
+  myItems.Append (theItem);
+  return true;
+}
+
+// =======================================================================
+// function : Remove
+// purpose  :
+// =======================================================================
+bool Graphic3d_SequenceOfHClipPlane::Remove (const Handle(Graphic3d_ClipPlane)& theItem)
+{
+  for (NCollection_Sequence<Handle(Graphic3d_ClipPlane)>::Iterator anItemIter (myItems); anItemIter.More(); anItemIter.Next())
+  {
+    if (anItemIter.Value() == theItem)
+    {
+      myItems.Remove (anItemIter);
+      return true;
+    }
+  }
+  return false;
+}
index 457e799..014aaeb 100755 (executable)
 #define _Graphic3d_SequenceOfHClipPlane_HeaderFile
 
 #include <NCollection_Sequence.hxx>
-#include <NCollection_Shared.hxx>
 #include <Graphic3d_ClipPlane.hxx>
 
-//! Class defining the sequence of clipping planes.
-class Graphic3d_SequenceOfHClipPlane : public Standard_Transient, public NCollection_Sequence<Handle(Graphic3d_ClipPlane)>
+//! Class defines a Clipping Volume as a logical OR (disjunction) operation between Graphic3d_ClipPlane in sequence.
+//! Each Graphic3d_ClipPlane represents either a single Plane clipping a halfspace (direction is specified by normal),
+//! or a sub-chain of planes defining a logical AND (conjunction) operation.
+//! Therefore, this collection allows defining a Clipping Volume through the limited set of Boolean operations between clipping Planes.
+//!
+//! The Clipping Volume can be assigned either to entire View or to a specific Object;
+//! in the latter case property ToOverrideGlobal() will specify if Object planes should override (suppress) globally defined ones
+//! or extend their definition through logical OR (disjunction) operation.
+//!
+//! Note that defining (many) planes will lead to performance degradation, and Graphics Driver may limit
+//! the overall number of simultaneously active clipping planes - but at least 6 planes should be supported on all configurations.
+class Graphic3d_SequenceOfHClipPlane : public Standard_Transient
 {
-DEFINE_STANDARD_RTTI_INLINE(Graphic3d_SequenceOfHClipPlane,Standard_Transient)
+  DEFINE_STANDARD_RTTIEXT(Graphic3d_SequenceOfHClipPlane, Standard_Transient)
+public:
+
+  //! Iterator through clipping planes.
+  class Iterator : public NCollection_Sequence<Handle(Graphic3d_ClipPlane)>::Iterator
+  {
+  public:
+    Iterator() {}
+    Iterator (const Graphic3d_SequenceOfHClipPlane& thePlanes) : NCollection_Sequence<Handle(Graphic3d_ClipPlane)>::Iterator (thePlanes.myItems) {}
+    Iterator (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes) { Init (thePlanes); }
+
+    void Init (const Graphic3d_SequenceOfHClipPlane& thePlanes) { NCollection_Sequence<Handle(Graphic3d_ClipPlane)>::Iterator::Init (thePlanes.myItems); }
+    void Init (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
+    {
+      if (!thePlanes.IsNull())
+      {
+        NCollection_Sequence<Handle(Graphic3d_ClipPlane)>::Iterator::Init (thePlanes->myItems);
+      }
+      else
+      {
+        *this = Iterator();
+      }
+    }
+  };
+
 public:
-  DEFINE_STANDARD_ALLOC
-  DEFINE_NCOLLECTION_ALLOC
 
   //! Empty constructor.
-  Graphic3d_SequenceOfHClipPlane() : myToOverrideGlobal (Standard_False) {}
+  Standard_EXPORT Graphic3d_SequenceOfHClipPlane();
 
   //! Return true if local properties should override global properties.
   Standard_Boolean ToOverrideGlobal() const { return myToOverrideGlobal; }
@@ -37,8 +68,35 @@ public:
   //! Setup flag defining if local properties should override global properties.
   void SetOverrideGlobal (const Standard_Boolean theToOverride) { myToOverrideGlobal = theToOverride; }
 
-private:
+  //! Return TRUE if sequence is empty.
+  bool IsEmpty() const { return myItems.IsEmpty(); }
+
+  //! Return the number of items in sequence.
+  Standard_Integer Size() const { return myItems.Size(); }
+
+  //! Append a plane.
+  //! @return TRUE if new item has been added (FALSE if item already existed)
+  Standard_EXPORT bool Append (const Handle(Graphic3d_ClipPlane)& theItem);
+
+  //! Remove a plane.
+  //! @return TRUE if item has been found and removed
+  Standard_EXPORT bool Remove (const Handle(Graphic3d_ClipPlane)& theItem);
+
+  //! Remove a plane.
+  void Remove (Iterator& theItem) { myItems.Remove (theItem); }
+
+  //! Clear the items out.
+  void Clear()
+  {
+    myItems.Clear();
+  }
+
+  //! Return the first item in sequence.
+  const Handle(Graphic3d_ClipPlane)& First() const { return myItems.First(); }
+
+protected:
 
+  NCollection_Sequence<Handle(Graphic3d_ClipPlane)> myItems;
   Standard_Boolean myToOverrideGlobal;
 
 };
index 80a9aa0..c9e4fa9 100755 (executable)
@@ -77,6 +77,7 @@ OpenGl_Caps.cxx
 OpenGl_Caps.hxx
 OpenGl_Clipping.cxx
 OpenGl_Clipping.hxx
+OpenGl_ClippingIterator.hxx
 OpenGl_Context.cxx
 OpenGl_Context.hxx
 OpenGl_Context_1.mm
index a729da3..0a438fb 100755 (executable)
@@ -15,6 +15,7 @@
 
 #include <OpenGl_CappingAlgo.hxx>
 
+#include <OpenGl_ClippingIterator.hxx>
 #include <OpenGl_Workspace.hxx>
 #include <OpenGl_Context.hxx>
 #include <OpenGl_PrimitiveArray.hxx>
@@ -37,6 +38,7 @@ namespace
     const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
     thePlane->Update (aContext, theAspectFace != NULL ? theAspectFace->Aspect() : Handle(Graphic3d_AspectFillArea3d)());
 
+    bool wasCullAllowed = theWorkspace->SetAllowFaceCulling (true);
     const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace();
     theWorkspace->SetAspectFace (thePlane->AspectFace());
 
@@ -50,13 +52,15 @@ namespace
     aContext->ModelWorldState.Pop();
     aContext->ApplyModelViewMatrix();
 
+    theWorkspace->SetAllowFaceCulling (wasCullAllowed);
     theWorkspace->SetAspectFace (aFaceAspect);
   }
 
   //! Render capping for specific structure.
   static void renderCappingForStructure (const Handle(OpenGl_Workspace)& theWorkspace,
                                          const OpenGl_Structure&         theStructure,
-                                         const OpenGl_ClippingIterator&  thePlaneIter,
+                                         const Handle(Graphic3d_ClipPlane)& theClipChain,
+                                         const Standard_Integer          theSubPlaneIndex,
                                          const Handle(OpenGl_CappingPlaneResource)& thePlane)
   {
     const Handle(OpenGl_Context)&      aContext     = theWorkspace->GetGlContext();
@@ -69,7 +73,7 @@ namespace
       }
 
       // enable only the rendering plane to generate stencil mask
-      aContext->ChangeClipping().DisableAllExcept (aContext, thePlaneIter);
+      aContext->ChangeClipping().DisableAllExcept (theClipChain, theSubPlaneIndex);
       aContext->ShaderManager()->UpdateClippingState();
 
       glClear (GL_STENCIL_BUFFER_BIT);
@@ -112,7 +116,7 @@ namespace
       theWorkspace->ApplyAspectFace();
 
       // enable all clip plane except the rendered one
-      aContext->ChangeClipping().EnableAllExcept (aContext, thePlaneIter);
+      aContext->ChangeClipping().EnableAllExcept (theClipChain, theSubPlaneIndex);
       aContext->ShaderManager()->UpdateClippingState();
 
       // render capping plane using the generated stencil mask
@@ -128,19 +132,18 @@ namespace
         glEnable (GL_DEPTH_TEST);
       }
 
-      renderPlane (theWorkspace, thePlane, aRenderPlane->ToUseObjectProperties()
-                                         ? aGroupIter.Value()->AspectFace()
-                                         : NULL);
+      renderPlane (theWorkspace, thePlane,
+                   aRenderPlane->ToUseObjectProperties() ? aGroupIter.Value()->AspectFace() : NULL);
 
       // turn on the current plane to restore initial state
-      aContext->ChangeClipping().SetEnabled (aContext, thePlaneIter, Standard_True);
+      aContext->ChangeClipping().ResetCappingFilter();
       aContext->ShaderManager()->RevertClippingState();
       aContext->ShaderManager()->RevertClippingState();
     }
 
     if (theStructure.InstancedStructure() != NULL)
     {
-      renderCappingForStructure (theWorkspace, *theStructure.InstancedStructure(), thePlaneIter, thePlane);
+      renderCappingForStructure (theWorkspace, *theStructure.InstancedStructure(), theClipChain, theSubPlaneIndex, thePlane);
     }
   }
 }
@@ -181,28 +184,32 @@ void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorks
   for (OpenGl_ClippingIterator aCappingIt (aContext->Clipping()); aCappingIt.More(); aCappingIt.Next())
   {
     // get plane being rendered
-    const Handle(Graphic3d_ClipPlane)& aRenderPlane = aCappingIt.Value();
-    if (!aRenderPlane->IsCapping()
+    const Handle(Graphic3d_ClipPlane)& aClipChain = aCappingIt.Value();
+    if (!aClipChain->IsCapping()
       || aCappingIt.IsDisabled())
     {
       continue;
     }
 
-    // get resource for the plane
-    const TCollection_AsciiString& aResId = aRenderPlane->GetId();
-    Handle(OpenGl_CappingPlaneResource) aPlaneRes;
-    if (!aContext->GetResource (aResId, aPlaneRes))
+    Standard_Integer aSubPlaneIndex = 1;
+    for (const Graphic3d_ClipPlane* aSubPlaneIter = aClipChain.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
     {
-      // share and register for release once the resource is no longer used
-      aPlaneRes = new OpenGl_CappingPlaneResource (aRenderPlane);
-      aContext->ShareResource (aResId, aPlaneRes);
-    }
+      // get resource for the plane
+      const TCollection_AsciiString& aResId = aSubPlaneIter->GetId();
+      Handle(OpenGl_CappingPlaneResource) aPlaneRes;
+      if (!aContext->GetResource (aResId, aPlaneRes))
+      {
+        // share and register for release once the resource is no longer used
+        aPlaneRes = new OpenGl_CappingPlaneResource (aSubPlaneIter);
+        aContext->ShareResource (aResId, aPlaneRes);
+      }
 
-    renderCappingForStructure (theWorkspace, theStructure, aCappingIt, aPlaneRes);
+      renderCappingForStructure (theWorkspace, theStructure, aClipChain, aSubPlaneIndex, aPlaneRes);
 
-    // set delayed resource release
-    aPlaneRes.Nullify();
-    aContext->ReleaseResource (aResId, Standard_True);
+      // set delayed resource release
+      aPlaneRes.Nullify();
+      aContext->ReleaseResource (aResId, Standard_True);
+    }
   }
 
   // restore previous application state
index a4b7793..d551231 100755 (executable)
@@ -29,21 +29,21 @@ namespace
   //!  - 4 floats, UV texture coordinates
   static const GLfloat THE_CAPPING_PLN_VERTS[12 * (4 + 4 + 4)] =
   {
-    0.0f, 0.0f, 0.0f, 1.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
-    1.0f, 0.0f, 0.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,   1.0f, 0.0f, 0.0f, 0.0f,
-    0.0f, 0.0f, 1.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f,-1.0f, 0.0f, 0.0f,
+    0.0f, 0.0f, 0.0f, 1.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
+    0.0f, 0.0f, 1.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f,-1.0f, 0.0f, 0.0f,
+    1.0f, 0.0f, 0.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,   1.0f, 0.0f, 0.0f, 0.0f,
 
-    0.0f, 0.0f, 0.0f, 1.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
-    0.0f, 0.0f, 1.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f,-1.0f, 0.0f, 0.0f,
-   -1.0f, 0.0f, 0.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,  -1.0f, 0.0f, 0.0f, 0.0f,
+    0.0f, 0.0f, 0.0f, 1.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
+   -1.0f, 0.0f, 0.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,  -1.0f, 0.0f, 0.0f, 0.0f,
+    0.0f, 0.0f, 1.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f,-1.0f, 0.0f, 0.0f,
 
-    0.0f, 0.0f, 0.0f, 1.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
-   -1.0f, 0.0f, 0.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,  -1.0f, 0.0f, 0.0f, 0.0f,
-    0.0f, 0.0f,-1.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f, 1.0f, 0.0f, 0.0f,
+    0.0f, 0.0f, 0.0f, 1.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
+    0.0f, 0.0f,-1.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f, 1.0f, 0.0f, 0.0f,
+   -1.0f, 0.0f, 0.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,  -1.0f, 0.0f, 0.0f, 0.0f,
 
-    0.0f, 0.0f, 0.0f, 1.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
-    0.0f, 0.0f,-1.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f, 1.0f, 0.0f, 0.0f,
-    1.0f, 0.0f, 0.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,   1.0f, 0.0f, 0.0f, 0.0f
+    0.0f, 0.0f, 0.0f, 1.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
+    1.0f, 0.0f, 0.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,   1.0f, 0.0f, 0.0f, 0.0f,
+    0.0f, 0.0f,-1.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f, 1.0f, 0.0f, 0.0f
   };
 
   static const OpenGl_Matrix OpenGl_IdentityMatrix =
index edc9b71..a572df8 100755 (executable)
 
 #include <OpenGl_Clipping.hxx>
 
-#include <OpenGl_GlCore11.hxx>
-#include <OpenGl_Workspace.hxx>
-#include <OpenGl_Context.hxx>
+#include <OpenGl_ClippingIterator.hxx>
 
 // =======================================================================
-// function : OpenGl_ClippingIterator
+// function : OpenGl_Clipping
 // purpose  :
 // =======================================================================
-OpenGl_ClippingIterator::OpenGl_ClippingIterator (const OpenGl_Clipping& theClipping)
-: myDisabled  (&theClipping.myDisabledPlanes),
-  myCurrIndex (1)
-{
-  if (!theClipping.myPlanesGlobal.IsNull())
-  {
-    myIter1.Init (*theClipping.myPlanesGlobal);
-  }
-  if (!theClipping.myPlanesLocal.IsNull())
-  {
-    myIter2.Init (*theClipping.myPlanesLocal);
-  }
-}
-
-// =======================================================================
-// function : OpenGl_ClippingState
-// purpose  :
-// =======================================================================
-OpenGl_Clipping::OpenGl_Clipping ()
-: myNbClipping (0),
+OpenGl_Clipping::OpenGl_Clipping()
+: myCappedSubPlane (0),
+  myNbClipping (0),
   myNbCapping  (0),
+  myNbChains   (0),
   myNbDisabled (0)
 {}
 
@@ -51,32 +33,36 @@ OpenGl_Clipping::OpenGl_Clipping ()
 // function : Init
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::Init (const Standard_Integer )
+void OpenGl_Clipping::Init()
 {
   myPlanesGlobal.Nullify();
   myPlanesLocal.Nullify();
 
   myNbClipping = 0;
   myNbCapping  = 0;
+  myNbChains   = 0;
   myNbDisabled = 0;
+  myCappedSubPlane = 0;
+  myCappedChain.Nullify();
 }
 
 // =======================================================================
 // function : Reset
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::Reset (const Handle(OpenGl_Context)& theGlCtx,
-                             const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
+void OpenGl_Clipping::Reset (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
 {
   const Standard_Integer aStartIndex = myPlanesGlobal.IsNull() ? 1 : myPlanesGlobal->Size() + 1;
-  remove (theGlCtx, myPlanesLocal,  aStartIndex);
-  remove (theGlCtx, myPlanesGlobal, 1);
+  remove (myPlanesLocal,  aStartIndex);
+  remove (myPlanesGlobal, 1);
 
   myPlanesGlobal = thePlanes;
   myPlanesLocal.Nullify();
 
-  add (theGlCtx, thePlanes, 1);
+  add (thePlanes, 1);
   myNbDisabled = 0;
+  myCappedSubPlane = 0;
+  myCappedChain.Nullify();
 
   // Method ::add() implicitly extends myDisabledPlanes (NCollection_Vector::SetValue()),
   // however we do not reset myDisabledPlanes and mySkipFilter beforehand to avoid redundant memory re-allocations.
@@ -88,23 +74,21 @@ void OpenGl_Clipping::Reset (const Handle(OpenGl_Context)& theGlCtx,
 // function : SetLocalPlanes
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::SetLocalPlanes (const Handle(OpenGl_Context)& theGlCtx,
-                                      const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
+void OpenGl_Clipping::SetLocalPlanes (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
 {
   const Standard_Integer aStartIndex = myPlanesGlobal.IsNull() ? 1 : myPlanesGlobal->Size() + 1;
-  remove (theGlCtx, myPlanesLocal, aStartIndex);
+  remove (myPlanesLocal, aStartIndex);
 
   myPlanesLocal = thePlanes;
 
-  add (theGlCtx, thePlanes, aStartIndex);
+  add (thePlanes, aStartIndex);
 }
 
 // =======================================================================
 // function : add
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::add (const Handle(OpenGl_Context)& ,
-                           const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
+void OpenGl_Clipping::add (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
                            const Standard_Integer theStartIndex)
 {
   if (thePlanes.IsNull())
@@ -122,13 +106,15 @@ void OpenGl_Clipping::add (const Handle(OpenGl_Context)& ,
       continue;
     }
 
+    const Standard_Integer aNbSubPlanes = aPlane->NbChainNextPlanes();
+    myNbChains += 1;
     if (aPlane->IsCapping())
     {
-      ++myNbCapping;
+      myNbCapping += aNbSubPlanes;
     }
     else
     {
-      ++myNbClipping;
+      myNbClipping += aNbSubPlanes;
     }
   }
 }
@@ -137,8 +123,7 @@ void OpenGl_Clipping::add (const Handle(OpenGl_Context)& ,
 // function : remove
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::remove (const Handle(OpenGl_Context)& ,
-                              const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
+void OpenGl_Clipping::remove (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
                               const Standard_Integer theStartIndex)
 {
   if (thePlanes.IsNull())
@@ -156,13 +141,15 @@ void OpenGl_Clipping::remove (const Handle(OpenGl_Context)& ,
       continue;
     }
 
+    const Standard_Integer aNbSubPlanes = aPlane->NbChainNextPlanes();
+    myNbChains -= 1;
     if (aPlane->IsCapping())
     {
-      --myNbCapping;
+      myNbCapping -= aNbSubPlanes;
     }
     else
     {
-      --myNbClipping;
+      myNbClipping -= aNbSubPlanes;
     }
   }
 }
@@ -171,8 +158,7 @@ void OpenGl_Clipping::remove (const Handle(OpenGl_Context)& ,
 // function : SetEnabled
 // purpose  :
 // =======================================================================
-Standard_Boolean OpenGl_Clipping::SetEnabled (const Handle(OpenGl_Context)&  ,
-                                              const OpenGl_ClippingIterator& thePlane,
+Standard_Boolean OpenGl_Clipping::SetEnabled (const OpenGl_ClippingIterator& thePlane,
                                               const Standard_Boolean         theIsEnabled)
 {
   const Standard_Integer aPlaneIndex = thePlane.PlaneIndex();
@@ -183,15 +169,17 @@ Standard_Boolean OpenGl_Clipping::SetEnabled (const Handle(OpenGl_Context)&  ,
   }
 
   isDisabled = !theIsEnabled;
+  const Standard_Integer aNbSubPlanes = thePlane.Value()->NbChainNextPlanes();
   if (thePlane.Value()->IsCapping())
   {
-    myNbCapping += (theIsEnabled ? 1 : -1);
+    myNbCapping += (theIsEnabled ? aNbSubPlanes : -aNbSubPlanes);
   }
   else
   {
-    myNbClipping += (theIsEnabled ? 1 : -1);
+    myNbClipping += (theIsEnabled ? aNbSubPlanes : -aNbSubPlanes);
   }
-  myNbDisabled -= (theIsEnabled ? 1 : -1);
+  myNbChains   += (theIsEnabled ? 1 : -1);
+  myNbDisabled += (theIsEnabled ? -aNbSubPlanes : aNbSubPlanes);
   return Standard_True;
 }
 
@@ -199,7 +187,7 @@ Standard_Boolean OpenGl_Clipping::SetEnabled (const Handle(OpenGl_Context)&  ,
 // function : RestoreDisabled
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::RestoreDisabled (const Handle(OpenGl_Context)& )
+void OpenGl_Clipping::RestoreDisabled()
 {
   if (myNbDisabled == 0)
   {
@@ -217,13 +205,15 @@ void OpenGl_Clipping::RestoreDisabled (const Handle(OpenGl_Context)& )
 
     isDisabled = Standard_False;
     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
+    const Standard_Integer aNbSubPlanes = aPlane->NbChainNextPlanes();
+    myNbChains += 1;
     if (aPlane->IsCapping())
     {
-      ++myNbCapping;
+      myNbCapping += aNbSubPlanes;
     }
     else
     {
-      ++myNbClipping;
+      myNbClipping += aNbSubPlanes;
     }
   }
 }
@@ -232,7 +222,7 @@ void OpenGl_Clipping::RestoreDisabled (const Handle(OpenGl_Context)& )
 // function : DisableGlobal
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::DisableGlobal (const Handle(OpenGl_Context)& theGlCtx)
+void OpenGl_Clipping::DisableGlobal()
 {
   for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
   {
@@ -242,7 +232,7 @@ void OpenGl_Clipping::DisableGlobal (const Handle(OpenGl_Context)& theGlCtx)
       return;
     }
 
-    SetEnabled (theGlCtx, aPlaneIter, Standard_False);
+    SetEnabled (aPlaneIter, Standard_False);
   }
 }
 
@@ -250,38 +240,30 @@ void OpenGl_Clipping::DisableGlobal (const Handle(OpenGl_Context)& theGlCtx)
 // function : DisableAllExcept
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::DisableAllExcept (const Handle(OpenGl_Context)&  theGlCtx,
-                                        const OpenGl_ClippingIterator& thePlane)
+void OpenGl_Clipping::DisableAllExcept (const Handle(Graphic3d_ClipPlane)& theChain,
+                                        const Standard_Integer theSubPlaneIndex)
 {
-  for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
-  {
-    if (aPlaneIter.IsDisabled())
-    {
-      mySkipFilter.SetValue (aPlaneIter.PlaneIndex(), Standard_True);
-      continue;
-    }
-
-    const Standard_Boolean isOn = (aPlaneIter.PlaneIndex() == thePlane.PlaneIndex());
-    SetEnabled (theGlCtx, aPlaneIter, isOn);
-    mySkipFilter.SetValue (aPlaneIter.PlaneIndex(), Standard_False);
-  }
+  myCappedChain = theChain;
+  myCappedSubPlane = theSubPlaneIndex;
 }
 
 // =======================================================================
 // function : EnableAllExcept
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::EnableAllExcept (const Handle(OpenGl_Context)&  theGlCtx,
-                                       const OpenGl_ClippingIterator& thePlane)
+void OpenGl_Clipping::EnableAllExcept (const Handle(Graphic3d_ClipPlane)& theChain,
+                                       const Standard_Integer theSubPlaneIndex)
 {
-  for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
-  {
-    if (mySkipFilter.Value (aPlaneIter.PlaneIndex()))
-    {
-      continue;
-    }
+  myCappedChain = theChain;
+  myCappedSubPlane = -theSubPlaneIndex;
+}
 
-    const Standard_Boolean isOn = (aPlaneIter.PlaneIndex() != thePlane.PlaneIndex());
-    SetEnabled (theGlCtx, aPlaneIter, isOn);
-  }
+// =======================================================================
+// function : ResetCappingFilter
+// purpose  :
+// =======================================================================
+void OpenGl_Clipping::ResetCappingFilter()
+{
+  myCappedChain.Nullify();
+  myCappedSubPlane = 0;
 }
index 6e1c5d3..b2fe1f3 100755 (executable)
@@ -20,7 +20,6 @@
 #include <NCollection_Vector.hxx>
 #include <Standard_TypeDef.hxx>
 
-class OpenGl_Context;
 class OpenGl_ClippingIterator;
 
 //! This class contains logics related to tracking and modification of clipping plane
@@ -30,35 +29,51 @@ class OpenGl_ClippingIterator;
 //! class.
 class OpenGl_Clipping
 {
+  friend class OpenGl_ClippingIterator;
 public: //! @name general methods
 
   //! Default constructor.
   Standard_EXPORT OpenGl_Clipping();
 
   //! Initialize.
-  //! @param theMaxPlanes [in] number of clipping planes supported by OpenGl context.
-  Standard_EXPORT void Init (const Standard_Integer theMaxPlanes);
+  Standard_EXPORT void Init();
 
   //! Setup list of global (for entire view) clipping planes
   //! and clears local plane list if it was not released before.
-  Standard_EXPORT void Reset (const Handle(OpenGl_Context)& theGlCtx,
-                              const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes);
+  Standard_EXPORT void Reset (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes);
 
   //! Setup list of local (for current object) clipping planes.
-  Standard_EXPORT void SetLocalPlanes (const Handle(OpenGl_Context)& theGlCtx,
-                                       const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes);
-
-  //! @return true if there are enabled clipping planes (NOT capping)
-  Standard_Boolean IsClippingOn() const { return myNbClipping > 0; }
+  Standard_EXPORT void SetLocalPlanes (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes);
 
   //! @return true if there are enabled capping planes
   Standard_Boolean IsCappingOn() const { return myNbCapping > 0; }
 
   //! @return true if there are enabled clipping or capping planes
-  Standard_Boolean IsClippingOrCappingOn() const { return (myNbClipping + myNbCapping) > 0; }
+  Standard_Boolean IsClippingOrCappingOn() const { return NbClippingOrCappingOn() > 0; }
 
   //! @return number of enabled clipping + capping planes
-  Standard_Integer NbClippingOrCappingOn() const { return myNbClipping + myNbCapping; }
+  Standard_Integer NbClippingOrCappingOn() const
+  {
+    if (IsCappingDisableAllExcept())
+    {
+      return 1; // all Chains are disabled - only single (sub) plane is active
+    }
+    return myNbClipping + myNbCapping
+        + (IsCappingEnableAllExcept() ? -1 : 0); // exclude 1 plane with Capping filter turned ON
+  }
+
+  //! Return TRUE if there are clipping chains in the list (defining more than 1 sub-plane)
+  Standard_Boolean HasClippingChains() const
+  {
+    if (IsCappingDisableAllExcept()                 // all chains are disabled - only single (sub) plane is active;
+     || myNbChains == (myNbClipping + myNbCapping)) // no sub-planes
+    {
+      return Standard_False;
+    }
+    return !IsCappingEnableAllExcept()
+         || myCappedChain->NbChainNextPlanes() == 1
+         || myNbChains > 1; // if capping filter ON - chains counter should be decremented
+  }
 
 public: //! @name advanced method for disabling defined planes
 
@@ -66,26 +81,46 @@ public: //! @name advanced method for disabling defined planes
   Standard_Boolean HasDisabled() const { return myNbDisabled > 0; }
 
   //! Disable plane temporarily.
-  Standard_EXPORT Standard_Boolean SetEnabled (const Handle(OpenGl_Context)&  theGlCtx,
-                                               const OpenGl_ClippingIterator& thePlane,
+  Standard_EXPORT Standard_Boolean SetEnabled (const OpenGl_ClippingIterator& thePlane,
                                                const Standard_Boolean         theIsEnabled);
 
   //! Temporarily disable all planes from the global (view) list, keep only local (object) list.
-  Standard_EXPORT void DisableGlobal (const Handle(OpenGl_Context)& theGlCtx);
+  Standard_EXPORT void DisableGlobal();
 
   //! Restore all temporarily disabled planes.
   //! Does NOT affect constantly disabled planes Graphic3d_ClipPlane::IsOn().
-  Standard_EXPORT void RestoreDisabled (const Handle(OpenGl_Context)& theGlCtx);
+  Standard_EXPORT void RestoreDisabled();
+
+//! @name capping algorithm filter
+public:
+
+  //! Chain which is either temporary disabled or the only one enabled for Capping algorithm.
+  const Handle(Graphic3d_ClipPlane)& CappedChain() const { return myCappedChain; }
+
+  //! Sub-plane index within filtered Chain; positive number for DisableAllExcept and negative for EnableAllExcept.
+  Standard_Integer CappedSubPlane() const { return myCappedSubPlane; }
+
+  //! Return TRUE if capping algorithm is in state, when all clipping planes are temporarily disabled except currently processed one.
+  bool IsCappingFilterOn() const { return !myCappedChain.IsNull(); }
+
+  //! Return TRUE if capping algorithm is in state, when all clipping planes are temporarily disabled except currently processed one.
+  bool IsCappingDisableAllExcept() const { return myCappedSubPlane > 0; }
+
+  //! Return TRUE if capping algorithm is in state, when all clipping planes are enabled except currently rendered one.
+  bool IsCappingEnableAllExcept() const { return myCappedSubPlane < 0; }
 
-  //! Temporarily disable all planes except specified one.
+  //! Temporarily disable all planes except specified one for Capping algorithm.
   //! Does not affect already disabled planes.
-  Standard_EXPORT void DisableAllExcept (const Handle(OpenGl_Context)&  theGlCtx,
-                                         const OpenGl_ClippingIterator& thePlane);
+  Standard_EXPORT void DisableAllExcept (const Handle(Graphic3d_ClipPlane)& theChain,
+                                         const Standard_Integer theSubPlaneIndex);
 
-  //! Enable back planes disabled by ::DisableAllExcept().
+  //! Enable back planes disabled by ::DisableAllExcept() for Capping algorithm.
   //! Keeps only specified plane enabled.
-  Standard_EXPORT void EnableAllExcept (const Handle(OpenGl_Context)&  theGlCtx,
-                                        const OpenGl_ClippingIterator& thePlane);
+  Standard_EXPORT void EnableAllExcept (const Handle(Graphic3d_ClipPlane)& theChain,
+                                        const Standard_Integer theSubPlaneIndex);
+
+  //! Resets chain filter for Capping algorithm.
+  Standard_EXPORT void ResetCappingFilter();
 
 protected: //! @name clipping state modification commands
 
@@ -98,18 +133,15 @@ protected: //! @name clipping state modification commands
   //! Within FFP, method also temporarily resets ModelView matrix before calling glClipPlane().
   //! Otherwise the method just redirects to addLazy().
   //!
-  //! @param theGlCtx [in] context to access the matrices
   //! @param thePlanes [in/out] the list of planes to be added
   //! The list then provides information on which planes were really added to clipping state.
   //! This list then can be used to fall back to previous state.
-  Standard_EXPORT void add (const Handle(OpenGl_Context)& theGlCtx,
-                            const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
+  Standard_EXPORT void add (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
                             const Standard_Integer theStartIndex);
 
   //! Remove the passed set of clipping planes from the context state.
   //! @param thePlanes [in] the planes to remove from list.
-  Standard_EXPORT void remove (const Handle(OpenGl_Context)& theGlCtx,
-                               const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
+  Standard_EXPORT void remove (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
                                const Standard_Integer theStartIndex);
 
 private:
@@ -117,70 +149,19 @@ private:
   Handle(Graphic3d_SequenceOfHClipPlane)   myPlanesGlobal;   //!< global clipping planes
   Handle(Graphic3d_SequenceOfHClipPlane)   myPlanesLocal;    //!< object clipping planes
   NCollection_Vector<Standard_Boolean>     myDisabledPlanes; //!< ids of disabled planes
-  NCollection_Vector<Standard_Boolean>     mySkipFilter;     //!< ids of planes that were disabled before calling ::DisableAllExcept()
+
+  Handle(Graphic3d_ClipPlane)              myCappedChain;    //!< chain which is either temporary disabled or the only one enabled for Capping algorithm
+  Standard_Integer                         myCappedSubPlane; //!< sub-plane index within filtered chain; positive number for DisableAllExcept and negative for EnableAllExcept
+
   Standard_Integer                         myNbClipping;     //!< number of enabled clipping-only planes (NOT capping)
   Standard_Integer                         myNbCapping;      //!< number of enabled capping  planes
+  Standard_Integer                         myNbChains;       //!< number of enabled chains
   Standard_Integer                         myNbDisabled;     //!< number of defined but disabled planes
 
 private:
-
   //! Copying allowed only within Handles
   OpenGl_Clipping            (const OpenGl_Clipping& );
   OpenGl_Clipping& operator= (const OpenGl_Clipping& );
-
-  friend class OpenGl_ClippingIterator;
-};
-
-//! The iterator through clipping planes.
-class OpenGl_ClippingIterator
-{
-public:
-
-  //! Main constructor.
-  Standard_EXPORT OpenGl_ClippingIterator(const OpenGl_Clipping& theClipping);
-
-  //! Return true if iterator points to the valid clipping plane.
-  bool More() const { return myIter1.More() || myIter2.More(); }
-
-  //! Go to the next clipping plane.
-  void Next()
-  {
-    ++myCurrIndex;
-    if (myIter1.More())
-    {
-      myIter1.Next();
-    }
-    else
-    {
-      myIter2.Next();
-    }
-  }
-
-  //! Return true if plane has been temporarily disabled
-  //! either by Graphic3d_ClipPlane->IsOn() property or by temporary filter.
-  bool IsDisabled() const { return myDisabled->Value (myCurrIndex) || !Value()->IsOn(); }
-
-  //! Return the plane at current iterator position.
-  const Handle(Graphic3d_ClipPlane)& Value() const
-  {
-    return myIter1.More()
-         ? myIter1.Value()
-         : myIter2.Value();
-  }
-
-  //! Return true if plane from the global (view) list.
-  bool IsGlobal() const { return myIter1.More(); }
-
-  //! Return the plane index.
-  Standard_Integer PlaneIndex() const { return myCurrIndex; }
-
-private:
-
-  Graphic3d_SequenceOfHClipPlane::Iterator myIter1;
-  Graphic3d_SequenceOfHClipPlane::Iterator myIter2;
-  const NCollection_Vector<Standard_Boolean>* myDisabled;
-  Standard_Integer myCurrIndex;
-
 };
 
 #endif
diff --git a/src/OpenGl/OpenGl_ClippingIterator.hxx b/src/OpenGl/OpenGl_ClippingIterator.hxx
new file mode 100644 (file)
index 0000000..3cae9bd
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (c) 2013-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_ClippingIterator_Header
+#define OpenGl_ClippingIterator_Header
+
+#include <OpenGl_Clipping.hxx>
+
+//! The iterator through clipping planes.
+class OpenGl_ClippingIterator
+{
+public:
+
+  //! Main constructor.
+  OpenGl_ClippingIterator(const OpenGl_Clipping& theClipping)
+  : myDisabled  (&theClipping.myDisabledPlanes),
+    myCurrIndex (1)
+  {
+    myIter1.Init (theClipping.myPlanesGlobal);
+    myIter2.Init (theClipping.myPlanesLocal);
+  }
+
+  //! Return true if iterator points to the valid clipping plane.
+  bool More() const { return myIter1.More() || myIter2.More(); }
+
+  //! Go to the next clipping plane.
+  void Next()
+  {
+    ++myCurrIndex;
+    if (myIter1.More())
+    {
+      myIter1.Next();
+    }
+    else
+    {
+      myIter2.Next();
+    }
+  }
+
+  //! Return true if plane has been temporarily disabled either by Graphic3d_ClipPlane->IsOn() property or by temporary filter.
+  //! Beware that this method does NOT handle a Chain filter for Capping algorithm OpenGl_Clipping::CappedChain()!
+  bool IsDisabled() const { return myDisabled->Value (myCurrIndex) || !Value()->IsOn(); }
+
+  //! Return the plane at current iterator position.
+  const Handle(Graphic3d_ClipPlane)& Value() const
+  {
+    return myIter1.More()
+         ? myIter1.Value()
+         : myIter2.Value();
+  }
+
+  //! Return true if plane from the global (view) list.
+  bool IsGlobal() const { return myIter1.More(); }
+
+  //! Return the plane index.
+  Standard_Integer PlaneIndex() const { return myCurrIndex; }
+
+private:
+
+  Graphic3d_SequenceOfHClipPlane::Iterator myIter1;
+  Graphic3d_SequenceOfHClipPlane::Iterator myIter2;
+  const NCollection_Vector<Standard_Boolean>* myDisabled;
+  Standard_Integer myCurrIndex;
+
+};
+
+#endif // OpenGl_ClippingIterator_Header
index 39a494c..487e4e0 100644 (file)
@@ -1465,7 +1465,7 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
     glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax);
   }
 
-  myClippingState.Init (myMaxClipPlanes);
+  myClippingState.Init();
 
 #if !defined(GL_ES_VERSION_2_0)
 
index f539a68..1d44dd9 100644 (file)
@@ -396,7 +396,8 @@ void OpenGl_Group::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
   const Handle(OpenGl_RenderFilter)& aFilter = theWorkspace->GetRenderFilter();
 
   // Setup aspects
-  theWorkspace->SetAllowFaceCulling (myIsClosed);
+  theWorkspace->SetAllowFaceCulling (myIsClosed
+                                 && !theWorkspace->GetGlContext()->Clipping().IsClippingOrCappingOn());
   const OpenGl_AspectLine*   aBackAspectLine   = theWorkspace->AspectLine();
   const OpenGl_AspectFace*   aBackAspectFace   = theWorkspace->AspectFace();
   const OpenGl_AspectMarker* aBackAspectMarker = theWorkspace->AspectMarker();
index f04c547..9c44813 100644 (file)
@@ -31,10 +31,12 @@ enum OpenGl_ProgramOptions
   OpenGl_PO_StippleLine = 0x020, //!< stipple line
   OpenGl_PO_ClipPlanes1 = 0x040, //!< handle 1 clipping plane
   OpenGl_PO_ClipPlanes2 = 0x080, //!< handle 2 clipping planes
+  //OpenGl_PO_ClipPlanes3 = OpenGl_PO_ClipPlanes1|OpenGl_PO_ClipPlanes2, //!< handle 3 clipping planes - not implemented
   OpenGl_PO_ClipPlanesN = 0x100, //!< handle N clipping planes
-  OpenGl_PO_AlphaTest   = 0x200, //!< discard fragment by alpha test (defined by cutoff value)
-  OpenGl_PO_WriteOit    = 0x400, //!< write coverage buffer for Blended Order-Independent Transparency
-  OpenGl_PO_NB          = 0x800  //!< overall number of combinations
+  OpenGl_PO_ClipChains  = 0x200, //!< handle chains of clipping planes
+  OpenGl_PO_AlphaTest   = 0x400, //!< discard fragment by alpha test (defined by cutoff value)
+  OpenGl_PO_WriteOit    = 0x800, //!< write coverage buffer for Blended Order-Independent Transparency
+  OpenGl_PO_NB          = 0x1000 //!< overall number of combinations
 };
 
 //! Alias to programs array of predefined length
index a83169c..a939255 100644 (file)
@@ -20,7 +20,7 @@
 #include <OpenGl_AspectLine.hxx>
 #include <OpenGl_AspectMarker.hxx>
 #include <OpenGl_AspectText.hxx>
-#include <OpenGl_Clipping.hxx>
+#include <OpenGl_ClippingIterator.hxx>
 #include <OpenGl_Context.hxx>
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_ShaderProgram.hxx>
@@ -238,6 +238,25 @@ const char THE_FRAG_CLIP_PLANES_N[] =
   EOL"    }"
   EOL"  }";
 
+//! Process chains of clipping planes in Fragment Shader.
+const char THE_FRAG_CLIP_CHAINS_N[] =
+EOL"  for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount;)"
+EOL"  {"
+EOL"    vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
+EOL"    if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
+EOL"    {"
+EOL"      if (occClipPlaneChains[aPlaneIter] == 1)"
+EOL"      {"
+EOL"        discard;"
+EOL"      }"
+EOL"      aPlaneIter += 1;"
+EOL"    }"
+EOL"    else"
+EOL"    {"
+EOL"      aPlaneIter += occClipPlaneChains[aPlaneIter];"
+EOL"    }"
+EOL"  }";
+
 //! Process 1 clipping plane in Fragment Shader.
 const char THE_FRAG_CLIP_PLANES_1[] =
   EOL"  vec4 aClipEquation0 = occClipPlaneEquations[0];"
@@ -256,6 +275,16 @@ const char THE_FRAG_CLIP_PLANES_2[] =
   EOL"    discard;"
   EOL"  }";
 
+//! Process a chain of 2 clipping planes in Fragment Shader (3/4 section).
+const char THE_FRAG_CLIP_CHAINS_2[] =
+EOL"  vec4 aClipEquation0 = occClipPlaneEquations[0];"
+EOL"  vec4 aClipEquation1 = occClipPlaneEquations[1];"
+EOL"  if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
+EOL"   && dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
+EOL"  {"
+EOL"    discard;"
+EOL"  }";
+
 #if !defined(GL_ES_VERSION_2_0)
 
   static const GLfloat THE_DEFAULT_AMBIENT[4]    = { 0.0f, 0.0f, 0.0f, 1.0f };
@@ -930,10 +959,14 @@ void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)
 
     Standard_Integer aPlaneId = 0;
     Standard_Boolean toRestoreModelView = Standard_False;
+    const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
     for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
     {
       const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
-      if (aPlaneIter.IsDisabled())
+      if (aPlaneIter.IsDisabled()
+       || aPlane->IsChain()
+       || (aPlane == aCappedChain
+        && myContext->Clipping().IsCappingEnableAllExcept()))
       {
         continue;
       }
@@ -995,21 +1028,21 @@ void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)
   }
 
   const Standard_Integer aNbClipPlanesMax = theProgram->NbClipPlanesMax();
-  const GLint aNbPlanes = Min (myContext->Clipping().NbClippingOrCappingOn(), aNbClipPlanesMax);
-  theProgram->SetUniform (myContext,
-                          theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
-                          aNbPlanes);
+  const Standard_Integer aNbPlanes = Min (myContext->Clipping().NbClippingOrCappingOn(), aNbClipPlanesMax);
   if (aNbPlanes < 1)
   {
+    theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), 0);
     return;
   }
 
   if (myClipPlaneArray.Size() < aNbClipPlanesMax)
   {
     myClipPlaneArray.Resize (0, aNbClipPlanesMax - 1, false);
+    myClipChainArray.Resize (0, aNbClipPlanesMax - 1, false);
   }
 
   Standard_Integer aPlaneId = 0;
+  const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
   for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
   {
     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
@@ -1017,29 +1050,64 @@ void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)
     {
       continue;
     }
-    else if (aPlaneId >= aNbClipPlanesMax)
+
+    if (myContext->Clipping().IsCappingDisableAllExcept())
     {
-      myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
-                              TCollection_AsciiString("Warning: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
+      // enable only specific (sub) plane
+      if (aPlane != aCappedChain)
+      {
+        continue;
+      }
+
+      Standard_Integer aSubPlaneIndex = 1;
+      for (const Graphic3d_ClipPlane* aSubPlaneIter = aCappedChain.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
+      {
+        if (aSubPlaneIndex == myContext->Clipping().CappedSubPlane())
+        {
+          addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), 1);
+          break;
+        }
+      }
       break;
     }
+    else if (aPlane == aCappedChain) // && myContext->Clipping().IsCappingEnableAllExcept()
+    {
+      // enable sub-planes within processed Chain as reversed and ORed, excluding filtered plane
+      if (aPlaneId + aPlane->NbChainNextPlanes() - 1 > aNbClipPlanesMax)
+      {
+        myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
+                                TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
+        break;
+      }
 
-    const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
-    OpenGl_Vec4& aPlaneEq = myClipPlaneArray.ChangeValue (aPlaneId);
-    aPlaneEq.x() = float(anEquation.x());
-    aPlaneEq.y() = float(anEquation.y());
-    aPlaneEq.z() = float(anEquation.z());
-    aPlaneEq.w() = float(anEquation.w());
-    if (myHasLocalOrigin)
+      Standard_Integer aSubPlaneIndex = 1;
+      for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
+      {
+        if (aSubPlaneIndex != -myContext->Clipping().CappedSubPlane())
+        {
+          addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->ReversedEquation(), 1);
+        }
+      }
+    }
+    else
     {
-      const gp_XYZ        aPos = aPlane->ToPlane().Position().Location().XYZ() - myLocalOrigin;
-      const Standard_Real aD   = -(anEquation.x() * aPos.X() + anEquation.y() * aPos.Y() + anEquation.z() * aPos.Z());
-      aPlaneEq.w() = float(aD);
+      // normal case
+      if (aPlaneId + aPlane->NbChainNextPlanes() > aNbClipPlanesMax)
+      {
+        myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
+                                TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
+        break;
+      }
+      for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get())
+      {
+        addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), aSubPlaneIter->NbChainNextPlanes());
+      }
     }
-    ++aPlaneId;
   }
 
+  theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), aPlaneId);
   theProgram->SetUniform (myContext, aLocEquations, aNbClipPlanesMax, &myClipPlaneArray.First());
+  theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_CHAINS), aNbClipPlanesMax, &myClipChainArray.First());
 }
 
 // =======================================================================
@@ -1532,12 +1600,16 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha
     else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
     {
       aNbClipPlanes = 2;
-      aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_2;
+      aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
+                         ? THE_FRAG_CLIP_CHAINS_2
+                         : THE_FRAG_CLIP_PLANES_2;
     }
     else
     {
       aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
-      aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
+      aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
+                          ? THE_FRAG_CLIP_CHAINS_N
+                          : THE_FRAG_CLIP_PLANES_N;
     }
   }
   if ((theBits & OpenGl_PO_WriteOit) != 0)
@@ -1895,12 +1967,16 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
     else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
     {
       aNbClipPlanes = 2;
-      aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_2;
+      aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
+                          ? THE_FRAG_CLIP_CHAINS_2
+                          : THE_FRAG_CLIP_PLANES_2;
     }
     else
     {
       aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
-      aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
+      aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
+                         ? THE_FRAG_CLIP_CHAINS_N
+                         : THE_FRAG_CLIP_PLANES_N;
     }
   }
   if ((theBits & OpenGl_PO_WriteOit) != 0)
@@ -2054,12 +2130,16 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
     else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
     {
       aNbClipPlanes = 2;
-      aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_2;
+      aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
+                         ? THE_FRAG_CLIP_CHAINS_2
+                         : THE_FRAG_CLIP_PLANES_2;
     }
     else
     {
       aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
-      aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
+      aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
+                         ? THE_FRAG_CLIP_CHAINS_N
+                         : THE_FRAG_CLIP_PLANES_N;
     }
   }
   if ((theBits & OpenGl_PO_WriteOit) != 0)
index 7c423e0..4cc8364 100644 (file)
@@ -414,6 +414,11 @@ protected:
     if (aNbPlanes > 0)
     {
       aBits |= OpenGl_PO_ClipPlanesN;
+      if (myContext->Clipping().HasClippingChains())
+      {
+        aBits |= OpenGl_PO_ClipChains;
+      }
+
       if (aNbPlanes == 1)
       {
         aBits |= OpenGl_PO_ClipPlanes1;
@@ -570,6 +575,29 @@ protected:
 
 protected:
 
+  //! Append clipping plane definition to temporary buffers.
+  void addClippingPlane (Standard_Integer& thePlaneId,
+                         const Graphic3d_ClipPlane& thePlane,
+                         const Graphic3d_Vec4d& theEq,
+                         const Standard_Integer theChainFwd) const
+  {
+    myClipChainArray.SetValue (thePlaneId, theChainFwd);
+    OpenGl_Vec4& aPlaneEq = myClipPlaneArray.ChangeValue (thePlaneId);
+    aPlaneEq.x() = float(theEq.x());
+    aPlaneEq.y() = float(theEq.y());
+    aPlaneEq.z() = float(theEq.z());
+    aPlaneEq.w() = float(theEq.w());
+    if (myHasLocalOrigin)
+    {
+      const gp_XYZ        aPos = thePlane.ToPlane().Position().Location().XYZ() - myLocalOrigin;
+      const Standard_Real aD   = -(theEq.x() * aPos.X() + theEq.y() * aPos.Y() + theEq.z() * aPos.Z());
+      aPlaneEq.w() = float(aD);
+    }
+    ++thePlaneId;
+  }
+
+protected:
+
   Handle(OpenGl_ShaderProgramFFP)    myFfpProgram;
 
   Graphic3d_TypeOfShadingModel       myShadingModel;       //!< lighting shading model
@@ -602,6 +630,7 @@ protected:
   mutable NCollection_Array1<OpenGl_ShaderLightParameters> myLightParamsArray;
   mutable NCollection_Array1<OpenGl_Vec4>                  myClipPlaneArray;
   mutable NCollection_Array1<OpenGl_Vec4d>                 myClipPlaneArrayFfp;
+  mutable NCollection_Array1<Standard_Integer>             myClipChainArray;
 
 private:
 
index 784dc52..3b2bb56 100755 (executable)
@@ -56,6 +56,7 @@ Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
   "occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE
 
   "occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS
+  "occClipPlaneChains",    // OpenGl_OCC_CLIP_PLANE_CHAINS
   "occClipPlaneCount",     // OpenGl_OCC_CLIP_PLANE_COUNT
 
   "occLightSourcesCount",  // OpenGl_OCC_LIGHT_SOURCE_COUNT
index 87941ff..1f15f01 100755 (executable)
@@ -50,6 +50,7 @@ enum OpenGl_StateVariable
 
   // OpenGL clip planes state
   OpenGl_OCC_CLIP_PLANE_EQUATIONS,
+  OpenGl_OCC_CLIP_PLANE_CHAINS,
   OpenGl_OCC_CLIP_PLANE_COUNT,
 
   // OpenGL light state
@@ -224,7 +225,7 @@ public:
   Standard_Integer NbLightsMax() const { return myNbLightsMax; }
 
   //! Return the length of array of clipping planes (THE_MAX_CLIP_PLANES),
-  //! to be used for initialization occClipPlaneEquations (OpenGl_OCC_CLIP_PLANE_EQUATIONS).
+  //! to be used for initialization occClipPlaneEquations (OpenGl_OCC_CLIP_PLANE_EQUATIONS) and occClipPlaneChains (OpenGl_OCC_CLIP_PLANE_CHAINS).
   Standard_Integer NbClipPlanesMax() const { return myNbClipPlanesMax; }
 
   //! Return the length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS),
index 60b5aec..34870a5 100644 (file)
@@ -16,6 +16,7 @@
 #include <OpenGl_CappingAlgo.hxx>
 #include <OpenGl_Context.hxx>
 #include <OpenGl_GlCore11.hxx>
+#include <OpenGl_ClippingIterator.hxx>
 #include <OpenGl_GraphicDriver.hxx>
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_ShaderProgram.hxx>
@@ -24,9 +25,6 @@
 #include <OpenGl_View.hxx>
 #include <OpenGl_Workspace.hxx>
 
-#include <Graphic3d_SequenceOfHClipPlane.hxx>
-
-
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure,Graphic3d_CStructure)
 
 //! Auxiliary class for bounding box presentation
@@ -551,7 +549,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
   }
 
   // Collect clipping planes of structure scope
-  aCtx->ChangeClipping().SetLocalPlanes (aCtx, myClipPlanes);
+  aCtx->ChangeClipping().SetLocalPlanes (myClipPlanes);
 
   // True if structure is fully clipped
   bool isClipped = false;
@@ -562,7 +560,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
     if (!myClipPlanes.IsNull()
       && myClipPlanes->ToOverrideGlobal())
     {
-      aCtx->ChangeClipping().DisableGlobal (aCtx);
+      aCtx->ChangeClipping().DisableGlobal();
       hasDisabled = aCtx->Clipping().HasDisabled();
     }
     else if (!myTrsfPers.IsNull())
@@ -583,9 +581,8 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
           }
 
           // check for clipping
-          const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
           const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
-          if (aPlaneEquation.Dot (aCheckPnt) < 0.0) // vertex is outside the half-space
+          if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
           {
             isClipped = true;
             break;
@@ -593,7 +590,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
         }
       }
 
-      aCtx->ChangeClipping().DisableGlobal (aCtx);
+      aCtx->ChangeClipping().DisableGlobal();
       hasDisabled = aCtx->Clipping().HasDisabled();
     }
 
@@ -610,26 +607,15 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
           continue;
         }
 
-        // check for clipping
-        const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
-        const Graphic3d_Vec4d aMaxPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMax().x() : aBBox.CornerMin().x(),
-                                       aPlaneEquation.y() > 0.0 ? aBBox.CornerMax().y() : aBBox.CornerMin().y(),
-                                       aPlaneEquation.z() > 0.0 ? aBBox.CornerMax().z() : aBBox.CornerMin().z(),
-                                       1.0);
-        if (aPlaneEquation.Dot (aMaxPnt) < 0.0) // max vertex is outside the half-space
+        const Graphic3d_ClipState aBoxState = aPlane->ProbeBox (aBBox);
+        if (aBoxState == Graphic3d_ClipState_Out)
         {
           isClipped = true;
           break;
         }
-
-        // check for no intersection (e.g. object is "entirely not clipped")
-        const Graphic3d_Vec4d aMinPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMin().x() : aBBox.CornerMax().x(),
-                                       aPlaneEquation.y() > 0.0 ? aBBox.CornerMin().y() : aBBox.CornerMax().y(),
-                                       aPlaneEquation.z() > 0.0 ? aBBox.CornerMin().z() : aBBox.CornerMax().z(),
-                                       1.0);
-        if (aPlaneEquation.Dot (aMinPnt) > 0.0) // min vertex is inside the half-space
+        else if (aBoxState == Graphic3d_ClipState_In)
         {
-          aCtx->ChangeClipping().SetEnabled (aCtx, aPlaneIt, Standard_False);
+          aCtx->ChangeClipping().SetEnabled (aPlaneIt, false);
           hasDisabled = true;
         }
       }
@@ -667,9 +653,9 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
   if (hasDisabled)
   {
     // enable planes that were previously disabled
-    aCtx->ChangeClipping().RestoreDisabled (aCtx);
+    aCtx->ChangeClipping().RestoreDisabled();
   }
-  aCtx->ChangeClipping().SetLocalPlanes (aCtx, Handle(Graphic3d_SequenceOfHClipPlane)());
+  aCtx->ChangeClipping().SetLocalPlanes (Handle(Graphic3d_SequenceOfHClipPlane)());
   if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
     || hasDisabled)
   {
index d499839..247e44f 100644 (file)
@@ -1205,7 +1205,7 @@ void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
   const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
 
   // Specify clipping planes in view transformation space
-  aContext->ChangeClipping().Reset (aContext, myClipPlanes);
+  aContext->ChangeClipping().Reset (myClipPlanes);
   if (!myClipPlanes.IsNull()
    && !myClipPlanes->IsEmpty())
   {
@@ -1218,7 +1218,7 @@ void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
   // Apply restored view matrix.
   aContext->ApplyWorldViewMatrix();
 
-  aContext->ChangeClipping().Reset (aContext, Handle(Graphic3d_SequenceOfHClipPlane)());
+  aContext->ChangeClipping().Reset (Handle(Graphic3d_SequenceOfHClipPlane)());
   if (!myClipPlanes.IsNull()
    && !myClipPlanes->IsEmpty())
   {
index 8c14002..37060f3 100644 (file)
@@ -280,20 +280,12 @@ const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace()
 {
   if (myView->BackfacingModel() == Graphic3d_TOBM_AUTOMATIC)
   {
-    // manage back face culling mode, disable culling when clipping is enabled
     bool toSuppressBackFaces = myToAllowFaceCulling
                             && myAspectFaceSet->Aspect()->ToSuppressBackFaces();
     if (toSuppressBackFaces)
     {
-      if (myGlContext->Clipping().IsClippingOrCappingOn()
-       || myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH)
-      {
-        toSuppressBackFaces = false;
-      }
-    }
-    if (toSuppressBackFaces)
-    {
-      if (myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Blend
+      if (myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH
+       || myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Blend
        || myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Mask
        || (myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_BlendAuto
         && myAspectFaceSet->Aspect()->FrontMaterial().Transparency() != 0.0f))
index 4a3e602..7645942 100644 (file)
@@ -122,7 +122,7 @@ public:
   //! @return true if depth writing is enabled.
   Standard_Boolean& UseDepthWrite() { return myUseDepthWrite; }
 
-  //! @return true if clipping algorithm enabled
+  //! @return true if frustum culling algorithm is enabled
   Standard_EXPORT Standard_Boolean IsCullingEnabled() const;
 
   //// RELATED TO STATUS ////
@@ -133,7 +133,12 @@ public:
   //! Allow or disallow face culling.
   //! This call does NOT affect current state of back face culling;
   //! ApplyAspectFace() should be called to update state.
-  void SetAllowFaceCulling (bool theToAllow) { myToAllowFaceCulling = theToAllow; }
+  bool SetAllowFaceCulling (bool theToAllow)
+  {
+    const bool wasAllowed = myToAllowFaceCulling;
+    myToAllowFaceCulling = theToAllow;
+    return wasAllowed;
+  }
 
   //! Return true if following structures should apply highlight color.
   bool ToHighlight() const { return !myHighlightStyle.IsNull(); }
index 653a3f9..599ff82 100644 (file)
@@ -19,6 +19,7 @@
 #include <Graphic3d_Buffer.hxx>
 #include <Graphic3d_IndexBuffer.hxx>
 #include <Graphic3d_TypeOfPrimitiveArray.hxx>
+#include <NCollection_Shared.hxx>
 #include <Select3D_SensitiveSet.hxx>
 #include <Select3D_BVHIndexBuffer.hxx>
 #include <TColStd_HPackedMapOfInteger.hxx>
index d191a41..7bcd65c 100644 (file)
@@ -276,7 +276,7 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint)
   // {i, j, k} vectors and store them to corresponding class fields
   cacheVertexProjections (this);
 
-  myViewClipRange.Clear();
+  myViewClipRange.SetVoid();
 
   myScale = 1.0;
 }
@@ -306,7 +306,7 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt,
   // {i, j, k} vectors and store them to corresponding class fields
   cacheVertexProjections (this);
 
-  myViewClipRange.Clear();
+  myViewClipRange.SetVoid();
 
   myScale = 1.0;
 }
@@ -645,53 +645,74 @@ gp_Pnt SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth
 // purpose  :
 // =======================================================================
 void SelectMgr_RectangularFrustum::computeClippingRange (const Graphic3d_SequenceOfHClipPlane& thePlanes,
-                                                         Standard_Real& theDepthMin,
-                                                         Standard_Real& theDepthMax)
+                                                         SelectMgr_ViewClipRange& theRange)
 {
-  theDepthMax = DBL_MAX;
-  theDepthMin = -DBL_MAX;
   Standard_Real aPlaneA, aPlaneB, aPlaneC, aPlaneD;
   for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes); aPlaneIt.More(); aPlaneIt.Next())
   {
     const Handle(Graphic3d_ClipPlane)& aClipPlane = aPlaneIt.Value();
     if (!aClipPlane->IsOn())
+    {
       continue;
+    }
 
-    gp_Pln aGeomPlane = aClipPlane->ToPlane();
+    Bnd_Range aSubRange (RealFirst(), RealLast());
+    for (const Graphic3d_ClipPlane* aSubPlaneIter = aClipPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get())
+    {
+      const gp_Pln aGeomPlane = aSubPlaneIter->ToPlane();
+      aGeomPlane.Coefficients (aPlaneA, aPlaneB, aPlaneC, aPlaneD);
 
-    aGeomPlane.Coefficients (aPlaneA, aPlaneB, aPlaneC, aPlaneD);
+      const gp_XYZ& aPlaneDirXYZ = aGeomPlane.Axis().Direction().XYZ();
+      Standard_Real aDotProduct = myViewRayDir.XYZ().Dot (aPlaneDirXYZ);
+      Standard_Real aDistance   = -myNearPickedPnt.XYZ().Dot (aPlaneDirXYZ) - aPlaneD;
 
-    const gp_XYZ& aPlaneDirXYZ = aGeomPlane.Axis().Direction().XYZ();
+      // check whether the pick line is parallel to clip plane
+      if (Abs (aDotProduct) < Precision::Angular())
+      {
+        // line lies below the plane and is not clipped, skip
+        continue;
+      }
 
-    Standard_Real aDotProduct = myViewRayDir.XYZ ().Dot (aPlaneDirXYZ);
-    Standard_Real aDistance = - myNearPickedPnt.XYZ ().Dot (aPlaneDirXYZ)
-                              - aPlaneD;
+      // compute distance to point of pick line intersection with the plane
+      const Standard_Real aParam = aDistance / aDotProduct;
 
-    // check whether the pick line is parallel to clip plane
-    if (Abs (aDotProduct) < Precision::Angular())
-    {
-      // line lies below the plane and is not clipped, skip
-      continue;
-    }
+      const gp_Pnt anIntersectionPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aParam;
+      Standard_Real aDistToPln = anIntersectionPnt.Distance (myNearPickedPnt);
+      if (aParam < 0.0)
+      {
+        // the plane is "behind" the ray
+        aDistToPln = -aDistToPln;
+      }
 
-    // compute distance to point of pick line intersection with the plane
-    const Standard_Real aParam = aDistance / aDotProduct;
-    const gp_Pnt anIntersectionPt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aParam;
-    Standard_Real aDistToPln = anIntersectionPt.Distance (myNearPickedPnt);
-    if (aParam < 0.0)
-    {
-      // the plane is "behind" the ray
-      aDistToPln = -aDistToPln;
+      // change depth limits for case of opposite and directed planes
+      if (!aClipPlane->IsChain())
+      {
+        if (aDotProduct < 0.0)
+        {
+          theRange.ChangeMain().Add (Bnd_Range (aDistToPln, RealLast()));
+        }
+        else
+        {
+          theRange.ChangeMain().Add (Bnd_Range (RealFirst(), aDistToPln));
+        }
+      }
+      else
+      {
+        if (aDotProduct < 0.0)
+        {
+          aSubRange.TrimFrom (aDistToPln);
+        }
+        else
+        {
+          aSubRange.TrimTo (aDistToPln);
+        }
+      }
     }
 
-    // change depth limits for case of opposite and directed planes
-    if (aDotProduct < 0.0)
-    {
-      theDepthMax = Min (aDistToPln, theDepthMax);
-    }
-    else if (aDistToPln > theDepthMin)
+    if (!aSubRange.IsVoid()
+      && aClipPlane->IsChain())
     {
-      theDepthMin = Max (aDistToPln, theDepthMin);
+      theRange.AddSubRange (aSubRange);
     }
   }
 }
@@ -704,10 +725,9 @@ void SelectMgr_RectangularFrustum::computeClippingRange (const Graphic3d_Sequenc
 Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
                                                           const Standard_Real theDepth)
 {
-  Standard_Real aMaxDepth, aMinDepth;
-  computeClippingRange (thePlanes, aMinDepth, aMaxDepth);
-
-  return (theDepth <= aMinDepth || theDepth >= aMaxDepth);
+  SelectMgr_ViewClipRange aRange;
+  computeClippingRange (thePlanes, aRange);
+  return aRange.IsClipped (theDepth);
 }
 
 // =======================================================================
@@ -719,13 +739,11 @@ void SelectMgr_RectangularFrustum::SetViewClipping (const Handle(Graphic3d_Seque
   if (thePlanes.IsNull()
    || thePlanes->IsEmpty())
   {
-    myViewClipRange.Clear();
+    myViewClipRange.SetVoid();
     return;
   }
 
-  Standard_Real aMaxDepth, aMinDepth;
-  computeClippingRange (*thePlanes, aMinDepth, aMaxDepth);
-  myViewClipRange.Set (aMinDepth, aMaxDepth);
+  computeClippingRange (*thePlanes, myViewClipRange);
 }
 
 // =======================================================================
@@ -734,14 +752,8 @@ void SelectMgr_RectangularFrustum::SetViewClipping (const Handle(Graphic3d_Seque
 // =======================================================================
 Standard_Boolean SelectMgr_RectangularFrustum::isViewClippingOk (const Standard_Real theDepth) const
 {
-  if (!myViewClipRange.IsValid()
-   || !myIsViewClipEnabled)
-  {
-    return Standard_True;
-  }
-
-  return myViewClipRange.MaxDepth() > theDepth
-    && myViewClipRange.MinDepth() < theDepth;
+  return !myIsViewClipEnabled
+      || !myViewClipRange.IsClipped (theDepth);
 }
 
 // =======================================================================
index 4c9276a..5d5713a 100644 (file)
@@ -149,8 +149,7 @@ protected:
 
   //! Computes valid depth range for the given clipping planes
   Standard_EXPORT void computeClippingRange (const Graphic3d_SequenceOfHClipPlane& thePlanes,
-                                             Standard_Real& theDepthMin,
-                                             Standard_Real& theDepthMax);
+                                             SelectMgr_ViewClipRange& theRange);
 
   //! Returns false if theDepth must be clipped by current view clip range
   Standard_EXPORT Standard_Boolean isViewClippingOk (const Standard_Real theDepth) const;
index 7fc0931..77abb97 100644 (file)
 #ifndef _SelectMgr_ViewClipRange_HeaderFile
 #define _SelectMgr_ViewClipRange_HeaderFile
 
+#include <Bnd_Range.hxx>
 #include <Standard_TypeDef.hxx>
 
 //! Class for handling depth clipping range.
 //! It is used to perform checks in case if global (for the whole view)
-//! clipping planes are defined inside of SelectMgr_RectangularFrustum
-//! class methods.
+//! clipping planes are defined inside of SelectMgr_RectangularFrustum class methods.
 class SelectMgr_ViewClipRange
 {
 public:
-  //! Creates new empty view clip range
+  //! Creates an empty clip range.
   SelectMgr_ViewClipRange()
   {
-    Clear();
+    SetVoid();
   }
 
-  //! Sets boundaries and validates view clipping range
-  void Set (const Standard_Real theDepthMin, const Standard_Real theDepthMax)
+  //! Check if the given depth is not within clipping range(s),
+  //! e.g. TRUE means depth is clipped.
+  Standard_Boolean IsClipped (const Standard_Real theDepth) const
   {
-    myMin = theDepthMin;
-    myMax = theDepthMax;
-    myIsValid = Standard_True;
+    for (size_t aRangeIter = 0; aRangeIter < myRanges.size(); ++aRangeIter)
+    {
+      if (!myRanges[aRangeIter].IsOut (theDepth))
+      {
+        return Standard_True;
+      }
+    }
+    return Standard_False;
   }
 
-  //! Returns true if clip range is set and depth of each matched
-  //! primitive must be tested for satisfying the defined interval
-  Standard_Boolean IsValid() const
+  //! Clears clipping range.
+  void SetVoid()
   {
-    return myIsValid;
+    myRanges.resize (1);
+    myRanges[0].SetVoid();
   }
 
-  //! Returns the upper bound of valid depth range
-  Standard_Real MaxDepth() const
-  {
-    return myMax;
-  }
+  //! Returns the main range.
+  Bnd_Range& ChangeMain() { return myRanges[0]; }
 
-  //! Returns the lower bound of valid depth range
-  Standard_Real MinDepth() const
-  {
-    return myMin;
-  }
-
-  //! Invalidates view clipping range
-  void Clear()
-  {
-    myIsValid = Standard_False;
-  }
+  //! Adds a sub-range.
+  void AddSubRange (const Bnd_Range& theRange) { myRanges.push_back (theRange); }
 
 private:
-  Standard_Real    myMin;      //!< Lower bound of valid depth range
-  Standard_Real    myMax;      //!< Upper bound of valid depth range
-  Standard_Boolean myIsValid;  //!< The flag is set to true when range boundaries are set and depth check must be performed
+
+  std::vector<Bnd_Range> myRanges;
+
 };
 
 #endif // _SelectMgr_ViewClipRange_HeaderFile
index a555ab7..4bfe074 100644 (file)
@@ -225,9 +225,8 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_Sensitive
             continue;
           }
 
-          const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
-          const Graphic3d_Vec4d  aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
-          if (aPlaneEquation.Dot (aCheckPnt) < 0.0) // vertex is outside the half-space
+          const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
+          if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
           {
             return;
           }
index a3b7e12..5cd1ef0 100644 (file)
@@ -173,5 +173,6 @@ uniform               float     occAlphaCutoff;    //!< alpha test cutoff value
 //! Parameters of clipping planes
 #if defined(THE_MAX_CLIP_PLANES) && (THE_MAX_CLIP_PLANES > 0)
 uniform               vec4 occClipPlaneEquations[THE_MAX_CLIP_PLANES];
+uniform THE_PREC_ENUM int  occClipPlaneChains[THE_MAX_CLIP_PLANES]; //! Indicating the number of planes in the Chain
 uniform THE_PREC_ENUM int  occClipPlaneCount;   //!< Total number of clip planes
 #endif
index ed3045e..74663c4 100644 (file)
@@ -176,5 +176,6 @@ static const char Shaders_Declarations_glsl[] =
   "//! Parameters of clipping planes\n"
   "#if defined(THE_MAX_CLIP_PLANES) && (THE_MAX_CLIP_PLANES > 0)\n"
   "uniform               vec4 occClipPlaneEquations[THE_MAX_CLIP_PLANES];\n"
+  "uniform THE_PREC_ENUM int  occClipPlaneChains[THE_MAX_CLIP_PLANES]; //! Indicating the number of planes in the Chain\n"
   "uniform THE_PREC_ENUM int  occClipPlaneCount;   //!< Total number of clip planes\n"
   "#endif\n";
index 6f53cd3..b04a299 100644 (file)
@@ -2626,8 +2626,13 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
 
   for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
   {
-    const TCollection_AsciiString& aName   = aPrsIter.CurrentName();
-    Handle(AIS_InteractiveObject)  aPrs    = aPrsIter.Current();
+    const TCollection_AsciiString& aName = aPrsIter.CurrentName();
+    Handle(AIS_InteractiveObject)  aPrs  = aPrsIter.Current();
+    if (aPrs.IsNull())
+    {
+      return 1;
+    }
+
     Handle(Prs3d_Drawer)           aDrawer = aPrs->Attributes();
     Handle(AIS_ColoredShape) aColoredPrs;
     Standard_Boolean toDisplay = Standard_False;
index 94a66bf..a430426 100644 (file)
@@ -8375,8 +8375,8 @@ static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, cons
     {
       aClipPlane->SetOn (toEnable);
     }
-    else if (aChangeArg == "-equation"
-          || aChangeArg == "equation")
+    else if (aChangeArg.StartsWith ("-equation")
+          || aChangeArg.StartsWith ("equation"))
     {
       if (aNbChangeArgs < 5)
       {
@@ -8384,13 +8384,74 @@ static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, cons
         return 1;
       }
 
-      Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
-      Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
-      Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
-      Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
-      aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
+      Standard_Integer aSubIndex = 1;
+      Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
+      if (aPrefixLen < aChangeArg.Length())
+      {
+        TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
+        if (!aSubStr.IsIntegerValue()
+          || aSubStr.IntegerValue() <= 0)
+        {
+          std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
+          return 1;
+        }
+        aSubIndex = aSubStr.IntegerValue();
+      }
+
+      Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
+      Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
+      Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
+      Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
+      Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
+      for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
+      {
+        if (aSubPln->ChainNextPlane().IsNull())
+        {
+          aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
+        }
+        aSubPln = aSubPln->ChainNextPlane();
+      }
+      aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
+      aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
       anArgIter += 4;
     }
+    else if ((aChangeArg == "-boxinterior"
+           || aChangeArg == "-boxint"
+           || aChangeArg == "-box")
+            && aNbChangeArgs >= 7)
+    {
+      Graphic3d_BndBox3d aBndBox;
+      aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
+      aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
+      anArgIter += 6;
+
+      Standard_Integer aNbSubPlanes = 6;
+      const Graphic3d_Vec3d aDirArray[6] =
+      {
+        Graphic3d_Vec3d (-1, 0, 0),
+        Graphic3d_Vec3d ( 1, 0, 0),
+        Graphic3d_Vec3d ( 0,-1, 0),
+        Graphic3d_Vec3d ( 0, 1, 0),
+        Graphic3d_Vec3d ( 0, 0,-1),
+        Graphic3d_Vec3d ( 0, 0, 1),
+      };
+      Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
+      for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
+      {
+        const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
+        const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
+        aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
+        if (aSubPlaneIter + 1 == aNbSubPlanes)
+        {
+          aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
+        }
+        else
+        {
+          aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
+        }
+        aSubPln = aSubPln->ChainNextPlane();
+      }
+    }
     else if (aChangeArg == "-capping"
           || aChangeArg == "capping")
     {
@@ -12300,7 +12361,9 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     __FILE__,VHLRType,group);
   theCommands.Add("vclipplane",
               "vclipplane planeName [{0|1}]"
-      "\n\t\t:   [-equation A B C D]"
+      "\n\t\t:   [-equation1 A B C D]"
+      "\n\t\t:   [-equation2 A B C D]"
+      "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
       "\n\t\t:   [-maxPlanes]"
       "\n\t\t:   [-capping {0|1}]"
index 966059e..cd53b63 100644 (file)
@@ -1,10 +1,8 @@
+puts "REQUIRED All: Error: clipping planes limit"
 puts "==========="
-puts "OCC25052"
+puts "OCC25052: Visualization - activation of all Clipping Planes within driver limit leads to broken planes management"
 puts "==========="
 puts ""
-##########################################################################
-# Visualization - activation of all Clipping Planes within driver limit leads to broken planes management
-##########################################################################
 
 set Image1 ${imagedir}/${casename}_1.png
 set Image9 ${imagedir}/${casename}_9.png
diff --git a/tests/v3d/glsl/clipping1 b/tests/v3d/glsl/clipping1
new file mode 100644 (file)
index 0000000..126b99b
--- /dev/null
@@ -0,0 +1,91 @@
+puts "========"
+puts "0029729: Visualization, Graphic3d_ClipPlane - add support of clipping plane chains"
+puts "========"
+
+vclear
+vclose ALL
+vinit View1
+
+set aCapParams "-capping 1 -color 0.5 0.5 0.5 -texname [locate_data_file images/hatch_1.png] -texscale 0.02 -0.02 -useObjMaterial 1"
+
+pload MODELING VISUALIZATION
+
+# create the geometry
+box b0sole 10 10   0 30 30 70
+box b0hole 20 20 -10 10 10 90
+bcut b0 b0sole b0hole
+box b1 40 20 0 10 30 70
+box b2 20 40 0 20 10 70
+box b3 0  40 0 20 10 70
+box b4 0  10 0 10 30 70
+box b5 0   0 0 30 10 70
+
+set aNbParts 6
+set aColors { RED YELLOW GREEN GRAY MAGENTA1 ORANGE }
+
+compound b0 b1 b2 b3 b4 b5 cc
+
+# create the viewer
+vclear
+vclose ALL
+vinit name=View1 w=512 h=512
+vviewparams -scale 4.66737 -proj 0.465292 -0.577133 0.671134 -up -0.46873 0.482524 0.739907 -at 15.807 37.1157 21.9799
+
+vpoint p0 0 0 0
+vzbufftrihedron
+
+puts "Display the geometry as dedicated objects"
+for { set aPartIter 0 } { $aPartIter < $aNbParts } { incr aPartIter } {
+  vdisplay -noupdate -dispMode 1 b${aPartIter}
+  set aColor [lindex $aColors $aPartIter]
+  vsetcolor -noupdate b${aPartIter} $aColor
+}
+
+puts "Display the geometry as sole object"
+vdisplay -noupdate -dispMode 1 cc
+for { set aPartIter 0 } { $aPartIter < $aNbParts } { incr aPartIter } {
+  set aColor [lindex $aColors $aPartIter]
+  vaspects -noupdate cc -subShapes b${aPartIter} -setColor $aColor
+}
+# show also connected interactive object
+vconnectto co -70 0 0 cc
+vsetdispmode co 1
+vsetlocation cc 70 0 0
+
+set aPln1Z 40
+set aPln2Y 15
+
+vremove -noupdate p1 p2 p3 pp1 pp2
+vpoint p1 0 0 1
+vpoint p2 1 0 1
+vpoint p3 0 1 1
+vplane pp1 p1 p2 p3
+vsetlocation -noupdate pp1 25 0 [expr $aPln1Z - 1]
+vremove -noupdate p1 p2 p3
+
+vpoint p1 0 1 0
+vpoint p2 1 1 0
+vpoint p3 0 1 1
+vplane pp2 p1 p2 p3
+vsetlocation -noupdate pp2 25 $aPln2Y 35
+vremove -noupdate p1 p2 p3
+verase pp1 pp2
+vfit
+vdisplay pp1 pp2
+
+vclipplane pln -set {*}$aCapParams -equation1 0 0 -1 40 -equation2  0 1 0 -15
+vdump $::imagedir/${::casename}_2.png
+
+vclipplane pln -set {*}$aCapParams -equation1 0 0 -1 40 -equation2  0 1 0 -15 -equation3 -1 0 0 5
+vdump $::imagedir/${::casename}_3.png
+
+vsettransparency b0 b1 b2 b3 b4 b5 0.5
+vdump $::imagedir/${::casename}_3transp.png
+
+vviewparams -scale 8.51584 -proj 0.284186 0.750426 0.59674 -up -0.228109 -0.55161 0.802305 -at 24.2647 23.8116 32.8743
+vclipplane pln -set {*}$aCapParams -boxint 25 25 25 55 55 55
+vsettransparency b0 b1 b2 b3 b4 b5 0
+vdump $::imagedir/${::casename}_6.png
+
+vsettransparency b0 b1 b2 b3 b4 b5 0.5
+vdump $::imagedir/${::casename}_6transp.png