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 |
28 | OpenGl_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 | // ======================================================================= |
41 | OpenGl_Layer::~OpenGl_Layer() |
42 | { |
43 | // |
44 | } |
45 | |
46 | // ======================================================================= |
47 | // function : Add |
48 | // purpose : |
49 | // ======================================================================= |
50 | void 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 | // ======================================================================= |
83 | bool 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 |
126 | void OpenGl_Layer::InvalidateBVHData() const |
a1954302 |
127 | { |
128 | myIsBVHPrimitivesNeedsReset = Standard_True; |
129 | } |
130 | |
131 | // ======================================================================= |
50d06d8f |
132 | // function : BoundingBox |
133 | // purpose : |
134 | // ======================================================================= |
135 | const 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 | // ======================================================================= |
252 | Standard_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 | // ======================================================================= |
381 | void 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 | // ======================================================================= |
410 | void 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 | // ======================================================================= |
470 | void 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(); |
492 | aBVHTree = myBVHPrimitivesTrsfPers.BVH (aProjection, aWorldView, aWVPState); |
493 | } |
494 | else |
495 | { |
496 | if (myBVHPrimitives.Size() == 0) |
825aa485 |
497 | continue; |
97f937cc |
498 | |
825aa485 |
499 | aBVHTree = myBVHPrimitives.BVH(); |
500 | } |
501 | |
502 | Standard_Integer aNode = 0; // a root node |
503 | |
504 | if (!theSelector.Intersect (aBVHTree->MinPoint (0), |
505 | aBVHTree->MaxPoint (0))) |
506 | { |
507 | continue; |
508 | } |
509 | |
510 | Standard_Integer aStack[32]; |
511 | Standard_Integer aHead = -1; |
512 | for (;;) |
513 | { |
514 | if (!aBVHTree->IsOuter (aNode)) |
a1954302 |
515 | { |
825aa485 |
516 | const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode); |
517 | const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode); |
518 | const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx), |
519 | aBVHTree->MaxPoint (aLeftChildIdx)); |
520 | const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx), |
521 | aBVHTree->MaxPoint (aRightChildIdx)); |
522 | if (isLeftChildIn |
523 | && isRightChildIn) |
524 | { |
525 | aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx; |
526 | aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx; |
527 | myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst; |
528 | } |
529 | else if (isLeftChildIn |
530 | || isRightChildIn) |
531 | { |
532 | aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx; |
533 | } |
534 | else |
535 | { |
536 | if (aHead < 0) |
537 | { |
538 | break; |
539 | } |
540 | |
541 | aNode = aStack[aHead--]; |
542 | } |
a1954302 |
543 | } |
544 | else |
545 | { |
825aa485 |
546 | Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode); |
547 | const OpenGl_Structure* aStruct = |
548 | isTrsfPers ? myBVHPrimitivesTrsfPers.GetStructureById (aIdx) |
549 | : myBVHPrimitives.GetStructureById (aIdx); |
550 | aStruct->MarkAsNotCulled(); |
a1954302 |
551 | if (aHead < 0) |
552 | { |
825aa485 |
553 | break; |
a1954302 |
554 | } |
555 | |
14a35e5d |
556 | aNode = aStack[aHead--]; |
a1954302 |
557 | } |
558 | } |
a1954302 |
559 | } |
560 | } |
561 | |
562 | // ======================================================================= |
563 | // function : Append |
564 | // purpose : |
565 | // ======================================================================= |
566 | Standard_Boolean OpenGl_Layer::Append (const OpenGl_Layer& theOther) |
567 | { |
568 | // the source priority list shouldn't have more priorities |
569 | const Standard_Integer aNbPriorities = theOther.NbPriorities(); |
570 | if (aNbPriorities > NbPriorities()) |
571 | { |
572 | return Standard_False; |
573 | } |
574 | |
575 | // add all structures to destination priority list |
576 | for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) |
577 | { |
9f112210 |
578 | const OpenGl_IndexedMapOfStructure& aStructures = theOther.myArray (aPriorityIter); |
579 | for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx) |
a1954302 |
580 | { |
9f112210 |
581 | Add (aStructures.FindKey (aStructIdx), aPriorityIter); |
a1954302 |
582 | } |
583 | } |
584 | |
585 | return Standard_True; |
586 | } |
587 | |
c5751993 |
588 | //======================================================================= |
589 | //function : Render |
a1954302 |
590 | //purpose : |
c5751993 |
591 | //======================================================================= |
a1954302 |
592 | void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace, |
593 | const OpenGl_GlobalLayerSettings& theDefaultSettings) const |
c5751993 |
594 | { |
550f3b8b |
595 | TEL_POFFSET_PARAM anAppliedOffsetParams = theWorkspace->AppliedPolygonOffset(); |
596 | |
c5751993 |
597 | // separate depth buffers |
598 | if (IsSettingEnabled (Graphic3d_ZLayerDepthClear)) |
599 | { |
600 | glClear (GL_DEPTH_BUFFER_BIT); |
601 | } |
eae454e3 |
602 | |
c5751993 |
603 | // handle depth test |
604 | if (IsSettingEnabled (Graphic3d_ZLayerDepthTest)) |
605 | { |
550f3b8b |
606 | // assuming depth test is enabled by default |
607 | glDepthFunc (theDefaultSettings.DepthFunc); |
c5751993 |
608 | } |
609 | else |
610 | { |
611 | glDepthFunc (GL_ALWAYS); |
612 | } |
eae454e3 |
613 | |
83da37b1 |
614 | // save environment texture |
615 | Handle(OpenGl_Texture) anEnvironmentTexture = theWorkspace->EnvironmentTexture(); |
616 | if (!myLayerSettings.UseEnvironmentTexture) |
617 | { |
618 | theWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)()); |
619 | } |
620 | |
c5751993 |
621 | // handle depth offset |
622 | if (IsSettingEnabled (Graphic3d_ZLayerDepthOffset)) |
623 | { |
550f3b8b |
624 | theWorkspace->SetPolygonOffset (Aspect_POM_Fill, |
625 | myLayerSettings.DepthOffsetFactor, |
626 | myLayerSettings.DepthOffsetUnits); |
c5751993 |
627 | } |
628 | else |
629 | { |
550f3b8b |
630 | theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode, |
631 | anAppliedOffsetParams.factor, |
632 | anAppliedOffsetParams.units); |
c5751993 |
633 | } |
634 | |
635 | // handle depth write |
eae454e3 |
636 | theWorkspace->UseDepthWrite() = IsSettingEnabled (Graphic3d_ZLayerDepthWrite); |
637 | glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE); |
c5751993 |
638 | |
639 | // render priority list |
a1954302 |
640 | theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace); |
550f3b8b |
641 | |
642 | // always restore polygon offset between layers rendering |
643 | theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode, |
644 | anAppliedOffsetParams.factor, |
645 | anAppliedOffsetParams.units); |
83da37b1 |
646 | |
647 | // restore environment texture |
648 | if (!myLayerSettings.UseEnvironmentTexture) |
649 | { |
650 | theWorkspace->SetEnvironmentTexture (anEnvironmentTexture); |
651 | } |
c5751993 |
652 | } |