#include <OpenGl_Workspace.hxx>
#include <OpenGl_Context.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
+// =======================================================================
+// function : OpenGl_ClippingIterator
+// 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 ()
-: myEmptyPlaneIds (new Aspect_GenId (GL_CLIP_PLANE0, GL_CLIP_PLANE0 + 5)),
+: myEmptyPlaneIds (new NCollection_Shared<Aspect_GenId> (1, 6)),
myNbClipping (0),
- myNbCapping (0)
+ myNbCapping (0),
+ myNbDisabled (0)
{}
// =======================================================================
// =======================================================================
void OpenGl_Clipping::Init (const Standard_Integer theMaxPlanes)
{
- 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);
+ myNbDisabled = 0;
+ myEmptyPlaneIds = new NCollection_Shared<Aspect_GenId> (1, theMaxPlanes);
}
// =======================================================================
-// function : add
+// function : Reset
// purpose :
// =======================================================================
-void OpenGl_Clipping::add (const Handle(OpenGl_Context)& theGlCtx,
- Graphic3d_SequenceOfHClipPlane& thePlanes)
+void OpenGl_Clipping::Reset (const Handle(OpenGl_Context)& theGlCtx,
+ const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
{
- const bool toUseFfp = theGlCtx->core11 != NULL
- && theGlCtx->caps->ffpEnable;
- if (!toUseFfp)
- {
- addLazy (theGlCtx, thePlanes);
- return;
- }
+ const Standard_Integer aStartIndex = myPlanesGlobal.IsNull() ? 1 : myPlanesGlobal->Size() + 1;
+ remove (theGlCtx, myPlanesLocal, aStartIndex);
+ remove (theGlCtx, myPlanesGlobal, 1);
- // Set either identity or pure view matrix.
- theGlCtx->ApplyWorldViewMatrix();
+ myPlanesGlobal = thePlanes;
+ myPlanesLocal.Nullify();
- addLazy (theGlCtx, thePlanes);
+ add (theGlCtx, thePlanes, 1);
+ myNbDisabled = 0;
- // Restore combined model-view matrix.
- theGlCtx->ApplyModelViewMatrix();
+ // 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.
+}
+
+// =======================================================================
+// function : SetLocalPlanes
+// purpose :
+// =======================================================================
+void OpenGl_Clipping::SetLocalPlanes (const Handle(OpenGl_Context)& theGlCtx,
+ const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
+{
+ const Standard_Integer aStartIndex = myPlanesGlobal.IsNull() ? 1 : myPlanesGlobal->Size() + 1;
+ remove (theGlCtx, myPlanesLocal, aStartIndex);
+
+ myPlanesLocal = thePlanes;
+
+ add (theGlCtx, thePlanes, aStartIndex);
}
// =======================================================================
-// function : addLazy
+// function : add
// purpose :
// =======================================================================
-void OpenGl_Clipping::addLazy (const Handle(OpenGl_Context)& theGlCtx,
- Graphic3d_SequenceOfHClipPlane& thePlanes)
+void OpenGl_Clipping::add (const Handle(OpenGl_Context)& theGlCtx,
+ const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
+ const Standard_Integer theStartIndex)
{
+ if (thePlanes.IsNull())
+ {
+ return;
+ }
+
#if !defined(GL_ES_VERSION_2_0)
const bool toUseFfp = theGlCtx->core11 != NULL
&& theGlCtx->caps->ffpEnable;
+ if (toUseFfp)
+ {
+ // Set either identity or pure view matrix.
+ theGlCtx->ApplyWorldViewMatrix();
+ }
#else
(void )theGlCtx;
#endif
- Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
- while (aPlaneIt.More() && myEmptyPlaneIds->HasFree())
+ 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 (anID, Standard_True));
-
#if !defined(GL_ES_VERSION_2_0)
- if (toUseFfp)
+ if (toUseFfp && myEmptyPlaneIds->HasFree())
{
- ::glEnable ((GLenum)anID);
- theGlCtx->core11->glClipPlane ((GLenum)anID, aPlane->GetEquation());
+ const Standard_Integer anFfpPlaneID = GL_CLIP_PLANE0 + myEmptyPlaneIds->Next();
+ ::glEnable ((GLenum )anFfpPlaneID);
+ theGlCtx->core11->glClipPlane ((GLenum )anFfpPlaneID, aPlane->GetEquation());
}
#endif
if (aPlane->IsCapping())
{
++myNbClipping;
}
-
- aPlaneIt.Next();
}
- if (!myEmptyPlaneIds->HasFree())
+#if !defined(GL_ES_VERSION_2_0)
+ // Restore combined model-view matrix.
+ if (toUseFfp)
{
- while (aPlaneIt.More())
- {
- thePlanes.Remove (aPlaneIt);
- }
+ theGlCtx->ApplyModelViewMatrix();
}
+#endif
}
// =======================================================================
-// function : Remove
+// function : remove
// purpose :
// =======================================================================
-void OpenGl_Clipping::Remove (const Handle(OpenGl_Context)& theGlCtx,
- const Graphic3d_SequenceOfHClipPlane& thePlanes)
+void OpenGl_Clipping::remove (const Handle(OpenGl_Context)& theGlCtx,
+ const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
+ const Standard_Integer theStartIndex)
{
+ if (thePlanes.IsNull())
+ {
+ return;
+ }
+
#if !defined(GL_ES_VERSION_2_0)
const bool toUseFfp = theGlCtx->core11 != NULL
&& theGlCtx->caps->ffpEnable;
(void )theGlCtx;
#endif
- Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
- for (; aPlaneIt.More(); aPlaneIt.Next())
+ 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)
+ const Standard_Integer anFfpPlaneID = myEmptyPlaneIds->Lower() + aPlaneIndex - 1;
+ if (anFfpPlaneID <= myEmptyPlaneIds->Upper())
{
- #if !defined(GL_ES_VERSION_2_0)
if (toUseFfp)
{
- ::glDisable ((GLenum)anID);
- }
- #endif
- if (aPlane->IsCapping())
- {
- --myNbCapping;
- }
- else
- {
- --myNbClipping;
+ ::glDisable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
}
+ myEmptyPlaneIds->Free (anFfpPlaneID);
}
+ #endif
- 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))
+ if (aPlane->IsCapping())
{
- myPlanes.Remove (aPlaneIt);
+ --myNbCapping;
}
else
{
- aPlaneIt.Next();
+ --myNbClipping;
}
}
}
// function : SetEnabled
// purpose :
// =======================================================================
-void OpenGl_Clipping::SetEnabled (const Handle(OpenGl_Context)& theGlCtx,
- const Handle(Graphic3d_ClipPlane)& thePlane,
- const Standard_Boolean theIsEnabled)
+Standard_Boolean OpenGl_Clipping::SetEnabled (const Handle(OpenGl_Context)& theGlCtx,
+ 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;
}
- PlaneProps& aProps = myPlaneStates.ChangeFind (thePlane);
- if (theIsEnabled == aProps.IsEnabled)
+ isDisabled = !theIsEnabled;
+
+#if !defined(GL_ES_VERSION_2_0)
+ const bool toUseFfp = theGlCtx->core11 != NULL
+ && theGlCtx->caps->ffpEnable;
+ if (toUseFfp)
+ {
+ const Standard_Integer anFfpPlaneID = myEmptyPlaneIds->Lower() + aPlaneIndex - 1;
+ if (anFfpPlaneID <= myEmptyPlaneIds->Upper())
+ {
+ if (theIsEnabled)
+ {
+ ::glEnable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
+ }
+ else
+ {
+ ::glDisable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
+ }
+ }
+ }
+#else
+ (void )theGlCtx;
+#endif
+
+ if (thePlane.Value()->IsCapping())
+ {
+ myNbCapping += (theIsEnabled ? 1 : -1);
+ }
+ else
+ {
+ myNbClipping += (theIsEnabled ? 1 : -1);
+ }
+ myNbDisabled -= (theIsEnabled ? 1 : -1);
+ return Standard_True;
+}
+
+// =======================================================================
+// function : RestoreDisabled
+// purpose :
+// =======================================================================
+void OpenGl_Clipping::RestoreDisabled (const Handle(OpenGl_Context)& theGlCtx)
+{
+ if (myNbDisabled == 0)
{
return;
}
+ myNbDisabled = 0;
#if !defined(GL_ES_VERSION_2_0)
- GLenum anID = (GLenum)aProps.ContextID;
const bool toUseFfp = theGlCtx->core11 != NULL
&& theGlCtx->caps->ffpEnable;
#else
(void )theGlCtx;
#endif
- if (theIsEnabled)
+ for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
{
+ Standard_Boolean& isDisabled = myDisabledPlanes.ChangeValue (aPlaneIter.PlaneIndex());
+ if (!isDisabled)
+ {
+ continue;
+ }
+
+ isDisabled = Standard_False;
#if !defined(GL_ES_VERSION_2_0)
if (toUseFfp)
{
- ::glEnable (anID);
+ const Standard_Integer anFfpPlaneID = myEmptyPlaneIds->Lower() + aPlaneIter.PlaneIndex() - 1;
+ if (anFfpPlaneID <= myEmptyPlaneIds->Upper())
+ {
+ ::glEnable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
+ }
}
#endif
- if (thePlane->IsCapping())
+
+ const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
+ if (aPlane->IsCapping())
{
++myNbCapping;
}
++myNbClipping;
}
}
- else
+}
+
+// =======================================================================
+// function : DisableGlobal
+// purpose :
+// =======================================================================
+void OpenGl_Clipping::DisableGlobal (const Handle(OpenGl_Context)& theGlCtx)
+{
+ for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
{
- #if !defined(GL_ES_VERSION_2_0)
- if (toUseFfp)
+ if (!aPlaneIter.IsGlobal())
{
- ::glDisable (anID);
+ // local planes always follow global ones in iterator
+ return;
}
- #endif
- if (thePlane->IsCapping())
+
+ SetEnabled (theGlCtx, aPlaneIter, Standard_False);
+ }
+}
+
+// =======================================================================
+// function : DisableAllExcept
+// purpose :
+// =======================================================================
+void OpenGl_Clipping::DisableAllExcept (const Handle(OpenGl_Context)& theGlCtx,
+ const OpenGl_ClippingIterator& thePlane)
+{
+ for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
+ {
+ if (aPlaneIter.IsDisabled())
{
- --myNbCapping;
+ mySkipFilter.SetValue (aPlaneIter.PlaneIndex(), Standard_True);
+ continue;
}
- else
+
+ const Standard_Boolean isOn = (aPlaneIter.PlaneIndex() == thePlane.PlaneIndex());
+ SetEnabled (theGlCtx, aPlaneIter, isOn);
+ mySkipFilter.SetValue (aPlaneIter.PlaneIndex(), Standard_False);
+ }
+}
+
+// =======================================================================
+// function : EnableAllExcept
+// purpose :
+// =======================================================================
+void OpenGl_Clipping::EnableAllExcept (const Handle(OpenGl_Context)& theGlCtx,
+ const OpenGl_ClippingIterator& thePlane)
+{
+ for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
+ {
+ if (mySkipFilter.Value (aPlaneIter.PlaneIndex()))
{
- --myNbClipping;
+ continue;
}
- }
- aProps.IsEnabled = theIsEnabled;
+ const Standard_Boolean isOn = (aPlaneIter.PlaneIndex() != thePlane.PlaneIndex());
+ SetEnabled (theGlCtx, aPlaneIter, isOn);
+ }
}