0024001: Stereographic rendering support
[occt.git] / src / OpenGl / OpenGl_SceneGeometry.cxx
CommitLineData
e276548b 1// Created on: 2013-08-27
2// Created by: Denis BOGOLEPOV
3// Copyright (c) 2013 OPEN CASCADE SAS
4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
e276548b 6//
973c2be1 7// This library is free software; you can redistribute it and / or modify it
8// under the terms of the GNU Lesser General Public version 2.1 as published
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.
e276548b 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
e276548b 15
16#ifdef HAVE_CONFIG_H
17 #include <config.h>
18#endif
19
20#ifdef HAVE_OPENCL
21
22#include <limits>
23
24#include <OpenGl_SceneGeometry.hxx>
25
26namespace
27{
28
29 //! Number of node bins per axis.
30 static const int THE_NUMBER_OF_BINS = 32;
31
32 //! Max number of triangles per leaf node.
33 static const int THE_MAX_LEAF_TRIANGLES = 4;
34
35 //! Useful constant for null integer 4D vector.
36 static const OpenGl_RTVec4i THE_ZERO_VEC_4I;
37
38 //! Useful constant for null floating-point 4D vector.
39 static const OpenGl_RTVec4f THE_ZERO_VEC_4F;
40
41};
42
43// =======================================================================
64c759f8 44// function : OpenGl_RaytraceMaterial
e276548b 45// purpose : Creates new default material
46// =======================================================================
47OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial()
48: Ambient (THE_ZERO_VEC_4F),
49 Diffuse (THE_ZERO_VEC_4F),
50 Specular (THE_ZERO_VEC_4F),
51 Emission (THE_ZERO_VEC_4F),
52 Reflection (THE_ZERO_VEC_4F),
53 Refraction (THE_ZERO_VEC_4F),
54 Transparency (THE_ZERO_VEC_4F)
55{ }
56
57// =======================================================================
64c759f8 58// function : OpenGl_RaytraceMaterial
e276548b 59// purpose : Creates new material with specified properties
60// =======================================================================
61OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial (const OpenGl_RTVec4f& theAmbient,
62 const OpenGl_RTVec4f& theDiffuse,
63 const OpenGl_RTVec4f& theSpecular)
64: Ambient (theAmbient),
65 Diffuse (theDiffuse),
66 Specular (theSpecular),
67 Emission (THE_ZERO_VEC_4F),
68 Reflection (THE_ZERO_VEC_4F),
69 Refraction (THE_ZERO_VEC_4F),
70 Transparency (THE_ZERO_VEC_4F)
71{
72 //
73}
74
75// =======================================================================
64c759f8 76// function : OpenGl_RaytraceMaterial
e276548b 77// purpose : Creates new material with specified properties
78// =======================================================================
79OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial (const OpenGl_RTVec4f& theAmbient,
80 const OpenGl_RTVec4f& theDiffuse,
81 const OpenGl_RTVec4f& theSpecular,
82 const OpenGl_RTVec4f& theEmission,
83 const OpenGl_RTVec4f& theTranspar)
84: Ambient (theAmbient),
85 Diffuse (theDiffuse),
86 Specular (theSpecular),
87 Emission (theEmission),
88 Reflection (THE_ZERO_VEC_4F),
89 Refraction (THE_ZERO_VEC_4F),
90 Transparency (theTranspar)
91{
92 //
93}
94
95// =======================================================================
64c759f8 96// function : OpenGl_RaytraceMaterial
e276548b 97// purpose : Creates new material with specified properties
98// =======================================================================
99OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial (const OpenGl_RTVec4f& theAmbient,
100 const OpenGl_RTVec4f& theDiffuse,
101 const OpenGl_RTVec4f& theSpecular,
102 const OpenGl_RTVec4f& theEmission,
103 const OpenGl_RTVec4f& theTranspar,
104 const OpenGl_RTVec4f& theReflection,
105 const OpenGl_RTVec4f& theRefraction)
106: Ambient (theAmbient),
107 Diffuse (theDiffuse),
108 Specular (theSpecular),
109 Emission (theEmission),
110 Reflection (theReflection),
111 Refraction (theRefraction),
112 Transparency (theTranspar)
113{
114 //
115}
116
117// =======================================================================
118// function : OpenGl_LightSource
119// purpose : Creates new light source
120// =======================================================================
121OpenGl_RaytraceLight::OpenGl_RaytraceLight (const OpenGl_RTVec4f& theAmbient)
122: Ambient (theAmbient)
123{
124 //
125}
126
127// =======================================================================
128// function : OpenGl_LightSource
129// purpose : Creates new light source
130// =======================================================================
131OpenGl_RaytraceLight::OpenGl_RaytraceLight (const OpenGl_RTVec4f& theDiffuse,
132 const OpenGl_RTVec4f& thePosition)
133: Diffuse (theDiffuse),
134 Position (thePosition)
135{
136 //
137}
138
139// =======================================================================
140// function : Center
141// purpose : Returns centroid of specified triangle
142// =======================================================================
143OpenGl_RTVec4f OpenGl_RaytraceScene::Center (const int theTriangle) const
144{
d5af8626 145 const OpenGl_RTVec4i& anIndex = Triangles [theTriangle];
146
e276548b 147 return ( Vertices[anIndex.x()] +
148 Vertices[anIndex.y()] +
149 Vertices[anIndex.z()] ) * ( 1.f / 3.f );
150}
151
152// =======================================================================
153// function : CenterAxis
154// purpose : Returns centroid of specified triangle
155// =======================================================================
156float OpenGl_RaytraceScene::CenterAxis (const int theTriangle,
157 const int theAxis) const
158{
d5af8626 159 const OpenGl_RTVec4i& anIndex = Triangles [theTriangle];
160
e276548b 161 return ( Vertices[anIndex.x()][theAxis] +
162 Vertices[anIndex.y()][theAxis] +
163 Vertices[anIndex.z()][theAxis] ) * ( 1.f / 3.f );
164}
165
166// =======================================================================
167// function : Box
168// purpose : Returns AABB of specified triangle
169// =======================================================================
170OpenGl_AABB OpenGl_RaytraceScene::Box (const int theTriangle) const
171{
d5af8626 172 const OpenGl_RTVec4i& anIndex = Triangles[theTriangle];
e276548b 173
d5af8626 174 const OpenGl_RTVec4f& pA = Vertices[anIndex.x()];
175 const OpenGl_RTVec4f& pB = Vertices[anIndex.y()];
176 const OpenGl_RTVec4f& pC = Vertices[anIndex.z()];
e276548b 177
178 OpenGl_AABB aBox (pA);
179
180 aBox.Add (pB);
181 aBox.Add (pC);
182
183 return aBox;
184}
185
186// =======================================================================
187// function : Clear
188// purpose : Clears all scene geometry data
189// =======================================================================
190void OpenGl_RaytraceScene::Clear()
191{
192 AABB.Clear();
193
194 OpenGl_RTArray4f anEmptyNormals;
195 Normals.swap (anEmptyNormals);
196
197 OpenGl_RTArray4f anEmptyVertices;
198 Vertices.swap (anEmptyVertices);
199
200 OpenGl_RTArray4i anEmptyTriangles;
201 Triangles.swap (anEmptyTriangles);
202
203 std::vector<OpenGl_RaytraceMaterial,
204 NCollection_StdAllocator<OpenGl_RaytraceMaterial> > anEmptyMaterials;
205
206 Materials.swap (anEmptyMaterials);
207}
208
209// =======================================================================
210// function : OpenGl_Node
211// purpose : Creates new empty BVH node
212// =======================================================================
213OpenGl_BVHNode::OpenGl_BVHNode()
214: myMinPoint (THE_ZERO_VEC_4F),
215 myMaxPoint (THE_ZERO_VEC_4F),
216 myDataRcrd (THE_ZERO_VEC_4I)
217{
218 //
219}
220
221// =======================================================================
222// function : OpenGl_Node
223// purpose : Creates new BVH node with specified data
224// =======================================================================
225OpenGl_BVHNode::OpenGl_BVHNode (const OpenGl_RTVec4f& theMinPoint,
226 const OpenGl_RTVec4f& theMaxPoint,
227 const OpenGl_RTVec4i& theDataRcrd)
228: myMinPoint (theMinPoint),
229 myMaxPoint (theMaxPoint),
230 myDataRcrd (theDataRcrd)
231{
232 //
233}
234
235// =======================================================================
236// function : OpenGl_Node
237// purpose : Creates new leaf BVH node with specified data
238// =======================================================================
239OpenGl_BVHNode::OpenGl_BVHNode (const OpenGl_AABB& theAABB,
240 const int theBegTriangle,
241 const int theEndTriangle)
242: myMinPoint (theAABB.CornerMin()),
243 myMaxPoint (theAABB.CornerMax()),
244 myDataRcrd (1,
245 theBegTriangle,
246 theEndTriangle,
247 0)
248{
249 //
250}
251
252// =======================================================================
253// function : OpenGl_Node
254// purpose : Creates new leaf BVH node with specified data
255// =======================================================================
256OpenGl_BVHNode::OpenGl_BVHNode (const OpenGl_RTVec4f& theMinPoint,
257 const OpenGl_RTVec4f& theMaxPoint,
258 const int theBegTriangle,
259 const int theEndTriangle)
260: myMinPoint (theMinPoint),
261 myMaxPoint (theMaxPoint),
262 myDataRcrd (1,
263 theBegTriangle,
264 theEndTriangle,
265 0)
266{
267 //
268}
269
270// =======================================================================
271// function : CleanUp
272// purpose : Removes all tree nodes
273// =======================================================================
274void OpenGl_BVH::CleanUp()
275{
276 OpenGl_RTArray4f anEmptyMinPointBuffer;
277 myMinPointBuffer.swap (anEmptyMinPointBuffer);
278
279 OpenGl_RTArray4f anEmptyMaxPointBuffer;
280 myMaxPointBuffer.swap (anEmptyMaxPointBuffer);
281
282 OpenGl_RTArray4i anEmptyDataRcrdBuffer;
283 myDataRcrdBuffer.swap (anEmptyDataRcrdBuffer);
284}
285
286// =======================================================================
287// function : Node
288// purpose : Returns node with specified index
289// =======================================================================
290OpenGl_BVHNode OpenGl_BVH::Node (const int theIndex) const
291{
292 return OpenGl_BVHNode (myMinPointBuffer[theIndex],
293 myMaxPointBuffer[theIndex],
294 myDataRcrdBuffer[theIndex]);
295}
296
297// =======================================================================
298// function : SetNode
299// purpose : Replaces node with specified index
300// =======================================================================
301void OpenGl_BVH::SetNode (const int theIndex,
302 const OpenGl_BVHNode& theNode)
303{
304 if (theIndex < static_cast<int> (myMinPointBuffer.size()))
305 {
306 myMinPointBuffer[theIndex] = theNode.myMinPoint;
307 myMaxPointBuffer[theIndex] = theNode.myMaxPoint;
308 myDataRcrdBuffer[theIndex] = theNode.myDataRcrd;
309 }
310}
311
312// =======================================================================
313// function : PushNode
314// purpose : Adds new node to the tree
315// =======================================================================
316int OpenGl_BVH::PushNode (const OpenGl_BVHNode& theNode)
317{
318 myMinPointBuffer.push_back (theNode.myMinPoint);
319 myMaxPointBuffer.push_back (theNode.myMaxPoint);
320 myDataRcrdBuffer.push_back (theNode.myDataRcrd);
321 return static_cast<int> (myDataRcrdBuffer.size() - 1);
322}
323
324// =======================================================================
325// function : OpenGl_NodeBuildTask
326// purpose : Creates new node building task
327// =======================================================================
328OpenGl_BVHNodeTask::OpenGl_BVHNodeTask()
329: NodeToBuild (0),
330 BegTriangle (0),
331 EndTriangle (0)
332{
333 //
334}
335
336// =======================================================================
337// function : OpenGl_NodeBuildTask
338// purpose : Creates new node building task
339// =======================================================================
340OpenGl_BVHNodeTask::OpenGl_BVHNodeTask (const int theNodeToBuild,
341 const int theBegTriangle,
342 const int theEndTriangle)
343: NodeToBuild (theNodeToBuild),
344 BegTriangle (theBegTriangle),
345 EndTriangle (theEndTriangle)
346{
347 //
348}
349
350// =======================================================================
351// function : OpenGl_BinnedBVHBuilder
352// purpose : Creates new binned BVH builder
353// =======================================================================
354OpenGl_BinnedBVHBuilder::OpenGl_BinnedBVHBuilder()
355: myMaxDepth (30)
356{
357 //
358}
359
360// =======================================================================
361// function : ~OpenGl_BinnedBVHBuilder
362// purpose : Releases binned BVH builder
363// =======================================================================
364OpenGl_BinnedBVHBuilder::~OpenGl_BinnedBVHBuilder()
365{
366 //
367}
368
369#define BVH_DEBUG_OUTPUT_
370
371#if defined( BVH_DEBUG_OUTPUT )
372 #include <iostream>
373#endif
374
375// =======================================================================
376// function : ReinterpretIntAsFloat
377// purpose : Reinterprets bits of integer value as floating-point value
378// =======================================================================
379inline float ReinterpretIntAsFloat (int theValue)
380{
381 return *reinterpret_cast< float* > (&theValue);
382}
383
384// =======================================================================
385// function : Build
386// purpose : Builds BVH tree using binned SAH algorithm
387// =======================================================================
388void OpenGl_BinnedBVHBuilder::Build (OpenGl_RaytraceScene& theGeometry,
389 const float theEpsilon)
390{
391 CleanUp();
392
393#ifdef BVH_DEBUG_OUTPUT
394 std::cout << "Start building BVH..." << std::endl;
395
396 std::cout << "Triangles: " << theGeometry.Triangles.size() << std::endl;
397#endif
398
399 if (theGeometry.Triangles.size() == 0)
400 return;
401
402 // Create root node with all scene triangles
403 OpenGl_AABB anAABB = theGeometry.AABB;
404 anAABB.CornerMin() = OpenGl_RTVec4f (anAABB.CornerMin().x() - theEpsilon,
405 anAABB.CornerMin().y() - theEpsilon,
406 anAABB.CornerMin().z() - theEpsilon,
407 1.0f);
408 anAABB.CornerMax() = OpenGl_RTVec4f (anAABB.CornerMax().x() + theEpsilon,
409 anAABB.CornerMax().y() + theEpsilon,
410 anAABB.CornerMax().z() + theEpsilon,
411 1.0f);
412 myTree.PushNode (OpenGl_BVHNode (anAABB, 0, static_cast<int> (theGeometry.Triangles.size() - 1)));
413
414#ifdef BVH_DEBUG_OUTPUT
415 std::cout << "Push root node: [" << 0 << ", " <<
416 theGeometry.Triangles.size() - 1 << "]" << std::endl;
417#endif
418
419 // Setup splitting task for the root node
420 myNodeTasksQueue.push_back (OpenGl_BVHNodeTask (0, 0, static_cast<int> (theGeometry.Triangles.size() - 1)));
421
422 // Building nodes while tasks queue is not empty
423 for (int aTaskId = 0; aTaskId < static_cast<int> (myNodeTasksQueue.size()); ++aTaskId)
424 {
425 BuildNode (theGeometry, aTaskId);
426 }
427
428 // Write support data to optimize traverse
429 for (int aNode = 0; aNode < static_cast<int> (myTree.DataRcrdBuffer().size()); ++aNode)
430 {
431 OpenGl_RTVec4i aData = myTree.DataRcrdBuffer()[aNode];
432 myTree.MinPointBuffer()[aNode].w() = ReinterpretIntAsFloat (aData[0] ? aData[1] : -aData[1]);
433 myTree.MaxPointBuffer()[aNode].w() = ReinterpretIntAsFloat (aData[0] ? aData[2] : -aData[2]);
434 }
435}
436
437// =======================================================================
438// function : CleanUp
439// purpose : Clears previously built tree
440// =======================================================================
441void OpenGl_BinnedBVHBuilder::CleanUp()
442{
443 myTree.CleanUp();
444 myNodeTasksQueue.clear();
445}
446
447// =======================================================================
448// function : SetMaxDepth
449// purpose : Sets maximum tree depth
450// =======================================================================
451void OpenGl_BinnedBVHBuilder::SetMaxDepth (const int theMaxDepth)
452{
453 if (theMaxDepth > 1 && theMaxDepth < 30)
454 {
455 myMaxDepth = theMaxDepth - 1;
456 }
457}
458
459//! Minimum node size to split.
460static const float THE_NODE_MIN_SIZE = 1e-4f;
461
462// =======================================================================
463// function : BuildNode
464// purpose : Builds node using task info
465// =======================================================================
466void OpenGl_BinnedBVHBuilder::BuildNode (OpenGl_RaytraceScene& theGeometry,
467 const int theTask)
468{
469 OpenGl_BVHNodeTask aTask = myNodeTasksQueue[theTask];
470 OpenGl_BVHNode aNode = myTree.Node (aTask.NodeToBuild);
471
472#ifdef BVH_DEBUG_OUTPUT
473 std::cout << "Build node " << aTask.NodeToBuild << ": [" <<
474 aTask.BegTriangle << ", " << aTask.EndTriangle << "]" << std::endl;
475#endif
476
477 OpenGl_AABB anAABB (aNode.MinPoint(), aNode.MaxPoint());
478 const OpenGl_RTVec4f aNodeSize = anAABB.Size();
479 const float aNodeArea = anAABB.Area();
480
481 // Parameters for storing best split
482 float aMinSplitCost = std::numeric_limits<float>::max();
483
484 int aMinSplitAxis = -1;
485 int aMinSplitIndex = 0;
486 int aMinSplitLftCount = 0;
487 int aMinSplitRghCount = 0;
488
489 OpenGl_AABB aMinSplitLftAABB;
490 OpenGl_AABB aMinSplitRghAABB;
491
492 // Find best split
493 for (int anAxis = 0; anAxis < 3; ++anAxis)
494 {
495 if (aNodeSize[anAxis] <= THE_NODE_MIN_SIZE)
496 continue;
497
498 OpenGl_BinVector aBins (THE_NUMBER_OF_BINS);
499 GetSubVolumes (theGeometry, aNode, aBins, anAxis);
500
501 // Choose the best split (with minimum SAH cost)
502 for (int aSplit = 1; aSplit < THE_NUMBER_OF_BINS; ++aSplit)
503 {
504 int aLftCount = 0;
505 int aRghCount = 0;
506 OpenGl_AABB aLftAABB;
507 OpenGl_AABB aRghAABB;
508 for (int anIndex = 0; anIndex < aSplit; ++anIndex)
509 {
510 aLftCount += aBins[anIndex].Count;
511 aLftAABB.Combine (aBins[anIndex].Volume);
512 }
513
514 for (int anIndex = aSplit; anIndex < THE_NUMBER_OF_BINS; ++anIndex)
515 {
516 aRghCount += aBins[anIndex].Count;
517 aRghAABB.Combine (aBins[anIndex].Volume);
518 }
519
520 // Simple SAH evaluation
521 float aCost = ( aLftAABB.Area() / aNodeArea ) * aLftCount +
522 ( aRghAABB.Area() / aNodeArea ) * aRghCount;
523
524#ifdef BVH_DEBUG_OUTPUT
525 std::cout << "\t\tBin " << aSplit << ", Cost = " << aCost << std::endl;
526#endif
527
528 if (aCost <= aMinSplitCost)
529 {
530 aMinSplitCost = aCost;
531 aMinSplitAxis = anAxis;
532 aMinSplitIndex = aSplit;
533 aMinSplitLftAABB = aLftAABB;
534 aMinSplitRghAABB = aRghAABB;
535 aMinSplitLftCount = aLftCount;
536 aMinSplitRghCount = aRghCount;
537 }
538 }
539 }
540
541 if (aMinSplitAxis == -1)
542 {
543 // make outer (leaf) node
544 myTree.DataRcrdBuffer()[aTask.NodeToBuild].x() = 1;
545 return;
546 }
547
548#ifdef BVH_DEBUG_OUTPUT
549 switch (aMinSplitAxis)
550 {
551 case 0:
552 std::cout << "\tSplit axis: X = " << aMinSplitIndex << std::endl;
553 break;
554 case 1:
555 std::cout << "\tSplit axis: Y = " << aMinSplitIndex << std::endl;
556 break;
557 case 2:
558 std::cout << "\tSplit axis: Z = " << aMinSplitIndex << std::endl;
559 break;
560 }
561#endif
562
563 int aMiddle = SplitTriangles (theGeometry, aTask.BegTriangle, aTask.EndTriangle,
564 aNode, aMinSplitIndex - 1, aMinSplitAxis);
565
566#ifdef BVH_DEBUG_OUTPUT
567 std::cout << "\tLeft child: [" << aTask.BegTriangle << ", "
568 << aMiddle - 1 << "]" << std::endl;
569
570 std::cout << "\tRight child: [" << aMiddle << ", "
571 << aTask.EndTriangle << "]" << std::endl;
572#endif
573
574#define BVH_SIDE_LFT 1
575#define BVH_SIDE_RGH 2
576
577 // Setting up tasks for child nodes
578 for (int aSide = BVH_SIDE_LFT; aSide <= BVH_SIDE_RGH; ++aSide)
579 {
580 OpenGl_RTVec4f aMinPoint = (aSide == BVH_SIDE_LFT)
581 ? aMinSplitLftAABB.CornerMin()
582 : aMinSplitRghAABB.CornerMin();
583 OpenGl_RTVec4f aMaxPoint = (aSide == BVH_SIDE_LFT)
584 ? aMinSplitLftAABB.CornerMax()
585 : aMinSplitRghAABB.CornerMax();
586
587 int aBegTriangle = (aSide == BVH_SIDE_LFT)
588 ? aTask.BegTriangle
589 : aMiddle;
590 int aEndTriangle = (aSide == BVH_SIDE_LFT)
591 ? aMiddle - 1
592 : aTask.EndTriangle;
593
594 OpenGl_BVHNode aChild (aMinPoint, aMaxPoint, aBegTriangle, aEndTriangle);
595 aChild.SetLevel (aNode.Level() + 1);
596
597 // Check to see if child node must be split
598 const int aNbTriangles = (aSide == BVH_SIDE_LFT)
599 ? aMinSplitLftCount
600 : aMinSplitRghCount;
601
602 const int isChildALeaf = (aNbTriangles <= THE_MAX_LEAF_TRIANGLES) || (aNode.Level() >= myMaxDepth);
603 if (isChildALeaf)
604 aChild.SetOuter();
605 else
606 aChild.SetInner();
607
608 const int aChildIndex = myTree.PushNode (aChild);
609
610 // Modify parent node
611 myTree.DataRcrdBuffer()[aTask.NodeToBuild].x() = 0; // inner node flag
612 if (aSide == BVH_SIDE_LFT)
613 myTree.DataRcrdBuffer()[aTask.NodeToBuild].y() = aChildIndex; // left child
614 else
615 myTree.DataRcrdBuffer()[aTask.NodeToBuild].z() = aChildIndex; // right child
616
617 // Make new building task
618 if (!isChildALeaf)
619 myNodeTasksQueue.push_back (OpenGl_BVHNodeTask (aChildIndex, aBegTriangle, aEndTriangle));
620 }
621}
622
623// =======================================================================
624// function : SplitTriangles
625// purpose : Splits node triangles into two intervals for child nodes
626// =======================================================================
627int OpenGl_BinnedBVHBuilder::SplitTriangles (OpenGl_RaytraceScene& theGeometry,
628 const int theBegTriangle,
629 const int theEndTriangle,
630 OpenGl_BVHNode& theNode,
631 int theBin,
632 const int theAxis)
633{
634 int aLftIndex (theBegTriangle);
635 int aRghIndex (theEndTriangle);
636
637 const float aMin = theNode.MinPoint()[theAxis];
638 const float aMax = theNode.MaxPoint()[theAxis];
639
640 const float aStep = (aMax - aMin) / THE_NUMBER_OF_BINS;
641
642 do
643 {
644 while ((int )floorf ((theGeometry.CenterAxis (aLftIndex, theAxis) - aMin) / aStep) <= theBin
645 && aLftIndex < theEndTriangle)
646 {
647 ++aLftIndex;
648 }
649 while ((int )floorf ((theGeometry.CenterAxis (aRghIndex, theAxis) - aMin) / aStep) > theBin
650 && aRghIndex > theBegTriangle)
651 {
652 --aRghIndex;
653 }
654
655 if (aLftIndex <= aRghIndex)
656 {
657 if (aLftIndex != aRghIndex)
658 {
659 OpenGl_RTVec4i aLftTrg = theGeometry.Triangles[aLftIndex];
660 OpenGl_RTVec4i aRghTrg = theGeometry.Triangles[aRghIndex];
661 theGeometry.Triangles[aLftIndex] = aRghTrg;
662 theGeometry.Triangles[aRghIndex] = aLftTrg;
663 }
664
665 aLftIndex++; aRghIndex--;
666 }
667 } while (aLftIndex <= aRghIndex);
668
669 return aLftIndex;
670}
671
672// =======================================================================
673// function : GetSubVolumes
674// purpose : Arranges node triangles into bins
675// =======================================================================
676void OpenGl_BinnedBVHBuilder::GetSubVolumes (OpenGl_RaytraceScene& theGeometry,
677 const OpenGl_BVHNode& theNode,
678 OpenGl_BinVector& theBins,
679 const int theAxis)
680{
681 const float aMin = theNode.MinPoint()[theAxis];
682 const float aMax = theNode.MaxPoint()[theAxis];
683
684 const float aStep = (aMax - aMin) / THE_NUMBER_OF_BINS;
685
686 for (int aTri = theNode.BegTriangle(); aTri <= theNode.EndTriangle(); ++aTri)
687 {
688 float aCenter = theGeometry.CenterAxis (aTri, theAxis);
689 int aBinIndex = (int )floorf ((aCenter - aMin) * ( 1.0f / aStep));
690 if (aBinIndex < 0)
691 {
692 aBinIndex = 0;
693 }
694 else if (aBinIndex >= THE_NUMBER_OF_BINS)
695 {
696 aBinIndex = THE_NUMBER_OF_BINS - 1;
697 }
698
699 theBins[aBinIndex].Count++;
700 theBins[aBinIndex].Volume.Combine (theGeometry.Box (aTri));
701 }
702}
703
704namespace OpenGl_Raytrace
705{
706 // =======================================================================
707 // function : IsRaytracedElement
708 // purpose : Checks to see if the element contains ray-trace geometry
709 // =======================================================================
710 Standard_Boolean IsRaytracedElement (const OpenGl_ElementNode* theNode)
711 {
712 if (TelParray == theNode->type)
713 {
714 OpenGl_PrimitiveArray* anArray = dynamic_cast< OpenGl_PrimitiveArray* > (theNode->elem);
715 return anArray->PArray()->type >= TelPolygonsArrayType;
716 }
717 return Standard_False;
718 }
719
720 // =======================================================================
721 // function : IsRaytracedGroup
722 // purpose : Checks to see if the group contains ray-trace geometry
723 // =======================================================================
724 Standard_Boolean IsRaytracedGroup (const OpenGl_Group *theGroup)
725 {
726 const OpenGl_ElementNode* aNode;
727 for (aNode = theGroup->FirstNode(); aNode != NULL; aNode = aNode->next)
728 {
729 if (IsRaytracedElement (aNode))
730 {
731 return Standard_True;
732 }
733 }
734 return Standard_False;
735 }
736
737 // =======================================================================
738 // function : IsRaytracedStructure
739 // purpose : Checks to see if the structure contains ray-trace geometry
740 // =======================================================================
741 Standard_Boolean IsRaytracedStructure (const OpenGl_Structure *theStructure)
742 {
743 for (OpenGl_ListOfGroup::Iterator anItg (theStructure->Groups());
744 anItg.More(); anItg.Next())
745 {
746 if (anItg.Value()->IsRaytracable())
747 return Standard_True;
748 }
749 for (OpenGl_ListOfStructure::Iterator anIts (theStructure->ConnectedStructures());
750 anIts.More(); anIts.Next())
751 {
752 if (IsRaytracedStructure (anIts.Value()))
753 return Standard_True;
754 }
755 return Standard_False;
756 }
757}
758
759#endif