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