0024224: Suspicious logics in changing clipping planes at OpenGl_Structure
authorapl <apl@opencascade.com>
Thu, 10 Oct 2013 13:14:52 +0000 (17:14 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 10 Oct 2013 13:15:53 +0000 (17:15 +0400)
1) Resolved buggy situation of shared clip planes between view and structure;
2) Added clipping plane equation space identification - to be used with shaders;
3) Code refactoring to resolve performance issue reported by 0024189;
4) Attachment of stencil buffer to FBO.

Added test case bugs/vis/bug24224

14 files changed:
src/Graphic3d/FILES
src/Graphic3d/Graphic3d_ClipPlane.hxx
src/Graphic3d/Graphic3d_SetOfHClipPlane_Handle.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_CappingAlgo.cxx
src/OpenGl/OpenGl_ClippingState.cxx
src/OpenGl/OpenGl_ClippingState.hxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_FrameBuffer.cxx
src/OpenGl/OpenGl_FrameBuffer.hxx
src/OpenGl/OpenGl_Structure.cxx
src/OpenGl/OpenGl_Structure.hxx
src/OpenGl/OpenGl_View_2.cxx
tests/bugs/vis/bug24224 [new file with mode: 0644]

index a627f0e..494616a 100755 (executable)
@@ -57,3 +57,4 @@ Graphic3d_ClipPlane.hxx
 Graphic3d_ClipPlane.cxx
 Graphic3d_ClipPlane_Handle.hxx
 Graphic3d_SetOfHClipPlane.hxx
+Graphic3d_SetOfHClipPlane_Handle.hxx
\ No newline at end of file
index 16e48d0..45afafe 100644 (file)
@@ -41,9 +41,10 @@ class Handle(Graphic3d_AspectFillArea3d);
 //! 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.
+//! 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
-//! dependant: at least 6 planes are available. Thus, take into account
+//! 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
@@ -72,16 +73,18 @@ public:
   //! @param theEquation [in] the plane equation.
   Standard_EXPORT Graphic3d_ClipPlane (const Equation& theEquation);
 
-  //! Construct clip plane from the passed geomertical definition.
+  //! Construct clip plane from the passed geometrical definition.
   //! By default the plane is on, capping is turned off.
   //! @param thePlane [in] the plane.
   Standard_EXPORT Graphic3d_ClipPlane (const gp_Pln& thePlane);
 
   //! Set plane equation by its geometrical definition.
+  //! The equation is specified in "world" coordinate system.
   //! @param thePlane [in] the plane.
   Standard_EXPORT void SetEquation (const gp_Pln& thePlane);
 
   //! 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);
 
@@ -108,7 +111,7 @@ public:
   //! @param theIsOn [in] the flag specifying whether the graphic driver should
   //! perform rendering of capping surface produced by this plane. The graphic
   //! driver produces this surface for convex graphics by means of stencil-test
-  //! and multipass rendering.
+  //! and multi-pass rendering.
   Standard_EXPORT void SetCapping(const Standard_Boolean theIsOn);
 
   //! Check state of capping surface rendering.
@@ -118,7 +121,7 @@ public:
     return myIsCapping;
   }
 
-  //! Get geomertical definition. The plane is built up
+  //! Get geometrical definition. The plane is built up
   //! from the equation clipping plane equation vector.
   //! @return geometrical definition of clipping plane.
   Standard_EXPORT gp_Pln ToPlane() const;
@@ -185,11 +188,11 @@ public: // @name user-defined graphical attributes
     return myId;
   }
 
-  //! Compute and return capping apsect from the graphical attributes.
+  //! Compute and return capping aspect from the graphical attributes.
   //! @return capping surface rendering aspect.
   Standard_EXPORT Handle(Graphic3d_AspectFillArea3d) CappingAspect() const;
 
-public: // @name modificaton counters
+public: // @name modification counters
 
   //! @return modification counter for equation.
   unsigned int MCountEquation() const
diff --git a/src/Graphic3d/Graphic3d_SetOfHClipPlane_Handle.hxx b/src/Graphic3d/Graphic3d_SetOfHClipPlane_Handle.hxx
new file mode 100644 (file)
index 0000000..71d80b2
--- /dev/null
@@ -0,0 +1,28 @@
+// Created on: 2013-10-08
+// Created by: Anton POLETAEV
+// Copyright (c) 2013 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 65 (the "License") You may not use the content of this file
+// except in compliance with the License Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file
+//
+// The Initial Developer of the Original Code is Open CASCADE SAS, having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License
+
+#ifndef _Graphic3d_SetOfHClipPlane_Handle_HeaderFile
+#define _Graphic3d_SetOfHClipPlane_Handle_HeaderFile
+
+#include <NCollection_Handle.hxx>
+#include <Graphic3d_SetOfHClipPlane.hxx>
+
+typedef NCollection_Handle<Graphic3d_SetOfHClipPlane> Handle(Graphic3d_SetOfHClipPlane);
+
+#endif
index 3340a97..482e267 100644 (file)
@@ -70,15 +70,11 @@ namespace
 void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorkspace,
                                         const OpenGl_ListOfGroup& theGroups)
 {
-  // do not draw capping surface for second transparency pass
-  if (theWorkspace->NamedStatus & OPENGL_NS_2NDPASSDO)
-    return;
-
   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
 
-  // check whether algorithm need to be runned
+  // check whether algorithm need to be performed
   Standard_Boolean isCapping = Standard_False;
-  Graphic3d_SetOfHClipPlane aContextPlanes = aContext->Clipping().Planes();
+  const Graphic3d_SetOfHClipPlane& aContextPlanes = aContext->Clipping().Planes();
   Graphic3d_SetOfHClipPlane::Iterator aCappingIt (aContextPlanes);
   for (; aCappingIt.More(); aCappingIt.Next())
   {
@@ -92,7 +88,9 @@ void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorks
 
   // do not perform algorithm is there is nothing to render
   if (!isCapping)
+  {
     return;
+  }
 
   // init internal data
   Init();
@@ -146,7 +144,7 @@ void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorks
       aGroupIt.Value()->Render (theWorkspace);
     }
 
-    // override material, cull backfaces
+    // override material, cull back faces
     theWorkspace->SetAspectFace (FrontCulling());
     theWorkspace->AspectFace (Standard_True);
 
index 308adba..25c7b0f 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <OpenGl_ClippingState.hxx>
 #include <OpenGl_GlCore11.hxx>
+#include <OpenGl_Workspace.hxx>
 
 namespace
 {
@@ -49,90 +50,34 @@ void OpenGl_ClippingState::Init (const Standard_Integer theMaxPlanes)
 }
 
 // =======================================================================
-// function : Planes
+// function : Add
 // purpose  :
 // =======================================================================
-Graphic3d_SetOfHClipPlane OpenGl_ClippingState::Planes() const
-{
-  Graphic3d_SetOfHClipPlane aRes;
-  OpenGl_MapOfContextPlanes::Iterator anIt (myPlanes);
-  for (; anIt.More(); anIt.Next())
-  {
-    aRes.Add (anIt.Key());
-  }
-
-  return aRes;
-}
-
-// =======================================================================
-// function : IsSet
-// purpose  :
-// =======================================================================
-Standard_Boolean OpenGl_ClippingState::IsSet (const Handle(Graphic3d_ClipPlane)& thePlane) const
-{
-  return myPlanes.IsBound (thePlane);
-}
-
-// =======================================================================
-// function : Set
-// purpose  :
-// =======================================================================
-void OpenGl_ClippingState::Set (const Graphic3d_SetOfHClipPlane& thePlanes,
-                                const Standard_Boolean theToEnable)
-{
-  Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (thePlanes);
-  for (; aPlaneIt.More() && myEmptyPlaneIds->Available() > 0; aPlaneIt.Next())
-  {
-    const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
-    if (IsSet (aPlane))
-      return;
-
-    Standard_Integer anId = myEmptyPlaneIds->Next();
-    myPlanes.Bind (aPlane, anId);
-    myPlaneStates.Bind (aPlane, theToEnable);
-
-    const GLenum anOpenGlId = (GLenum)anId;
-    if (theToEnable)
-    {
-      glEnable (anOpenGlId);
-    }
-    else
-    {
-      glDisable (anOpenGlId);
-    }
-
-    glClipPlane (anOpenGlId, aPlane->GetEquation());
-  }
-}
-
-// =======================================================================
-// function : Set
-// purpose  :
-// =======================================================================
-void OpenGl_ClippingState::Set (const Graphic3d_SetOfHClipPlane& thePlanes,
-                                const OpenGl_Matrix* theViewMatrix,
-                                const Standard_Boolean theToEnable)
+void OpenGl_ClippingState::Add (Graphic3d_SetOfHClipPlane& thePlanes,
+                                const EquationCoords& theCoordSpace,
+                                const Handle(OpenGl_Workspace)& theWS)
 {
   GLint aMatrixMode;
   glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
 
-  OpenGl_Matrix aCurrentMat;
-  glGetFloatv (GL_MODELVIEW_MATRIX, (GLfloat*)aCurrentMat.mat);
+  OpenGl_Matrix aCurrentMx;
+  glGetFloatv (GL_MODELVIEW_MATRIX, (GLfloat*) &aCurrentMx);
 
   if (aMatrixMode != GL_MODELVIEW)
   {
     glMatrixMode (GL_MODELVIEW);
   }
 
-  // load equation transform matrices
-  glLoadMatrixf ((theViewMatrix != NULL)
-    ? (const GLfloat*)theViewMatrix->mat
-    : (const GLfloat*)OpenGl_IdentityMatrix.mat);
+  switch (theCoordSpace)
+  {
+    case EquationCoords_View:  glLoadMatrixf ((const GLfloat*) &OpenGl_IdentityMatrix); break;
+    case EquationCoords_World: glLoadMatrixf ((const GLfloat*) theWS->ViewMatrix());    break;
+  }
 
-  Set (thePlanes, theToEnable);
+  Add (thePlanes, theCoordSpace);
 
   // restore model-view matrix
-  glLoadMatrixf ((GLfloat*)aCurrentMat.mat);
+  glLoadMatrixf ((GLfloat*) &aCurrentMx);
 
   // restore context matrix state
   if (aMatrixMode != GL_MODELVIEW)
@@ -142,86 +87,72 @@ void OpenGl_ClippingState::Set (const Graphic3d_SetOfHClipPlane& thePlanes,
 }
 
 // =======================================================================
-// function : Unset
+// function : Add
 // purpose  :
 // =======================================================================
-void OpenGl_ClippingState::Unset (const Graphic3d_SetOfHClipPlane& thePlanes)
+void OpenGl_ClippingState::Add (Graphic3d_SetOfHClipPlane& thePlanes, const EquationCoords& theCoordSpace)
 {
   Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (thePlanes);
-  for (; aPlaneIt.More(); aPlaneIt.Next())
+  while (aPlaneIt.More() && myEmptyPlaneIds->Available() > 0)
   {
     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
-    if (!IsSet (aPlane))
+    if (Contains (aPlane))
+    {
+      thePlanes.Remove (aPlaneIt);
       continue;
+    }
 
-    Standard_Integer anId = myPlanes.Find (aPlane);
-    myEmptyPlaneIds->Free (anId);
-    myPlanes.UnBind (aPlane);
-    myPlaneStates.UnBind (aPlane);
+    Standard_Integer anID = myEmptyPlaneIds->Next();
+    myPlanes.Add (aPlane);
+    myPlaneStates.Bind (aPlane, PlaneProps (theCoordSpace, anID, Standard_True));
 
-    const GLenum anOpenGlId = (GLenum)anId;
+    glEnable ((GLenum)anID);
+    glClipPlane ((GLenum)anID, aPlane->GetEquation());
+    aPlaneIt.Next();
+  }
 
-    glDisable (anOpenGlId);
-    glClipPlane (anOpenGlId, OpenGl_DefaultPlaneEq);
+  while (aPlaneIt.More() && myEmptyPlaneIds->Available() == 0)
+  {
+    thePlanes.Remove (aPlaneIt);
   }
 }
 
-//
-//// =======================================================================
-//// function : SetPlane
-//// purpose  :
-//// =======================================================================
-//Standard_Boolean OpenGl_ClippingState::SetPlane (const Handle(Graphic3d_ClipPlane)& thePlane,
-//                                                 const Standard_Boolean theToEnable)
-//{
-//  if (myEmptyPlaneIds->Available() == 0)
-//    return Standard_False;
-//
-//  if (IsPlaneSet (thePlane))
-//    return Standard_True;
-//
-//  Standard_Integer aPlaneId = myEmptyPlaneIds->Next();
-//  myPlanes.Bind (thePlane, aPlaneId);
-//  myPlaneStates.Bind (thePlane, theToEnable);
-//  if (theToEnable)
-//    glEnable (aPlaneId);
-//  else
-//    glDisable (aPlaneId);
-//
-//  glClipPlane (aPlaneId, thePlane->GetEquation());
-//
-//  return Standard_True;
-//}
-
-//// =======================================================================
-//// function : UnsetPlane
-//// purpose  :
-//// =======================================================================
-//void OpenGl_ClippingState::UnsetPlane (const Handle(Graphic3d_ClipPlane)& thePlane)
-//{
-//  if (!IsPlaneSet (thePlane))
-//    return;
-//
-//  Standard_Integer aPlaneId = myPlanes.Find (thePlane);
-//
-//  myEmptyPlaneIds->Free (aPlaneId);
-//  myPlanes.UnBind (thePlane);
-//  myPlaneStates.UnBind (thePlane);
-//
-//  glDisable (aPlaneId);
-//  glClipPlane (aPlaneId, OpenGl_DefaultPlaneEq);
-//}
-
 // =======================================================================
-// function : IsEnabled
+// function : Remove
 // purpose  :
 // =======================================================================
-Standard_Boolean OpenGl_ClippingState::IsEnabled (const Handle(Graphic3d_ClipPlane)& thePlane) const
+void OpenGl_ClippingState::Remove (const Graphic3d_SetOfHClipPlane& thePlanes)
 {
-  Standard_Boolean isSet;
-  return IsSet (thePlane)
-      && myPlaneStates.Find (thePlane, isSet)
-      && isSet;
+  Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (thePlanes);
+  for (; aPlaneIt.More(); aPlaneIt.Next())
+  {
+    const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
+    if (!Contains (aPlane))
+    {
+      continue;
+    }
+
+    Standard_Integer anID = myPlaneStates.Find (aPlane).ContextID;
+    myEmptyPlaneIds->Free (anID);
+    myPlaneStates.UnBind (aPlane);
+
+    glDisable ((GLenum)anID);
+  }
+
+  // renew collection of planes
+  aPlaneIt.Init (myPlanes);
+  while (aPlaneIt.More())
+  {
+    const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
+    if (!myPlaneStates.IsBound (aPlane))
+    {
+      myPlanes.Remove (aPlaneIt);
+    }
+    else
+    {
+      aPlaneIt.Next();
+    }
+  }
 }
 
 // =======================================================================
@@ -231,18 +162,26 @@ Standard_Boolean OpenGl_ClippingState::IsEnabled (const Handle(Graphic3d_ClipPla
 void OpenGl_ClippingState::SetEnabled (const Handle(Graphic3d_ClipPlane)& thePlane,
                                        const Standard_Boolean theIsEnabled)
 {
-  if (!IsSet (thePlane))
+  if (!Contains (thePlane))
+  {
     return;
+  }
 
-  Standard_Boolean& aState = myPlaneStates.ChangeFind (thePlane);
-  if (theIsEnabled == aState)
+  PlaneProps& aProps = myPlaneStates.ChangeFind (thePlane);
+  if (theIsEnabled == aProps.IsEnabled)
+  {
     return;
+  }
 
-  Standard_Integer aPlaneId = myPlanes.Find (thePlane);
+  GLenum anID = (GLenum)aProps.ContextID;
   if (theIsEnabled)
-    glEnable (aPlaneId);
+  {
+    glEnable (anID);
+  }
   else
-    glDisable (aPlaneId);
+  {
+    glDisable (anID);
+  }
 
-  aState = theIsEnabled;
+  aProps.IsEnabled = theIsEnabled;
 }
index c52df31..5b087c1 100644 (file)
@@ -27,6 +27,7 @@
 #include <NCollection_Handle.hxx>
 #include <Standard_TypeDef.hxx>
 #include <OpenGl_Matrix.hxx>
+#include <Handle_OpenGl_Workspace.hxx>
 
 //! This class contains logics related to tracking and modification of clipping plane
 //! state for particular OpenGl context. It contains information about enabled
@@ -37,67 +38,179 @@ class OpenGl_ClippingState
 {
 public:
 
+  //! Enumerates supported equation coordinate spaces.
+  enum EquationCoords
+  {
+    EquationCoords_View,
+    EquationCoords_World
+  };
+
+public: //! @name general methods
+
   //! Default constructor.
-  Standard_EXPORT OpenGl_ClippingState ();
+  Standard_EXPORT OpenGl_ClippingState();
 
   //! Initialize.
   //! @param theMaxPlanes [in] number of clipping planes supported by OpenGl context.
   Standard_EXPORT void Init (const Standard_Integer theMaxPlanes);
 
-  //! @return sequence of set clipping planes.
-  Standard_EXPORT Graphic3d_SetOfHClipPlane Planes() const;
+public: //! @name non-modifying getters
 
-  //! Check whether the clipping plane has been set for the current context state.
+  //! Check whether the clipping plane has been added to the current context state.
   //! @param thePlane [in] the plane to check.
   //! @return True if plane is set.
-  Standard_EXPORT Standard_Boolean IsSet (const Handle(Graphic3d_ClipPlane)& thePlane) const;
-
-  //! Set collection of clipping planes for available plane ids. Current model view matrix is used.
-  //! @param thePlanes [in] collection of planes.
-  //! @param theToEnable [in] the boolean flag notifying whether the planes should be enabled.
-  Standard_EXPORT void Set (const Graphic3d_SetOfHClipPlane& thePlanes,
-                            const Standard_Boolean theToEnable = Standard_True);
-
-  //! Set collection of clipping planes for available plane ids. Identity matrix in case
-  //! if passed matrix pointer is NULL.
-  //! @param thePlanes [in] collection of planes.
-  //! @param theViewMatrix [in] view matrix to be used to define plane equation.
-  //! @param theToEnable [in] the boolean flag notifying whether the planes should be enabled.
-  Standard_EXPORT void Set (const Graphic3d_SetOfHClipPlane& thePlanes,
-                            const OpenGl_Matrix* theViewMatrix,
-                            const Standard_Boolean theToEnable = Standard_True);
-
-  //! Unset and disable collection of clipping planes.
-  //! @param thePlanes [in] the plane to deactivate.
-  Standard_EXPORT void Unset (const Graphic3d_SetOfHClipPlane& thePlanes);
+  inline Standard_Boolean Contains (const Handle(Graphic3d_ClipPlane)& thePlane) const
+  {
+    return myPlaneStates.IsBound (thePlane);
+  }
+
+  //! Get clip planes defined for context.
+  //! @return sequence of set clipping planes.
+  inline const Graphic3d_SetOfHClipPlane& Planes() const
+  {
+    return myPlanes;
+  }
+
+  //! @return kind of equation coordinate space used for the clip plane.
+  inline EquationCoords GetEquationSpace (const Handle(Graphic3d_ClipPlane)& thePlane) const
+  {
+    return myPlaneStates.Find (thePlane).CoordSpace;
+  }
 
   //! Check whether the clipping plane has been set and enabled for the current context state.
   //! @param thePlane [in] the plane to check.
   //! @return True if plane is enabled.
-  Standard_EXPORT Standard_Boolean IsEnabled (const Handle(Graphic3d_ClipPlane)& thePlane) const;
+  inline Standard_Boolean IsEnabled (const Handle(Graphic3d_ClipPlane)& thePlane) const
+  {
+    return myPlaneStates.Find (thePlane).IsEnabled;
+  }
+
+public: //! @name clipping state modification commands
+
+  //! Add planes to the context clipping at the specified system of coordinates.
+  //! This methods loads appropriate transformation matrix from workspace to
+  //! to transform equation coordinates. The planes become enabled in the context.
+  //! If the number of the passed planes exceeds capabilities of OpenGl, the last planes
+  //! are simply ignored.
+  //! @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.
+  //! @param theCoordSpace [in] the equation definition space.
+  //! @param theWS [in] the workspace to access the matrices.
+  Standard_EXPORT void Add (Graphic3d_SetOfHClipPlane& thePlanes,
+                            const EquationCoords& theCoordSpace,
+                            const Handle(OpenGl_Workspace)& theWS);
+
+  //! Add planes to the context clipping at the specified system of coordinates.
+  //! This method assumes that appropriate matrix is already set in context state.
+  //! If the number of the passed planes exceeds capabilities of OpenGl, the last planes
+  //! are simply ignored.
+  //! @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.
+  //! @param theCoordSpace [in] the equation definition space.
+  Standard_EXPORT void Add (Graphic3d_SetOfHClipPlane& thePlanes,
+                            const EquationCoords& theCoordSpace);
+
+  //! 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 Graphic3d_SetOfHClipPlane& thePlanes);
+
+  //! Enable or disable clipping plane in the OpenGl context.
+  //! @param thePlane [in] the plane to affect.
+  //! @param theIsEnabled [in] the state of the plane.
+  Standard_EXPORT void SetEnabled (const Handle(Graphic3d_ClipPlane)& thePlane,
+                                   const Standard_Boolean theIsEnabled);
+
+public: //! @name Short-cuts
+
+  //! Add planes to the context clipping at the view system of coordinates.
+  //! If the number of the passed planes exceeds capabilities of OpenGl, the last planes
+  //! are simply ignored.
+  //! @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.
+  //! @param theWS [in] the workspace to access the matrices.
+  inline void AddView (Graphic3d_SetOfHClipPlane& thePlanes, const Handle(OpenGl_Workspace)& theWS)
+  {
+    Add (thePlanes, EquationCoords_View, theWS);
+  }
+
+  //! Add planes to the context clipping at the view system of coordinates.
+  //! If the number of the passed planes exceeds capabilities of OpenGl, the last planes
+  //! are simply ignored.
+  //! @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.
+  inline void AddView (Graphic3d_SetOfHClipPlane& thePlanes)
+  {
+    Add (thePlanes, EquationCoords_View);
+  }
+
+  //! Add planes to the context clipping at the world system of coordinates.
+  //! If the number of the passed planes exceeds capabilities of OpenGl, the last planes
+  //! are simply ignored.
+  //! @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.
+  //! @param theWS [in] the workspace to access the matrices.
+  inline void AddWorld (Graphic3d_SetOfHClipPlane& thePlanes, const Handle(OpenGl_Workspace)& theWS)
+  {
+    Add (thePlanes, EquationCoords_World, theWS);
+  }
+
+  //! Add planes to the context clipping at the world system of coordinates.
+  //! If the number of the passed planes exceeds capabilities of OpenGl, the last planes
+  //! are simply ignored.
+  //! @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.
+  inline void AddWorld (Graphic3d_SetOfHClipPlane& thePlanes)
+  {
+    Add (thePlanes, EquationCoords_World);
+  }
+
+  //! Remove all of the planes from context state.
+  inline void RemoveAll()
+  {
+    Remove (Planes());
+  }
+
+private:
 
-  //! Change enabled / disabled state of the clipping plane.
-  //! @param thePlane [in] the plane to change the state.
-  //! @param theIsEnabled [in] the flag indicating whether the plane should be enabled or not.
-  //! @return False if plane is not set for the context.
-  Standard_EXPORT void SetEnabled (const Handle(Graphic3d_ClipPlane)& thePlane, const Standard_Boolean theIsEnabled);
+  struct PlaneProps
+  {
+    // declare default constructor
+    // to allow compilation of template collections
+    PlaneProps() {}
+    PlaneProps (const EquationCoords theCoords,
+                const Standard_Integer theID,
+                const Standard_Boolean theIsEnabled)
+    {
+      CoordSpace = theCoords;
+      ContextID  = theID;
+      IsEnabled  = theIsEnabled;
+    }
+
+    EquationCoords   CoordSpace;
+    Standard_Integer ContextID;
+    Standard_Boolean IsEnabled;
+  };
 
 private:
 
-  typedef NCollection_DataMap<Handle(Graphic3d_ClipPlane), Standard_Integer> OpenGl_MapOfContextPlanes;
-  typedef NCollection_DataMap<Handle(Graphic3d_ClipPlane), Standard_Boolean> OpenGl_MapOfPlaneStates;
+  typedef NCollection_DataMap<Handle(Graphic3d_ClipPlane), PlaneProps> OpenGl_MapOfPlaneStates;
   typedef NCollection_Handle<Aspect_GenId> OpenGl_EmptyPlaneIds;
 
-  OpenGl_MapOfContextPlanes      myPlanes;          //!< map of clip planes bound for the ids
-  OpenGl_MapOfPlaneStates        myPlaneStates;     //!< map of clip planes state (enabled/disabled).
-  OpenGl_EmptyPlaneIds           myEmptyPlaneIds;   //!< generator of empty ids
+  Graphic3d_SetOfHClipPlane myPlanes;          //!< defined clipping planes.
+  OpenGl_MapOfPlaneStates   myPlaneStates;     //!< map of clip planes bound for the props.
+  OpenGl_EmptyPlaneIds      myEmptyPlaneIds;   //!< generator of empty ids.
 
 private:
 
   //! Copying allowed only within Handles
   OpenGl_ClippingState            (const OpenGl_ClippingState& );
   OpenGl_ClippingState& operator= (const OpenGl_ClippingState& );
-
 };
 
 #endif
index ab170f7..b7f0d48 100644 (file)
@@ -88,6 +88,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   extGS  (NULL),
   extBgra(Standard_False),
   extAnis(Standard_False),
+  extPDS(Standard_False),
   atiMem (Standard_False),
   nvxMem (Standard_False),
   mySharedResources (new OpenGl_ResourcesMap()),
@@ -640,6 +641,7 @@ void OpenGl_Context::init()
   arbNPTW = CheckExtension ("GL_ARB_texture_non_power_of_two");
   extBgra = CheckExtension ("GL_EXT_bgra");
   extAnis = CheckExtension ("GL_EXT_texture_filter_anisotropic");
+  extPDS  = CheckExtension ("GL_EXT_packed_depth_stencil");
   atiMem  = CheckExtension ("GL_ATI_meminfo");
   nvxMem  = CheckExtension ("GL_NVX_gpu_memory_info");
 
index a52bb6f..73a8eca 100644 (file)
@@ -313,6 +313,7 @@ public: // extensions
   OpenGl_ExtGS*    extGS;   //!< GL_EXT_geometry_shader4
   Standard_Boolean extBgra; //!< GL_EXT_bgra
   Standard_Boolean extAnis; //!< GL_EXT_texture_filter_anisotropic
+  Standard_Boolean extPDS;  //!< GL_EXT_packed_depth_stencil
   Standard_Boolean atiMem;  //!< GL_ATI_meminfo
   Standard_Boolean nvxMem;  //!< GL_NVX_gpu_memory_info
 
index d829e92..ddbc0b5 100644 (file)
@@ -47,7 +47,8 @@ OpenGl_FrameBuffer::OpenGl_FrameBuffer (GLint theTextureFormat)
   myTextFormat (theTextureFormat),
   myGlTextureId (NO_TEXTURE),
   myGlFBufferId (NO_FRAMEBUFFER),
-  myGlDepthRBId (NO_RENDERBUFFER)
+  myGlDepthRBId (NO_RENDERBUFFER),
+  myGlStencilRBId (NO_RENDERBUFFER)
 {
   //
 }
@@ -95,10 +96,26 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
     return Standard_False;
   }
 
-  // Create RenderBuffer (will be used as depth buffer)
-  theGlContext->extFBO->glGenRenderbuffersEXT (1, &myGlDepthRBId);
-  theGlContext->extFBO->glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, myGlDepthRBId);
-  theGlContext->extFBO->glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, mySizeX, mySizeY);
+  if (!theGlContext->extPDS)
+  {
+    // Create RenderBuffer to be used as depth buffer
+    theGlContext->extFBO->glGenRenderbuffersEXT (1, &myGlDepthRBId);
+    theGlContext->extFBO->glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, myGlDepthRBId);
+    theGlContext->extFBO->glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, mySizeX, mySizeY);
+
+    // Create RenderBuffer to be used as stencil buffer
+    theGlContext->extFBO->glGenRenderbuffersEXT (1, &myGlStencilRBId);
+    theGlContext->extFBO->glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, myGlStencilRBId);
+    theGlContext->extFBO->glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, mySizeX, mySizeY);
+  }
+  else
+  {
+    // Create combined depth stencil buffer
+    theGlContext->extFBO->glGenRenderbuffersEXT (1, &myGlDepthRBId);
+    theGlContext->extFBO->glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, myGlDepthRBId);
+    theGlContext->extFBO->glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, mySizeX, mySizeY);
+    myGlStencilRBId = myGlDepthRBId;
+  }
 
   // Build FBO and setup it as texture
   theGlContext->extFBO->glGenFramebuffersEXT (1, &myGlFBufferId);
@@ -107,6 +124,7 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
   glBindTexture (GL_TEXTURE_2D, myGlTextureId);
   theGlContext->extFBO->glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, myGlTextureId, 0);
   theGlContext->extFBO->glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, myGlDepthRBId);
+  theGlContext->extFBO->glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, myGlStencilRBId);
   if (theGlContext->extFBO->glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
   {
     if (!isPowerOfTwo (mySizeX) || !isPowerOfTwo (mySizeY))
@@ -142,6 +160,18 @@ void OpenGl_FrameBuffer::Release (const Handle(OpenGl_Context)& theGlContext)
       std::cerr << "OpenGl_FrameBuffer::Release() called with invalid OpenGl_Context!\n";
     }
   }
+  if (IsValidStencilBuffer())
+  {
+    if (!theGlContext.IsNull() && theGlContext->extFBO != NULL)
+    {
+      theGlContext->extFBO->glDeleteRenderbuffersEXT (1, &myGlStencilRBId);
+      myGlStencilRBId = NO_RENDERBUFFER;
+    }
+    else
+    {
+      std::cerr << "OpenGl_FrameBuffer::Release() called with invalid OpenGl_Context!\n";
+    }
+  }
   if (IsValidTexture())
   {
     glDeleteTextures (1, &myGlTextureId);
index e341f8f..20ba7f0 100644 (file)
@@ -72,7 +72,7 @@ public:
   //! Returns true if current object was initialized
   Standard_Boolean IsValid() const
   {
-    return IsValidFrameBuffer() && IsValidTexture() && IsValidDepthBuffer();
+    return IsValidFrameBuffer() && IsValidTexture() && IsValidDepthBuffer() && IsValidStencilBuffer();
   }
 
   //! Notice! Obsolete hardware (GeForce FX etc)
@@ -154,16 +154,22 @@ private:
     return myGlDepthRBId != NO_RENDERBUFFER;
   }
 
+  Standard_Boolean IsValidStencilBuffer() const
+  {
+    return myGlStencilRBId != NO_RENDERBUFFER;
+  }
+
 private:
 
-  GLsizei      mySizeX; // texture width
-  GLsizei      mySizeY; // texture height
-  GLsizei    myVPSizeX; // viewport width (should be <= texture width)
-  GLsizei    myVPSizeY; // viewport height (should be <= texture height)
-  GLint   myTextFormat; // GL_RGB, GL_RGBA,...
-  GLuint myGlTextureId; // GL texture ID
-  GLuint myGlFBufferId; // FBO object ID
-  GLuint myGlDepthRBId; // RenderBuffer object for depth ID
+  GLsizei      mySizeX;   // texture width
+  GLsizei      mySizeY;   // texture height
+  GLsizei    myVPSizeX;   // viewport width (should be <= texture width)
+  GLsizei    myVPSizeY;   // viewport height (should be <= texture height)
+  GLint   myTextFormat;   // GL_RGB, GL_RGBA,...
+  GLuint myGlTextureId;   // GL texture ID
+  GLuint myGlFBufferId;   // FBO object ID
+  GLuint myGlDepthRBId;   // RenderBuffer object for depth ID
+  GLuint myGlStencilRBId; // RenderBuffer object for stencil ID
 
 };
 
index 16a9ff9..c7c3f49 100644 (file)
@@ -28,6 +28,8 @@
 #include <OpenGl_Context.hxx>
 #include <OpenGl_telem_util.hxx>
 
+#include <Graphic3d_SetOfHClipPlane_Handle.hxx>
+
 //! Auxiliary class for bounding box presentation
 class OpenGl_BndBoxPrs : public OpenGl_Element
 {
@@ -459,20 +461,34 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
   // Set up plane equations for non-structure transformed global model-view matrix
   const Handle(OpenGl_Context)& aContext = AWorkspace->GetGlContext();
 
-  // Collect planes which should be turned on for structure
-  Graphic3d_SetOfHClipPlane aPlanesOn;
-  Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (myClipPlanes);
-  for (; aPlaneIt.More(); aPlaneIt.Next())
+  // List of planes to be applied to context state
+  Handle(Graphic3d_SetOfHClipPlane) aUserPlanes;
+
+  // Collect clipping planes of structure scope
+  if (!myClipPlanes.IsEmpty())
   {
-    const Handle(Graphic3d_ClipPlane)& aUserPln = aPlaneIt.Value();
-    if (aUserPln->IsOn())
-      aPlanesOn.Add (aUserPln);
+    Graphic3d_SetOfHClipPlane::Iterator aClippingIt (myClipPlanes);
+    for (; aClippingIt.More(); aClippingIt.Next())
+    {
+      const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value();
+      if (!aClipPlane->IsOn())
+      {
+        continue;
+      }
+
+      if (aUserPlanes.IsNull())
+      {
+        aUserPlanes = new Graphic3d_SetOfHClipPlane();
+      }
+
+      aUserPlanes->Add (aClipPlane);
+    }
   }
 
-  // set structure clipping planes
-  if (aPlanesOn.Size() > 0)
+  if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
   {
-    aContext->ChangeClipping().Set (aPlanesOn, AWorkspace->ViewMatrix());
+    // add planes at loaded view matrix state
+    aContext->ChangeClipping().AddWorld (*aUserPlanes, AWorkspace);
   }
 
   // Render groups
@@ -483,13 +499,16 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
     itg.Next();
   }
 
-  // Render cappings for structure groups
-  OpenGl_CappingAlgo::RenderCapping (AWorkspace, myGroups);
+  // Render capping for structure groups
+  if (!aContext->Clipping().Planes().IsEmpty())
+  {
+    OpenGl_CappingAlgo::RenderCapping (AWorkspace, myGroups);
+  }
 
-  // unset structure clipping planes
-  if (aPlanesOn.Size() > 0)
+  // Revert structure clippings
+  if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
   {
-    aContext->ChangeClipping().Unset (aPlanesOn);
+    aContext->ChangeClipping().Remove (*aUserPlanes);
   }
 
   // Restore highlight color
index e4c4b55..6a22a11 100644 (file)
@@ -100,11 +100,6 @@ protected:
 
   virtual ~OpenGl_Structure();
 
-  //! Draw capping surfaces by h/w for the clipping planes
-  //! enabled for the structure.
-  //! @param theWorkspace [in] the GL workspace, context state.
-  void DrawCapping (const Handle(OpenGl_Workspace)& theWorkspace) const;
-
 protected:
 
   //Structure_LABBegin
index 5a054c3..363b225 100644 (file)
@@ -989,42 +989,67 @@ D = -[Px,Py,Pz] dot |Nx|
 
   // Apply clipping planes
   {
-    if ( myZClip.Back.IsOn || myZClip.Front.IsOn )
-    {
-      Graphic3d_SetOfHClipPlane aZClipping;
+    const Handle(OpenGl_Context)& aContext = AWorkspace->GetGlContext();
 
+    if (myZClip.Back.IsOn || myZClip.Front.IsOn)
+    {
       const GLdouble ramp = myExtra.map.fpd - myExtra.map.bpd;
 
-      if ( myZClip.Back.IsOn )
+      Handle(Graphic3d_ClipPlane) aPlaneBack;
+      Handle(Graphic3d_ClipPlane) aPlaneFront;
+
+      if (myZClip.Back.IsOn)
       {
         const GLdouble back = ramp * myZClip.Back.Limit + myExtra.map.bpd;
-        const Graphic3d_ClipPlane::Equation aBack(0.0, 0.0, 1.0, -back);
-        aZClipping.Add (new Graphic3d_ClipPlane (aBack));
+        const Graphic3d_ClipPlane::Equation aBackEquation (0.0, 0.0, 1.0, -back);
+        aPlaneBack = new Graphic3d_ClipPlane (aBackEquation);
       }
 
-      if ( myZClip.Front.IsOn )
+      if (myZClip.Front.IsOn)
       {
         const GLdouble front = ramp * myZClip.Front.Limit + myExtra.map.bpd;
-        const Graphic3d_ClipPlane::Equation aFront (0.0, 0.0, -1.0, front);
-        aZClipping.Add (new Graphic3d_ClipPlane (aFront));
+        const Graphic3d_ClipPlane::Equation aFrontEquation (0.0, 0.0, -1.0, front);
+        aPlaneFront = new Graphic3d_ClipPlane (aFrontEquation);
       }
 
-      aContext->ChangeClipping().Set (aZClipping, &OpenGl_IdentityMatrix);
+      // do some "memory allocation"-wise optimization
+      if (!aPlaneBack.IsNull() || !aPlaneFront.IsNull())
+      {
+        Graphic3d_SetOfHClipPlane aSlicingPlanes;
+        if (!aPlaneBack.IsNull())
+        {
+          aSlicingPlanes.Add (aPlaneBack);
+        }
+
+        if (!aPlaneFront.IsNull())
+        {
+          aSlicingPlanes.Add (aPlaneFront);
+        }
+
+        // add planes at loaded view matrix state
+        aContext->ChangeClipping().AddView (aSlicingPlanes, AWorkspace);
+      }
     }
 
     // Apply user clipping planes
-    Graphic3d_SetOfHClipPlane aPlanesOn;
-    Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (myClipPlanes);
-    for (; aPlaneIt.More(); aPlaneIt.Next())
+    if (!myClipPlanes.IsEmpty())
     {
-      const Handle(Graphic3d_ClipPlane)& aUserPln = aPlaneIt.Value();
-      if (aUserPln->IsOn ())
-        aPlanesOn.Add (aUserPln);
-    }
+      Graphic3d_SetOfHClipPlane aUserPlanes;
+      Graphic3d_SetOfHClipPlane::Iterator aClippingIt (myClipPlanes);
+      for (; aClippingIt.More(); aClippingIt.Next())
+      {
+        const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value();
+        if (aClipPlane->IsOn())
+        {
+          aUserPlanes.Add (aClipPlane);
+        }
+      }
 
-    if (aPlanesOn.Size() > 0)
-    {
-      aContext->ChangeClipping().Set (aPlanesOn);
+      if (!aUserPlanes.IsEmpty())
+      {
+        // add planes at actual matrix state.
+        aContext->ChangeClipping().AddWorld (aUserPlanes);
+      }
     }
   }
 
@@ -1111,8 +1136,7 @@ D = -[Px,Py,Pz] dot |Nx|
   // and invoking optional callbacks
   AWorkspace->ResetAppliedAspect();
 
-  // Unset clip planes managed by driver
-  aContext->ChangeClipping().Unset (aContext->Clipping().Planes());
+  aContext->ChangeClipping().RemoveAll();
 
   // display global trihedron
   if (myTrihedron != NULL)
diff --git a/tests/bugs/vis/bug24224 b/tests/bugs/vis/bug24224
new file mode 100644 (file)
index 0000000..5840aab
--- /dev/null
@@ -0,0 +1,55 @@
+puts "==========="
+puts "OCC24224"
+puts "==========="
+puts ""
+##########################################################################
+# Suspicious logics in changing clipping planets at OpenGL_Structure
+##########################################################################
+
+## centre rectangle
+set x1_coord 150
+set y1_coord 250
+
+## right rectangle
+set x2_coord 255
+set y2_coord 320
+
+## left rectangle
+set x3_coord 73
+set y3_coord 150
+
+vinit
+box b1 0 0 0 10 10 10
+box b2 30 0 0 10 40 10
+box b3 -30 0 0 20 20 20
+vsetdispmode 1
+vdisplay b1 b2 b3
+vfit
+
+## test view-level clipping
+vclipplane create pln1
+vclipplane change pln1 equation 0 1 0 -5
+vclipplane change pln1 capping on
+vclipplane change pln1 capping color 0.9 0.9 0.9
+vclipplane set pln1 view Driver1/Viewer1/View1
+
+checkcolor $x1_coord $y1_coord 0.9 0.9 0.9
+checkcolor $x2_coord $y2_coord 0.9 0.9 0.9
+
+## test sharing of planes between view and object
+vclipplane set pln1 object b1
+
+## test object-level clipping
+vclipplane create pln2
+vclipplane change pln2 equation -0.707 0.707 0 -25
+vclipplane change pln2 capping on
+vclipplane change pln2 capping color 0.5 0.5 0.9
+vclipplane change pln2 capping hatch on
+vclipplane set pln2 object b3
+
+checkcolor $x3_coord $y3_coord 0.5 0.5 0.9
+
+set only_screen 1
+
+
+