1 // Created on: 2013-09-05
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_CappingAlgo.hxx>
17 #include <OpenGl_Workspace.hxx>
18 #include <OpenGl_Context.hxx>
19 #include <OpenGl_PrimitiveArray.hxx>
20 #include <OpenGl_CappingPlaneResource.hxx>
21 #include <OpenGl_Vec.hxx>
22 #include <OpenGl_Structure.hxx>
27 #if !defined(GL_ES_VERSION_2_0)
28 static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES;
29 static const GLint THE_FILLPRIM_TO = GL_POLYGON;
31 static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES;
32 static const GLint THE_FILLPRIM_TO = GL_TRIANGLE_FAN;
36 // =======================================================================
37 // function : RenderCapping
39 // =======================================================================
40 void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorkspace,
41 const Graphic3d_SequenceOfGroup& theGroups)
43 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
45 // check whether algorithm need to be performed
46 Standard_Boolean isCapping = Standard_False;
47 const Graphic3d_SequenceOfHClipPlane& aContextPlanes = aContext->Clipping().Planes();
48 Graphic3d_SequenceOfHClipPlane::Iterator aCappingIt (aContextPlanes);
49 for (; aCappingIt.More(); aCappingIt.Next())
51 const Handle(Graphic3d_ClipPlane)& aPlane = aCappingIt.Value();
52 if (aPlane->IsCapping())
54 isCapping = Standard_True;
59 // do not perform algorithm is there is nothing to render
65 // remember current aspect face defined in workspace
66 const OpenGl_AspectFace* aFaceAsp = theWorkspace->AspectFace (Standard_False);
68 // replace primitive groups rendering filter
69 Handle(OpenGl_RenderFilter) aRenderFilter = theWorkspace->GetRenderFilter();
70 theWorkspace->SetRenderFilter (theWorkspace->DefaultCappingAlgoFilter());
72 // prepare for rendering the clip planes
73 glEnable (GL_STENCIL_TEST);
75 // remember current state of depth
76 // function and change its value
78 glGetIntegerv (GL_DEPTH_FUNC, &aDepthFuncPrev);
79 glDepthFunc (GL_LESS);
81 // generate capping for every clip plane
82 for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
84 // get plane being rendered
85 const Handle(Graphic3d_ClipPlane)& aRenderPlane = aCappingIt.Value();
86 if (!aRenderPlane->IsCapping())
91 // enable only the rendering plane to generate stencil mask
92 Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (aContextPlanes);
93 for (; aPlaneIt.More(); aPlaneIt.Next())
95 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
96 const Standard_Boolean isOn = (aPlane == aRenderPlane);
97 aContext->ChangeClipping().SetEnabled (aPlane, isOn);
100 glClear (GL_STENCIL_BUFFER_BIT);
101 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
103 // override aspects, disable culling
104 theWorkspace->SetAspectFace (&theWorkspace->NoneCulling());
105 theWorkspace->AspectFace (Standard_True);
107 // evaluate number of pair faces
108 glDisable (GL_DEPTH_TEST);
109 glDepthMask (GL_FALSE);
110 glStencilFunc (GL_ALWAYS, 1, 0x01);
111 glStencilOp (GL_KEEP, GL_INVERT, GL_INVERT);
113 for (OpenGl_Structure::GroupIterator aGroupIt (theGroups); aGroupIt.More(); aGroupIt.Next())
115 if (aGroupIt.Value()->IsClosed())
117 aGroupIt.Value()->Render (theWorkspace);
121 // override material, cull back faces
122 theWorkspace->SetAspectFace (&theWorkspace->FrontCulling());
123 theWorkspace->AspectFace (Standard_True);
125 // enable all clip plane except the rendered one
126 for (aPlaneIt.Init (aContextPlanes); aPlaneIt.More(); aPlaneIt.Next())
128 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
129 const Standard_Boolean isOn = (aPlane != aRenderPlane);
130 aContext->ChangeClipping().SetEnabled (aPlane, isOn);
133 // render capping plane using the generated stencil mask
134 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
135 glDepthMask (GL_TRUE);
136 glStencilFunc (GL_EQUAL, 1, 0x01);
137 glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
138 glEnable (GL_DEPTH_TEST);
140 RenderPlane (theWorkspace, aRenderPlane);
143 // restore previous application state
144 glClear (GL_STENCIL_BUFFER_BIT);
145 glDepthFunc (aDepthFuncPrev);
146 glStencilFunc (GL_ALWAYS, 0, 0xFF);
147 glDisable (GL_STENCIL_TEST);
150 for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
152 aContext->ChangeClipping().SetEnabled (aCappingIt.Value(), Standard_True);
155 // restore rendering aspects
156 theWorkspace->SetAspectFace (aFaceAsp);
157 theWorkspace->SetRenderFilter (aRenderFilter);
160 // =======================================================================
161 // function : RenderPlane
163 // =======================================================================
164 void OpenGl_CappingAlgo::RenderPlane (const Handle(OpenGl_Workspace)& theWorkspace,
165 const Handle(Graphic3d_ClipPlane)& thePlane)
167 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
169 // get resource for the plane
170 TCollection_AsciiString aResId = thePlane->GetId();
172 Handle(OpenGl_CappingPlaneResource) aPlaneRes;
173 if (!aContext->GetResource (aResId, aPlaneRes))
175 // share and register for release once the resource is no longer used
176 aPlaneRes = new OpenGl_CappingPlaneResource (thePlane);
177 aContext->ShareResource (aResId, aPlaneRes);
180 aPlaneRes->Update (aContext);
182 const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace (Standard_False);
183 const OpenGl_AspectFace* aPlaneAspect = aPlaneRes->AspectFace();
184 if (aPlaneAspect != NULL)
186 theWorkspace->SetAspectFace (aPlaneAspect);
189 // set identity model matrix
190 aContext->ModelWorldState.Push();
191 aContext->ModelWorldState.SetCurrent (OpenGl_Mat4::Map (*aPlaneRes->Orientation()->mat));
192 aContext->ApplyModelViewMatrix();
194 aPlaneRes->Primitives().Render (theWorkspace);
196 aContext->ModelWorldState.Pop();
197 aContext->ApplyModelViewMatrix();
199 theWorkspace->SetAspectFace (aFaceAspect);
201 // set delayed resource release
203 aContext->ReleaseResource (aResId, Standard_True);
206 // =======================================================================
207 // function : CanRender
209 // =======================================================================
210 Standard_Boolean OpenGl_CappingAlgoFilter::CanRender (const OpenGl_Element* theElement)
212 const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theElement);
213 return aPArray != NULL
214 && aPArray->DrawMode() >= THE_FILLPRIM_FROM
215 && aPArray->DrawMode() <= THE_FILLPRIM_TO;