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> |
deb02f86 |
17 | |
25c35042 |
18 | #include <OpenGl_ClippingIterator.hxx> |
4269bd1b |
19 | #include <OpenGl_Workspace.hxx> |
20 | #include <OpenGl_Context.hxx> |
21 | #include <OpenGl_PrimitiveArray.hxx> |
22 | #include <OpenGl_CappingPlaneResource.hxx> |
23 | #include <OpenGl_Vec.hxx> |
b64d84be |
24 | #include <OpenGl_Structure.hxx> |
deb02f86 |
25 | #include <OpenGl_ShaderManager.hxx> |
4269bd1b |
26 | |
92efcf78 |
27 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter,OpenGl_RenderFilter) |
28 | |
4269bd1b |
29 | namespace |
30 | { |
3e05329c |
31 | //! Render infinite capping plane. |
32 | //! @param theWorkspace [in] the GL workspace, context state. |
33 | //! @param thePlane [in] the graphical plane, for which the capping surface is rendered. |
34 | static void renderPlane (const Handle(OpenGl_Workspace)& theWorkspace, |
35 | const Handle(OpenGl_CappingPlaneResource)& thePlane, |
36 | const OpenGl_AspectFace* theAspectFace) |
37 | { |
38 | const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); |
39 | thePlane->Update (aContext, theAspectFace != NULL ? theAspectFace->Aspect() : Handle(Graphic3d_AspectFillArea3d)()); |
40 | |
25c35042 |
41 | bool wasCullAllowed = theWorkspace->SetAllowFaceCulling (true); |
3e05329c |
42 | const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace(); |
43 | theWorkspace->SetAspectFace (thePlane->AspectFace()); |
44 | |
45 | // set identity model matrix |
46 | aContext->ModelWorldState.Push(); |
47 | aContext->ModelWorldState.SetCurrent (OpenGl_Mat4::Map (*thePlane->Orientation()->mat)); |
48 | aContext->ApplyModelViewMatrix(); |
49 | |
50 | thePlane->Primitives().Render (theWorkspace); |
51 | |
52 | aContext->ModelWorldState.Pop(); |
53 | aContext->ApplyModelViewMatrix(); |
54 | |
25c35042 |
55 | theWorkspace->SetAllowFaceCulling (wasCullAllowed); |
3e05329c |
56 | theWorkspace->SetAspectFace (aFaceAspect); |
57 | } |
58 | |
59 | //! Render capping for specific structure. |
60 | static void renderCappingForStructure (const Handle(OpenGl_Workspace)& theWorkspace, |
61 | const OpenGl_Structure& theStructure, |
25c35042 |
62 | const Handle(Graphic3d_ClipPlane)& theClipChain, |
63 | const Standard_Integer theSubPlaneIndex, |
3e05329c |
64 | const Handle(OpenGl_CappingPlaneResource)& thePlane) |
65 | { |
3202bf1e |
66 | const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); |
67 | const Handle(Graphic3d_ClipPlane)& aRenderPlane = thePlane->Plane(); |
3e05329c |
68 | for (OpenGl_Structure::GroupIterator aGroupIter (theStructure.Groups()); aGroupIter.More(); aGroupIter.Next()) |
69 | { |
70 | if (!aGroupIter.Value()->IsClosed()) |
71 | { |
72 | continue; |
73 | } |
74 | |
75 | // enable only the rendering plane to generate stencil mask |
25c35042 |
76 | aContext->ChangeClipping().DisableAllExcept (theClipChain, theSubPlaneIndex); |
3e05329c |
77 | aContext->ShaderManager()->UpdateClippingState(); |
78 | |
79 | glClear (GL_STENCIL_BUFFER_BIT); |
f88457e6 |
80 | const bool aColorMaskBack = aContext->SetColorMask (false); |
3e05329c |
81 | |
82 | // override aspects, disable culling |
83 | theWorkspace->SetAspectFace (&theWorkspace->NoneCulling()); |
84 | theWorkspace->ApplyAspectFace(); |
85 | |
86 | // evaluate number of pair faces |
a1073ae2 |
87 | if (theWorkspace->UseZBuffer()) |
88 | { |
89 | glDisable (GL_DEPTH_TEST); |
90 | } |
91 | if (theWorkspace->UseDepthWrite()) |
92 | { |
93 | glDepthMask (GL_FALSE); |
94 | } |
3e05329c |
95 | glStencilFunc (GL_ALWAYS, 1, 0x01); |
96 | glStencilOp (GL_KEEP, GL_INVERT, GL_INVERT); |
97 | |
98 | // render closed primitives |
99 | if (aRenderPlane->ToUseObjectProperties()) |
100 | { |
101 | aGroupIter.Value()->Render (theWorkspace); |
102 | } |
103 | else |
104 | { |
105 | for (; aGroupIter.More(); aGroupIter.Next()) |
106 | { |
107 | if (aGroupIter.Value()->IsClosed()) |
108 | { |
109 | aGroupIter.Value()->Render (theWorkspace); |
110 | } |
111 | } |
112 | } |
113 | |
114 | // override material, cull back faces |
115 | theWorkspace->SetAspectFace (&theWorkspace->FrontCulling()); |
116 | theWorkspace->ApplyAspectFace(); |
117 | |
118 | // enable all clip plane except the rendered one |
25c35042 |
119 | aContext->ChangeClipping().EnableAllExcept (theClipChain, theSubPlaneIndex); |
3e05329c |
120 | aContext->ShaderManager()->UpdateClippingState(); |
121 | |
122 | // render capping plane using the generated stencil mask |
f88457e6 |
123 | aContext->SetColorMask (aColorMaskBack); |
a1073ae2 |
124 | if (theWorkspace->UseDepthWrite()) |
125 | { |
126 | glDepthMask (GL_TRUE); |
127 | } |
3e05329c |
128 | glStencilFunc (GL_EQUAL, 1, 0x01); |
129 | glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP); |
a1073ae2 |
130 | if (theWorkspace->UseZBuffer()) |
131 | { |
132 | glEnable (GL_DEPTH_TEST); |
133 | } |
3e05329c |
134 | |
25c35042 |
135 | renderPlane (theWorkspace, thePlane, |
136 | aRenderPlane->ToUseObjectProperties() ? aGroupIter.Value()->AspectFace() : NULL); |
3e05329c |
137 | |
3202bf1e |
138 | // turn on the current plane to restore initial state |
25c35042 |
139 | aContext->ChangeClipping().ResetCappingFilter(); |
3e05329c |
140 | aContext->ShaderManager()->RevertClippingState(); |
141 | aContext->ShaderManager()->RevertClippingState(); |
142 | } |
143 | |
144 | if (theStructure.InstancedStructure() != NULL) |
145 | { |
25c35042 |
146 | renderCappingForStructure (theWorkspace, *theStructure.InstancedStructure(), theClipChain, theSubPlaneIndex, thePlane); |
3e05329c |
147 | } |
148 | } |
ca3c13d1 |
149 | } |
4269bd1b |
150 | |
151 | // ======================================================================= |
152 | // function : RenderCapping |
153 | // purpose : |
154 | // ======================================================================= |
cc6852f3 |
155 | void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorkspace, |
156 | const OpenGl_Structure& theStructure) |
4269bd1b |
157 | { |
4269bd1b |
158 | const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); |
3202bf1e |
159 | if (!aContext->Clipping().IsCappingOn()) |
b859a34d |
160 | { |
3202bf1e |
161 | // do not perform algorithm if there is nothing to render |
4269bd1b |
162 | return; |
b859a34d |
163 | } |
4269bd1b |
164 | |
4269bd1b |
165 | // remember current aspect face defined in workspace |
f9ba5c4d |
166 | const OpenGl_AspectFace* aFaceAsp = theWorkspace->AspectFace(); |
4269bd1b |
167 | |
168 | // replace primitive groups rendering filter |
4269bd1b |
169 | Handle(OpenGl_RenderFilter) aRenderFilter = theWorkspace->GetRenderFilter(); |
a1073ae2 |
170 | Handle(OpenGl_CappingAlgoFilter) aCappingFilter = theWorkspace->DefaultCappingAlgoFilter(); |
171 | aCappingFilter->SetPreviousFilter (aRenderFilter); |
172 | theWorkspace->SetRenderFilter (aCappingFilter); |
4269bd1b |
173 | |
174 | // prepare for rendering the clip planes |
175 | glEnable (GL_STENCIL_TEST); |
176 | |
347423b2 |
177 | // remember current state of depth |
178 | // function and change its value |
179 | GLint aDepthFuncPrev; |
180 | glGetIntegerv (GL_DEPTH_FUNC, &aDepthFuncPrev); |
181 | glDepthFunc (GL_LESS); |
182 | |
4269bd1b |
183 | // generate capping for every clip plane |
3202bf1e |
184 | for (OpenGl_ClippingIterator aCappingIt (aContext->Clipping()); aCappingIt.More(); aCappingIt.Next()) |
4269bd1b |
185 | { |
186 | // get plane being rendered |
25c35042 |
187 | const Handle(Graphic3d_ClipPlane)& aClipChain = aCappingIt.Value(); |
188 | if (!aClipChain->IsCapping() |
3202bf1e |
189 | || aCappingIt.IsDisabled()) |
4269bd1b |
190 | { |
191 | continue; |
192 | } |
193 | |
25c35042 |
194 | Standard_Integer aSubPlaneIndex = 1; |
195 | for (const Graphic3d_ClipPlane* aSubPlaneIter = aClipChain.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex) |
4269bd1b |
196 | { |
25c35042 |
197 | // get resource for the plane |
198 | const TCollection_AsciiString& aResId = aSubPlaneIter->GetId(); |
199 | Handle(OpenGl_CappingPlaneResource) aPlaneRes; |
200 | if (!aContext->GetResource (aResId, aPlaneRes)) |
201 | { |
202 | // share and register for release once the resource is no longer used |
203 | aPlaneRes = new OpenGl_CappingPlaneResource (aSubPlaneIter); |
204 | aContext->ShareResource (aResId, aPlaneRes); |
205 | } |
4269bd1b |
206 | |
25c35042 |
207 | renderCappingForStructure (theWorkspace, theStructure, aClipChain, aSubPlaneIndex, aPlaneRes); |
4269bd1b |
208 | |
25c35042 |
209 | // set delayed resource release |
210 | aPlaneRes.Nullify(); |
211 | aContext->ReleaseResource (aResId, Standard_True); |
212 | } |
4269bd1b |
213 | } |
214 | |
215 | // restore previous application state |
216 | glClear (GL_STENCIL_BUFFER_BIT); |
347423b2 |
217 | glDepthFunc (aDepthFuncPrev); |
4269bd1b |
218 | glStencilFunc (GL_ALWAYS, 0, 0xFF); |
219 | glDisable (GL_STENCIL_TEST); |
220 | |
4269bd1b |
221 | // restore rendering aspects |
222 | theWorkspace->SetAspectFace (aFaceAsp); |
223 | theWorkspace->SetRenderFilter (aRenderFilter); |
224 | } |
225 | |
4269bd1b |
226 | // ======================================================================= |
227 | // function : CanRender |
228 | // purpose : |
229 | // ======================================================================= |
a1073ae2 |
230 | Standard_Boolean OpenGl_CappingAlgoFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace, |
231 | const OpenGl_Element* theGlElement) |
4269bd1b |
232 | { |
a1073ae2 |
233 | if (!myFilter.IsNull() && !myFilter->ShouldRender (theWorkspace, theGlElement)) |
234 | { |
235 | return Standard_False; |
236 | } |
237 | |
64c6d8df |
238 | return theGlElement->IsFillDrawMode(); |
4269bd1b |
239 | } |