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>
24 IMPLEMENT_STANDARD_HANDLE(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter)
25 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter)
27 Handle(OpenGl_RenderFilter) OpenGl_CappingAlgo::myRenderFilter;
28 OpenGl_AspectFace OpenGl_CappingAlgo::myFrontCulling;
29 OpenGl_AspectFace OpenGl_CappingAlgo::myNoneCulling;
30 Standard_Boolean OpenGl_CappingAlgo::myIsInit = Standard_False;
35 #if !defined(GL_ES_VERSION_2_0)
36 static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES;
37 static const GLint THE_FILLPRIM_TO = GL_POLYGON;
39 static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES;
40 static const GLint THE_FILLPRIM_TO = GL_TRIANGLE_FAN;
43 static const OpenGl_Vec4 THE_CAPPING_PLN_VERTS[12] =
44 { OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
45 OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f),
46 OpenGl_Vec4 ( 0.0f, 0.0f, 1.0f, 0.0f),
47 OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
48 OpenGl_Vec4 ( 0.0f, 0.0f, 1.0f, 0.0f),
49 OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f),
50 OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
51 OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f),
52 OpenGl_Vec4 ( 0.0f, 0.0f,-1.0f, 0.0f),
53 OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
54 OpenGl_Vec4 ( 0.0f, 0.0f,-1.0f, 0.0f),
55 OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f) };
57 static const OpenGl_Vec4 THE_CAPPING_PLN_TCOORD[12] =
58 { OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
59 OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f),
60 OpenGl_Vec4 ( 0.0f, 1.0f, 0.0f, 0.0f),
61 OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
62 OpenGl_Vec4 ( 0.0f, 1.0f, 0.0f, 0.0f),
63 OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f),
64 OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
65 OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f),
66 OpenGl_Vec4 ( 0.0f,-1.0f, 0.0f, 0.0f),
67 OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
68 OpenGl_Vec4 ( 0.0f,-1.0f, 0.0f, 0.0f),
69 OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f) };
72 // =======================================================================
73 // function : RenderCapping
75 // =======================================================================
76 void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorkspace,
77 const Graphic3d_SequenceOfGroup& theGroups)
79 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
81 // check whether algorithm need to be performed
82 Standard_Boolean isCapping = Standard_False;
83 const Graphic3d_SequenceOfHClipPlane& aContextPlanes = aContext->Clipping().Planes();
84 Graphic3d_SequenceOfHClipPlane::Iterator aCappingIt (aContextPlanes);
85 for (; aCappingIt.More(); aCappingIt.Next())
87 const Handle(Graphic3d_ClipPlane)& aPlane = aCappingIt.Value();
88 if (aPlane->IsCapping())
90 isCapping = Standard_True;
95 // do not perform algorithm is there is nothing to render
101 // init internal data
104 // remember current aspect face defined in workspace
105 const OpenGl_AspectFace* aFaceAsp = theWorkspace->AspectFace (Standard_False);
107 // replace primitive groups rendering filter
108 static Handle(OpenGl_CappingAlgoFilter) aCappingFilter = new OpenGl_CappingAlgoFilter();
109 Handle(OpenGl_RenderFilter) aRenderFilter = theWorkspace->GetRenderFilter();
110 theWorkspace->SetRenderFilter (aCappingFilter);
112 // prepare for rendering the clip planes
113 glEnable (GL_STENCIL_TEST);
115 // remember current state of depth
116 // function and change its value
117 GLint aDepthFuncPrev;
118 glGetIntegerv (GL_DEPTH_FUNC, &aDepthFuncPrev);
119 glDepthFunc (GL_LESS);
121 // generate capping for every clip plane
122 for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
124 // get plane being rendered
125 const Handle(Graphic3d_ClipPlane)& aRenderPlane = aCappingIt.Value();
126 if (!aRenderPlane->IsCapping())
131 // enable only the rendering plane to generate stencil mask
132 Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (aContextPlanes);
133 for (; aPlaneIt.More(); aPlaneIt.Next())
135 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
136 const Standard_Boolean isOn = (aPlane == aRenderPlane);
137 aContext->ChangeClipping().SetEnabled (aPlane, isOn);
140 glClear (GL_STENCIL_BUFFER_BIT);
141 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
143 // override aspects, disable culling
144 theWorkspace->SetAspectFace (NoneCulling());
145 theWorkspace->AspectFace (Standard_True);
147 // evaluate number of pair faces
148 glDisable (GL_DEPTH_TEST);
149 glDepthMask (GL_FALSE);
150 glStencilFunc (GL_ALWAYS, 1, 0x01);
151 glStencilOp (GL_KEEP, GL_INVERT, GL_INVERT);
153 for (OpenGl_Structure::GroupIterator aGroupIt (theGroups); aGroupIt.More(); aGroupIt.Next())
155 if (aGroupIt.Value()->IsClosed())
157 aGroupIt.Value()->Render (theWorkspace);
161 // override material, cull back faces
162 theWorkspace->SetAspectFace (FrontCulling());
163 theWorkspace->AspectFace (Standard_True);
165 // enable all clip plane except the rendered one
166 for (aPlaneIt.Init (aContextPlanes); aPlaneIt.More(); aPlaneIt.Next())
168 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
169 const Standard_Boolean isOn = (aPlane != aRenderPlane);
170 aContext->ChangeClipping().SetEnabled (aPlane, isOn);
173 // render capping plane using the generated stencil mask
174 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
175 glDepthMask (GL_TRUE);
176 glStencilFunc (GL_EQUAL, 1, 0x01);
177 glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
178 glEnable (GL_DEPTH_TEST);
180 RenderPlane (theWorkspace, aRenderPlane);
183 // restore previous application state
184 glClear (GL_STENCIL_BUFFER_BIT);
185 glDepthFunc (aDepthFuncPrev);
186 glStencilFunc (GL_ALWAYS, 0, 0xFF);
187 glDisable (GL_STENCIL_TEST);
190 for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
192 aContext->ChangeClipping().SetEnabled (aCappingIt.Value(), Standard_True);
195 // restore rendering aspects
196 theWorkspace->SetAspectFace (aFaceAsp);
197 theWorkspace->SetRenderFilter (aRenderFilter);
200 // =======================================================================
201 // function : RenderPlane
203 // =======================================================================
204 void OpenGl_CappingAlgo::RenderPlane (const Handle(OpenGl_Workspace)& theWorkspace,
205 const Handle(Graphic3d_ClipPlane)& thePlane)
207 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
209 // get resource for the plane
210 TCollection_AsciiString aResId = thePlane->GetId();
212 Handle(OpenGl_CappingPlaneResource) aPlaneRes;
213 if (!aContext->GetResource (aResId, aPlaneRes))
215 // share and register for release once the resource is no longer used
216 aPlaneRes = new OpenGl_CappingPlaneResource (thePlane);
217 aContext->ShareResource (aResId, aPlaneRes);
220 aPlaneRes->Update (aContext);
222 const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace (Standard_False);
223 const OpenGl_AspectFace* aPlaneAspect = aPlaneRes->AspectFace();
224 if (aPlaneAspect != NULL)
226 theWorkspace->SetAspectFace (aPlaneAspect);
229 // apply aspect for rendering
230 theWorkspace->AspectFace (Standard_True);
232 // set identity model matrix
233 aContext->ModelWorldState.Push();
234 aContext->ModelWorldState.SetCurrent (OpenGl_Mat4::Map (*aPlaneRes->Orientation()->mat));
235 aContext->ApplyModelViewMatrix();
237 #if !defined(GL_ES_VERSION_2_0)
238 glNormal3f (0.0f, 1.0f, 0.0f);
239 glEnableClientState (GL_VERTEX_ARRAY);
240 glVertexPointer (4, GL_FLOAT, 0, (GLfloat* )&THE_CAPPING_PLN_VERTS);
241 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
242 glTexCoordPointer (4, GL_FLOAT, 0, (GLfloat*)&THE_CAPPING_PLN_TCOORD);
243 glDrawArrays (GL_TRIANGLES, 0, 12);
244 glDisableClientState (GL_VERTEX_ARRAY);
245 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
248 aContext->ModelWorldState.Pop();
249 aContext->ApplyModelViewMatrix();
251 theWorkspace->SetAspectFace (aFaceAspect);
253 // set delayed resource release
255 aContext->ReleaseResource (aResId, Standard_True);
258 // =======================================================================
261 // =======================================================================
262 void OpenGl_CappingAlgo::Init()
267 myRenderFilter = new OpenGl_CappingAlgoFilter();
268 myNoneCulling.ChangeCullingMode() = TelCullNone;
269 myNoneCulling.ChangeEdge() = 0;
271 myFrontCulling.ChangeCullingMode() = TelCullBack;
272 myFrontCulling.ChangeEdge() = 0;
274 myIsInit = Standard_True;
277 // =======================================================================
278 // function : CanRender
280 // =======================================================================
281 Standard_Boolean OpenGl_CappingAlgoFilter::CanRender (const OpenGl_Element* theElement)
283 const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theElement);
284 return aPArray != NULL
285 && aPArray->DrawMode() >= THE_FILLPRIM_FROM
286 && aPArray->DrawMode() <= THE_FILLPRIM_TO;