0028466: Visualization, OpenGl_Context - read GPU memory using WGL_AMD_gpu_associatio...
[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>
7c3ef2f7 20#include <OpenGl_ShaderManager.hxx>
a1954302 21#include <OpenGl_View.hxx>
550f3b8b 22#include <OpenGl_Workspace.hxx>
c04c30b3 23#include <Graphic3d_GraphicDriver.hxx>
c5751993 24
a1954302 25// =======================================================================
825aa485 26// function : OpenGl_Layer
a1954302 27// purpose :
28// =======================================================================
c5751993 29OpenGl_Layer::OpenGl_Layer (const Standard_Integer theNbPriorities)
50d06d8f 30: myArray (0, theNbPriorities - 1),
31 myNbStructures (0),
a1954302 32 myBVHIsLeftChildQueuedFirst (Standard_True),
33 myIsBVHPrimitivesNeedsReset (Standard_False)
c5751993 34{
50d06d8f 35 myIsBoundingBoxNeedsReset[0] = myIsBoundingBoxNeedsReset[1] = true;
c5751993 36}
37
a1954302 38// =======================================================================
39// function : ~OpenGl_Layer
40// purpose :
41// =======================================================================
42OpenGl_Layer::~OpenGl_Layer()
43{
44 //
45}
46
47// =======================================================================
48// function : Add
49// purpose :
50// =======================================================================
51void OpenGl_Layer::Add (const OpenGl_Structure* theStruct,
52 const Standard_Integer thePriority,
53 Standard_Boolean isForChangePriority)
54{
55 const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1);
56 if (theStruct == NULL)
57 {
58 return;
59 }
60
9f112210 61 myArray (anIndex).Add (theStruct);
a1954302 62 if (theStruct->IsAlwaysRendered())
63 {
64 theStruct->MarkAsNotCulled();
3fe9ce0e 65 if (!isForChangePriority)
66 {
67 myAlwaysRenderedMap.Add (theStruct);
68 }
a1954302 69 }
70 else if (!isForChangePriority)
71 {
778cd667 72 if (theStruct->TransformPersistence().IsNull())
825aa485 73 {
74 myBVHPrimitives.Add (theStruct);
75 }
76 else
77 {
78 myBVHPrimitivesTrsfPers.Add (theStruct);
79 }
a1954302 80 }
81 ++myNbStructures;
82}
83
84// =======================================================================
85// function : Remove
86// purpose :
87// =======================================================================
88bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct,
89 Standard_Integer& thePriority,
90 Standard_Boolean isForChangePriority)
91{
92 if (theStruct == NULL)
93 {
94 thePriority = -1;
95 return false;
96 }
97
98 const Standard_Integer aNbPriorities = myArray.Length();
99 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
100 {
9f112210 101 OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
102
103 const Standard_Integer anIndex = aStructures.FindIndex (theStruct);
104 if (anIndex != 0)
a1954302 105 {
9f112210 106 aStructures.Swap (anIndex, aStructures.Size());
107 aStructures.RemoveLast();
108
3fe9ce0e 109 if (!isForChangePriority)
a1954302 110 {
ef9a9362 111 Standard_Boolean isAlwaysRend = theStruct->IsAlwaysRendered();
112 if (!isAlwaysRend)
825aa485 113 {
ef9a9362 114 if (!myBVHPrimitives.Remove (theStruct))
3fe9ce0e 115 {
ef9a9362 116 if (!myBVHPrimitivesTrsfPers.Remove (theStruct))
117 {
118 isAlwaysRend = Standard_True;
119 }
3fe9ce0e 120 }
121 }
ef9a9362 122 if (isAlwaysRend)
3fe9ce0e 123 {
ef9a9362 124 const Standard_Integer anIndex2 = myAlwaysRenderedMap.FindIndex (theStruct);
125 if (anIndex2 != 0)
3fe9ce0e 126 {
ef9a9362 127 myAlwaysRenderedMap.Swap (myAlwaysRenderedMap.Size(), anIndex2);
128 myAlwaysRenderedMap.RemoveLast();
3fe9ce0e 129 }
825aa485 130 }
a1954302 131 }
9f112210 132 --myNbStructures;
133 thePriority = aPriorityIter;
134 return true;
a1954302 135 }
136 }
137
138 thePriority = -1;
139 return false;
140}
141
142// =======================================================================
143// function : InvalidateBVHData
144// purpose :
145// =======================================================================
50d06d8f 146void OpenGl_Layer::InvalidateBVHData() const
a1954302 147{
148 myIsBVHPrimitivesNeedsReset = Standard_True;
149}
150
3fe9ce0e 151//! Calculate a finite bounding box of infinite object as its middle point.
7c3ef2f7 152inline Graphic3d_BndBox3d centerOfinfiniteBndBox (const Graphic3d_BndBox3d& theBndBox)
3fe9ce0e 153{
154 // bounding borders of infinite line has been calculated as own point in center of this line
7c3ef2f7 155 const Graphic3d_Vec3d aDiagVec = theBndBox.CornerMax() - theBndBox.CornerMin();
156 return aDiagVec.SquareModulus() >= 500000.0 * 500000.0
157 ? Graphic3d_BndBox3d ((theBndBox.CornerMin() + theBndBox.CornerMax()) * 0.5)
158 : Graphic3d_BndBox3d();
3fe9ce0e 159}
160
161//! Return true if at least one vertex coordinate out of float range.
7c3ef2f7 162inline bool isInfiniteBndBox (const Graphic3d_BndBox3d& theBndBox)
3fe9ce0e 163{
164 return Abs (theBndBox.CornerMax().x()) >= ShortRealLast()
165 || Abs (theBndBox.CornerMax().y()) >= ShortRealLast()
166 || Abs (theBndBox.CornerMax().z()) >= ShortRealLast()
167 || Abs (theBndBox.CornerMin().x()) >= ShortRealLast()
168 || Abs (theBndBox.CornerMin().y()) >= ShortRealLast()
169 || Abs (theBndBox.CornerMin().z()) >= ShortRealLast();
170}
171
a1954302 172// =======================================================================
50d06d8f 173// function : BoundingBox
174// purpose :
175// =======================================================================
7c3ef2f7 176Bnd_Box OpenGl_Layer::BoundingBox (const Standard_Integer theViewId,
177 const Handle(Graphic3d_Camera)& theCamera,
178 const Standard_Integer theWindowWidth,
179 const Standard_Integer theWindowHeight,
180 const Standard_Boolean theToIncludeAuxiliary) const
50d06d8f 181{
150ed3d5 182 updateBVH();
183
3fe9ce0e 184 const Standard_Integer aBoxId = !theToIncludeAuxiliary ? 0 : 1;
7c3ef2f7 185 const Graphic3d_Mat4d& aProjectionMat = theCamera->ProjectionMatrix();
186 const Graphic3d_Mat4d& aWorldViewMat = theCamera->OrientationMatrix();
50d06d8f 187 if (myIsBoundingBoxNeedsReset[aBoxId])
188 {
189 // Recompute layer bounding box
7c3ef2f7 190 myBoundingBox[aBoxId].SetVoid();
50d06d8f 191
7c3ef2f7 192 for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next())
50d06d8f 193 {
7c3ef2f7 194 const OpenGl_IndexedMapOfStructure& aStructures = aMapIter.Value();
195 for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
50d06d8f 196 {
7c3ef2f7 197 const OpenGl_Structure* aStructure = aStructIter.Value();
3fe9ce0e 198 if (!aStructure->IsVisible (theViewId))
50d06d8f 199 {
200 continue;
201 }
202
203 // "FitAll" operation ignores object with transform persistence parameter
204 // but adds transform persistence point in a bounding box of layer (only zoom pers. objects).
778cd667 205 if (!aStructure->TransformPersistence().IsNull())
50d06d8f 206 {
3fe9ce0e 207 if (!theToIncludeAuxiliary
778cd667 208 && aStructure->TransformPersistence()->IsZoomOrRotate())
50d06d8f 209 {
778cd667 210 const gp_Pnt anAnchor = aStructure->TransformPersistence()->AnchorPoint();
7c3ef2f7 211 myBoundingBox[aBoxId].Add (anAnchor);
50d06d8f 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
778cd667 217 || aStructure->TransformPersistence()->IsTrihedronOr2d())
50d06d8f 218 {
219 continue;
220 }
221 }
222
7c3ef2f7 223 Graphic3d_BndBox3d 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
778cd667 236 if (!aStructure->TransformPersistence().IsNull())
50d06d8f 237 {
778cd667 238 aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox);
50d06d8f 239 }
240
3fe9ce0e 241 // skip too big boxes to prevent float overflow at camera parameters calculation
7c3ef2f7 242 if (aBox.IsValid()
243 && !isInfiniteBndBox (aBox))
50d06d8f 244 {
7c3ef2f7 245 myBoundingBox[aBoxId].Add (gp_Pnt (aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z()));
246 myBoundingBox[aBoxId].Add (gp_Pnt (aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z()));
50d06d8f 247 }
50d06d8f 248 }
249 }
250
251 myIsBoundingBoxNeedsReset[aBoxId] = false;
252 }
253
7c3ef2f7 254 Bnd_Box aResBox = myBoundingBox[aBoxId];
3fe9ce0e 255 if (!theToIncludeAuxiliary
256 || myAlwaysRenderedMap.IsEmpty())
257 {
7c3ef2f7 258 return aResBox;
3fe9ce0e 259 }
260
261 // add transformation-persistent objects which depend on camera position (and thus can not be cached) for operations like Z-fit
3fe9ce0e 262 for (NCollection_IndexedMap<const OpenGl_Structure*>::Iterator aStructIter (myAlwaysRenderedMap); aStructIter.More(); aStructIter.Next())
263 {
264 const OpenGl_Structure* aStructure = aStructIter.Value();
265 if (!aStructure->IsVisible (theViewId))
266 {
267 continue;
268 }
778cd667 269 else if (aStructure->TransformPersistence().IsNull()
270 || !aStructure->TransformPersistence()->IsTrihedronOr2d())
3fe9ce0e 271 {
272 continue;
273 }
274
7c3ef2f7 275 Graphic3d_BndBox3d aBox = aStructure->BoundingBox();
3fe9ce0e 276 if (!aBox.IsValid())
277 {
278 continue;
279 }
280
778cd667 281 aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox);
7c3ef2f7 282 if (aBox.IsValid()
283 && !isInfiniteBndBox (aBox))
3fe9ce0e 284 {
7c3ef2f7 285 aResBox.Add (gp_Pnt (aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z()));
286 aResBox.Add (gp_Pnt (aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z()));
3fe9ce0e 287 }
288 }
289
290 return aResBox;
50d06d8f 291}
292
293// =======================================================================
294// function : considerZoomPersistenceObjects
295// purpose :
296// =======================================================================
297Standard_Real OpenGl_Layer::considerZoomPersistenceObjects (const Standard_Integer theViewId,
298 const Handle(Graphic3d_Camera)& theCamera,
299 Standard_Integer theWindowWidth,
3fe9ce0e 300 Standard_Integer theWindowHeight) const
50d06d8f 301{
302 if (NbOfTransformPersistenceObjects() == 0)
303 {
304 return 1.0;
305 }
306
7c3ef2f7 307 const Graphic3d_Mat4d& aProjectionMat = theCamera->ProjectionMatrix();
308 const Graphic3d_Mat4d& aWorldViewMat = theCamera->OrientationMatrix();
50d06d8f 309 Standard_Real aMaxCoef = -std::numeric_limits<double>::max();
310
7c3ef2f7 311 for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next())
50d06d8f 312 {
7c3ef2f7 313 const OpenGl_IndexedMapOfStructure& aStructures = aMapIter.Value();
314 for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
50d06d8f 315 {
7c3ef2f7 316 const OpenGl_Structure* aStructure = aStructIter.Value();
3fe9ce0e 317 if (!aStructure->IsVisible (theViewId)
778cd667 318 || aStructure->TransformPersistence().IsNull()
319 || !aStructure->TransformPersistence()->IsZoomOrRotate())
50d06d8f 320 {
321 continue;
322 }
323
7c3ef2f7 324 Graphic3d_BndBox3d aBox = aStructure->BoundingBox();
3fe9ce0e 325 if (!aBox.IsValid())
50d06d8f 326 {
327 continue;
328 }
329
778cd667 330 aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox);
50d06d8f 331
7c3ef2f7 332 const BVH_Vec3d& aCornerMin = aBox.CornerMin();
333 const BVH_Vec3d& aCornerMax = aBox.CornerMax();
50d06d8f 334 const Standard_Integer aNbOfPoints = 8;
335 const gp_Pnt aPoints[aNbOfPoints] = { gp_Pnt (aCornerMin.x(), aCornerMin.y(), aCornerMin.z()),
336 gp_Pnt (aCornerMin.x(), aCornerMin.y(), aCornerMax.z()),
337 gp_Pnt (aCornerMin.x(), aCornerMax.y(), aCornerMin.z()),
338 gp_Pnt (aCornerMin.x(), aCornerMax.y(), aCornerMax.z()),
339 gp_Pnt (aCornerMax.x(), aCornerMin.y(), aCornerMin.z()),
340 gp_Pnt (aCornerMax.x(), aCornerMin.y(), aCornerMax.z()),
341 gp_Pnt (aCornerMax.x(), aCornerMax.y(), aCornerMin.z()),
342 gp_Pnt (aCornerMax.x(), aCornerMax.y(), aCornerMax.z()) };
343 gp_Pnt aConvertedPoints[aNbOfPoints];
344 Standard_Real aConvertedMinX = std::numeric_limits<double>::max();
345 Standard_Real aConvertedMaxX = -std::numeric_limits<double>::max();
346 Standard_Real aConvertedMinY = std::numeric_limits<double>::max();
347 Standard_Real aConvertedMaxY = -std::numeric_limits<double>::max();
348 for (Standard_Integer anIdx = 0; anIdx < aNbOfPoints; ++anIdx)
349 {
350 aConvertedPoints[anIdx] = theCamera->Project (aPoints[anIdx]);
351
352 aConvertedMinX = Min (aConvertedMinX, aConvertedPoints[anIdx].X());
353 aConvertedMaxX = Max (aConvertedMaxX, aConvertedPoints[anIdx].X());
354
355 aConvertedMinY = Min (aConvertedMinY, aConvertedPoints[anIdx].Y());
356 aConvertedMaxY = Max (aConvertedMaxY, aConvertedPoints[anIdx].Y());
357 }
358
359 const Standard_Boolean isBigObject = (Abs (aConvertedMaxX - aConvertedMinX) > 2.0) // width of zoom pers. object greater than width of window
360 || (Abs (aConvertedMaxY - aConvertedMinY) > 2.0); // height of zoom pers. object greater than height of window
361 const Standard_Boolean isAlreadyInScreen = (aConvertedMinX > -1.0 && aConvertedMinX < 1.0)
362 && (aConvertedMaxX > -1.0 && aConvertedMaxX < 1.0)
363 && (aConvertedMinY > -1.0 && aConvertedMinY < 1.0)
364 && (aConvertedMaxY > -1.0 && aConvertedMaxY < 1.0);
365 if (isBigObject || isAlreadyInScreen)
366 {
367 continue;
368 }
369
778cd667 370 const gp_Pnt aTPPoint = aStructure->TransformPersistence()->AnchorPoint();
50d06d8f 371 gp_Pnt aConvertedTPPoint = theCamera->Project (aTPPoint);
372 aConvertedTPPoint.SetZ (0.0);
373
374 if (aConvertedTPPoint.Coord().Modulus() < Precision::Confusion())
375 {
376 continue;
377 }
378
379 Standard_Real aShiftX = 0.0;
380 if (aConvertedMinX < -1.0)
381 {
382 aShiftX = ((aConvertedMaxX < -1.0) ? (-(1.0 + aConvertedMaxX) + (aConvertedMaxX - aConvertedMinX)) : -(1.0 + aConvertedMinX));
383 }
384 else if (aConvertedMaxX > 1.0)
385 {
386 aShiftX = ((aConvertedMinX > 1.0) ? ((aConvertedMinX - 1.0) + (aConvertedMaxX - aConvertedMinX)) : (aConvertedMaxX - 1.0));
387 }
388
389 Standard_Real aShiftY = 0.0;
390 if (aConvertedMinY < -1.0)
391 {
392 aShiftY = ((aConvertedMaxY < -1.0) ? (-(1.0 + aConvertedMaxY) + (aConvertedMaxY - aConvertedMinY)) : -(1.0 + aConvertedMinY));
393 }
394 else if (aConvertedMaxY > 1.0)
395 {
396 aShiftY = ((aConvertedMinY > 1.0) ? ((aConvertedMinY - 1.0) + (aConvertedMaxY - aConvertedMinY)) : (aConvertedMaxY - 1.0));
397 }
398
399 const Standard_Real aDifX = Abs (aConvertedTPPoint.X()) - aShiftX;
400 const Standard_Real aDifY = Abs (aConvertedTPPoint.Y()) - aShiftY;
401 if (aDifX > Precision::Confusion())
402 {
403 aMaxCoef = Max (aMaxCoef, Abs (aConvertedTPPoint.X()) / aDifX);
404 }
405 if (aDifY > Precision::Confusion())
406 {
407 aMaxCoef = Max (aMaxCoef, Abs (aConvertedTPPoint.Y()) / aDifY);
408 }
409 }
410 }
411
412 return (aMaxCoef > 0.0) ? aMaxCoef : 1.0;
413}
414
415// =======================================================================
a1954302 416// function : renderAll
417// purpose :
418// =======================================================================
419void OpenGl_Layer::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const
420{
7c3ef2f7 421 const Standard_Integer aViewId = theWorkspace->View()->Identification();
422 for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next())
a1954302 423 {
7c3ef2f7 424 const OpenGl_IndexedMapOfStructure& aStructures = aMapIter.Value();
425 for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
a1954302 426 {
7c3ef2f7 427 const OpenGl_Structure* aStruct = aStructIter.Value();
a1954302 428 if (!aStruct->IsVisible())
429 {
430 continue;
431 }
a272ed94 432 else if (!aStruct->ViewAffinity.IsNull()
433 && !aStruct->ViewAffinity->IsVisible (aViewId))
434 {
435 continue;
436 }
a1954302 437
438 aStruct->Render (theWorkspace);
439 }
440 }
441}
442
443// =======================================================================
3fe9ce0e 444// function : updateBVH
a1954302 445// purpose :
446// =======================================================================
3fe9ce0e 447void OpenGl_Layer::updateBVH() const
a1954302 448{
3fe9ce0e 449 if (!myIsBVHPrimitivesNeedsReset)
450 {
451 return;
452 }
453
454 myBVHPrimitives.Clear();
455 myBVHPrimitivesTrsfPers.Clear();
150ed3d5 456 myAlwaysRenderedMap.Clear();
3fe9ce0e 457 myIsBVHPrimitivesNeedsReset = Standard_False;
7c3ef2f7 458 for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next())
a1954302 459 {
7c3ef2f7 460 const OpenGl_IndexedMapOfStructure& aStructures = aMapIter.Value();
461 for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
825aa485 462 {
3fe9ce0e 463 const OpenGl_Structure* aStruct = aStructIter.Value();
464 if (aStruct->IsAlwaysRendered())
825aa485 465 {
150ed3d5 466 aStruct->MarkAsNotCulled();
467 myAlwaysRenderedMap.Add (aStruct);
3fe9ce0e 468 }
778cd667 469 else if (aStruct->TransformPersistence().IsNull())
3fe9ce0e 470 {
471 myBVHPrimitives.Add (aStruct);
472 }
473 else
474 {
475 myBVHPrimitivesTrsfPers.Add (aStruct);
825aa485 476 }
477 }
a1954302 478 }
3fe9ce0e 479}
480
481// =======================================================================
482// function : renderTraverse
483// purpose :
484// =======================================================================
485void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const
486{
487 updateBVH();
a1954302 488
c357e426 489 OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector();
a1954302 490 traverse (aSelector);
491
7c3ef2f7 492 const Standard_Integer aViewId = theWorkspace->View()->Identification();
493 for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next())
a1954302 494 {
7c3ef2f7 495 const OpenGl_IndexedMapOfStructure& aStructures = aMapIter.Value();
496 for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
a1954302 497 {
7c3ef2f7 498 const OpenGl_Structure* aStruct = aStructIter.Value();
3fe9ce0e 499 if (aStruct->IsCulled()
500 || !aStruct->IsVisible (aViewId))
a272ed94 501 {
502 continue;
503 }
a1954302 504
505 aStruct->Render (theWorkspace);
506 aStruct->ResetCullingStatus();
507 }
508 }
509}
510
511// =======================================================================
512// function : traverse
513// purpose :
514// =======================================================================
515void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const
516{
517 // handle a case when all objects are infinite
97f937cc 518 if (myBVHPrimitives .Size() == 0
519 && myBVHPrimitivesTrsfPers.Size() == 0)
a1954302 520 return;
521
a1954302 522 theSelector.CacheClipPtsProjections();
a1954302 523
7c3ef2f7 524 NCollection_Handle<BVH_Tree<Standard_Real, 3> > aBVHTree;
825aa485 525
526 for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx)
a1954302 527 {
825aa485 528 const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1;
529 if (isTrsfPers)
a1954302 530 {
825aa485 531 if (myBVHPrimitivesTrsfPers.Size() == 0)
825aa485 532 continue;
97f937cc 533
7c3ef2f7 534 const OpenGl_Mat4d& aProjection = theSelector.ProjectionMatrix();
535 const OpenGl_Mat4d& aWorldView = theSelector.WorldViewMatrix();
825aa485 536 const Graphic3d_WorldViewProjState& aWVPState = theSelector.WorldViewProjState();
91d96372 537 const Standard_Integer aViewportWidth = theSelector.ViewportWidth();
538 const Standard_Integer aViewportHeight = theSelector.ViewportHeight();
539
3fe9ce0e 540 aBVHTree = myBVHPrimitivesTrsfPers.BVH (theSelector.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState);
825aa485 541 }
542 else
543 {
544 if (myBVHPrimitives.Size() == 0)
825aa485 545 continue;
97f937cc 546
825aa485 547 aBVHTree = myBVHPrimitives.BVH();
548 }
549
550 Standard_Integer aNode = 0; // a root node
551
552 if (!theSelector.Intersect (aBVHTree->MinPoint (0),
553 aBVHTree->MaxPoint (0)))
554 {
555 continue;
556 }
557
558 Standard_Integer aStack[32];
559 Standard_Integer aHead = -1;
560 for (;;)
561 {
562 if (!aBVHTree->IsOuter (aNode))
a1954302 563 {
f2474958 564 const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode);
565 const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
825aa485 566 const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx),
567 aBVHTree->MaxPoint (aLeftChildIdx));
568 const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx),
569 aBVHTree->MaxPoint (aRightChildIdx));
570 if (isLeftChildIn
571 && isRightChildIn)
572 {
573 aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx;
574 aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx;
575 myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst;
576 }
577 else if (isLeftChildIn
578 || isRightChildIn)
579 {
580 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
581 }
582 else
583 {
584 if (aHead < 0)
585 {
586 break;
587 }
588
589 aNode = aStack[aHead--];
590 }
a1954302 591 }
592 else
593 {
825aa485 594 Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode);
595 const OpenGl_Structure* aStruct =
596 isTrsfPers ? myBVHPrimitivesTrsfPers.GetStructureById (aIdx)
597 : myBVHPrimitives.GetStructureById (aIdx);
598 aStruct->MarkAsNotCulled();
a1954302 599 if (aHead < 0)
600 {
825aa485 601 break;
a1954302 602 }
603
14a35e5d 604 aNode = aStack[aHead--];
a1954302 605 }
606 }
a1954302 607 }
608}
609
610// =======================================================================
611// function : Append
612// purpose :
613// =======================================================================
614Standard_Boolean OpenGl_Layer::Append (const OpenGl_Layer& theOther)
615{
616 // the source priority list shouldn't have more priorities
617 const Standard_Integer aNbPriorities = theOther.NbPriorities();
618 if (aNbPriorities > NbPriorities())
619 {
620 return Standard_False;
621 }
622
623 // add all structures to destination priority list
624 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
625 {
9f112210 626 const OpenGl_IndexedMapOfStructure& aStructures = theOther.myArray (aPriorityIter);
7c3ef2f7 627 for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
a1954302 628 {
7c3ef2f7 629 Add (aStructIter.Value(), aPriorityIter);
a1954302 630 }
631 }
632
633 return Standard_True;
634}
635
7c3ef2f7 636//=======================================================================
637//function : SetLayerSettings
638//purpose :
639//=======================================================================
640void OpenGl_Layer::SetLayerSettings (const Graphic3d_ZLayerSettings& theSettings)
641{
642 const Standard_Boolean toUpdateTrsf = !myLayerSettings.Origin().IsEqual (theSettings.Origin(), gp::Resolution());
643 myLayerSettings = theSettings;
644 if (toUpdateTrsf)
645 {
646 for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next())
647 {
648 OpenGl_IndexedMapOfStructure& aStructures = aMapIter.ChangeValue();
649 for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
650 {
651 OpenGl_Structure* aStructure = const_cast<OpenGl_Structure*> (aStructIter.Value());
652 aStructure->updateLayerTransformation();
653 }
654 }
655 }
656}
657
c5751993 658//=======================================================================
659//function : Render
a1954302 660//purpose :
c5751993 661//=======================================================================
a1954302 662void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace,
663 const OpenGl_GlobalLayerSettings& theDefaultSettings) const
c5751993 664{
7c3ef2f7 665 const Graphic3d_PolygonOffset anAppliedOffsetParams = theWorkspace->AppliedPolygonOffset();
b3eab8ef 666 // myLayerSettings.ToClearDepth() is handled outside
eae454e3 667
c5751993 668 // handle depth test
7c3ef2f7 669 if (myLayerSettings.ToEnableDepthTest())
c5751993 670 {
550f3b8b 671 // assuming depth test is enabled by default
672 glDepthFunc (theDefaultSettings.DepthFunc);
c5751993 673 }
674 else
675 {
676 glDepthFunc (GL_ALWAYS);
677 }
eae454e3 678
83da37b1 679 // save environment texture
680 Handle(OpenGl_Texture) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
7c3ef2f7 681 if (!myLayerSettings.UseEnvironmentTexture())
83da37b1 682 {
683 theWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
684 }
685
c5751993 686 // handle depth offset
7c3ef2f7 687 theWorkspace->SetPolygonOffset (myLayerSettings.PolygonOffset());
c5751993 688
689 // handle depth write
7c3ef2f7 690 theWorkspace->UseDepthWrite() = myLayerSettings.ToEnableDepthWrite();
eae454e3 691 glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE);
c5751993 692
7c3ef2f7 693 const Standard_Boolean hasLocalCS = !myLayerSettings.OriginTransformation().IsNull();
694 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
695 const Handle(Graphic3d_Camera)& aWorldCamera = theWorkspace->View()->Camera();
696 Handle(Graphic3d_Camera) aCameraBack;
697 if (hasLocalCS)
698 {
699 // Apply local camera transformation.
700 // The vertex position is computed by the following formula in GLSL program:
701 // gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;
702 // where:
703 // occProjectionMatrix - matrix defining orthographic/perspective/stereographic projection
704 // occWorldViewMatrix - world-view matrix defining Camera position and orientation
705 // occModelWorldMatrix - model-world matrix defining Object transformation from local coordinate system to the world coordinate system
706 // occVertex - input vertex position
707 //
708 // Since double precision is quite expensive on modern GPUs, and not available on old hardware,
709 // all these values are passed with single float precision to the shader.
710 // As result, single precision become insufficient for handling objects far from the world origin.
711 //
712 // Several approaches can be used to solve precision issues:
713 // - [Broute force] migrate to double precision for all matrices and vertex position.
714 // This is too expensive for most hardware.
715 // - Store only translation part with double precision and pass it to GLSL program.
716 // This requires modified GLSL programs for computing transformation
717 // and extra packing mechanism for hardware not supporting double precision natively.
718 // This solution is less expensive then previous one.
719 // - Move translation part of occModelWorldMatrix into occWorldViewMatrix.
720 // The main idea here is that while moving Camera towards the object,
721 // Camera translation part and Object translation part will compensate each other
722 // to fit into single float precision.
723 // But this operation should be performed with double precision - this is why we are moving
724 // translation part of occModelWorldMatrix to occWorldViewMatrix.
725 //
726 // All approaches might be useful in different scenarios, but for the moment we consider the last one as main scenario.
727 // Here we do the trick:
728 // - OpenGl_Layer defines the Local Origin, which is expected to be the center of objects stored within it.
729 // This Local Origin is included into occWorldViewMatrix during rendering.
730 // - OpenGl_Structure defines Object local transformation occModelWorldMatrix with subtracted Local Origin of the Layer.
731 // This means that Object itself should be defined within either Local Transformation equal or near to Local Origin of the Layer.
732 theWorkspace->View()->SetLocalOrigin (myLayerSettings.Origin());
733
734 NCollection_Mat4<Standard_Real> aWorldView = aWorldCamera->OrientationMatrix();
735 Graphic3d_TransformUtils::Translate (aWorldView, myLayerSettings.Origin().X(), myLayerSettings.Origin().Y(), myLayerSettings.Origin().Z());
736
737 NCollection_Mat4<Standard_ShortReal> aWorldViewF;
738 aWorldViewF.ConvertFrom (aWorldView);
739 aCtx->WorldViewState.SetCurrent (aWorldViewF);
740 aCtx->ShaderManager()->UpdateClippingState();
741 aCtx->ShaderManager()->UpdateLightSourceState();
742 }
743
c5751993 744 // render priority list
a1954302 745 theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace);
550f3b8b 746
7c3ef2f7 747 if (hasLocalCS)
748 {
749 aCtx->ShaderManager()->RevertClippingState();
750 aCtx->ShaderManager()->UpdateLightSourceState();
751
752 aCtx->WorldViewState.SetCurrent (aWorldCamera->OrientationMatrixF());
753 theWorkspace->View() ->SetLocalOrigin (gp_XYZ (0.0, 0.0, 0.0));
754 }
755
550f3b8b 756 // always restore polygon offset between layers rendering
b6472664 757 theWorkspace->SetPolygonOffset (anAppliedOffsetParams);
83da37b1 758
759 // restore environment texture
7c3ef2f7 760 if (!myLayerSettings.UseEnvironmentTexture())
83da37b1 761 {
762 theWorkspace->SetEnvironmentTexture (anEnvironmentTexture);
763 }
c5751993 764}