0030748: Visualization - Marker displayed in immediate layer ruins QT Quick view...
[occt.git] / src / OpenGl / OpenGl_Clipping.cxx
index 9bfce47..a572df8 100755 (executable)
 // commercial license or contractual agreement.
 
 #include <OpenGl_Clipping.hxx>
-#include <OpenGl_GlCore11.hxx>
-#include <OpenGl_Workspace.hxx>
 
-#if defined(GL_ES_VERSION_2_0)
-  // id does not matter for GLSL-based clipping, just for consistency
-  #define GL_CLIP_PLANE0 0x3000
-#endif
+#include <OpenGl_ClippingIterator.hxx>
 
 // =======================================================================
-// function : OpenGl_ClippingState
+// function : OpenGl_Clipping
 // purpose  :
 // =======================================================================
-OpenGl_Clipping::OpenGl_Clipping ()
-: myEmptyPlaneIds (new Aspect_GenId (GL_CLIP_PLANE0, GL_CLIP_PLANE0 + 5)),
+OpenGl_Clipping::OpenGl_Clipping()
+: myCappedSubPlane (0),
   myNbClipping (0),
-  myNbCapping  (0)
+  myNbCapping  (0),
+  myNbChains   (0),
+  myNbDisabled (0)
 {}
 
 // =======================================================================
 // function : Init
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::Init (const Standard_Integer theMaxPlanes)
+void OpenGl_Clipping::Init()
 {
-  myPlanes.Clear();
-  myPlaneStates.Clear();
+  myPlanesGlobal.Nullify();
+  myPlanesLocal.Nullify();
+
   myNbClipping = 0;
   myNbCapping  = 0;
-  Standard_Integer aLowerId = GL_CLIP_PLANE0;
-  Standard_Integer aUpperId = GL_CLIP_PLANE0 + theMaxPlanes - 1;
-  myEmptyPlaneIds = new Aspect_GenId (aLowerId, aUpperId);
+  myNbChains   = 0;
+  myNbDisabled = 0;
+  myCappedSubPlane = 0;
+  myCappedChain.Nullify();
 }
 
 // =======================================================================
-// function : Add
+// function : Reset
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::Add (Graphic3d_SequenceOfHClipPlane& thePlanes,
-                           const EquationCoords& theCoordSpace,
-                           const Handle(OpenGl_Workspace)& theWS)
+void OpenGl_Clipping::Reset (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
 {
-  Handle(OpenGl_Context) aContext = theWS->GetGlContext();
+  const Standard_Integer aStartIndex = myPlanesGlobal.IsNull() ? 1 : myPlanesGlobal->Size() + 1;
+  remove (myPlanesLocal,  aStartIndex);
+  remove (myPlanesGlobal, 1);
 
-  if (EquationCoords_View == theCoordSpace)
-  {
-    aContext->WorldViewState.Push();
-    aContext->WorldViewState.SetIdentity();
-  }
+  myPlanesGlobal = thePlanes;
+  myPlanesLocal.Nullify();
 
-  // Set either identity or pure view matrix.
-  aContext->ApplyWorldViewMatrix();
+  add (thePlanes, 1);
+  myNbDisabled = 0;
+  myCappedSubPlane = 0;
+  myCappedChain.Nullify();
 
-  Add (thePlanes, theCoordSpace);
+  // Method ::add() implicitly extends myDisabledPlanes (NCollection_Vector::SetValue()),
+  // however we do not reset myDisabledPlanes and mySkipFilter beforehand to avoid redundant memory re-allocations.
+  // So once extended, they will never reduce their size to lower values.
+  // This should not be a problem since overall number of clipping planes is expected to be quite small.
+}
 
-  if (EquationCoords_View == theCoordSpace)
-  {
-    aContext->WorldViewState.Pop();
-  }
+// =======================================================================
+// function : SetLocalPlanes
+// purpose  :
+// =======================================================================
+void OpenGl_Clipping::SetLocalPlanes (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
+{
+  const Standard_Integer aStartIndex = myPlanesGlobal.IsNull() ? 1 : myPlanesGlobal->Size() + 1;
+  remove (myPlanesLocal, aStartIndex);
 
-  // Restore combined model-view matrix.
-  aContext->ApplyModelViewMatrix();
+  myPlanesLocal = thePlanes;
 
+  add (thePlanes, aStartIndex);
 }
 
 // =======================================================================
-// function : Add
+// function : add
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::Add (Graphic3d_SequenceOfHClipPlane& thePlanes, const EquationCoords& theCoordSpace)
+void OpenGl_Clipping::add (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
+                           const Standard_Integer theStartIndex)
 {
-  Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
-  while (aPlaneIt.More() && myEmptyPlaneIds->HasFree())
+  if (thePlanes.IsNull())
+  {
+    return;
+  }
+
+  Standard_Integer aPlaneId = theStartIndex;
+  for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*thePlanes); aPlaneIt.More(); aPlaneIt.Next(), ++aPlaneId)
   {
     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
-    if (Contains (aPlane))
+    myDisabledPlanes.SetValue (aPlaneId, Standard_False); // automatically resizes the vector
+    if (!aPlane->IsOn())
     {
-      thePlanes.Remove (aPlaneIt);
       continue;
     }
 
-    Standard_Integer anID = myEmptyPlaneIds->Next();
-    myPlanes.Append (aPlane);
-    myPlaneStates.Bind (aPlane, PlaneProps (theCoordSpace, anID, Standard_True));
-
-  #if !defined(GL_ES_VERSION_2_0)
-    ::glEnable ((GLenum)anID);
-    ::glClipPlane ((GLenum)anID, aPlane->GetEquation());
-  #endif
+    const Standard_Integer aNbSubPlanes = aPlane->NbChainNextPlanes();
+    myNbChains += 1;
     if (aPlane->IsCapping())
     {
-      ++myNbCapping;
+      myNbCapping += aNbSubPlanes;
     }
     else
     {
-      ++myNbClipping;
-    }
-
-    aPlaneIt.Next();
-  }
-
-  if (!myEmptyPlaneIds->HasFree())
-  {
-    while (aPlaneIt.More())
-    {
-      thePlanes.Remove (aPlaneIt);
+      myNbClipping += aNbSubPlanes;
     }
   }
 }
 
 // =======================================================================
-// function : Remove
+// function : remove
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::Remove (const Graphic3d_SequenceOfHClipPlane& thePlanes)
+void OpenGl_Clipping::remove (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
+                              const Standard_Integer theStartIndex)
 {
-  Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
-  for (; aPlaneIt.More(); aPlaneIt.Next())
+  if (thePlanes.IsNull())
+  {
+    return;
+  }
+
+  Standard_Integer aPlaneIndex = theStartIndex;
+  for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*thePlanes); aPlaneIt.More(); aPlaneIt.Next(), ++aPlaneIndex)
   {
     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
-    if (!Contains (aPlane))
+    if (!aPlane->IsOn()
+     || myDisabledPlanes.Value (aPlaneIndex))
     {
       continue;
     }
 
-    Standard_Integer anID = myPlaneStates.Find (aPlane).ContextID;
-    PlaneProps& aProps = myPlaneStates.ChangeFind (aPlane);
-    if (aProps.IsEnabled)
-    {
-    #if !defined(GL_ES_VERSION_2_0)
-      glDisable ((GLenum)anID);
-    #endif
-      if (aPlane->IsCapping())
-      {
-        --myNbCapping;
-      }
-      else
-      {
-        --myNbClipping;
-      }
-    }
-
-    myEmptyPlaneIds->Free (anID);
-    myPlaneStates.UnBind (aPlane);
-  }
-
-  // renew collection of planes
-  aPlaneIt.Init (myPlanes);
-  while (aPlaneIt.More())
-  {
-    const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
-    if (!myPlaneStates.IsBound (aPlane))
+    const Standard_Integer aNbSubPlanes = aPlane->NbChainNextPlanes();
+    myNbChains -= 1;
+    if (aPlane->IsCapping())
     {
-      myPlanes.Remove (aPlaneIt);
+      myNbCapping -= aNbSubPlanes;
     }
     else
     {
-      aPlaneIt.Next();
+      myNbClipping -= aNbSubPlanes;
     }
   }
 }
@@ -179,51 +158,112 @@ void OpenGl_Clipping::Remove (const Graphic3d_SequenceOfHClipPlane& thePlanes)
 // function : SetEnabled
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::SetEnabled (const Handle(Graphic3d_ClipPlane)& thePlane,
-                                  const Standard_Boolean theIsEnabled)
+Standard_Boolean OpenGl_Clipping::SetEnabled (const OpenGl_ClippingIterator& thePlane,
+                                              const Standard_Boolean         theIsEnabled)
 {
-  if (!Contains (thePlane))
+  const Standard_Integer aPlaneIndex = thePlane.PlaneIndex();
+  Standard_Boolean& isDisabled = myDisabledPlanes.ChangeValue (aPlaneIndex);
+  if (isDisabled == !theIsEnabled)
   {
-    return;
+    return Standard_False;
+  }
+
+  isDisabled = !theIsEnabled;
+  const Standard_Integer aNbSubPlanes = thePlane.Value()->NbChainNextPlanes();
+  if (thePlane.Value()->IsCapping())
+  {
+    myNbCapping += (theIsEnabled ? aNbSubPlanes : -aNbSubPlanes);
+  }
+  else
+  {
+    myNbClipping += (theIsEnabled ? aNbSubPlanes : -aNbSubPlanes);
   }
+  myNbChains   += (theIsEnabled ? 1 : -1);
+  myNbDisabled += (theIsEnabled ? -aNbSubPlanes : aNbSubPlanes);
+  return Standard_True;
+}
 
-  PlaneProps& aProps = myPlaneStates.ChangeFind (thePlane);
-  if (theIsEnabled == aProps.IsEnabled)
+// =======================================================================
+// function : RestoreDisabled
+// purpose  :
+// =======================================================================
+void OpenGl_Clipping::RestoreDisabled()
+{
+  if (myNbDisabled == 0)
   {
     return;
   }
 
-#if !defined(GL_ES_VERSION_2_0)
-  GLenum anID = (GLenum)aProps.ContextID;
-#endif
-  if (theIsEnabled)
+  myNbDisabled = 0;
+  for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
   {
-  #if !defined(GL_ES_VERSION_2_0)
-    glEnable (anID);
-  #endif
-    if (thePlane->IsCapping())
+    Standard_Boolean& isDisabled = myDisabledPlanes.ChangeValue (aPlaneIter.PlaneIndex());
+    if (!isDisabled)
+    {
+      continue;
+    }
+
+    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;
     }
   }
-  else
+}
+
+// =======================================================================
+// function : DisableGlobal
+// purpose  :
+// =======================================================================
+void OpenGl_Clipping::DisableGlobal()
+{
+  for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
   {
-  #if !defined(GL_ES_VERSION_2_0)
-    glDisable (anID);
-  #endif
-    if (thePlane->IsCapping())
+    if (!aPlaneIter.IsGlobal())
     {
-      --myNbCapping;
-    }
-    else
-    {
-      --myNbClipping;
+      // local planes always follow global ones in iterator
+      return;
     }
+
+    SetEnabled (aPlaneIter, Standard_False);
   }
+}
+
+// =======================================================================
+// function : DisableAllExcept
+// purpose  :
+// =======================================================================
+void OpenGl_Clipping::DisableAllExcept (const Handle(Graphic3d_ClipPlane)& theChain,
+                                        const Standard_Integer theSubPlaneIndex)
+{
+  myCappedChain = theChain;
+  myCappedSubPlane = theSubPlaneIndex;
+}
 
-  aProps.IsEnabled = theIsEnabled;
+// =======================================================================
+// function : EnableAllExcept
+// purpose  :
+// =======================================================================
+void OpenGl_Clipping::EnableAllExcept (const Handle(Graphic3d_ClipPlane)& theChain,
+                                       const Standard_Integer theSubPlaneIndex)
+{
+  myCappedChain = theChain;
+  myCappedSubPlane = -theSubPlaneIndex;
+}
+
+// =======================================================================
+// function : ResetCappingFilter
+// purpose  :
+// =======================================================================
+void OpenGl_Clipping::ResetCappingFilter()
+{
+  myCappedChain.Nullify();
+  myCappedSubPlane = 0;
 }