1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-16 10:08:36 +03:00

0026364: Foundation Classes, TKMath - Optimize BVH binned algorithm

This commit is contained in:
dbp 2015-06-23 12:34:06 +03:00 committed by bugmaster
parent 65578e1c7c
commit a1c05aa5ec
2 changed files with 35 additions and 27 deletions

View File

@ -42,9 +42,19 @@ class BVH_BinnedBuilder : public BVH_QueueBuilder<T, N>
{ {
public: public:
//! Type for the array of bins of BVH tree node. //! Type of the array of bins of BVH tree node.
typedef BVH_Bin<T, N> BVH_BinVector[Bins]; typedef BVH_Bin<T, N> BVH_BinVector[Bins];
//! Describes split plane candidate.
struct BVH_SplitPlane
{
BVH_Bin<T, N> LftVoxel;
BVH_Bin<T, N> RghVoxel;
};
//! Type of the array of split plane candidates.
typedef BVH_SplitPlane BVH_SplitPlanes[Bins + 1];
public: public:
//! Creates binned SAH BVH builder. //! Creates binned SAH BVH builder.

View File

@ -212,45 +212,43 @@ typename BVH_QueueBuilder<T, N>::BVH_ChildNodes BVH_BinnedBuilder<T, N, Bins>::B
for (Standard_Integer anAxis = myUseMainAxis ? aMainAxis : 0; anAxis <= (myUseMainAxis ? aMainAxis : Min (N - 1, 2)); ++anAxis) for (Standard_Integer anAxis = myUseMainAxis ? aMainAxis : 0; anAxis <= (myUseMainAxis ? aMainAxis : Min (N - 1, 2)); ++anAxis)
{ {
if (BVH::VecComp<T, N>::Get (aSize, anAxis) <= BVH::THE_NODE_MIN_SIZE) if (BVH::VecComp<T, N>::Get (aSize, anAxis) <= BVH::THE_NODE_MIN_SIZE)
{
continue; continue;
}
BVH_BinVector aBins; BVH_BinVector aBinVector;
GetSubVolumes (theSet, theBVH, theNode, aBins, anAxis); GetSubVolumes (theSet, theBVH, theNode, aBinVector, anAxis);
BVH_SplitPlanes aSplitPlanes;
for (Standard_Integer aLftSplit = 1, aRghSplit = Bins - 1; aLftSplit < Bins; ++aLftSplit, --aRghSplit)
{
aSplitPlanes[aLftSplit].LftVoxel.Count = aSplitPlanes[aLftSplit - 1].LftVoxel.Count + aBinVector[aLftSplit - 1].Count;
aSplitPlanes[aRghSplit].RghVoxel.Count = aSplitPlanes[aRghSplit + 1].RghVoxel.Count + aBinVector[aRghSplit + 0].Count;
aSplitPlanes[aLftSplit].LftVoxel.Box = aSplitPlanes[aLftSplit - 1].LftVoxel.Box;
aSplitPlanes[aRghSplit].RghVoxel.Box = aSplitPlanes[aRghSplit + 1].RghVoxel.Box;
aSplitPlanes[aLftSplit].LftVoxel.Box.Combine (aBinVector[aLftSplit - 1].Box);
aSplitPlanes[aRghSplit].RghVoxel.Box.Combine (aBinVector[aRghSplit + 0].Box);
}
// Choose the best split (with minimum SAH cost) // Choose the best split (with minimum SAH cost)
for (Standard_Integer aSplit = 1; aSplit < Bins; ++aSplit) for (Standard_Integer aSplit = 1; aSplit < Bins; ++aSplit)
{ {
Standard_Integer aLftCount = 0;
Standard_Integer aRghCount = 0;
BVH_Box<T, N> aLftAABB;
BVH_Box<T, N> aRghAABB;
for (Standard_Integer anIndex = 0; anIndex < aSplit; ++anIndex)
{
aLftCount += aBins[anIndex].Count;
aLftAABB.Combine (aBins[anIndex].Box);
}
for (Standard_Integer anIndex = aSplit; anIndex < Bins; ++anIndex)
{
aRghCount += aBins[anIndex].Count;
aRghAABB.Combine (aBins[anIndex].Box);
}
// Simple SAH evaluation // Simple SAH evaluation
Standard_Real aCost = (static_cast<Standard_Real> (aLftAABB.Area()) /* / aNodeArea */) * aLftCount Standard_Real aCost =
+ (static_cast<Standard_Real> (aRghAABB.Area()) /* / aNodeArea */) * aRghCount; (static_cast<Standard_Real> (aSplitPlanes[aSplit].LftVoxel.Box.Area()) /* / S(N) */) * aSplitPlanes[aSplit].LftVoxel.Count
+ (static_cast<Standard_Real> (aSplitPlanes[aSplit].RghVoxel.Box.Area()) /* / S(N) */) * aSplitPlanes[aSplit].RghVoxel.Count;
if (aCost <= aMinSplitCost) if (aCost <= aMinSplitCost)
{ {
aMinSplitCost = aCost; aMinSplitCost = aCost;
aMinSplitAxis = anAxis; aMinSplitAxis = anAxis;
aMinSplitIndex = aSplit; aMinSplitIndex = aSplit;
aMinSplitBoxLft = aLftAABB; aMinSplitBoxLft = aSplitPlanes[aSplit].LftVoxel.Box;
aMinSplitBoxRgh = aRghAABB; aMinSplitBoxRgh = aSplitPlanes[aSplit].RghVoxel.Box;
aMinSplitNumLft = aLftCount; aMinSplitNumLft = aSplitPlanes[aSplit].LftVoxel.Count;
aMinSplitNumRgh = aRghCount; aMinSplitNumRgh = aSplitPlanes[aSplit].RghVoxel.Count;
} }
} }
} }