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