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 | { |
34 | static const OpenGl_Vec4 THE_CAPPING_PLN_VERTS[12] = |
35 | { OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), |
36 | OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f), |
37 | OpenGl_Vec4 ( 0.0f, 0.0f, 1.0f, 0.0f), |
38 | OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), |
39 | OpenGl_Vec4 ( 0.0f, 0.0f, 1.0f, 0.0f), |
40 | OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f), |
41 | OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), |
42 | OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f), |
43 | OpenGl_Vec4 ( 0.0f, 0.0f,-1.0f, 0.0f), |
44 | OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), |
45 | OpenGl_Vec4 ( 0.0f, 0.0f,-1.0f, 0.0f), |
46 | OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f) }; |
47 | |
48 | static const OpenGl_Vec4 THE_CAPPING_PLN_TCOORD[12] = |
49 | { OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), |
50 | OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f), |
51 | OpenGl_Vec4 ( 0.0f, 1.0f, 0.0f, 0.0f), |
52 | OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), |
53 | OpenGl_Vec4 ( 0.0f, 1.0f, 0.0f, 0.0f), |
54 | OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f), |
55 | OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), |
56 | OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f), |
57 | OpenGl_Vec4 ( 0.0f,-1.0f, 0.0f, 0.0f), |
58 | OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), |
59 | OpenGl_Vec4 ( 0.0f,-1.0f, 0.0f, 0.0f), |
60 | OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f) }; |
61 | }; |
62 | |
63 | // ======================================================================= |
64 | // function : RenderCapping |
65 | // purpose : |
66 | // ======================================================================= |
b64d84be |
67 | void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorkspace, |
68 | const Graphic3d_SequenceOfGroup& theGroups) |
4269bd1b |
69 | { |
4269bd1b |
70 | const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); |
71 | |
b859a34d |
72 | // check whether algorithm need to be performed |
4269bd1b |
73 | Standard_Boolean isCapping = Standard_False; |
51b10cd4 |
74 | const Graphic3d_SequenceOfHClipPlane& aContextPlanes = aContext->Clipping().Planes(); |
75 | Graphic3d_SequenceOfHClipPlane::Iterator aCappingIt (aContextPlanes); |
4269bd1b |
76 | for (; aCappingIt.More(); aCappingIt.Next()) |
77 | { |
78 | const Handle(Graphic3d_ClipPlane)& aPlane = aCappingIt.Value(); |
79 | if (aPlane->IsCapping()) |
80 | { |
81 | isCapping = Standard_True; |
82 | break; |
83 | } |
84 | } |
85 | |
86 | // do not perform algorithm is there is nothing to render |
87 | if (!isCapping) |
b859a34d |
88 | { |
4269bd1b |
89 | return; |
b859a34d |
90 | } |
4269bd1b |
91 | |
92 | // init internal data |
93 | Init(); |
94 | |
95 | // remember current aspect face defined in workspace |
96 | const OpenGl_AspectFace* aFaceAsp = theWorkspace->AspectFace (Standard_False); |
97 | |
98 | // replace primitive groups rendering filter |
99 | static Handle(OpenGl_CappingAlgoFilter) aCappingFilter = new OpenGl_CappingAlgoFilter(); |
100 | Handle(OpenGl_RenderFilter) aRenderFilter = theWorkspace->GetRenderFilter(); |
101 | theWorkspace->SetRenderFilter (aCappingFilter); |
102 | |
103 | // prepare for rendering the clip planes |
104 | glEnable (GL_STENCIL_TEST); |
105 | |
347423b2 |
106 | // remember current state of depth |
107 | // function and change its value |
108 | GLint aDepthFuncPrev; |
109 | glGetIntegerv (GL_DEPTH_FUNC, &aDepthFuncPrev); |
110 | glDepthFunc (GL_LESS); |
111 | |
4269bd1b |
112 | // generate capping for every clip plane |
113 | for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next()) |
114 | { |
115 | // get plane being rendered |
116 | const Handle(Graphic3d_ClipPlane)& aRenderPlane = aCappingIt.Value(); |
117 | if (!aRenderPlane->IsCapping()) |
118 | { |
119 | continue; |
120 | } |
121 | |
122 | // enable only the rendering plane to generate stencil mask |
51b10cd4 |
123 | Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (aContextPlanes); |
4269bd1b |
124 | for (; aPlaneIt.More(); aPlaneIt.Next()) |
125 | { |
126 | const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value(); |
127 | const Standard_Boolean isOn = (aPlane == aRenderPlane); |
128 | aContext->ChangeClipping().SetEnabled (aPlane, isOn); |
129 | } |
130 | |
131 | glClear (GL_STENCIL_BUFFER_BIT); |
132 | glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); |
133 | |
134 | // override aspects, disable culling |
135 | theWorkspace->SetAspectFace (NoneCulling()); |
136 | theWorkspace->AspectFace (Standard_True); |
137 | |
138 | // evaluate number of pair faces |
139 | glDisable (GL_DEPTH_TEST); |
140 | glDepthMask (GL_FALSE); |
141 | glStencilFunc (GL_ALWAYS, 1, 0x01); |
142 | glStencilOp (GL_KEEP, GL_INVERT, GL_INVERT); |
143 | |
b64d84be |
144 | for (OpenGl_Structure::GroupIterator aGroupIt (theGroups); aGroupIt.More(); aGroupIt.Next()) |
4269bd1b |
145 | { |
31c0e219 |
146 | if (aGroupIt.Value()->IsClosed()) |
147 | { |
148 | aGroupIt.Value()->Render (theWorkspace); |
149 | } |
4269bd1b |
150 | } |
151 | |
b859a34d |
152 | // override material, cull back faces |
4269bd1b |
153 | theWorkspace->SetAspectFace (FrontCulling()); |
154 | theWorkspace->AspectFace (Standard_True); |
155 | |
156 | // enable all clip plane except the rendered one |
157 | for (aPlaneIt.Init (aContextPlanes); aPlaneIt.More(); aPlaneIt.Next()) |
158 | { |
159 | const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value(); |
160 | const Standard_Boolean isOn = (aPlane != aRenderPlane); |
161 | aContext->ChangeClipping().SetEnabled (aPlane, isOn); |
162 | } |
163 | |
164 | // render capping plane using the generated stencil mask |
165 | glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
166 | glDepthMask (GL_TRUE); |
4269bd1b |
167 | glStencilFunc (GL_EQUAL, 1, 0x01); |
168 | glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP); |
169 | glEnable (GL_DEPTH_TEST); |
170 | |
171 | RenderPlane (theWorkspace, aRenderPlane); |
172 | } |
173 | |
174 | // restore previous application state |
175 | glClear (GL_STENCIL_BUFFER_BIT); |
347423b2 |
176 | glDepthFunc (aDepthFuncPrev); |
4269bd1b |
177 | glStencilFunc (GL_ALWAYS, 0, 0xFF); |
178 | glDisable (GL_STENCIL_TEST); |
179 | |
180 | // enable clipping |
181 | for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next()) |
182 | { |
183 | aContext->ChangeClipping().SetEnabled (aCappingIt.Value(), Standard_True); |
184 | } |
185 | |
186 | // restore rendering aspects |
187 | theWorkspace->SetAspectFace (aFaceAsp); |
188 | theWorkspace->SetRenderFilter (aRenderFilter); |
189 | } |
190 | |
191 | // ======================================================================= |
192 | // function : RenderPlane |
193 | // purpose : |
194 | // ======================================================================= |
195 | void OpenGl_CappingAlgo::RenderPlane (const Handle(OpenGl_Workspace)& theWorkspace, |
196 | const Handle(Graphic3d_ClipPlane)& thePlane) |
197 | { |
198 | const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); |
199 | |
200 | // get resource for the plane |
201 | TCollection_AsciiString aResId = thePlane->GetId(); |
202 | |
203 | Handle(OpenGl_CappingPlaneResource) aPlaneRes; |
204 | if (!aContext->GetResource (aResId, aPlaneRes)) |
205 | { |
206 | // share and register for release once the resource is no longer used |
207 | aPlaneRes = new OpenGl_CappingPlaneResource (thePlane); |
208 | aContext->ShareResource (aResId, aPlaneRes); |
209 | } |
210 | |
211 | aPlaneRes->Update (aContext); |
212 | |
213 | const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace (Standard_False); |
214 | const OpenGl_AspectFace* aPlaneAspect = aPlaneRes->AspectFace(); |
215 | if (aPlaneAspect != NULL) |
216 | { |
217 | theWorkspace->SetAspectFace (aPlaneAspect); |
218 | } |
219 | |
220 | // apply aspect for rendering |
221 | theWorkspace->AspectFace (Standard_True); |
222 | |
223 | // set identity model matrix |
224 | const OpenGl_Matrix* aModelMatrix = theWorkspace->SetStructureMatrix (&OpenGl_IdentityMatrix); |
225 | |
226 | glMultMatrixf ((const GLfloat*)aPlaneRes->Orientation()); |
227 | glNormal3f (0.0f, 1.0f, 0.0f); |
228 | glEnableClientState (GL_VERTEX_ARRAY); |
229 | glVertexPointer (4, GL_FLOAT, 0, (GLfloat* )&THE_CAPPING_PLN_VERTS); |
230 | glEnableClientState (GL_TEXTURE_COORD_ARRAY); |
231 | glTexCoordPointer (4, GL_FLOAT, 0, (GLfloat*)&THE_CAPPING_PLN_TCOORD); |
232 | glDrawArrays (GL_TRIANGLES, 0, 12); |
233 | glDisableClientState (GL_VERTEX_ARRAY); |
234 | glDisableClientState (GL_TEXTURE_COORD_ARRAY); |
235 | |
392ac980 |
236 | theWorkspace->SetStructureMatrix (aModelMatrix, true); |
4269bd1b |
237 | theWorkspace->SetAspectFace (aFaceAspect); |
238 | |
239 | // set delayed resource release |
240 | aPlaneRes.Nullify(); |
241 | aContext->ReleaseResource (aResId, Standard_True); |
242 | } |
243 | |
244 | // ======================================================================= |
245 | // function : Init |
246 | // purpose : |
247 | // ======================================================================= |
248 | void OpenGl_CappingAlgo::Init() |
249 | { |
250 | if (myIsInit) |
251 | return; |
252 | |
253 | myRenderFilter = new OpenGl_CappingAlgoFilter(); |
fd4a6963 |
254 | myNoneCulling.ChangeCullingMode() = TelCullNone; |
255 | myNoneCulling.ChangeEdge() = 0; |
4269bd1b |
256 | |
fd4a6963 |
257 | myFrontCulling.ChangeCullingMode() = TelCullBack; |
258 | myFrontCulling.ChangeEdge() = 0; |
4269bd1b |
259 | |
260 | myIsInit = Standard_True; |
261 | } |
262 | |
263 | // ======================================================================= |
264 | // function : CanRender |
265 | // purpose : |
266 | // ======================================================================= |
267 | Standard_Boolean OpenGl_CappingAlgoFilter::CanRender (const OpenGl_Element* theElement) |
268 | { |
871fa103 |
269 | const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theElement); |
270 | return aPArray != NULL |
271 | && aPArray->DrawMode() >= GL_TRIANGLES |
272 | && aPArray->DrawMode() <= GL_POLYGON; |
4269bd1b |
273 | } |