4269bd1b |
1 | // Created on: 2013-09-05 |
2 | // Created by: Anton POLETAEV |
d5f74e42 |
3 | // Copyright (c) 2013-2014 OPEN CASCADE SAS |
4269bd1b |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
4269bd1b |
6 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
4269bd1b |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
4269bd1b |
15 | |
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> |
b64d84be |
22 | #include <OpenGl_Structure.hxx> |
4269bd1b |
23 | |
24 | IMPLEMENT_STANDARD_HANDLE(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter) |
25 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter) |
26 | |
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; |
31 | |
32 | namespace |
33 | { |
ca3c13d1 |
34 | |
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; |
38 | #else |
39 | static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES; |
40 | static const GLint THE_FILLPRIM_TO = GL_TRIANGLE_FAN; |
41 | #endif |
42 | |
4269bd1b |
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) }; |
56 | |
ca3c13d1 |
57 | static const OpenGl_Vec4 THE_CAPPING_PLN_TCOORD[12] = |
4269bd1b |
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) }; |
ca3c13d1 |
70 | } |
4269bd1b |
71 | |
72 | // ======================================================================= |
73 | // function : RenderCapping |
74 | // purpose : |
75 | // ======================================================================= |
b64d84be |
76 | void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorkspace, |
77 | const Graphic3d_SequenceOfGroup& theGroups) |
4269bd1b |
78 | { |
4269bd1b |
79 | const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); |
80 | |
b859a34d |
81 | // check whether algorithm need to be performed |
4269bd1b |
82 | Standard_Boolean isCapping = Standard_False; |
51b10cd4 |
83 | const Graphic3d_SequenceOfHClipPlane& aContextPlanes = aContext->Clipping().Planes(); |
84 | Graphic3d_SequenceOfHClipPlane::Iterator aCappingIt (aContextPlanes); |
4269bd1b |
85 | for (; aCappingIt.More(); aCappingIt.Next()) |
86 | { |
87 | const Handle(Graphic3d_ClipPlane)& aPlane = aCappingIt.Value(); |
88 | if (aPlane->IsCapping()) |
89 | { |
90 | isCapping = Standard_True; |
91 | break; |
92 | } |
93 | } |
94 | |
95 | // do not perform algorithm is there is nothing to render |
96 | if (!isCapping) |
b859a34d |
97 | { |
4269bd1b |
98 | return; |
b859a34d |
99 | } |
4269bd1b |
100 | |
101 | // init internal data |
102 | Init(); |
103 | |
104 | // remember current aspect face defined in workspace |
105 | const OpenGl_AspectFace* aFaceAsp = theWorkspace->AspectFace (Standard_False); |
106 | |
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); |
111 | |
112 | // prepare for rendering the clip planes |
113 | glEnable (GL_STENCIL_TEST); |
114 | |
347423b2 |
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); |
120 | |
4269bd1b |
121 | // generate capping for every clip plane |
122 | for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next()) |
123 | { |
124 | // get plane being rendered |
125 | const Handle(Graphic3d_ClipPlane)& aRenderPlane = aCappingIt.Value(); |
126 | if (!aRenderPlane->IsCapping()) |
127 | { |
128 | continue; |
129 | } |
130 | |
131 | // enable only the rendering plane to generate stencil mask |
51b10cd4 |
132 | Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (aContextPlanes); |
4269bd1b |
133 | for (; aPlaneIt.More(); aPlaneIt.Next()) |
134 | { |
135 | const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value(); |
136 | const Standard_Boolean isOn = (aPlane == aRenderPlane); |
137 | aContext->ChangeClipping().SetEnabled (aPlane, isOn); |
138 | } |
139 | |
140 | glClear (GL_STENCIL_BUFFER_BIT); |
141 | glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); |
142 | |
143 | // override aspects, disable culling |
144 | theWorkspace->SetAspectFace (NoneCulling()); |
145 | theWorkspace->AspectFace (Standard_True); |
146 | |
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); |
152 | |
b64d84be |
153 | for (OpenGl_Structure::GroupIterator aGroupIt (theGroups); aGroupIt.More(); aGroupIt.Next()) |
4269bd1b |
154 | { |
31c0e219 |
155 | if (aGroupIt.Value()->IsClosed()) |
156 | { |
157 | aGroupIt.Value()->Render (theWorkspace); |
158 | } |
4269bd1b |
159 | } |
160 | |
b859a34d |
161 | // override material, cull back faces |
4269bd1b |
162 | theWorkspace->SetAspectFace (FrontCulling()); |
163 | theWorkspace->AspectFace (Standard_True); |
164 | |
165 | // enable all clip plane except the rendered one |
166 | for (aPlaneIt.Init (aContextPlanes); aPlaneIt.More(); aPlaneIt.Next()) |
167 | { |
168 | const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value(); |
169 | const Standard_Boolean isOn = (aPlane != aRenderPlane); |
170 | aContext->ChangeClipping().SetEnabled (aPlane, isOn); |
171 | } |
172 | |
173 | // render capping plane using the generated stencil mask |
174 | glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
175 | glDepthMask (GL_TRUE); |
4269bd1b |
176 | glStencilFunc (GL_EQUAL, 1, 0x01); |
177 | glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP); |
178 | glEnable (GL_DEPTH_TEST); |
179 | |
180 | RenderPlane (theWorkspace, aRenderPlane); |
181 | } |
182 | |
183 | // restore previous application state |
184 | glClear (GL_STENCIL_BUFFER_BIT); |
347423b2 |
185 | glDepthFunc (aDepthFuncPrev); |
4269bd1b |
186 | glStencilFunc (GL_ALWAYS, 0, 0xFF); |
187 | glDisable (GL_STENCIL_TEST); |
188 | |
189 | // enable clipping |
190 | for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next()) |
191 | { |
192 | aContext->ChangeClipping().SetEnabled (aCappingIt.Value(), Standard_True); |
193 | } |
194 | |
195 | // restore rendering aspects |
196 | theWorkspace->SetAspectFace (aFaceAsp); |
197 | theWorkspace->SetRenderFilter (aRenderFilter); |
198 | } |
199 | |
200 | // ======================================================================= |
201 | // function : RenderPlane |
202 | // purpose : |
203 | // ======================================================================= |
204 | void OpenGl_CappingAlgo::RenderPlane (const Handle(OpenGl_Workspace)& theWorkspace, |
205 | const Handle(Graphic3d_ClipPlane)& thePlane) |
206 | { |
207 | const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); |
208 | |
209 | // get resource for the plane |
210 | TCollection_AsciiString aResId = thePlane->GetId(); |
211 | |
212 | Handle(OpenGl_CappingPlaneResource) aPlaneRes; |
213 | if (!aContext->GetResource (aResId, aPlaneRes)) |
214 | { |
215 | // share and register for release once the resource is no longer used |
216 | aPlaneRes = new OpenGl_CappingPlaneResource (thePlane); |
217 | aContext->ShareResource (aResId, aPlaneRes); |
218 | } |
219 | |
220 | aPlaneRes->Update (aContext); |
221 | |
222 | const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace (Standard_False); |
223 | const OpenGl_AspectFace* aPlaneAspect = aPlaneRes->AspectFace(); |
224 | if (aPlaneAspect != NULL) |
225 | { |
226 | theWorkspace->SetAspectFace (aPlaneAspect); |
227 | } |
228 | |
229 | // apply aspect for rendering |
230 | theWorkspace->AspectFace (Standard_True); |
231 | |
232 | // set identity model matrix |
c827ea3a |
233 | aContext->ModelWorldState.Push(); |
234 | aContext->ModelWorldState.SetCurrent (OpenGl_Mat4::Map (*aPlaneRes->Orientation()->mat)); |
235 | aContext->ApplyModelViewMatrix(); |
236 | |
ca3c13d1 |
237 | #if !defined(GL_ES_VERSION_2_0) |
4269bd1b |
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); |
ca3c13d1 |
246 | #endif |
4269bd1b |
247 | |
c827ea3a |
248 | aContext->ModelWorldState.Pop(); |
249 | aContext->ApplyModelViewMatrix(); |
250 | |
4269bd1b |
251 | theWorkspace->SetAspectFace (aFaceAspect); |
252 | |
253 | // set delayed resource release |
254 | aPlaneRes.Nullify(); |
255 | aContext->ReleaseResource (aResId, Standard_True); |
256 | } |
257 | |
258 | // ======================================================================= |
259 | // function : Init |
260 | // purpose : |
261 | // ======================================================================= |
262 | void OpenGl_CappingAlgo::Init() |
263 | { |
264 | if (myIsInit) |
265 | return; |
266 | |
267 | myRenderFilter = new OpenGl_CappingAlgoFilter(); |
fd4a6963 |
268 | myNoneCulling.ChangeCullingMode() = TelCullNone; |
269 | myNoneCulling.ChangeEdge() = 0; |
4269bd1b |
270 | |
fd4a6963 |
271 | myFrontCulling.ChangeCullingMode() = TelCullBack; |
272 | myFrontCulling.ChangeEdge() = 0; |
4269bd1b |
273 | |
274 | myIsInit = Standard_True; |
275 | } |
276 | |
277 | // ======================================================================= |
278 | // function : CanRender |
279 | // purpose : |
280 | // ======================================================================= |
281 | Standard_Boolean OpenGl_CappingAlgoFilter::CanRender (const OpenGl_Element* theElement) |
282 | { |
871fa103 |
283 | const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theElement); |
284 | return aPArray != NULL |
ca3c13d1 |
285 | && aPArray->DrawMode() >= THE_FILLPRIM_FROM |
286 | && aPArray->DrawMode() <= THE_FILLPRIM_TO; |
4269bd1b |
287 | } |