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