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