0027696: Return max distance in xdistcs Draw command
[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)
50d06d8f 29: myArray (0, theNbPriorities - 1),
30 myNbStructures (0),
a1954302 31 myBVHIsLeftChildQueuedFirst (Standard_True),
32 myIsBVHPrimitivesNeedsReset (Standard_False)
c5751993 33{
50d06d8f 34 myIsBoundingBoxNeedsReset[0] = myIsBoundingBoxNeedsReset[1] = true;
c5751993 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();
3fe9ce0e 64 if (!isForChangePriority)
65 {
66 myAlwaysRenderedMap.Add (theStruct);
67 }
a1954302 68 }
69 else if (!isForChangePriority)
70 {
97f937cc 71 if (theStruct->TransformPersistence.Flags == Graphic3d_TMF_None)
825aa485 72 {
73 myBVHPrimitives.Add (theStruct);
74 }
75 else
76 {
77 myBVHPrimitivesTrsfPers.Add (theStruct);
78 }
a1954302 79 }
80 ++myNbStructures;
81}
82
83// =======================================================================
84// function : Remove
85// purpose :
86// =======================================================================
87bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct,
88 Standard_Integer& thePriority,
89 Standard_Boolean isForChangePriority)
90{
91 if (theStruct == NULL)
92 {
93 thePriority = -1;
94 return false;
95 }
96
97 const Standard_Integer aNbPriorities = myArray.Length();
98 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
99 {
9f112210 100 OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
101
102 const Standard_Integer anIndex = aStructures.FindIndex (theStruct);
103 if (anIndex != 0)
a1954302 104 {
9f112210 105 aStructures.Swap (anIndex, aStructures.Size());
106 aStructures.RemoveLast();
107
3fe9ce0e 108 if (!isForChangePriority)
a1954302 109 {
3fe9ce0e 110 if (theStruct->IsAlwaysRendered())
825aa485 111 {
3fe9ce0e 112 const Standard_Integer anIndex2 = myAlwaysRenderedMap.FindIndex (theStruct);
113 if (anIndex2 != 0)
114 {
115 myAlwaysRenderedMap.Swap (myAlwaysRenderedMap.Size(), anIndex2);
116 myAlwaysRenderedMap.RemoveLast();
117 }
118 }
119 else
120 {
121 if (!myBVHPrimitives.Remove (theStruct))
122 {
123 myBVHPrimitivesTrsfPers.Remove (theStruct);
124 }
825aa485 125 }
a1954302 126 }
9f112210 127 --myNbStructures;
128 thePriority = aPriorityIter;
129 return true;
a1954302 130 }
131 }
132
133 thePriority = -1;
134 return false;
135}
136
137// =======================================================================
138// function : InvalidateBVHData
139// purpose :
140// =======================================================================
50d06d8f 141void OpenGl_Layer::InvalidateBVHData() const
a1954302 142{
143 myIsBVHPrimitivesNeedsReset = Standard_True;
144}
145
3fe9ce0e 146//! Calculate a finite bounding box of infinite object as its middle point.
147inline Graphic3d_BndBox4f centerOfinfiniteBndBox (const Graphic3d_BndBox4f& theBndBox)
148{
149 // bounding borders of infinite line has been calculated as own point in center of this line
150 const Graphic3d_Vec4 aDiagVec = theBndBox.CornerMax() - theBndBox.CornerMin();
151 return aDiagVec.xyz().SquareModulus() >= 500000.0f * 500000.0f
152 ? Graphic3d_BndBox4f ((theBndBox.CornerMin() + theBndBox.CornerMax()) * 0.5f)
153 : Graphic3d_BndBox4f();
154}
155
156//! Return true if at least one vertex coordinate out of float range.
157inline bool isInfiniteBndBox (const Graphic3d_BndBox4f& theBndBox)
158{
159 return Abs (theBndBox.CornerMax().x()) >= ShortRealLast()
160 || Abs (theBndBox.CornerMax().y()) >= ShortRealLast()
161 || Abs (theBndBox.CornerMax().z()) >= ShortRealLast()
162 || Abs (theBndBox.CornerMin().x()) >= ShortRealLast()
163 || Abs (theBndBox.CornerMin().y()) >= ShortRealLast()
164 || Abs (theBndBox.CornerMin().z()) >= ShortRealLast();
165}
166
a1954302 167// =======================================================================
50d06d8f 168// function : BoundingBox
169// purpose :
170// =======================================================================
3fe9ce0e 171Graphic3d_BndBox4f OpenGl_Layer::BoundingBox (const Standard_Integer theViewId,
172 const Handle(Graphic3d_Camera)& theCamera,
173 const Standard_Integer theWindowWidth,
174 const Standard_Integer theWindowHeight,
175 const Standard_Boolean theToIncludeAuxiliary) const
50d06d8f 176{
150ed3d5 177 updateBVH();
178
3fe9ce0e 179 const Standard_Integer aBoxId = !theToIncludeAuxiliary ? 0 : 1;
180 const Graphic3d_Mat4& aProjectionMat = theCamera->ProjectionMatrixF();
181 const Graphic3d_Mat4& aWorldViewMat = theCamera->OrientationMatrixF();
50d06d8f 182 if (myIsBoundingBoxNeedsReset[aBoxId])
183 {
184 // Recompute layer bounding box
185 myBoundingBox[aBoxId].Clear();
186
187 const Standard_Integer aNbPriorities = myArray.Length();
188 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
189 {
190 const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
191 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
192 {
193 const OpenGl_Structure* aStructure = aStructures.FindKey (aStructIdx);
3fe9ce0e 194 if (!aStructure->IsVisible (theViewId))
50d06d8f 195 {
196 continue;
197 }
198
199 // "FitAll" operation ignores object with transform persistence parameter
200 // but adds transform persistence point in a bounding box of layer (only zoom pers. objects).
201 if (aStructure->TransformPersistence.Flags != Graphic3d_TMF_None)
202 {
3fe9ce0e 203 if (!theToIncludeAuxiliary
204 && (aStructure->TransformPersistence.Flags & Graphic3d_TMF_ZoomPers) != 0)
50d06d8f 205 {
50d06d8f 206 BVH_Vec4f aTPPoint (static_cast<float> (aStructure->TransformPersistence.Point.x()),
207 static_cast<float> (aStructure->TransformPersistence.Point.y()),
208 static_cast<float> (aStructure->TransformPersistence.Point.z()),
209 1.0f);
210
211 myBoundingBox[aBoxId].Combine (aTPPoint);
212 continue;
213 }
214 // Panning and 2d persistence apply changes to projection or/and its translation components.
215 // It makes them incompatible with z-fitting algorithm. Ignored by now.
3fe9ce0e 216 else if (!theToIncludeAuxiliary
217 || (aStructure->TransformPersistence.Flags & (Graphic3d_TMF_2d | Graphic3d_TMF_PanPers | Graphic3d_TMF_TriedronPers)) != 0)
50d06d8f 218 {
219 continue;
220 }
221 }
222
223 Graphic3d_BndBox4f aBox = aStructure->BoundingBox();
3fe9ce0e 224 if (!aBox.IsValid())
225 {
226 continue;
227 }
50d06d8f 228
229 if (aStructure->IsInfinite
3fe9ce0e 230 && !theToIncludeAuxiliary)
50d06d8f 231 {
3fe9ce0e 232 // include center of infinite object
233 aBox = centerOfinfiniteBndBox (aBox);
50d06d8f 234 }
235
236 if (aStructure->TransformPersistence.Flags != Graphic3d_TMF_None)
237 {
3fe9ce0e 238 aStructure->TransformPersistence.Apply (theCamera,
239 aProjectionMat,
50d06d8f 240 aWorldViewMat,
241 theWindowWidth,
242 theWindowHeight,
243 aBox);
244 }
245
3fe9ce0e 246 // skip too big boxes to prevent float overflow at camera parameters calculation
247 if (!isInfiniteBndBox (aBox))
50d06d8f 248 {
3fe9ce0e 249 myBoundingBox[aBoxId].Combine (aBox);
50d06d8f 250 }
50d06d8f 251 }
252 }
253
254 myIsBoundingBoxNeedsReset[aBoxId] = false;
255 }
256
3fe9ce0e 257 if (!theToIncludeAuxiliary
258 || myAlwaysRenderedMap.IsEmpty())
259 {
260 return myBoundingBox[aBoxId];
261 }
262
263 // add transformation-persistent objects which depend on camera position (and thus can not be cached) for operations like Z-fit
264 Graphic3d_BndBox4f aResBox = myBoundingBox[aBoxId];
265 for (NCollection_IndexedMap<const OpenGl_Structure*>::Iterator aStructIter (myAlwaysRenderedMap); aStructIter.More(); aStructIter.Next())
266 {
267 const OpenGl_Structure* aStructure = aStructIter.Value();
268 if (!aStructure->IsVisible (theViewId))
269 {
270 continue;
271 }
150ed3d5 272 else if ((aStructure->TransformPersistence.Flags & (Graphic3d_TMF_TriedronPers | Graphic3d_TMF_2d)) == 0)
3fe9ce0e 273 {
274 continue;
275 }
276
277 Graphic3d_BndBox4f aBox = aStructure->BoundingBox();
278 if (!aBox.IsValid())
279 {
280 continue;
281 }
282
283 aStructure->TransformPersistence.Apply (theCamera,
284 aProjectionMat,
285 aWorldViewMat,
286 theWindowWidth,
287 theWindowHeight,
288 aBox);
289 if (!isInfiniteBndBox (aBox))
290 {
291 aResBox.Combine (aBox);
292 }
293 }
294
295 return aResBox;
50d06d8f 296}
297
298// =======================================================================
299// function : considerZoomPersistenceObjects
300// purpose :
301// =======================================================================
302Standard_Real OpenGl_Layer::considerZoomPersistenceObjects (const Standard_Integer theViewId,
303 const Handle(Graphic3d_Camera)& theCamera,
304 Standard_Integer theWindowWidth,
3fe9ce0e 305 Standard_Integer theWindowHeight) const
50d06d8f 306{
307 if (NbOfTransformPersistenceObjects() == 0)
308 {
309 return 1.0;
310 }
311
312 const Standard_Integer aNbPriorities = myArray.Length();
313 const Graphic3d_Mat4& aProjectionMat = theCamera->ProjectionMatrixF();
314 const Graphic3d_Mat4& aWorldViewMat = theCamera->OrientationMatrixF();
315 Standard_Real aMaxCoef = -std::numeric_limits<double>::max();
316
317 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
318 {
319 const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
320 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
321 {
322 OpenGl_Structure* aStructure = const_cast<OpenGl_Structure*> (aStructures.FindKey (aStructIdx));
3fe9ce0e 323 if (!aStructure->IsVisible (theViewId)
324 || (aStructure->TransformPersistence.Flags & Graphic3d_TMF_ZoomPers) == 0)
50d06d8f 325 {
326 continue;
327 }
328
3fe9ce0e 329 Graphic3d_BndBox4f aBox = aStructure->BoundingBox();
330 if (!aBox.IsValid())
50d06d8f 331 {
332 continue;
333 }
334
3fe9ce0e 335 aStructure->TransformPersistence.Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox);
50d06d8f 336
337 const BVH_Vec4f& aCornerMin = aBox.CornerMin();
338 const BVH_Vec4f& aCornerMax = aBox.CornerMax();
339 const Standard_Integer aNbOfPoints = 8;
340 const gp_Pnt aPoints[aNbOfPoints] = { gp_Pnt (aCornerMin.x(), aCornerMin.y(), aCornerMin.z()),
341 gp_Pnt (aCornerMin.x(), aCornerMin.y(), aCornerMax.z()),
342 gp_Pnt (aCornerMin.x(), aCornerMax.y(), aCornerMin.z()),
343 gp_Pnt (aCornerMin.x(), aCornerMax.y(), aCornerMax.z()),
344 gp_Pnt (aCornerMax.x(), aCornerMin.y(), aCornerMin.z()),
345 gp_Pnt (aCornerMax.x(), aCornerMin.y(), aCornerMax.z()),
346 gp_Pnt (aCornerMax.x(), aCornerMax.y(), aCornerMin.z()),
347 gp_Pnt (aCornerMax.x(), aCornerMax.y(), aCornerMax.z()) };
348 gp_Pnt aConvertedPoints[aNbOfPoints];
349 Standard_Real aConvertedMinX = std::numeric_limits<double>::max();
350 Standard_Real aConvertedMaxX = -std::numeric_limits<double>::max();
351 Standard_Real aConvertedMinY = std::numeric_limits<double>::max();
352 Standard_Real aConvertedMaxY = -std::numeric_limits<double>::max();
353 for (Standard_Integer anIdx = 0; anIdx < aNbOfPoints; ++anIdx)
354 {
355 aConvertedPoints[anIdx] = theCamera->Project (aPoints[anIdx]);
356
357 aConvertedMinX = Min (aConvertedMinX, aConvertedPoints[anIdx].X());
358 aConvertedMaxX = Max (aConvertedMaxX, aConvertedPoints[anIdx].X());
359
360 aConvertedMinY = Min (aConvertedMinY, aConvertedPoints[anIdx].Y());
361 aConvertedMaxY = Max (aConvertedMaxY, aConvertedPoints[anIdx].Y());
362 }
363
364 const Standard_Boolean isBigObject = (Abs (aConvertedMaxX - aConvertedMinX) > 2.0) // width of zoom pers. object greater than width of window
365 || (Abs (aConvertedMaxY - aConvertedMinY) > 2.0); // height of zoom pers. object greater than height of window
366 const Standard_Boolean isAlreadyInScreen = (aConvertedMinX > -1.0 && aConvertedMinX < 1.0)
367 && (aConvertedMaxX > -1.0 && aConvertedMaxX < 1.0)
368 && (aConvertedMinY > -1.0 && aConvertedMinY < 1.0)
369 && (aConvertedMaxY > -1.0 && aConvertedMaxY < 1.0);
370 if (isBigObject || isAlreadyInScreen)
371 {
372 continue;
373 }
374
375 const gp_Pnt aTPPoint (aStructure->TransformPersistence.Point.x(),
376 aStructure->TransformPersistence.Point.y(),
377 aStructure->TransformPersistence.Point.z());
378 gp_Pnt aConvertedTPPoint = theCamera->Project (aTPPoint);
379 aConvertedTPPoint.SetZ (0.0);
380
381 if (aConvertedTPPoint.Coord().Modulus() < Precision::Confusion())
382 {
383 continue;
384 }
385
386 Standard_Real aShiftX = 0.0;
387 if (aConvertedMinX < -1.0)
388 {
389 aShiftX = ((aConvertedMaxX < -1.0) ? (-(1.0 + aConvertedMaxX) + (aConvertedMaxX - aConvertedMinX)) : -(1.0 + aConvertedMinX));
390 }
391 else if (aConvertedMaxX > 1.0)
392 {
393 aShiftX = ((aConvertedMinX > 1.0) ? ((aConvertedMinX - 1.0) + (aConvertedMaxX - aConvertedMinX)) : (aConvertedMaxX - 1.0));
394 }
395
396 Standard_Real aShiftY = 0.0;
397 if (aConvertedMinY < -1.0)
398 {
399 aShiftY = ((aConvertedMaxY < -1.0) ? (-(1.0 + aConvertedMaxY) + (aConvertedMaxY - aConvertedMinY)) : -(1.0 + aConvertedMinY));
400 }
401 else if (aConvertedMaxY > 1.0)
402 {
403 aShiftY = ((aConvertedMinY > 1.0) ? ((aConvertedMinY - 1.0) + (aConvertedMaxY - aConvertedMinY)) : (aConvertedMaxY - 1.0));
404 }
405
406 const Standard_Real aDifX = Abs (aConvertedTPPoint.X()) - aShiftX;
407 const Standard_Real aDifY = Abs (aConvertedTPPoint.Y()) - aShiftY;
408 if (aDifX > Precision::Confusion())
409 {
410 aMaxCoef = Max (aMaxCoef, Abs (aConvertedTPPoint.X()) / aDifX);
411 }
412 if (aDifY > Precision::Confusion())
413 {
414 aMaxCoef = Max (aMaxCoef, Abs (aConvertedTPPoint.Y()) / aDifY);
415 }
416 }
417 }
418
419 return (aMaxCoef > 0.0) ? aMaxCoef : 1.0;
420}
421
422// =======================================================================
a1954302 423// function : renderAll
424// purpose :
425// =======================================================================
426void OpenGl_Layer::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const
427{
428 const Standard_Integer aNbPriorities = myArray.Length();
c357e426 429 const Standard_Integer aViewId = theWorkspace->View()->Identification();
a1954302 430 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
431 {
9f112210 432 const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
433 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
a1954302 434 {
9f112210 435 const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx);
a1954302 436 if (!aStruct->IsVisible())
437 {
438 continue;
439 }
a272ed94 440 else if (!aStruct->ViewAffinity.IsNull()
441 && !aStruct->ViewAffinity->IsVisible (aViewId))
442 {
443 continue;
444 }
a1954302 445
446 aStruct->Render (theWorkspace);
447 }
448 }
449}
450
451// =======================================================================
3fe9ce0e 452// function : updateBVH
a1954302 453// purpose :
454// =======================================================================
3fe9ce0e 455void OpenGl_Layer::updateBVH() const
a1954302 456{
3fe9ce0e 457 if (!myIsBVHPrimitivesNeedsReset)
458 {
459 return;
460 }
461
462 myBVHPrimitives.Clear();
463 myBVHPrimitivesTrsfPers.Clear();
150ed3d5 464 myAlwaysRenderedMap.Clear();
3fe9ce0e 465 myIsBVHPrimitivesNeedsReset = Standard_False;
466 for (Standard_Integer aPriorityIdx = 0, aNbPriorities = myArray.Length(); aPriorityIdx < aNbPriorities; ++aPriorityIdx)
a1954302 467 {
3fe9ce0e 468 for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (myArray (aPriorityIdx)); aStructIter.More(); aStructIter.Next())
825aa485 469 {
3fe9ce0e 470 const OpenGl_Structure* aStruct = aStructIter.Value();
471 if (aStruct->IsAlwaysRendered())
825aa485 472 {
150ed3d5 473 aStruct->MarkAsNotCulled();
474 myAlwaysRenderedMap.Add (aStruct);
3fe9ce0e 475 }
150ed3d5 476 else if (aStruct->TransformPersistence.Flags == Graphic3d_TMF_None)
3fe9ce0e 477 {
478 myBVHPrimitives.Add (aStruct);
479 }
480 else
481 {
482 myBVHPrimitivesTrsfPers.Add (aStruct);
825aa485 483 }
484 }
a1954302 485 }
3fe9ce0e 486}
487
488// =======================================================================
489// function : renderTraverse
490// purpose :
491// =======================================================================
492void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const
493{
494 updateBVH();
a1954302 495
c357e426 496 OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector();
a1954302 497 traverse (aSelector);
498
499 const Standard_Integer aNbPriorities = myArray.Length();
c357e426 500 const Standard_Integer aViewId = theWorkspace->View()->Identification();
a1954302 501 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
502 {
9f112210 503 const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
504 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
a1954302 505 {
9f112210 506 const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx);
3fe9ce0e 507 if (aStruct->IsCulled()
508 || !aStruct->IsVisible (aViewId))
a272ed94 509 {
510 continue;
511 }
a1954302 512
513 aStruct->Render (theWorkspace);
514 aStruct->ResetCullingStatus();
515 }
516 }
517}
518
519// =======================================================================
520// function : traverse
521// purpose :
522// =======================================================================
523void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const
524{
525 // handle a case when all objects are infinite
97f937cc 526 if (myBVHPrimitives .Size() == 0
527 && myBVHPrimitivesTrsfPers.Size() == 0)
a1954302 528 return;
529
a1954302 530 theSelector.CacheClipPtsProjections();
a1954302 531
825aa485 532 NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> > aBVHTree;
533
534 for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx)
a1954302 535 {
825aa485 536 const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1;
537 if (isTrsfPers)
a1954302 538 {
825aa485 539 if (myBVHPrimitivesTrsfPers.Size() == 0)
825aa485 540 continue;
97f937cc 541
542 const OpenGl_Mat4& aProjection = theSelector.ProjectionMatrix();
543 const OpenGl_Mat4& aWorldView = theSelector.WorldViewMatrix();
825aa485 544 const Graphic3d_WorldViewProjState& aWVPState = theSelector.WorldViewProjState();
91d96372 545 const Standard_Integer aViewportWidth = theSelector.ViewportWidth();
546 const Standard_Integer aViewportHeight = theSelector.ViewportHeight();
547
3fe9ce0e 548 aBVHTree = myBVHPrimitivesTrsfPers.BVH (theSelector.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState);
825aa485 549 }
550 else
551 {
552 if (myBVHPrimitives.Size() == 0)
825aa485 553 continue;
97f937cc 554
825aa485 555 aBVHTree = myBVHPrimitives.BVH();
556 }
557
558 Standard_Integer aNode = 0; // a root node
559
560 if (!theSelector.Intersect (aBVHTree->MinPoint (0),
561 aBVHTree->MaxPoint (0)))
562 {
563 continue;
564 }
565
566 Standard_Integer aStack[32];
567 Standard_Integer aHead = -1;
568 for (;;)
569 {
570 if (!aBVHTree->IsOuter (aNode))
a1954302 571 {
f2474958 572 const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode);
573 const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
825aa485 574 const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx),
575 aBVHTree->MaxPoint (aLeftChildIdx));
576 const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx),
577 aBVHTree->MaxPoint (aRightChildIdx));
578 if (isLeftChildIn
579 && isRightChildIn)
580 {
581 aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx;
582 aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx;
583 myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst;
584 }
585 else if (isLeftChildIn
586 || isRightChildIn)
587 {
588 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
589 }
590 else
591 {
592 if (aHead < 0)
593 {
594 break;
595 }
596
597 aNode = aStack[aHead--];
598 }
a1954302 599 }
600 else
601 {
825aa485 602 Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode);
603 const OpenGl_Structure* aStruct =
604 isTrsfPers ? myBVHPrimitivesTrsfPers.GetStructureById (aIdx)
605 : myBVHPrimitives.GetStructureById (aIdx);
606 aStruct->MarkAsNotCulled();
a1954302 607 if (aHead < 0)
608 {
825aa485 609 break;
a1954302 610 }
611
14a35e5d 612 aNode = aStack[aHead--];
a1954302 613 }
614 }
a1954302 615 }
616}
617
618// =======================================================================
619// function : Append
620// purpose :
621// =======================================================================
622Standard_Boolean OpenGl_Layer::Append (const OpenGl_Layer& theOther)
623{
624 // the source priority list shouldn't have more priorities
625 const Standard_Integer aNbPriorities = theOther.NbPriorities();
626 if (aNbPriorities > NbPriorities())
627 {
628 return Standard_False;
629 }
630
631 // add all structures to destination priority list
632 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
633 {
9f112210 634 const OpenGl_IndexedMapOfStructure& aStructures = theOther.myArray (aPriorityIter);
635 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
a1954302 636 {
9f112210 637 Add (aStructures.FindKey (aStructIdx), aPriorityIter);
a1954302 638 }
639 }
640
641 return Standard_True;
642}
643
c5751993 644//=======================================================================
645//function : Render
a1954302 646//purpose :
c5751993 647//=======================================================================
a1954302 648void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace,
649 const OpenGl_GlobalLayerSettings& theDefaultSettings) const
c5751993 650{
b6472664 651 Graphic3d_PolygonOffset anAppliedOffsetParams = theWorkspace->AppliedPolygonOffset();
550f3b8b 652
c5751993 653 // separate depth buffers
654 if (IsSettingEnabled (Graphic3d_ZLayerDepthClear))
655 {
656 glClear (GL_DEPTH_BUFFER_BIT);
657 }
eae454e3 658
c5751993 659 // handle depth test
660 if (IsSettingEnabled (Graphic3d_ZLayerDepthTest))
661 {
550f3b8b 662 // assuming depth test is enabled by default
663 glDepthFunc (theDefaultSettings.DepthFunc);
c5751993 664 }
665 else
666 {
667 glDepthFunc (GL_ALWAYS);
668 }
eae454e3 669
83da37b1 670 // save environment texture
671 Handle(OpenGl_Texture) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
672 if (!myLayerSettings.UseEnvironmentTexture)
673 {
674 theWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
675 }
676
c5751993 677 // handle depth offset
678 if (IsSettingEnabled (Graphic3d_ZLayerDepthOffset))
679 {
b6472664 680 Graphic3d_PolygonOffset aLayerPolygonOffset;
681 aLayerPolygonOffset.Mode = Aspect_POM_Fill;
682 aLayerPolygonOffset.Factor = myLayerSettings.DepthOffsetFactor;
683 aLayerPolygonOffset.Units = myLayerSettings.DepthOffsetUnits;
684 theWorkspace->SetPolygonOffset (aLayerPolygonOffset);
c5751993 685 }
686 else
687 {
b6472664 688 theWorkspace->SetPolygonOffset (anAppliedOffsetParams);
c5751993 689 }
690
691 // handle depth write
eae454e3 692 theWorkspace->UseDepthWrite() = IsSettingEnabled (Graphic3d_ZLayerDepthWrite);
693 glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE);
c5751993 694
695 // render priority list
a1954302 696 theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace);
550f3b8b 697
698 // always restore polygon offset between layers rendering
b6472664 699 theWorkspace->SetPolygonOffset (anAppliedOffsetParams);
83da37b1 700
701 // restore environment texture
702 if (!myLayerSettings.UseEnvironmentTexture)
703 {
704 theWorkspace->SetEnvironmentTexture (anEnvironmentTexture);
705 }
c5751993 706}