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