0024245: TKOpenGL - use Message_Messenger interface to report issues
[occt.git] / src / OpenGl / OpenGl_CappingAlgo.cxx
CommitLineData
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
27IMPLEMENT_STANDARD_HANDLE(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter)
28IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter)
29
30Handle(OpenGl_RenderFilter) OpenGl_CappingAlgo::myRenderFilter;
31OpenGl_AspectFace OpenGl_CappingAlgo::myFrontCulling;
32OpenGl_AspectFace OpenGl_CappingAlgo::myNoneCulling;
33Standard_Boolean OpenGl_CappingAlgo::myIsInit = Standard_False;
34
35namespace
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// =======================================================================
70void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorkspace,
71 const OpenGl_ListOfGroup& theGroups)
72{
73 // do not draw capping surface for second transparency pass
74 if (theWorkspace->NamedStatus & OPENGL_NS_2NDPASSDO)
75 return;
76
77 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
78
79 // check whether algorithm need to be runned
80 Standard_Boolean isCapping = Standard_False;
81 Graphic3d_SetOfHClipPlane aContextPlanes = aContext->Clipping().Planes();
82 Graphic3d_SetOfHClipPlane::Iterator aCappingIt (aContextPlanes);
83 for (; aCappingIt.More(); aCappingIt.Next())
84 {
85 const Handle(Graphic3d_ClipPlane)& aPlane = aCappingIt.Value();
86 if (aPlane->IsCapping())
87 {
88 isCapping = Standard_True;
89 break;
90 }
91 }
92
93 // do not perform algorithm is there is nothing to render
94 if (!isCapping)
95 return;
96
97 // init internal data
98 Init();
99
100 // remember current aspect face defined in workspace
101 const OpenGl_AspectFace* aFaceAsp = theWorkspace->AspectFace (Standard_False);
102
103 // replace primitive groups rendering filter
104 static Handle(OpenGl_CappingAlgoFilter) aCappingFilter = new OpenGl_CappingAlgoFilter();
105 Handle(OpenGl_RenderFilter) aRenderFilter = theWorkspace->GetRenderFilter();
106 theWorkspace->SetRenderFilter (aCappingFilter);
107
108 // prepare for rendering the clip planes
109 glEnable (GL_STENCIL_TEST);
110
111 // generate capping for every clip plane
112 for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
113 {
114 // get plane being rendered
115 const Handle(Graphic3d_ClipPlane)& aRenderPlane = aCappingIt.Value();
116 if (!aRenderPlane->IsCapping())
117 {
118 continue;
119 }
120
121 // enable only the rendering plane to generate stencil mask
122 Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (aContextPlanes);
123 for (; aPlaneIt.More(); aPlaneIt.Next())
124 {
125 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
126 const Standard_Boolean isOn = (aPlane == aRenderPlane);
127 aContext->ChangeClipping().SetEnabled (aPlane, isOn);
128 }
129
130 glClear (GL_STENCIL_BUFFER_BIT);
131 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
132
133 // override aspects, disable culling
134 theWorkspace->SetAspectFace (NoneCulling());
135 theWorkspace->AspectFace (Standard_True);
136
137 // evaluate number of pair faces
138 glDisable (GL_DEPTH_TEST);
139 glDepthMask (GL_FALSE);
140 glStencilFunc (GL_ALWAYS, 1, 0x01);
141 glStencilOp (GL_KEEP, GL_INVERT, GL_INVERT);
142
143 OpenGl_ListOfGroup::Iterator aGroupIt (theGroups);
144 for (; aGroupIt.More(); aGroupIt.Next())
145 {
146 aGroupIt.Value()->Render (theWorkspace);
147 }
148
149 // override material, cull backfaces
150 theWorkspace->SetAspectFace (FrontCulling());
151 theWorkspace->AspectFace (Standard_True);
152
153 // enable all clip plane except the rendered one
154 for (aPlaneIt.Init (aContextPlanes); aPlaneIt.More(); aPlaneIt.Next())
155 {
156 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
157 const Standard_Boolean isOn = (aPlane != aRenderPlane);
158 aContext->ChangeClipping().SetEnabled (aPlane, isOn);
159 }
160
161 // render capping plane using the generated stencil mask
162 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
163 glDepthMask (GL_TRUE);
164 glDepthFunc (GL_LESS);
165 glStencilFunc (GL_EQUAL, 1, 0x01);
166 glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
167 glEnable (GL_DEPTH_TEST);
168
169 RenderPlane (theWorkspace, aRenderPlane);
170 }
171
172 // restore previous application state
173 glClear (GL_STENCIL_BUFFER_BIT);
174 glStencilFunc (GL_ALWAYS, 0, 0xFF);
175 glDisable (GL_STENCIL_TEST);
176
177 // enable clipping
178 for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
179 {
180 aContext->ChangeClipping().SetEnabled (aCappingIt.Value(), Standard_True);
181 }
182
183 // restore rendering aspects
184 theWorkspace->SetAspectFace (aFaceAsp);
185 theWorkspace->SetRenderFilter (aRenderFilter);
186}
187
188// =======================================================================
189// function : RenderPlane
190// purpose :
191// =======================================================================
192void OpenGl_CappingAlgo::RenderPlane (const Handle(OpenGl_Workspace)& theWorkspace,
193 const Handle(Graphic3d_ClipPlane)& thePlane)
194{
195 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
196
197 // get resource for the plane
198 TCollection_AsciiString aResId = thePlane->GetId();
199
200 Handle(OpenGl_CappingPlaneResource) aPlaneRes;
201 if (!aContext->GetResource (aResId, aPlaneRes))
202 {
203 // share and register for release once the resource is no longer used
204 aPlaneRes = new OpenGl_CappingPlaneResource (thePlane);
205 aContext->ShareResource (aResId, aPlaneRes);
206 }
207
208 aPlaneRes->Update (aContext);
209
210 const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace (Standard_False);
211 const OpenGl_AspectFace* aPlaneAspect = aPlaneRes->AspectFace();
212 if (aPlaneAspect != NULL)
213 {
214 theWorkspace->SetAspectFace (aPlaneAspect);
215 }
216
217 // apply aspect for rendering
218 theWorkspace->AspectFace (Standard_True);
219
220 // set identity model matrix
221 const OpenGl_Matrix* aModelMatrix = theWorkspace->SetStructureMatrix (&OpenGl_IdentityMatrix);
222
223 glMultMatrixf ((const GLfloat*)aPlaneRes->Orientation());
224 glNormal3f (0.0f, 1.0f, 0.0f);
225 glEnableClientState (GL_VERTEX_ARRAY);
226 glVertexPointer (4, GL_FLOAT, 0, (GLfloat* )&THE_CAPPING_PLN_VERTS);
227 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
228 glTexCoordPointer (4, GL_FLOAT, 0, (GLfloat*)&THE_CAPPING_PLN_TCOORD);
229 glDrawArrays (GL_TRIANGLES, 0, 12);
230 glDisableClientState (GL_VERTEX_ARRAY);
231 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
232
233 theWorkspace->SetStructureMatrix (aModelMatrix);
234 theWorkspace->SetAspectFace (aFaceAspect);
235
236 // set delayed resource release
237 aPlaneRes.Nullify();
238 aContext->ReleaseResource (aResId, Standard_True);
239}
240
241// =======================================================================
242// function : Init
243// purpose :
244// =======================================================================
245void OpenGl_CappingAlgo::Init()
246{
247 if (myIsInit)
248 return;
249
250 myRenderFilter = new OpenGl_CappingAlgoFilter();
251 myNoneCulling.CullingMode = TelCullNone;
252 myNoneCulling.Edge = 0;
253
254 myFrontCulling.CullingMode = TelCullBack;
255 myFrontCulling.Edge = 0;
256
257 myIsInit = Standard_True;
258}
259
260// =======================================================================
261// function : CanRender
262// purpose :
263// =======================================================================
264Standard_Boolean OpenGl_CappingAlgoFilter::CanRender (const OpenGl_Element* theElement)
265{
266 const OpenGl_PrimitiveArray* aPArray =
267 dynamic_cast<const OpenGl_PrimitiveArray*> (theElement);
268 if (!aPArray)
269 return Standard_False;
270
271 switch (aPArray->PArray()->type)
272 {
273 case TelPolygonsArrayType :
274 case TelTrianglesArrayType :
275 case TelQuadranglesArrayType :
276 case TelTriangleStripsArrayType :
277 case TelQuadrangleStripsArrayType :
278 case TelTriangleFansArrayType :
279 return Standard_True;
280
281 default:
282 return Standard_False;
283 }
284}