0031511: Point Cloud Rendering, Volume Rendering - reuse Graphic3d_CullingTool
[occt.git] / src / Graphic3d / Graphic3d_Layer.cxx
CommitLineData
d325cb7f 1// Copyright (c) 2011-2019 OPEN CASCADE SAS
c5751993 2//
3// This file is part of Open CASCADE Technology software library.
4//
0a36ca0a 5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
c5751993 7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
10//
11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
13
d325cb7f 14#include <Graphic3d_Layer.hxx>
a1954302 15
d325cb7f 16#include <Graphic3d_CStructure.hxx>
17#include <Graphic3d_CullingTool.hxx>
c5751993 18
d325cb7f 19IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_Layer, Standard_Transient)
f5b72419 20
a1954302 21// =======================================================================
d325cb7f 22// function : Graphic3d_Layer
a1954302 23// purpose :
24// =======================================================================
1c728f2d 25Graphic3d_Layer::Graphic3d_Layer (Graphic3d_ZLayerId theId,
26 Standard_Integer theNbPriorities,
d325cb7f 27 const Handle(Select3D_BVHBuilder3d)& theBuilder)
50d06d8f 28: myArray (0, theNbPriorities - 1),
29 myNbStructures (0),
15669413 30 myNbStructuresNotCulled (0),
1c728f2d 31 myLayerId (theId),
f5b72419 32 myBVHPrimitivesTrsfPers (theBuilder),
a1954302 33 myBVHIsLeftChildQueuedFirst (Standard_True),
15669413 34 myIsBVHPrimitivesNeedsReset (Standard_False)
c5751993 35{
50d06d8f 36 myIsBoundingBoxNeedsReset[0] = myIsBoundingBoxNeedsReset[1] = true;
c5751993 37}
38
a1954302 39// =======================================================================
d325cb7f 40// function : ~Graphic3d_Layer
a1954302 41// purpose :
42// =======================================================================
d325cb7f 43Graphic3d_Layer::~Graphic3d_Layer()
a1954302 44{
45 //
46}
47
48// =======================================================================
49// function : Add
50// purpose :
51// =======================================================================
d325cb7f 52void Graphic3d_Layer::Add (const Graphic3d_CStructure* theStruct,
53 Standard_Integer thePriority,
54 Standard_Boolean isForChangePriority)
a1954302 55{
56 const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1);
57 if (theStruct == NULL)
58 {
59 return;
60 }
61
9f112210 62 myArray (anIndex).Add (theStruct);
a1954302 63 if (theStruct->IsAlwaysRendered())
64 {
65 theStruct->MarkAsNotCulled();
3fe9ce0e 66 if (!isForChangePriority)
67 {
68 myAlwaysRenderedMap.Add (theStruct);
69 }
a1954302 70 }
71 else if (!isForChangePriority)
72 {
778cd667 73 if (theStruct->TransformPersistence().IsNull())
825aa485 74 {
75 myBVHPrimitives.Add (theStruct);
76 }
77 else
78 {
79 myBVHPrimitivesTrsfPers.Add (theStruct);
80 }
a1954302 81 }
82 ++myNbStructures;
83}
84
85// =======================================================================
86// function : Remove
87// purpose :
88// =======================================================================
d325cb7f 89bool Graphic3d_Layer::Remove (const Graphic3d_CStructure* theStruct,
90 Standard_Integer& thePriority,
91 Standard_Boolean isForChangePriority)
a1954302 92{
93 if (theStruct == NULL)
94 {
95 thePriority = -1;
96 return false;
97 }
98
99 const Standard_Integer aNbPriorities = myArray.Length();
100 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
101 {
d325cb7f 102 Graphic3d_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
9f112210 103 const Standard_Integer anIndex = aStructures.FindIndex (theStruct);
d325cb7f 104 if (anIndex == 0)
a1954302 105 {
d325cb7f 106 continue;
107 }
108
109 aStructures.Swap (anIndex, aStructures.Size());
110 aStructures.RemoveLast();
9f112210 111
d325cb7f 112 if (!isForChangePriority)
113 {
114 Standard_Boolean isAlwaysRend = theStruct->IsAlwaysRendered();
115 if (!isAlwaysRend)
a1954302 116 {
d325cb7f 117 if (!myBVHPrimitives.Remove (theStruct))
825aa485 118 {
d325cb7f 119 if (!myBVHPrimitivesTrsfPers.Remove (theStruct))
3fe9ce0e 120 {
d325cb7f 121 isAlwaysRend = Standard_True;
3fe9ce0e 122 }
123 }
d325cb7f 124 }
125 if (isAlwaysRend)
126 {
127 const Standard_Integer anIndex2 = myAlwaysRenderedMap.FindIndex (theStruct);
128 if (anIndex2 != 0)
3fe9ce0e 129 {
d325cb7f 130 myAlwaysRenderedMap.Swap (myAlwaysRenderedMap.Size(), anIndex2);
131 myAlwaysRenderedMap.RemoveLast();
825aa485 132 }
a1954302 133 }
134 }
d325cb7f 135 --myNbStructures;
136 thePriority = aPriorityIter;
137 return true;
a1954302 138 }
139
140 thePriority = -1;
141 return false;
142}
143
144// =======================================================================
145// function : InvalidateBVHData
146// purpose :
147// =======================================================================
d325cb7f 148void Graphic3d_Layer::InvalidateBVHData()
a1954302 149{
150 myIsBVHPrimitivesNeedsReset = Standard_True;
151}
152
3fe9ce0e 153//! Calculate a finite bounding box of infinite object as its middle point.
7c3ef2f7 154inline Graphic3d_BndBox3d centerOfinfiniteBndBox (const Graphic3d_BndBox3d& theBndBox)
3fe9ce0e 155{
156 // bounding borders of infinite line has been calculated as own point in center of this line
7c3ef2f7 157 const Graphic3d_Vec3d aDiagVec = theBndBox.CornerMax() - theBndBox.CornerMin();
158 return aDiagVec.SquareModulus() >= 500000.0 * 500000.0
159 ? Graphic3d_BndBox3d ((theBndBox.CornerMin() + theBndBox.CornerMax()) * 0.5)
160 : Graphic3d_BndBox3d();
3fe9ce0e 161}
162
163//! Return true if at least one vertex coordinate out of float range.
7c3ef2f7 164inline bool isInfiniteBndBox (const Graphic3d_BndBox3d& theBndBox)
3fe9ce0e 165{
166 return Abs (theBndBox.CornerMax().x()) >= ShortRealLast()
167 || Abs (theBndBox.CornerMax().y()) >= ShortRealLast()
168 || Abs (theBndBox.CornerMax().z()) >= ShortRealLast()
169 || Abs (theBndBox.CornerMin().x()) >= ShortRealLast()
170 || Abs (theBndBox.CornerMin().y()) >= ShortRealLast()
171 || Abs (theBndBox.CornerMin().z()) >= ShortRealLast();
172}
173
a1954302 174// =======================================================================
50d06d8f 175// function : BoundingBox
176// purpose :
177// =======================================================================
d325cb7f 178Bnd_Box Graphic3d_Layer::BoundingBox (Standard_Integer theViewId,
179 const Handle(Graphic3d_Camera)& theCamera,
180 Standard_Integer theWindowWidth,
181 Standard_Integer theWindowHeight,
182 Standard_Boolean theToIncludeAuxiliary) const
50d06d8f 183{
150ed3d5 184 updateBVH();
185
3fe9ce0e 186 const Standard_Integer aBoxId = !theToIncludeAuxiliary ? 0 : 1;
7c3ef2f7 187 const Graphic3d_Mat4d& aProjectionMat = theCamera->ProjectionMatrix();
188 const Graphic3d_Mat4d& aWorldViewMat = theCamera->OrientationMatrix();
50d06d8f 189 if (myIsBoundingBoxNeedsReset[aBoxId])
190 {
191 // Recompute layer bounding box
7c3ef2f7 192 myBoundingBox[aBoxId].SetVoid();
50d06d8f 193
d325cb7f 194 for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next())
50d06d8f 195 {
d325cb7f 196 const Graphic3d_IndexedMapOfStructure& aStructures = aMapIter.Value();
197 for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
50d06d8f 198 {
d325cb7f 199 const Graphic3d_CStructure* aStructure = aStructIter.Value();
3fe9ce0e 200 if (!aStructure->IsVisible (theViewId))
50d06d8f 201 {
202 continue;
203 }
204
205 // "FitAll" operation ignores object with transform persistence parameter
206 // but adds transform persistence point in a bounding box of layer (only zoom pers. objects).
778cd667 207 if (!aStructure->TransformPersistence().IsNull())
50d06d8f 208 {
3fe9ce0e 209 if (!theToIncludeAuxiliary
778cd667 210 && aStructure->TransformPersistence()->IsZoomOrRotate())
50d06d8f 211 {
778cd667 212 const gp_Pnt anAnchor = aStructure->TransformPersistence()->AnchorPoint();
7c3ef2f7 213 myBoundingBox[aBoxId].Add (anAnchor);
50d06d8f 214 continue;
215 }
216 // Panning and 2d persistence apply changes to projection or/and its translation components.
217 // It makes them incompatible with z-fitting algorithm. Ignored by now.
3fe9ce0e 218 else if (!theToIncludeAuxiliary
778cd667 219 || aStructure->TransformPersistence()->IsTrihedronOr2d())
50d06d8f 220 {
221 continue;
222 }
223 }
224
7c3ef2f7 225 Graphic3d_BndBox3d aBox = aStructure->BoundingBox();
3fe9ce0e 226 if (!aBox.IsValid())
227 {
228 continue;
229 }
50d06d8f 230
231 if (aStructure->IsInfinite
3fe9ce0e 232 && !theToIncludeAuxiliary)
50d06d8f 233 {
3fe9ce0e 234 // include center of infinite object
235 aBox = centerOfinfiniteBndBox (aBox);
50d06d8f 236 }
237
778cd667 238 if (!aStructure->TransformPersistence().IsNull())
50d06d8f 239 {
778cd667 240 aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox);
50d06d8f 241 }
242
3fe9ce0e 243 // skip too big boxes to prevent float overflow at camera parameters calculation
7c3ef2f7 244 if (aBox.IsValid()
245 && !isInfiniteBndBox (aBox))
50d06d8f 246 {
7c3ef2f7 247 myBoundingBox[aBoxId].Add (gp_Pnt (aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z()));
248 myBoundingBox[aBoxId].Add (gp_Pnt (aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z()));
50d06d8f 249 }
50d06d8f 250 }
251 }
252
253 myIsBoundingBoxNeedsReset[aBoxId] = false;
254 }
255
7c3ef2f7 256 Bnd_Box aResBox = myBoundingBox[aBoxId];
3fe9ce0e 257 if (!theToIncludeAuxiliary
258 || myAlwaysRenderedMap.IsEmpty())
259 {
7c3ef2f7 260 return aResBox;
3fe9ce0e 261 }
262
263 // add transformation-persistent objects which depend on camera position (and thus can not be cached) for operations like Z-fit
d325cb7f 264 for (NCollection_IndexedMap<const Graphic3d_CStructure*>::Iterator aStructIter (myAlwaysRenderedMap); aStructIter.More(); aStructIter.Next())
3fe9ce0e 265 {
d325cb7f 266 const Graphic3d_CStructure* aStructure = aStructIter.Value();
3fe9ce0e 267 if (!aStructure->IsVisible (theViewId))
268 {
269 continue;
270 }
778cd667 271 else if (aStructure->TransformPersistence().IsNull()
272 || !aStructure->TransformPersistence()->IsTrihedronOr2d())
3fe9ce0e 273 {
274 continue;
275 }
276
7c3ef2f7 277 Graphic3d_BndBox3d aBox = aStructure->BoundingBox();
3fe9ce0e 278 if (!aBox.IsValid())
279 {
280 continue;
281 }
282
778cd667 283 aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox);
7c3ef2f7 284 if (aBox.IsValid()
285 && !isInfiniteBndBox (aBox))
3fe9ce0e 286 {
7c3ef2f7 287 aResBox.Add (gp_Pnt (aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z()));
288 aResBox.Add (gp_Pnt (aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z()));
3fe9ce0e 289 }
290 }
291
292 return aResBox;
50d06d8f 293}
294
295// =======================================================================
296// function : considerZoomPersistenceObjects
297// purpose :
298// =======================================================================
d325cb7f 299Standard_Real Graphic3d_Layer::considerZoomPersistenceObjects (Standard_Integer theViewId,
300 const Handle(Graphic3d_Camera)& theCamera,
301 Standard_Integer theWindowWidth,
302 Standard_Integer theWindowHeight) const
50d06d8f 303{
304 if (NbOfTransformPersistenceObjects() == 0)
305 {
306 return 1.0;
307 }
308
7c3ef2f7 309 const Graphic3d_Mat4d& aProjectionMat = theCamera->ProjectionMatrix();
310 const Graphic3d_Mat4d& aWorldViewMat = theCamera->OrientationMatrix();
50d06d8f 311 Standard_Real aMaxCoef = -std::numeric_limits<double>::max();
312
d325cb7f 313 for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next())
50d06d8f 314 {
d325cb7f 315 const Graphic3d_IndexedMapOfStructure& aStructures = aMapIter.Value();
316 for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
50d06d8f 317 {
d325cb7f 318 const Graphic3d_CStructure* aStructure = aStructIter.Value();
3fe9ce0e 319 if (!aStructure->IsVisible (theViewId)
778cd667 320 || aStructure->TransformPersistence().IsNull()
321 || !aStructure->TransformPersistence()->IsZoomOrRotate())
50d06d8f 322 {
323 continue;
324 }
325
7c3ef2f7 326 Graphic3d_BndBox3d aBox = aStructure->BoundingBox();
3fe9ce0e 327 if (!aBox.IsValid())
50d06d8f 328 {
329 continue;
330 }
331
778cd667 332 aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox);
50d06d8f 333
7c3ef2f7 334 const BVH_Vec3d& aCornerMin = aBox.CornerMin();
335 const BVH_Vec3d& aCornerMax = aBox.CornerMax();
50d06d8f 336 const Standard_Integer aNbOfPoints = 8;
337 const gp_Pnt aPoints[aNbOfPoints] = { gp_Pnt (aCornerMin.x(), aCornerMin.y(), aCornerMin.z()),
338 gp_Pnt (aCornerMin.x(), aCornerMin.y(), aCornerMax.z()),
339 gp_Pnt (aCornerMin.x(), aCornerMax.y(), aCornerMin.z()),
340 gp_Pnt (aCornerMin.x(), aCornerMax.y(), aCornerMax.z()),
341 gp_Pnt (aCornerMax.x(), aCornerMin.y(), aCornerMin.z()),
342 gp_Pnt (aCornerMax.x(), aCornerMin.y(), aCornerMax.z()),
343 gp_Pnt (aCornerMax.x(), aCornerMax.y(), aCornerMin.z()),
344 gp_Pnt (aCornerMax.x(), aCornerMax.y(), aCornerMax.z()) };
345 gp_Pnt aConvertedPoints[aNbOfPoints];
346 Standard_Real aConvertedMinX = std::numeric_limits<double>::max();
347 Standard_Real aConvertedMaxX = -std::numeric_limits<double>::max();
348 Standard_Real aConvertedMinY = std::numeric_limits<double>::max();
349 Standard_Real aConvertedMaxY = -std::numeric_limits<double>::max();
350 for (Standard_Integer anIdx = 0; anIdx < aNbOfPoints; ++anIdx)
351 {
352 aConvertedPoints[anIdx] = theCamera->Project (aPoints[anIdx]);
353
354 aConvertedMinX = Min (aConvertedMinX, aConvertedPoints[anIdx].X());
355 aConvertedMaxX = Max (aConvertedMaxX, aConvertedPoints[anIdx].X());
356
357 aConvertedMinY = Min (aConvertedMinY, aConvertedPoints[anIdx].Y());
358 aConvertedMaxY = Max (aConvertedMaxY, aConvertedPoints[anIdx].Y());
359 }
360
361 const Standard_Boolean isBigObject = (Abs (aConvertedMaxX - aConvertedMinX) > 2.0) // width of zoom pers. object greater than width of window
362 || (Abs (aConvertedMaxY - aConvertedMinY) > 2.0); // height of zoom pers. object greater than height of window
363 const Standard_Boolean isAlreadyInScreen = (aConvertedMinX > -1.0 && aConvertedMinX < 1.0)
364 && (aConvertedMaxX > -1.0 && aConvertedMaxX < 1.0)
365 && (aConvertedMinY > -1.0 && aConvertedMinY < 1.0)
366 && (aConvertedMaxY > -1.0 && aConvertedMaxY < 1.0);
367 if (isBigObject || isAlreadyInScreen)
368 {
369 continue;
370 }
371
778cd667 372 const gp_Pnt aTPPoint = aStructure->TransformPersistence()->AnchorPoint();
50d06d8f 373 gp_Pnt aConvertedTPPoint = theCamera->Project (aTPPoint);
374 aConvertedTPPoint.SetZ (0.0);
375
376 if (aConvertedTPPoint.Coord().Modulus() < Precision::Confusion())
377 {
378 continue;
379 }
380
381 Standard_Real aShiftX = 0.0;
382 if (aConvertedMinX < -1.0)
383 {
384 aShiftX = ((aConvertedMaxX < -1.0) ? (-(1.0 + aConvertedMaxX) + (aConvertedMaxX - aConvertedMinX)) : -(1.0 + aConvertedMinX));
385 }
386 else if (aConvertedMaxX > 1.0)
387 {
388 aShiftX = ((aConvertedMinX > 1.0) ? ((aConvertedMinX - 1.0) + (aConvertedMaxX - aConvertedMinX)) : (aConvertedMaxX - 1.0));
389 }
390
391 Standard_Real aShiftY = 0.0;
392 if (aConvertedMinY < -1.0)
393 {
394 aShiftY = ((aConvertedMaxY < -1.0) ? (-(1.0 + aConvertedMaxY) + (aConvertedMaxY - aConvertedMinY)) : -(1.0 + aConvertedMinY));
395 }
396 else if (aConvertedMaxY > 1.0)
397 {
398 aShiftY = ((aConvertedMinY > 1.0) ? ((aConvertedMinY - 1.0) + (aConvertedMaxY - aConvertedMinY)) : (aConvertedMaxY - 1.0));
399 }
400
401 const Standard_Real aDifX = Abs (aConvertedTPPoint.X()) - aShiftX;
402 const Standard_Real aDifY = Abs (aConvertedTPPoint.Y()) - aShiftY;
403 if (aDifX > Precision::Confusion())
404 {
405 aMaxCoef = Max (aMaxCoef, Abs (aConvertedTPPoint.X()) / aDifX);
406 }
407 if (aDifY > Precision::Confusion())
408 {
409 aMaxCoef = Max (aMaxCoef, Abs (aConvertedTPPoint.Y()) / aDifY);
410 }
411 }
412 }
413
414 return (aMaxCoef > 0.0) ? aMaxCoef : 1.0;
415}
416
417// =======================================================================
3fe9ce0e 418// function : updateBVH
a1954302 419// purpose :
420// =======================================================================
d325cb7f 421void Graphic3d_Layer::updateBVH() const
a1954302 422{
3fe9ce0e 423 if (!myIsBVHPrimitivesNeedsReset)
424 {
425 return;
426 }
427
428 myBVHPrimitives.Clear();
429 myBVHPrimitivesTrsfPers.Clear();
150ed3d5 430 myAlwaysRenderedMap.Clear();
3fe9ce0e 431 myIsBVHPrimitivesNeedsReset = Standard_False;
d325cb7f 432 for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next())
a1954302 433 {
d325cb7f 434 const Graphic3d_IndexedMapOfStructure& aStructures = aMapIter.Value();
435 for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
825aa485 436 {
d325cb7f 437 const Graphic3d_CStructure* aStruct = aStructIter.Value();
3fe9ce0e 438 if (aStruct->IsAlwaysRendered())
825aa485 439 {
150ed3d5 440 aStruct->MarkAsNotCulled();
441 myAlwaysRenderedMap.Add (aStruct);
3fe9ce0e 442 }
778cd667 443 else if (aStruct->TransformPersistence().IsNull())
3fe9ce0e 444 {
445 myBVHPrimitives.Add (aStruct);
446 }
447 else
448 {
449 myBVHPrimitivesTrsfPers.Add (aStruct);
825aa485 450 }
451 }
a1954302 452 }
3fe9ce0e 453}
454
9ad4ff93 455namespace
456{
457 //! This structure describes the node in BVH
458 struct NodeInStack
459 {
460 NodeInStack (Standard_Integer theId = 0,
461 Standard_Boolean theIsFullInside = false) : Id (theId), IsFullInside (theIsFullInside) {}
462
463 Standard_Integer Id; //!< node identifier
464 Standard_Boolean IsFullInside; //!< if the node is completely inside
465 };
466}
467
3fe9ce0e 468// =======================================================================
2b8832bb 469// function : UpdateCulling
3fe9ce0e 470// purpose :
471// =======================================================================
d325cb7f 472void Graphic3d_Layer::UpdateCulling (Standard_Integer theViewId,
473 const Graphic3d_CullingTool& theSelector,
474 const Graphic3d_RenderingParams::FrustumCulling theFrustumCullingState)
3fe9ce0e 475{
476 updateBVH();
a1954302 477
15669413 478 myNbStructuresNotCulled = myNbStructures;
0e3025bc 479 if (theFrustumCullingState != Graphic3d_RenderingParams::FrustumCulling_NoUpdate)
a1954302 480 {
d325cb7f 481 Standard_Boolean toTraverse = (theFrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On);
482 for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (myBVHPrimitives.Structures()); aStructIter.More(); aStructIter.Next())
0e3025bc 483 {
d325cb7f 484 const Graphic3d_CStructure* aStruct = aStructIter.Value();
0e3025bc 485 aStruct->SetCulled (toTraverse);
486 }
d325cb7f 487 for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (myBVHPrimitivesTrsfPers.Structures()); aStructIter.More(); aStructIter.Next())
0e3025bc 488 {
d325cb7f 489 const Graphic3d_CStructure* aStruct = aStructIter.Value();
0e3025bc 490 aStruct->SetCulled (toTraverse);
491 }
a1954302 492 }
a1954302 493
0e3025bc 494 if (theFrustumCullingState != Graphic3d_RenderingParams::FrustumCulling_On)
2b8832bb 495 {
496 return;
497 }
498 if (myBVHPrimitives .Size() == 0
499 && myBVHPrimitivesTrsfPers.Size() == 0)
500 {
501 return;
502 }
503
15669413 504 myNbStructuresNotCulled = myAlwaysRenderedMap.Extent();
d325cb7f 505 Graphic3d_CullingTool::CullingContext aCullCtx;
2b8832bb 506 theSelector.SetCullingDistance(aCullCtx, myLayerSettings.CullingDistance());
507 theSelector.SetCullingSize (aCullCtx, myLayerSettings.CullingSize());
825aa485 508 for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx)
a1954302 509 {
825aa485 510 const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1;
2b8832bb 511 opencascade::handle<BVH_Tree<Standard_Real, 3> > aBVHTree;
825aa485 512 if (isTrsfPers)
a1954302 513 {
825aa485 514 if (myBVHPrimitivesTrsfPers.Size() == 0)
825aa485 515 continue;
97f937cc 516
d325cb7f 517 const Graphic3d_Mat4d& aProjection = theSelector.ProjectionMatrix();
518 const Graphic3d_Mat4d& aWorldView = theSelector.WorldViewMatrix();
825aa485 519 const Graphic3d_WorldViewProjState& aWVPState = theSelector.WorldViewProjState();
91d96372 520 const Standard_Integer aViewportWidth = theSelector.ViewportWidth();
521 const Standard_Integer aViewportHeight = theSelector.ViewportHeight();
522
3fe9ce0e 523 aBVHTree = myBVHPrimitivesTrsfPers.BVH (theSelector.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState);
825aa485 524 }
525 else
526 {
527 if (myBVHPrimitives.Size() == 0)
825aa485 528 continue;
97f937cc 529
825aa485 530 aBVHTree = myBVHPrimitives.BVH();
531 }
532
9ad4ff93 533 const bool toCheckFullInside = true;
534 NodeInStack aNode (0, toCheckFullInside); // a root node
535 if (theSelector.IsCulled (aCullCtx, aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0), toCheckFullInside ? &aNode.IsFullInside : NULL))
825aa485 536 {
537 continue;
538 }
539
9ad4ff93 540 NodeInStack aStack[BVH_Constants_MaxTreeDepth];
825aa485 541 Standard_Integer aHead = -1;
542 for (;;)
543 {
9ad4ff93 544 if (!aBVHTree->IsOuter (aNode.Id))
a1954302 545 {
9ad4ff93 546 NodeInStack aLeft (aBVHTree->Child<0> (aNode.Id), toCheckFullInside);
547 NodeInStack aRight(aBVHTree->Child<1> (aNode.Id), toCheckFullInside);
548 bool isLeftChildIn = true, isRightChildIn = true;
549 if (aNode.IsFullInside)
550 {
551 // small size should be always checked
552 isLeftChildIn = !theSelector.IsTooSmall (aCullCtx, aBVHTree->MinPoint (aLeft.Id), aBVHTree->MaxPoint (aLeft.Id));
553 isRightChildIn = !theSelector.IsTooSmall (aCullCtx, aBVHTree->MinPoint (aRight.Id), aBVHTree->MaxPoint (aRight.Id));
554 }
555 else
556 {
557 isLeftChildIn = !theSelector.IsCulled (aCullCtx, aBVHTree->MinPoint (aLeft.Id), aBVHTree->MaxPoint (aLeft.Id), toCheckFullInside ? &aLeft.IsFullInside : NULL);
558 if (!isLeftChildIn)
559 {
560 aLeft.IsFullInside = false;
561 }
562
563 isRightChildIn = !theSelector.IsCulled (aCullCtx, aBVHTree->MinPoint (aRight.Id), aBVHTree->MaxPoint (aRight.Id), toCheckFullInside ? &aRight.IsFullInside : NULL);
564 if (!isRightChildIn)
565 {
566 aRight.IsFullInside = false;
567 }
568 }
569
825aa485 570 if (isLeftChildIn
571 && isRightChildIn)
572 {
9ad4ff93 573 aNode = myBVHIsLeftChildQueuedFirst ? aLeft : aRight;
574 aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRight : aLeft;
825aa485 575 myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst;
576 }
577 else if (isLeftChildIn
578 || isRightChildIn)
579 {
9ad4ff93 580 aNode = isLeftChildIn ? aLeft : aRight;
825aa485 581 }
582 else
583 {
584 if (aHead < 0)
585 {
586 break;
587 }
588
589 aNode = aStack[aHead--];
590 }
a1954302 591 }
592 else
593 {
9ad4ff93 594 const Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode.Id);
595 const Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode.Id);
a2803f37 596 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
5dc0517d 597 {
a2803f37 598 const Graphic3d_CStructure* aStruct = isTrsfPers
599 ? myBVHPrimitivesTrsfPers.GetStructureById (anIdx)
600 : myBVHPrimitives.GetStructureById (anIdx);
601 if (aStruct->IsVisible (theViewId))
602 {
603 aStruct->MarkAsNotCulled();
604 ++myNbStructuresNotCulled;
605 }
5dc0517d 606 }
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// =======================================================================
d325cb7f 622Standard_Boolean Graphic3d_Layer::Append (const Graphic3d_Layer& theOther)
a1954302 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 {
d325cb7f 634 const Graphic3d_IndexedMapOfStructure& aStructures = theOther.myArray (aPriorityIter);
635 for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
a1954302 636 {
7c3ef2f7 637 Add (aStructIter.Value(), aPriorityIter);
a1954302 638 }
639 }
640
641 return Standard_True;
642}
643
c5751993 644//=======================================================================
7c3ef2f7 645//function : SetLayerSettings
646//purpose :
647//=======================================================================
d325cb7f 648void Graphic3d_Layer::SetLayerSettings (const Graphic3d_ZLayerSettings& theSettings)
7c3ef2f7 649{
650 const Standard_Boolean toUpdateTrsf = !myLayerSettings.Origin().IsEqual (theSettings.Origin(), gp::Resolution());
651 myLayerSettings = theSettings;
d325cb7f 652 if (!toUpdateTrsf)
7c3ef2f7 653 {
d325cb7f 654 return;
7c3ef2f7 655 }
656
d325cb7f 657 for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next())
83da37b1 658 {
d325cb7f 659 Graphic3d_IndexedMapOfStructure& aStructures = aMapIter.ChangeValue();
660 for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
661 {
662 Graphic3d_CStructure* aStructure = const_cast<Graphic3d_CStructure* >(aStructIter.Value());
663 aStructure->updateLayerTransformation();
664 }
83da37b1 665 }
c5751993 666}
bc73b006 667
668// =======================================================================
669// function : DumpJson
670// purpose :
671// =======================================================================
672void Graphic3d_Layer::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
673{
674 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
675
676 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, this)
677 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLayerId)
678 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myNbStructures)
679 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myNbStructuresNotCulled)
680
681 const Standard_Integer aNbPriorities = myArray.Length();
682 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
683 {
684 const Graphic3d_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
685 for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
686 {
687 const Graphic3d_CStructure* aStructure = aStructIter.Value();
688 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, aStructure)
689 }
690 }
691
692 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myLayerSettings)
693
694 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myBVHIsLeftChildQueuedFirst)
695 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsBVHPrimitivesNeedsReset)
696 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsBoundingBoxNeedsReset[0])
697 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsBoundingBoxNeedsReset[1])
698
699 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myBoundingBox[0])
700 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myBoundingBox[1])
701}