diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index a627f0ef4b..494616ae23 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -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 diff --git a/src/Graphic3d/Graphic3d_ClipPlane.hxx b/src/Graphic3d/Graphic3d_ClipPlane.hxx index 16e48d044a..45afafea42 100644 --- a/src/Graphic3d/Graphic3d_ClipPlane.hxx +++ b/src/Graphic3d/Graphic3d_ClipPlane.hxx @@ -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 index 0000000000..71d80b2974 --- /dev/null +++ b/src/Graphic3d/Graphic3d_SetOfHClipPlane_Handle.hxx @@ -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 +#include + +typedef NCollection_Handle Handle(Graphic3d_SetOfHClipPlane); + +#endif diff --git a/src/OpenGl/OpenGl_CappingAlgo.cxx b/src/OpenGl/OpenGl_CappingAlgo.cxx index 3340a97b8c..482e267436 100644 --- a/src/OpenGl/OpenGl_CappingAlgo.cxx +++ b/src/OpenGl/OpenGl_CappingAlgo.cxx @@ -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); diff --git a/src/OpenGl/OpenGl_ClippingState.cxx b/src/OpenGl/OpenGl_ClippingState.cxx index 308adbab8a..25c7b0fc7c 100644 --- a/src/OpenGl/OpenGl_ClippingState.cxx +++ b/src/OpenGl/OpenGl_ClippingState.cxx @@ -19,6 +19,7 @@ #include #include +#include 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); + while (aPlaneIt.More() && myEmptyPlaneIds->Available() > 0) + { + const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value(); + if (Contains (aPlane)) + { + thePlanes.Remove (aPlaneIt); + continue; + } + + Standard_Integer anID = myEmptyPlaneIds->Next(); + myPlanes.Add (aPlane); + myPlaneStates.Bind (aPlane, PlaneProps (theCoordSpace, anID, Standard_True)); + + glEnable ((GLenum)anID); + glClipPlane ((GLenum)anID, aPlane->GetEquation()); + aPlaneIt.Next(); + } + + while (aPlaneIt.More() && myEmptyPlaneIds->Available() == 0) + { + thePlanes.Remove (aPlaneIt); + } +} + +// ======================================================================= +// function : Remove +// purpose : +// ======================================================================= +void OpenGl_ClippingState::Remove (const Graphic3d_SetOfHClipPlane& thePlanes) { Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (thePlanes); for (; aPlaneIt.More(); aPlaneIt.Next()) { const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value(); - if (!IsSet (aPlane)) + if (!Contains (aPlane)) + { continue; + } - Standard_Integer anId = myPlanes.Find (aPlane); - myEmptyPlaneIds->Free (anId); - myPlanes.UnBind (aPlane); + Standard_Integer anID = myPlaneStates.Find (aPlane).ContextID; + myEmptyPlaneIds->Free (anID); myPlaneStates.UnBind (aPlane); - const GLenum anOpenGlId = (GLenum)anId; - - glDisable (anOpenGlId); - glClipPlane (anOpenGlId, OpenGl_DefaultPlaneEq); + glDisable ((GLenum)anID); } -} -// -//// ======================================================================= -//// 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 -// purpose : -// ======================================================================= -Standard_Boolean OpenGl_ClippingState::IsEnabled (const Handle(Graphic3d_ClipPlane)& thePlane) const -{ - Standard_Boolean isSet; - return IsSet (thePlane) - && myPlaneStates.Find (thePlane, isSet) - && isSet; + // 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; } diff --git a/src/OpenGl/OpenGl_ClippingState.hxx b/src/OpenGl/OpenGl_ClippingState.hxx index c52df31782..5b087c1582 100644 --- a/src/OpenGl/OpenGl_ClippingState.hxx +++ b/src/OpenGl/OpenGl_ClippingState.hxx @@ -27,6 +27,7 @@ #include #include #include +#include //! 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; + inline Standard_Boolean Contains (const Handle(Graphic3d_ClipPlane)& thePlane) const + { + return myPlaneStates.IsBound (thePlane); + } - //! 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); + //! Get clip planes defined for context. + //! @return sequence of set clipping planes. + inline const Graphic3d_SetOfHClipPlane& Planes() const + { + return myPlanes; + } - //! 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); + //! @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; + } - //! 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); +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: - typedef NCollection_DataMap OpenGl_MapOfContextPlanes; - typedef NCollection_DataMap OpenGl_MapOfPlaneStates; + 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 OpenGl_MapOfPlaneStates; typedef NCollection_Handle 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 diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index ab170f79c5..b7f0d48471 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -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"); diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index a52bb6f64b..73a8eca385 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -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 diff --git a/src/OpenGl/OpenGl_FrameBuffer.cxx b/src/OpenGl/OpenGl_FrameBuffer.cxx index d829e92075..ddbc0b54a2 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.cxx +++ b/src/OpenGl/OpenGl_FrameBuffer.cxx @@ -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); diff --git a/src/OpenGl/OpenGl_FrameBuffer.hxx b/src/OpenGl/OpenGl_FrameBuffer.hxx index e341f8f098..20ba7f05ae 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.hxx +++ b/src/OpenGl/OpenGl_FrameBuffer.hxx @@ -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 }; diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index 16a9ff9845..c7c3f49b16 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -28,6 +28,8 @@ #include #include +#include + //! 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); - - // unset structure clipping planes - if (aPlanesOn.Size() > 0) + // Render capping for structure groups + if (!aContext->Clipping().Planes().IsEmpty()) { - aContext->ChangeClipping().Unset (aPlanesOn); + OpenGl_CappingAlgo::RenderCapping (AWorkspace, myGroups); + } + + // Revert structure clippings + if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty()) + { + aContext->ChangeClipping().Remove (*aUserPlanes); } // Restore highlight color diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx index e4c4b55c5d..6a22a118d8 100644 --- a/src/OpenGl/OpenGl_Structure.hxx +++ b/src/OpenGl/OpenGl_Structure.hxx @@ -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 diff --git a/src/OpenGl/OpenGl_View_2.cxx b/src/OpenGl/OpenGl_View_2.cxx index 5a054c3674..363b225951 100644 --- a/src/OpenGl/OpenGl_View_2.cxx +++ b/src/OpenGl/OpenGl_View_2.cxx @@ -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 index 0000000000..5840aabd0f --- /dev/null +++ b/tests/bugs/vis/bug24224 @@ -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 + + +