0027341: Incorrect exact HLR results
[occt.git] / src / OpenGl / OpenGl_Layer.cxx
... / ...
CommitLineData
1// Created on: 2014-03-31
2// Created by: Danila ULYANOV
3// Copyright (c) 2014 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
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
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.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16#include <OpenGl_Layer.hxx>
17
18#include <OpenGl_BVHTreeSelector.hxx>
19#include <OpenGl_Structure.hxx>
20#include <OpenGl_View.hxx>
21#include <OpenGl_Workspace.hxx>
22#include <Graphic3d_GraphicDriver.hxx>
23
24// =======================================================================
25// function : OpenGl_Layer
26// purpose :
27// =======================================================================
28OpenGl_Layer::OpenGl_Layer (const Standard_Integer theNbPriorities)
29: myArray (0, theNbPriorities - 1),
30 myNbStructures (0),
31 myBVHIsLeftChildQueuedFirst (Standard_True),
32 myIsBVHPrimitivesNeedsReset (Standard_False)
33{
34 //
35}
36
37// =======================================================================
38// function : ~OpenGl_Layer
39// purpose :
40// =======================================================================
41OpenGl_Layer::~OpenGl_Layer()
42{
43 //
44}
45
46// =======================================================================
47// function : Add
48// purpose :
49// =======================================================================
50void OpenGl_Layer::Add (const OpenGl_Structure* theStruct,
51 const Standard_Integer thePriority,
52 Standard_Boolean isForChangePriority)
53{
54 const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1);
55 if (theStruct == NULL)
56 {
57 return;
58 }
59
60 myArray (anIndex).Add (theStruct);
61 if (theStruct->IsAlwaysRendered())
62 {
63 theStruct->MarkAsNotCulled();
64 }
65 else if (!isForChangePriority)
66 {
67 if (theStruct->TransformPersistence.Flags == Graphic3d_TMF_None)
68 {
69 myBVHPrimitives.Add (theStruct);
70 }
71 else
72 {
73 myBVHPrimitivesTrsfPers.Add (theStruct);
74 }
75 }
76 ++myNbStructures;
77}
78
79// =======================================================================
80// function : Remove
81// purpose :
82// =======================================================================
83bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct,
84 Standard_Integer& thePriority,
85 Standard_Boolean isForChangePriority)
86{
87 if (theStruct == NULL)
88 {
89 thePriority = -1;
90 return false;
91 }
92
93 const Standard_Integer aNbPriorities = myArray.Length();
94 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
95 {
96 OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
97
98 const Standard_Integer anIndex = aStructures.FindIndex (theStruct);
99 if (anIndex != 0)
100 {
101 aStructures.Swap (anIndex, aStructures.Size());
102 aStructures.RemoveLast();
103
104 if (!theStruct->IsAlwaysRendered()
105 && !isForChangePriority)
106 {
107 if (!myBVHPrimitives.Remove (theStruct))
108 {
109 myBVHPrimitivesTrsfPers.Remove (theStruct);
110 }
111 }
112 --myNbStructures;
113 thePriority = aPriorityIter;
114 return true;
115 }
116 }
117
118 thePriority = -1;
119 return false;
120}
121
122// =======================================================================
123// function : InvalidateBVHData
124// purpose :
125// =======================================================================
126void OpenGl_Layer::InvalidateBVHData()
127{
128 myIsBVHPrimitivesNeedsReset = Standard_True;
129}
130
131// =======================================================================
132// function : renderAll
133// purpose :
134// =======================================================================
135void OpenGl_Layer::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const
136{
137 const Standard_Integer aNbPriorities = myArray.Length();
138 const Standard_Integer aViewId = theWorkspace->View()->Identification();
139 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
140 {
141 const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
142 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
143 {
144 const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx);
145 if (!aStruct->IsVisible())
146 {
147 continue;
148 }
149 else if (!aStruct->ViewAffinity.IsNull()
150 && !aStruct->ViewAffinity->IsVisible (aViewId))
151 {
152 continue;
153 }
154
155 aStruct->Render (theWorkspace);
156 }
157 }
158}
159
160// =======================================================================
161// function : renderTraverse
162// purpose :
163// =======================================================================
164void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const
165{
166 if (myIsBVHPrimitivesNeedsReset)
167 {
168 myBVHPrimitives.Clear();
169 myBVHPrimitivesTrsfPers.Clear();
170 myIsBVHPrimitivesNeedsReset = Standard_False;
171 for (Standard_Integer aPriorityIdx = 0, aNbPriorities = myArray.Length(); aPriorityIdx < aNbPriorities; ++aPriorityIdx)
172 {
173 for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (myArray (aPriorityIdx)); aStructIter.More(); aStructIter.Next())
174 {
175 const OpenGl_Structure* aStruct = aStructIter.Value();
176
177 if (aStruct->IsAlwaysRendered())
178 continue;
179
180 if (aStruct->TransformPersistence.Flags == Graphic3d_TMF_None)
181 {
182 myBVHPrimitives.Add (aStruct);
183 }
184 else
185 {
186 myBVHPrimitivesTrsfPers.Add (aStruct);
187 }
188 }
189 }
190 }
191
192 OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector();
193 traverse (aSelector);
194
195 const Standard_Integer aNbPriorities = myArray.Length();
196 const Standard_Integer aViewId = theWorkspace->View()->Identification();
197 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
198 {
199 const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
200 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
201 {
202 const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx);
203 if (!aStruct->IsVisible()
204 || aStruct->IsCulled())
205 {
206 continue;
207 }
208 else if (!aStruct->ViewAffinity.IsNull()
209 && !aStruct->ViewAffinity->IsVisible (aViewId))
210 {
211 continue;
212 }
213
214 aStruct->Render (theWorkspace);
215 aStruct->ResetCullingStatus();
216 }
217 }
218}
219
220// =======================================================================
221// function : traverse
222// purpose :
223// =======================================================================
224void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const
225{
226 // handle a case when all objects are infinite
227 if (myBVHPrimitives .Size() == 0
228 && myBVHPrimitivesTrsfPers.Size() == 0)
229 return;
230
231 theSelector.CacheClipPtsProjections();
232
233 NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> > aBVHTree;
234
235 for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx)
236 {
237 const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1;
238 if (isTrsfPers)
239 {
240 if (myBVHPrimitivesTrsfPers.Size() == 0)
241 continue;
242
243 const OpenGl_Mat4& aProjection = theSelector.ProjectionMatrix();
244 const OpenGl_Mat4& aWorldView = theSelector.WorldViewMatrix();
245 const Graphic3d_WorldViewProjState& aWVPState = theSelector.WorldViewProjState();
246 aBVHTree = myBVHPrimitivesTrsfPers.BVH (aProjection, aWorldView, aWVPState);
247 }
248 else
249 {
250 if (myBVHPrimitives.Size() == 0)
251 continue;
252
253 aBVHTree = myBVHPrimitives.BVH();
254 }
255
256 Standard_Integer aNode = 0; // a root node
257
258 if (!theSelector.Intersect (aBVHTree->MinPoint (0),
259 aBVHTree->MaxPoint (0)))
260 {
261 continue;
262 }
263
264 Standard_Integer aStack[32];
265 Standard_Integer aHead = -1;
266 for (;;)
267 {
268 if (!aBVHTree->IsOuter (aNode))
269 {
270 const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode);
271 const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
272 const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx),
273 aBVHTree->MaxPoint (aLeftChildIdx));
274 const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx),
275 aBVHTree->MaxPoint (aRightChildIdx));
276 if (isLeftChildIn
277 && isRightChildIn)
278 {
279 aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx;
280 aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx;
281 myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst;
282 }
283 else if (isLeftChildIn
284 || isRightChildIn)
285 {
286 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
287 }
288 else
289 {
290 if (aHead < 0)
291 {
292 break;
293 }
294
295 aNode = aStack[aHead--];
296 }
297 }
298 else
299 {
300 Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode);
301 const OpenGl_Structure* aStruct =
302 isTrsfPers ? myBVHPrimitivesTrsfPers.GetStructureById (aIdx)
303 : myBVHPrimitives.GetStructureById (aIdx);
304 aStruct->MarkAsNotCulled();
305 if (aHead < 0)
306 {
307 break;
308 }
309
310 aNode = aStack[aHead--];
311 }
312 }
313 }
314}
315
316// =======================================================================
317// function : Append
318// purpose :
319// =======================================================================
320Standard_Boolean OpenGl_Layer::Append (const OpenGl_Layer& theOther)
321{
322 // the source priority list shouldn't have more priorities
323 const Standard_Integer aNbPriorities = theOther.NbPriorities();
324 if (aNbPriorities > NbPriorities())
325 {
326 return Standard_False;
327 }
328
329 // add all structures to destination priority list
330 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
331 {
332 const OpenGl_IndexedMapOfStructure& aStructures = theOther.myArray (aPriorityIter);
333 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
334 {
335 Add (aStructures.FindKey (aStructIdx), aPriorityIter);
336 }
337 }
338
339 return Standard_True;
340}
341
342//=======================================================================
343//function : Render
344//purpose :
345//=======================================================================
346void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace,
347 const OpenGl_GlobalLayerSettings& theDefaultSettings) const
348{
349 TEL_POFFSET_PARAM anAppliedOffsetParams = theWorkspace->AppliedPolygonOffset();
350
351 // separate depth buffers
352 if (IsSettingEnabled (Graphic3d_ZLayerDepthClear))
353 {
354 glClear (GL_DEPTH_BUFFER_BIT);
355 }
356
357 // handle depth test
358 if (IsSettingEnabled (Graphic3d_ZLayerDepthTest))
359 {
360 // assuming depth test is enabled by default
361 glDepthFunc (theDefaultSettings.DepthFunc);
362 }
363 else
364 {
365 glDepthFunc (GL_ALWAYS);
366 }
367
368 // save environment texture
369 Handle(OpenGl_Texture) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
370 if (!myLayerSettings.UseEnvironmentTexture)
371 {
372 theWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
373 }
374
375 // handle depth offset
376 if (IsSettingEnabled (Graphic3d_ZLayerDepthOffset))
377 {
378 theWorkspace->SetPolygonOffset (Aspect_POM_Fill,
379 myLayerSettings.DepthOffsetFactor,
380 myLayerSettings.DepthOffsetUnits);
381 }
382 else
383 {
384 theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
385 anAppliedOffsetParams.factor,
386 anAppliedOffsetParams.units);
387 }
388
389 // handle depth write
390 theWorkspace->UseDepthWrite() = IsSettingEnabled (Graphic3d_ZLayerDepthWrite);
391 glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE);
392
393 // render priority list
394 theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace);
395
396 // always restore polygon offset between layers rendering
397 theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
398 anAppliedOffsetParams.factor,
399 anAppliedOffsetParams.units);
400
401 // restore environment texture
402 if (!myLayerSettings.UseEnvironmentTexture)
403 {
404 theWorkspace->SetEnvironmentTexture (anEnvironmentTexture);
405 }
406}