0027341: Incorrect exact HLR results
[occt.git] / src / OpenGl / OpenGl_Layer.cxx
CommitLineData
c5751993 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//
0a36ca0a 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
c5751993 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>
a1954302 17
18#include <OpenGl_BVHTreeSelector.hxx>
19#include <OpenGl_Structure.hxx>
20#include <OpenGl_View.hxx>
550f3b8b 21#include <OpenGl_Workspace.hxx>
c04c30b3 22#include <Graphic3d_GraphicDriver.hxx>
c5751993 23
a1954302 24// =======================================================================
825aa485 25// function : OpenGl_Layer
a1954302 26// purpose :
27// =======================================================================
c5751993 28OpenGl_Layer::OpenGl_Layer (const Standard_Integer theNbPriorities)
a1954302 29: myArray (0, theNbPriorities - 1),
30 myNbStructures (0),
31 myBVHIsLeftChildQueuedFirst (Standard_True),
32 myIsBVHPrimitivesNeedsReset (Standard_False)
c5751993 33{
34 //
35}
36
a1954302 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
9f112210 60 myArray (anIndex).Add (theStruct);
a1954302 61 if (theStruct->IsAlwaysRendered())
62 {
63 theStruct->MarkAsNotCulled();
64 }
65 else if (!isForChangePriority)
66 {
97f937cc 67 if (theStruct->TransformPersistence.Flags == Graphic3d_TMF_None)
825aa485 68 {
69 myBVHPrimitives.Add (theStruct);
70 }
71 else
72 {
73 myBVHPrimitivesTrsfPers.Add (theStruct);
74 }
a1954302 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 {
9f112210 96 OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
97
98 const Standard_Integer anIndex = aStructures.FindIndex (theStruct);
99 if (anIndex != 0)
a1954302 100 {
9f112210 101 aStructures.Swap (anIndex, aStructures.Size());
102 aStructures.RemoveLast();
103
104 if (!theStruct->IsAlwaysRendered()
105 && !isForChangePriority)
a1954302 106 {
825aa485 107 if (!myBVHPrimitives.Remove (theStruct))
108 {
109 myBVHPrimitivesTrsfPers.Remove (theStruct);
110 }
a1954302 111 }
9f112210 112 --myNbStructures;
113 thePriority = aPriorityIter;
114 return true;
a1954302 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();
c357e426 138 const Standard_Integer aViewId = theWorkspace->View()->Identification();
a1954302 139 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
140 {
9f112210 141 const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
142 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
a1954302 143 {
9f112210 144 const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx);
a1954302 145 if (!aStruct->IsVisible())
146 {
147 continue;
148 }
a272ed94 149 else if (!aStruct->ViewAffinity.IsNull()
150 && !aStruct->ViewAffinity->IsVisible (aViewId))
151 {
152 continue;
153 }
a1954302 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 {
825aa485 168 myBVHPrimitives.Clear();
169 myBVHPrimitivesTrsfPers.Clear();
a1954302 170 myIsBVHPrimitivesNeedsReset = Standard_False;
825aa485 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
97f937cc 180 if (aStruct->TransformPersistence.Flags == Graphic3d_TMF_None)
825aa485 181 {
182 myBVHPrimitives.Add (aStruct);
183 }
184 else
185 {
186 myBVHPrimitivesTrsfPers.Add (aStruct);
187 }
188 }
189 }
a1954302 190 }
191
c357e426 192 OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector();
a1954302 193 traverse (aSelector);
194
195 const Standard_Integer aNbPriorities = myArray.Length();
c357e426 196 const Standard_Integer aViewId = theWorkspace->View()->Identification();
a1954302 197 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
198 {
9f112210 199 const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
200 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
a1954302 201 {
9f112210 202 const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx);
a1954302 203 if (!aStruct->IsVisible()
204 || aStruct->IsCulled())
205 {
206 continue;
207 }
a272ed94 208 else if (!aStruct->ViewAffinity.IsNull()
209 && !aStruct->ViewAffinity->IsVisible (aViewId))
210 {
211 continue;
212 }
a1954302 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
97f937cc 227 if (myBVHPrimitives .Size() == 0
228 && myBVHPrimitivesTrsfPers.Size() == 0)
a1954302 229 return;
230
a1954302 231 theSelector.CacheClipPtsProjections();
a1954302 232
825aa485 233 NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> > aBVHTree;
234
235 for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx)
a1954302 236 {
825aa485 237 const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1;
238 if (isTrsfPers)
a1954302 239 {
825aa485 240 if (myBVHPrimitivesTrsfPers.Size() == 0)
825aa485 241 continue;
97f937cc 242
243 const OpenGl_Mat4& aProjection = theSelector.ProjectionMatrix();
244 const OpenGl_Mat4& aWorldView = theSelector.WorldViewMatrix();
825aa485 245 const Graphic3d_WorldViewProjState& aWVPState = theSelector.WorldViewProjState();
246 aBVHTree = myBVHPrimitivesTrsfPers.BVH (aProjection, aWorldView, aWVPState);
247 }
248 else
249 {
250 if (myBVHPrimitives.Size() == 0)
825aa485 251 continue;
97f937cc 252
825aa485 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))
a1954302 269 {
825aa485 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 }
a1954302 297 }
298 else
299 {
825aa485 300 Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode);
301 const OpenGl_Structure* aStruct =
302 isTrsfPers ? myBVHPrimitivesTrsfPers.GetStructureById (aIdx)
303 : myBVHPrimitives.GetStructureById (aIdx);
304 aStruct->MarkAsNotCulled();
a1954302 305 if (aHead < 0)
306 {
825aa485 307 break;
a1954302 308 }
309
14a35e5d 310 aNode = aStack[aHead--];
a1954302 311 }
312 }
a1954302 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 {
9f112210 332 const OpenGl_IndexedMapOfStructure& aStructures = theOther.myArray (aPriorityIter);
333 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
a1954302 334 {
9f112210 335 Add (aStructures.FindKey (aStructIdx), aPriorityIter);
a1954302 336 }
337 }
338
339 return Standard_True;
340}
341
c5751993 342//=======================================================================
343//function : Render
a1954302 344//purpose :
c5751993 345//=======================================================================
a1954302 346void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace,
347 const OpenGl_GlobalLayerSettings& theDefaultSettings) const
c5751993 348{
550f3b8b 349 TEL_POFFSET_PARAM anAppliedOffsetParams = theWorkspace->AppliedPolygonOffset();
350
c5751993 351 // separate depth buffers
352 if (IsSettingEnabled (Graphic3d_ZLayerDepthClear))
353 {
354 glClear (GL_DEPTH_BUFFER_BIT);
355 }
eae454e3 356
c5751993 357 // handle depth test
358 if (IsSettingEnabled (Graphic3d_ZLayerDepthTest))
359 {
550f3b8b 360 // assuming depth test is enabled by default
361 glDepthFunc (theDefaultSettings.DepthFunc);
c5751993 362 }
363 else
364 {
365 glDepthFunc (GL_ALWAYS);
366 }
eae454e3 367
83da37b1 368 // save environment texture
369 Handle(OpenGl_Texture) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
370 if (!myLayerSettings.UseEnvironmentTexture)
371 {
372 theWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
373 }
374
c5751993 375 // handle depth offset
376 if (IsSettingEnabled (Graphic3d_ZLayerDepthOffset))
377 {
550f3b8b 378 theWorkspace->SetPolygonOffset (Aspect_POM_Fill,
379 myLayerSettings.DepthOffsetFactor,
380 myLayerSettings.DepthOffsetUnits);
c5751993 381 }
382 else
383 {
550f3b8b 384 theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
385 anAppliedOffsetParams.factor,
386 anAppliedOffsetParams.units);
c5751993 387 }
388
389 // handle depth write
eae454e3 390 theWorkspace->UseDepthWrite() = IsSettingEnabled (Graphic3d_ZLayerDepthWrite);
391 glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE);
c5751993 392
393 // render priority list
a1954302 394 theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace);
550f3b8b 395
396 // always restore polygon offset between layers rendering
397 theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
398 anAppliedOffsetParams.factor,
399 anAppliedOffsetParams.units);
83da37b1 400
401 // restore environment texture
402 if (!myLayerSettings.UseEnvironmentTexture)
403 {
404 theWorkspace->SetEnvironmentTexture (anEnvironmentTexture);
405 }
c5751993 406}