4269bd1b |
1 | // Created on: 2013-09-05 |
2 | // Created by: Anton POLETAEV |
3 | // Copyright (c) 2013 OPEN CASCADE SAS |
4 | // |
5 | // The content of this file is subject to the Open CASCADE Technology Public |
6 | // License Version 6.5 (the "License"). You may not use the content of this file |
7 | // except in compliance with the License. Please obtain a copy of the License |
8 | // at http://www.opencascade.org and read it completely before using this file. |
9 | // |
10 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
11 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
12 | // |
13 | // The Original Code and all software distributed under the License is |
14 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
15 | // Initial Developer hereby disclaims all such warranties, including without |
16 | // limitation, any warranties of merchantability, fitness for a particular |
17 | // purpose or non-infringement. Please see the License for the specific terms |
18 | // and conditions governing the rights and limitations under the License. |
19 | |
20 | #include <OpenGl_CappingAlgo.hxx> |
21 | #include <OpenGl_Workspace.hxx> |
22 | #include <OpenGl_Context.hxx> |
23 | #include <OpenGl_PrimitiveArray.hxx> |
24 | #include <OpenGl_CappingPlaneResource.hxx> |
25 | #include <OpenGl_Vec.hxx> |
26 | |
27 | IMPLEMENT_STANDARD_HANDLE(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter) |
28 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter) |
29 | |
30 | Handle(OpenGl_RenderFilter) OpenGl_CappingAlgo::myRenderFilter; |
31 | OpenGl_AspectFace OpenGl_CappingAlgo::myFrontCulling; |
32 | OpenGl_AspectFace OpenGl_CappingAlgo::myNoneCulling; |
33 | Standard_Boolean OpenGl_CappingAlgo::myIsInit = Standard_False; |
34 | |
35 | namespace |
36 | { |
37 | static const OpenGl_Vec4 THE_CAPPING_PLN_VERTS[12] = |
38 | { OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), |
39 | OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f), |
40 | OpenGl_Vec4 ( 0.0f, 0.0f, 1.0f, 0.0f), |
41 | OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), |
42 | OpenGl_Vec4 ( 0.0f, 0.0f, 1.0f, 0.0f), |
43 | OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f), |
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 | |
51 | static const OpenGl_Vec4 THE_CAPPING_PLN_TCOORD[12] = |
52 | { OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), |
53 | OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f), |
54 | OpenGl_Vec4 ( 0.0f, 1.0f, 0.0f, 0.0f), |
55 | OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), |
56 | OpenGl_Vec4 ( 0.0f, 1.0f, 0.0f, 0.0f), |
57 | OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f), |
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 | }; |
65 | |
66 | // ======================================================================= |
67 | // function : RenderCapping |
68 | // purpose : |
69 | // ======================================================================= |
70 | void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorkspace, |
71 | const OpenGl_ListOfGroup& theGroups) |
72 | { |
4269bd1b |
73 | const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); |
74 | |
b859a34d |
75 | // check whether algorithm need to be performed |
4269bd1b |
76 | Standard_Boolean isCapping = Standard_False; |
51b10cd4 |
77 | const Graphic3d_SequenceOfHClipPlane& aContextPlanes = aContext->Clipping().Planes(); |
78 | Graphic3d_SequenceOfHClipPlane::Iterator aCappingIt (aContextPlanes); |
4269bd1b |
79 | for (; aCappingIt.More(); aCappingIt.Next()) |
80 | { |
81 | const Handle(Graphic3d_ClipPlane)& aPlane = aCappingIt.Value(); |
82 | if (aPlane->IsCapping()) |
83 | { |
84 | isCapping = Standard_True; |
85 | break; |
86 | } |
87 | } |
88 | |
89 | // do not perform algorithm is there is nothing to render |
90 | if (!isCapping) |
b859a34d |
91 | { |
4269bd1b |
92 | return; |
b859a34d |
93 | } |
4269bd1b |
94 | |
95 | // init internal data |
96 | Init(); |
97 | |
98 | // remember current aspect face defined in workspace |
99 | const OpenGl_AspectFace* aFaceAsp = theWorkspace->AspectFace (Standard_False); |
100 | |
101 | // replace primitive groups rendering filter |
102 | static Handle(OpenGl_CappingAlgoFilter) aCappingFilter = new OpenGl_CappingAlgoFilter(); |
103 | Handle(OpenGl_RenderFilter) aRenderFilter = theWorkspace->GetRenderFilter(); |
104 | theWorkspace->SetRenderFilter (aCappingFilter); |
105 | |
106 | // prepare for rendering the clip planes |
107 | glEnable (GL_STENCIL_TEST); |
108 | |
109 | // generate capping for every clip plane |
110 | for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next()) |
111 | { |
112 | // get plane being rendered |
113 | const Handle(Graphic3d_ClipPlane)& aRenderPlane = aCappingIt.Value(); |
114 | if (!aRenderPlane->IsCapping()) |
115 | { |
116 | continue; |
117 | } |
118 | |
119 | // enable only the rendering plane to generate stencil mask |
51b10cd4 |
120 | Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (aContextPlanes); |
4269bd1b |
121 | for (; aPlaneIt.More(); aPlaneIt.Next()) |
122 | { |
123 | const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value(); |
124 | const Standard_Boolean isOn = (aPlane == aRenderPlane); |
125 | aContext->ChangeClipping().SetEnabled (aPlane, isOn); |
126 | } |
127 | |
128 | glClear (GL_STENCIL_BUFFER_BIT); |
129 | glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); |
130 | |
131 | // override aspects, disable culling |
132 | theWorkspace->SetAspectFace (NoneCulling()); |
133 | theWorkspace->AspectFace (Standard_True); |
134 | |
135 | // evaluate number of pair faces |
136 | glDisable (GL_DEPTH_TEST); |
137 | glDepthMask (GL_FALSE); |
138 | glStencilFunc (GL_ALWAYS, 1, 0x01); |
139 | glStencilOp (GL_KEEP, GL_INVERT, GL_INVERT); |
140 | |
141 | OpenGl_ListOfGroup::Iterator aGroupIt (theGroups); |
142 | for (; aGroupIt.More(); aGroupIt.Next()) |
143 | { |
144 | aGroupIt.Value()->Render (theWorkspace); |
145 | } |
146 | |
b859a34d |
147 | // override material, cull back faces |
4269bd1b |
148 | theWorkspace->SetAspectFace (FrontCulling()); |
149 | theWorkspace->AspectFace (Standard_True); |
150 | |
151 | // enable all clip plane except the rendered one |
152 | for (aPlaneIt.Init (aContextPlanes); aPlaneIt.More(); aPlaneIt.Next()) |
153 | { |
154 | const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value(); |
155 | const Standard_Boolean isOn = (aPlane != aRenderPlane); |
156 | aContext->ChangeClipping().SetEnabled (aPlane, isOn); |
157 | } |
158 | |
159 | // render capping plane using the generated stencil mask |
160 | glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
161 | glDepthMask (GL_TRUE); |
162 | glDepthFunc (GL_LESS); |
163 | glStencilFunc (GL_EQUAL, 1, 0x01); |
164 | glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP); |
165 | glEnable (GL_DEPTH_TEST); |
166 | |
167 | RenderPlane (theWorkspace, aRenderPlane); |
168 | } |
169 | |
170 | // restore previous application state |
171 | glClear (GL_STENCIL_BUFFER_BIT); |
172 | glStencilFunc (GL_ALWAYS, 0, 0xFF); |
173 | glDisable (GL_STENCIL_TEST); |
174 | |
175 | // enable clipping |
176 | for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next()) |
177 | { |
178 | aContext->ChangeClipping().SetEnabled (aCappingIt.Value(), Standard_True); |
179 | } |
180 | |
181 | // restore rendering aspects |
182 | theWorkspace->SetAspectFace (aFaceAsp); |
183 | theWorkspace->SetRenderFilter (aRenderFilter); |
184 | } |
185 | |
186 | // ======================================================================= |
187 | // function : RenderPlane |
188 | // purpose : |
189 | // ======================================================================= |
190 | void OpenGl_CappingAlgo::RenderPlane (const Handle(OpenGl_Workspace)& theWorkspace, |
191 | const Handle(Graphic3d_ClipPlane)& thePlane) |
192 | { |
193 | const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); |
194 | |
195 | // get resource for the plane |
196 | TCollection_AsciiString aResId = thePlane->GetId(); |
197 | |
198 | Handle(OpenGl_CappingPlaneResource) aPlaneRes; |
199 | if (!aContext->GetResource (aResId, aPlaneRes)) |
200 | { |
201 | // share and register for release once the resource is no longer used |
202 | aPlaneRes = new OpenGl_CappingPlaneResource (thePlane); |
203 | aContext->ShareResource (aResId, aPlaneRes); |
204 | } |
205 | |
206 | aPlaneRes->Update (aContext); |
207 | |
208 | const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace (Standard_False); |
209 | const OpenGl_AspectFace* aPlaneAspect = aPlaneRes->AspectFace(); |
210 | if (aPlaneAspect != NULL) |
211 | { |
212 | theWorkspace->SetAspectFace (aPlaneAspect); |
213 | } |
214 | |
215 | // apply aspect for rendering |
216 | theWorkspace->AspectFace (Standard_True); |
217 | |
218 | // set identity model matrix |
219 | const OpenGl_Matrix* aModelMatrix = theWorkspace->SetStructureMatrix (&OpenGl_IdentityMatrix); |
220 | |
221 | glMultMatrixf ((const GLfloat*)aPlaneRes->Orientation()); |
222 | glNormal3f (0.0f, 1.0f, 0.0f); |
223 | glEnableClientState (GL_VERTEX_ARRAY); |
224 | glVertexPointer (4, GL_FLOAT, 0, (GLfloat* )&THE_CAPPING_PLN_VERTS); |
225 | glEnableClientState (GL_TEXTURE_COORD_ARRAY); |
226 | glTexCoordPointer (4, GL_FLOAT, 0, (GLfloat*)&THE_CAPPING_PLN_TCOORD); |
227 | glDrawArrays (GL_TRIANGLES, 0, 12); |
228 | glDisableClientState (GL_VERTEX_ARRAY); |
229 | glDisableClientState (GL_TEXTURE_COORD_ARRAY); |
230 | |
392ac980 |
231 | theWorkspace->SetStructureMatrix (aModelMatrix, true); |
4269bd1b |
232 | theWorkspace->SetAspectFace (aFaceAspect); |
233 | |
234 | // set delayed resource release |
235 | aPlaneRes.Nullify(); |
236 | aContext->ReleaseResource (aResId, Standard_True); |
237 | } |
238 | |
239 | // ======================================================================= |
240 | // function : Init |
241 | // purpose : |
242 | // ======================================================================= |
243 | void OpenGl_CappingAlgo::Init() |
244 | { |
245 | if (myIsInit) |
246 | return; |
247 | |
248 | myRenderFilter = new OpenGl_CappingAlgoFilter(); |
fd4a6963 |
249 | myNoneCulling.ChangeCullingMode() = TelCullNone; |
250 | myNoneCulling.ChangeEdge() = 0; |
4269bd1b |
251 | |
fd4a6963 |
252 | myFrontCulling.ChangeCullingMode() = TelCullBack; |
253 | myFrontCulling.ChangeEdge() = 0; |
4269bd1b |
254 | |
255 | myIsInit = Standard_True; |
256 | } |
257 | |
258 | // ======================================================================= |
259 | // function : CanRender |
260 | // purpose : |
261 | // ======================================================================= |
262 | Standard_Boolean OpenGl_CappingAlgoFilter::CanRender (const OpenGl_Element* theElement) |
263 | { |
264 | const OpenGl_PrimitiveArray* aPArray = |
265 | dynamic_cast<const OpenGl_PrimitiveArray*> (theElement); |
266 | if (!aPArray) |
267 | return Standard_False; |
268 | |
269 | switch (aPArray->PArray()->type) |
270 | { |
271 | case TelPolygonsArrayType : |
272 | case TelTrianglesArrayType : |
273 | case TelQuadranglesArrayType : |
274 | case TelTriangleStripsArrayType : |
275 | case TelQuadrangleStripsArrayType : |
276 | case TelTriangleFansArrayType : |
277 | return Standard_True; |
278 | |
279 | default: |
280 | return Standard_False; |
281 | } |
282 | } |