// commercial license or contractual agreement.
#include <OpenGl_Clipping.hxx>
+
#include <OpenGl_GlCore11.hxx>
#include <OpenGl_Workspace.hxx>
+#include <OpenGl_Context.hxx>
+
+// =======================================================================
+// 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_PLANE5)),
+: 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 (Graphic3d_SequenceOfHClipPlane& thePlanes,
- const EquationCoords& theCoordSpace,
- const Handle(OpenGl_Workspace)& theWS)
+void OpenGl_Clipping::Reset (const Handle(OpenGl_Context)& theGlCtx,
+ const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
{
- GLint aMatrixMode;
- glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
+ const Standard_Integer aStartIndex = myPlanesGlobal.IsNull() ? 1 : myPlanesGlobal->Size() + 1;
+ remove (theGlCtx, myPlanesLocal, aStartIndex);
+ remove (theGlCtx, myPlanesGlobal, 1);
- OpenGl_Matrix aCurrentMx;
- glGetFloatv (GL_MODELVIEW_MATRIX, (GLfloat*) &aCurrentMx);
+ myPlanesGlobal = thePlanes;
+ myPlanesLocal.Nullify();
- if (aMatrixMode != GL_MODELVIEW)
- {
- glMatrixMode (GL_MODELVIEW);
- }
+ add (theGlCtx, thePlanes, 1);
+ myNbDisabled = 0;
- switch (theCoordSpace)
- {
- case EquationCoords_View: glLoadMatrixf ((const GLfloat*) &OpenGl_IdentityMatrix); break;
- case EquationCoords_World: glLoadMatrixf ((const GLfloat*) theWS->ViewMatrix()); break;
- }
+ // 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.
+}
- Add (thePlanes, theCoordSpace);
+// =======================================================================
+// 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);
- // restore model-view matrix
- glLoadMatrixf ((GLfloat*) &aCurrentMx);
+ myPlanesLocal = thePlanes;
- // restore context matrix state
- if (aMatrixMode != GL_MODELVIEW)
- {
- glMatrixMode (aMatrixMode);
- }
+ add (theGlCtx, thePlanes, aStartIndex);
}
// =======================================================================
-// function : Add
+// function : add
// purpose :
// =======================================================================
-void OpenGl_Clipping::Add (Graphic3d_SequenceOfHClipPlane& thePlanes, const EquationCoords& theCoordSpace)
+void OpenGl_Clipping::add (const Handle(OpenGl_Context)& theGlCtx,
+ const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
+ const Standard_Integer theStartIndex)
{
- Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
- while (aPlaneIt.More() && myEmptyPlaneIds->HasFree())
+ 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
+
+ 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));
-
- glEnable ((GLenum)anID);
- glClipPlane ((GLenum)anID, aPlane->GetEquation());
+ #if !defined(GL_ES_VERSION_2_0)
+ if (toUseFfp && myEmptyPlaneIds->HasFree())
+ {
+ const Standard_Integer anFfpPlaneID = GL_CLIP_PLANE0 + myEmptyPlaneIds->Next();
+ ::glEnable ((GLenum )anFfpPlaneID);
+ theGlCtx->core11->glClipPlane ((GLenum )anFfpPlaneID, aPlane->GetEquation());
+ }
+ #endif
if (aPlane->IsCapping())
{
++myNbCapping;
{
++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 Graphic3d_SequenceOfHClipPlane& thePlanes)
+void OpenGl_Clipping::remove (const Handle(OpenGl_Context)& theGlCtx,
+ const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
+ const Standard_Integer theStartIndex)
{
- Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
- for (; aPlaneIt.More(); aPlaneIt.Next())
+ if (thePlanes.IsNull())
+ {
+ return;
+ }
+
+#if !defined(GL_ES_VERSION_2_0)
+ const bool toUseFfp = theGlCtx->core11 != NULL
+ && theGlCtx->caps->ffpEnable;
+#else
+ (void )theGlCtx;
+#endif
+
+ 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())
{
- glDisable ((GLenum)anID);
- if (aPlane->IsCapping())
- {
- --myNbCapping;
- }
- else
+ if (toUseFfp)
{
- --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(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;
+ }
+
+ 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
- PlaneProps& aProps = myPlaneStates.ChangeFind (thePlane);
- if (theIsEnabled == aProps.IsEnabled)
+ 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;
}
- GLenum anID = (GLenum)aProps.ContextID;
- if (theIsEnabled)
+ myNbDisabled = 0;
+#if !defined(GL_ES_VERSION_2_0)
+ const bool toUseFfp = theGlCtx->core11 != NULL
+ && theGlCtx->caps->ffpEnable;
+#else
+ (void )theGlCtx;
+#endif
+ for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
{
- glEnable (anID);
- if (thePlane->IsCapping())
+ Standard_Boolean& isDisabled = myDisabledPlanes.ChangeValue (aPlaneIter.PlaneIndex());
+ if (!isDisabled)
+ {
+ continue;
+ }
+
+ isDisabled = Standard_False;
+ #if !defined(GL_ES_VERSION_2_0)
+ if (toUseFfp)
+ {
+ const Standard_Integer anFfpPlaneID = myEmptyPlaneIds->Lower() + aPlaneIter.PlaneIndex() - 1;
+ if (anFfpPlaneID <= myEmptyPlaneIds->Upper())
+ {
+ ::glEnable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
+ }
+ }
+ #endif
+
+ 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())
{
- glDisable (anID);
- if (thePlane->IsCapping())
+ if (!aPlaneIter.IsGlobal())
{
- --myNbCapping;
+ // local planes always follow global ones in iterator
+ return;
}
- else
+
+ 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())
{
- --myNbClipping;
+ 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);
}
+}
+
+// =======================================================================
+// 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()))
+ {
+ continue;
+ }
- aProps.IsEnabled = theIsEnabled;
+ const Standard_Boolean isOn = (aPlaneIter.PlaneIndex() != thePlane.PlaneIndex());
+ SetEnabled (theGlCtx, aPlaneIter, isOn);
+ }
}