// Created on: 2013-09-05
// Created by: Anton POLETAEV
-// Copyright (c) 2013 OPEN CASCADE SAS
+// Copyright (c) 2013-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
// commercial license or contractual agreement.
#include <OpenGl_CappingAlgo.hxx>
+
#include <OpenGl_Workspace.hxx>
#include <OpenGl_Context.hxx>
#include <OpenGl_PrimitiveArray.hxx>
#include <OpenGl_CappingPlaneResource.hxx>
#include <OpenGl_Vec.hxx>
+#include <OpenGl_Structure.hxx>
+#include <OpenGl_ShaderManager.hxx>
-IMPLEMENT_STANDARD_HANDLE(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter)
-IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter)
-
-Handle(OpenGl_RenderFilter) OpenGl_CappingAlgo::myRenderFilter;
-OpenGl_AspectFace OpenGl_CappingAlgo::myFrontCulling;
-OpenGl_AspectFace OpenGl_CappingAlgo::myNoneCulling;
-Standard_Boolean OpenGl_CappingAlgo::myIsInit = Standard_False;
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter,OpenGl_RenderFilter)
namespace
{
- static const OpenGl_Vec4 THE_CAPPING_PLN_VERTS[12] =
- { OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
- OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f),
- OpenGl_Vec4 ( 0.0f, 0.0f, 1.0f, 0.0f),
- OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
- OpenGl_Vec4 ( 0.0f, 0.0f, 1.0f, 0.0f),
- OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f),
- OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
- OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f),
- OpenGl_Vec4 ( 0.0f, 0.0f,-1.0f, 0.0f),
- OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
- OpenGl_Vec4 ( 0.0f, 0.0f,-1.0f, 0.0f),
- OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f) };
-
- static const OpenGl_Vec4 THE_CAPPING_PLN_TCOORD[12] =
- { OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
- OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f),
- OpenGl_Vec4 ( 0.0f, 1.0f, 0.0f, 0.0f),
- OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
- OpenGl_Vec4 ( 0.0f, 1.0f, 0.0f, 0.0f),
- OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f),
- OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
- OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f),
- OpenGl_Vec4 ( 0.0f,-1.0f, 0.0f, 0.0f),
- OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
- OpenGl_Vec4 ( 0.0f,-1.0f, 0.0f, 0.0f),
- OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f) };
-};
+#if !defined(GL_ES_VERSION_2_0)
+ static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES;
+ static const GLint THE_FILLPRIM_TO = GL_POLYGON;
+#else
+ static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES;
+ static const GLint THE_FILLPRIM_TO = GL_TRIANGLE_FAN;
+#endif
+
+ //! Render infinite capping plane.
+ //! @param theWorkspace [in] the GL workspace, context state.
+ //! @param thePlane [in] the graphical plane, for which the capping surface is rendered.
+ static void renderPlane (const Handle(OpenGl_Workspace)& theWorkspace,
+ const Handle(OpenGl_CappingPlaneResource)& thePlane,
+ const OpenGl_AspectFace* theAspectFace)
+ {
+ const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
+ thePlane->Update (aContext, theAspectFace != NULL ? theAspectFace->Aspect() : Handle(Graphic3d_AspectFillArea3d)());
+
+ const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace();
+ theWorkspace->SetAspectFace (thePlane->AspectFace());
+
+ // set identity model matrix
+ aContext->ModelWorldState.Push();
+ aContext->ModelWorldState.SetCurrent (OpenGl_Mat4::Map (*thePlane->Orientation()->mat));
+ aContext->ApplyModelViewMatrix();
+
+ thePlane->Primitives().Render (theWorkspace);
+
+ aContext->ModelWorldState.Pop();
+ aContext->ApplyModelViewMatrix();
+
+ theWorkspace->SetAspectFace (aFaceAspect);
+ }
+
+ //! Render capping for specific structure.
+ static void renderCappingForStructure (const Handle(OpenGl_Workspace)& theWorkspace,
+ const OpenGl_Structure& theStructure,
+ const OpenGl_ClippingIterator& thePlaneIter,
+ const Handle(OpenGl_CappingPlaneResource)& thePlane)
+ {
+ const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
+ const Handle(Graphic3d_ClipPlane)& aRenderPlane = thePlane->Plane();
+ for (OpenGl_Structure::GroupIterator aGroupIter (theStructure.Groups()); aGroupIter.More(); aGroupIter.Next())
+ {
+ if (!aGroupIter.Value()->IsClosed())
+ {
+ continue;
+ }
+
+ // enable only the rendering plane to generate stencil mask
+ aContext->ChangeClipping().DisableAllExcept (aContext, thePlaneIter);
+ aContext->ShaderManager()->UpdateClippingState();
+
+ glClear (GL_STENCIL_BUFFER_BIT);
+ glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ // override aspects, disable culling
+ theWorkspace->SetAspectFace (&theWorkspace->NoneCulling());
+ theWorkspace->ApplyAspectFace();
+
+ // evaluate number of pair faces
+ glDisable (GL_DEPTH_TEST);
+ glDepthMask (GL_FALSE);
+ glStencilFunc (GL_ALWAYS, 1, 0x01);
+ glStencilOp (GL_KEEP, GL_INVERT, GL_INVERT);
+
+ // render closed primitives
+ if (aRenderPlane->ToUseObjectProperties())
+ {
+ aGroupIter.Value()->Render (theWorkspace);
+ }
+ else
+ {
+ for (; aGroupIter.More(); aGroupIter.Next())
+ {
+ if (aGroupIter.Value()->IsClosed())
+ {
+ aGroupIter.Value()->Render (theWorkspace);
+ }
+ }
+ }
+
+ // override material, cull back faces
+ theWorkspace->SetAspectFace (&theWorkspace->FrontCulling());
+ theWorkspace->ApplyAspectFace();
+
+ // enable all clip plane except the rendered one
+ aContext->ChangeClipping().EnableAllExcept (aContext, thePlaneIter);
+ aContext->ShaderManager()->UpdateClippingState();
+
+ // render capping plane using the generated stencil mask
+ glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDepthMask (GL_TRUE);
+ glStencilFunc (GL_EQUAL, 1, 0x01);
+ glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
+ glEnable (GL_DEPTH_TEST);
+
+ renderPlane (theWorkspace, thePlane, aRenderPlane->ToUseObjectProperties()
+ ? aGroupIter.Value()->AspectFace()
+ : NULL);
+
+ // turn on the current plane to restore initial state
+ aContext->ChangeClipping().SetEnabled (aContext, thePlaneIter, Standard_True);
+ aContext->ShaderManager()->RevertClippingState();
+ aContext->ShaderManager()->RevertClippingState();
+ }
+
+ if (theStructure.InstancedStructure() != NULL)
+ {
+ renderCappingForStructure (theWorkspace, *theStructure.InstancedStructure(), thePlaneIter, thePlane);
+ }
+ }
+}
// =======================================================================
// function : RenderCapping
// purpose :
// =======================================================================
void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorkspace,
- const OpenGl_ListOfGroup& theGroups)
+ const OpenGl_Structure& theStructure)
{
const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
-
- // check whether algorithm need to be performed
- Standard_Boolean isCapping = Standard_False;
- const Graphic3d_SequenceOfHClipPlane& aContextPlanes = aContext->Clipping().Planes();
- Graphic3d_SequenceOfHClipPlane::Iterator aCappingIt (aContextPlanes);
- for (; aCappingIt.More(); aCappingIt.Next())
- {
- const Handle(Graphic3d_ClipPlane)& aPlane = aCappingIt.Value();
- if (aPlane->IsCapping())
- {
- isCapping = Standard_True;
- break;
- }
- }
-
- // do not perform algorithm is there is nothing to render
- if (!isCapping)
+ if (!aContext->Clipping().IsCappingOn())
{
+ // do not perform algorithm if there is nothing to render
return;
}
- // init internal data
- Init();
-
// remember current aspect face defined in workspace
- const OpenGl_AspectFace* aFaceAsp = theWorkspace->AspectFace (Standard_False);
+ const OpenGl_AspectFace* aFaceAsp = theWorkspace->AspectFace();
// replace primitive groups rendering filter
- static Handle(OpenGl_CappingAlgoFilter) aCappingFilter = new OpenGl_CappingAlgoFilter();
Handle(OpenGl_RenderFilter) aRenderFilter = theWorkspace->GetRenderFilter();
- theWorkspace->SetRenderFilter (aCappingFilter);
+ theWorkspace->SetRenderFilter (theWorkspace->DefaultCappingAlgoFilter());
// prepare for rendering the clip planes
glEnable (GL_STENCIL_TEST);
+ // remember current state of depth
+ // function and change its value
+ GLint aDepthFuncPrev;
+ glGetIntegerv (GL_DEPTH_FUNC, &aDepthFuncPrev);
+ glDepthFunc (GL_LESS);
+
// generate capping for every clip plane
- for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
+ for (OpenGl_ClippingIterator aCappingIt (aContext->Clipping()); aCappingIt.More(); aCappingIt.Next())
{
// get plane being rendered
const Handle(Graphic3d_ClipPlane)& aRenderPlane = aCappingIt.Value();
- if (!aRenderPlane->IsCapping())
+ if (!aRenderPlane->IsCapping()
+ || aCappingIt.IsDisabled())
{
continue;
}
- // enable only the rendering plane to generate stencil mask
- Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (aContextPlanes);
- for (; aPlaneIt.More(); aPlaneIt.Next())
- {
- const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
- const Standard_Boolean isOn = (aPlane == aRenderPlane);
- aContext->ChangeClipping().SetEnabled (aPlane, isOn);
- }
-
- glClear (GL_STENCIL_BUFFER_BIT);
- glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
- // override aspects, disable culling
- theWorkspace->SetAspectFace (NoneCulling());
- theWorkspace->AspectFace (Standard_True);
-
- // evaluate number of pair faces
- glDisable (GL_DEPTH_TEST);
- glDepthMask (GL_FALSE);
- glStencilFunc (GL_ALWAYS, 1, 0x01);
- glStencilOp (GL_KEEP, GL_INVERT, GL_INVERT);
-
- OpenGl_ListOfGroup::Iterator aGroupIt (theGroups);
- for (; aGroupIt.More(); aGroupIt.Next())
- {
- aGroupIt.Value()->Render (theWorkspace);
- }
-
- // override material, cull back faces
- theWorkspace->SetAspectFace (FrontCulling());
- theWorkspace->AspectFace (Standard_True);
-
- // enable all clip plane except the rendered one
- for (aPlaneIt.Init (aContextPlanes); aPlaneIt.More(); aPlaneIt.Next())
+ // get resource for the plane
+ const TCollection_AsciiString& aResId = aRenderPlane->GetId();
+ Handle(OpenGl_CappingPlaneResource) aPlaneRes;
+ if (!aContext->GetResource (aResId, aPlaneRes))
{
- const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
- const Standard_Boolean isOn = (aPlane != aRenderPlane);
- aContext->ChangeClipping().SetEnabled (aPlane, isOn);
+ // share and register for release once the resource is no longer used
+ aPlaneRes = new OpenGl_CappingPlaneResource (aRenderPlane);
+ aContext->ShareResource (aResId, aPlaneRes);
}
- // render capping plane using the generated stencil mask
- glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glDepthMask (GL_TRUE);
- glDepthFunc (GL_LESS);
- glStencilFunc (GL_EQUAL, 1, 0x01);
- glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
- glEnable (GL_DEPTH_TEST);
+ renderCappingForStructure (theWorkspace, theStructure, aCappingIt, aPlaneRes);
- RenderPlane (theWorkspace, aRenderPlane);
+ // set delayed resource release
+ aPlaneRes.Nullify();
+ aContext->ReleaseResource (aResId, Standard_True);
}
// restore previous application state
glClear (GL_STENCIL_BUFFER_BIT);
+ glDepthFunc (aDepthFuncPrev);
glStencilFunc (GL_ALWAYS, 0, 0xFF);
glDisable (GL_STENCIL_TEST);
- // enable clipping
- for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
- {
- aContext->ChangeClipping().SetEnabled (aCappingIt.Value(), Standard_True);
- }
-
// restore rendering aspects
theWorkspace->SetAspectFace (aFaceAsp);
theWorkspace->SetRenderFilter (aRenderFilter);
}
-// =======================================================================
-// function : RenderPlane
-// purpose :
-// =======================================================================
-void OpenGl_CappingAlgo::RenderPlane (const Handle(OpenGl_Workspace)& theWorkspace,
- const Handle(Graphic3d_ClipPlane)& thePlane)
-{
- const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
-
- // get resource for the plane
- TCollection_AsciiString aResId = thePlane->GetId();
-
- Handle(OpenGl_CappingPlaneResource) aPlaneRes;
- if (!aContext->GetResource (aResId, aPlaneRes))
- {
- // share and register for release once the resource is no longer used
- aPlaneRes = new OpenGl_CappingPlaneResource (thePlane);
- aContext->ShareResource (aResId, aPlaneRes);
- }
-
- aPlaneRes->Update (aContext);
-
- const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace (Standard_False);
- const OpenGl_AspectFace* aPlaneAspect = aPlaneRes->AspectFace();
- if (aPlaneAspect != NULL)
- {
- theWorkspace->SetAspectFace (aPlaneAspect);
- }
-
- // apply aspect for rendering
- theWorkspace->AspectFace (Standard_True);
-
- // set identity model matrix
- const OpenGl_Matrix* aModelMatrix = theWorkspace->SetStructureMatrix (&OpenGl_IdentityMatrix);
-
- glMultMatrixf ((const GLfloat*)aPlaneRes->Orientation());
- glNormal3f (0.0f, 1.0f, 0.0f);
- glEnableClientState (GL_VERTEX_ARRAY);
- glVertexPointer (4, GL_FLOAT, 0, (GLfloat* )&THE_CAPPING_PLN_VERTS);
- glEnableClientState (GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer (4, GL_FLOAT, 0, (GLfloat*)&THE_CAPPING_PLN_TCOORD);
- glDrawArrays (GL_TRIANGLES, 0, 12);
- glDisableClientState (GL_VERTEX_ARRAY);
- glDisableClientState (GL_TEXTURE_COORD_ARRAY);
-
- theWorkspace->SetStructureMatrix (aModelMatrix, true);
- theWorkspace->SetAspectFace (aFaceAspect);
-
- // set delayed resource release
- aPlaneRes.Nullify();
- aContext->ReleaseResource (aResId, Standard_True);
-}
-
-// =======================================================================
-// function : Init
-// purpose :
-// =======================================================================
-void OpenGl_CappingAlgo::Init()
-{
- if (myIsInit)
- return;
-
- myRenderFilter = new OpenGl_CappingAlgoFilter();
- myNoneCulling.ChangeCullingMode() = TelCullNone;
- myNoneCulling.ChangeEdge() = 0;
-
- myFrontCulling.ChangeCullingMode() = TelCullBack;
- myFrontCulling.ChangeEdge() = 0;
-
- myIsInit = Standard_True;
-}
-
// =======================================================================
// function : CanRender
// purpose :
// =======================================================================
Standard_Boolean OpenGl_CappingAlgoFilter::CanRender (const OpenGl_Element* theElement)
{
- const OpenGl_PrimitiveArray* aPArray =
- dynamic_cast<const OpenGl_PrimitiveArray*> (theElement);
- if (!aPArray)
- return Standard_False;
-
- switch (aPArray->PArray()->type)
- {
- case TelPolygonsArrayType :
- case TelTrianglesArrayType :
- case TelQuadranglesArrayType :
- case TelTriangleStripsArrayType :
- case TelQuadrangleStripsArrayType :
- case TelTriangleFansArrayType :
- return Standard_True;
-
- default:
- return Standard_False;
- }
+ const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theElement);
+ return aPArray != NULL
+ && aPArray->DrawMode() >= THE_FILLPRIM_FROM
+ && aPArray->DrawMode() <= THE_FILLPRIM_TO;
}