File indexing completed on 2025-01-18 10:03:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BVH_BinnedBuilder_HeaderFile
0017 #define BVH_BinnedBuilder_HeaderFile
0018
0019 #include <BVH_QueueBuilder.hxx>
0020
0021 #include <algorithm>
0022
0023 #if defined (_WIN32) && defined (max)
0024 #undef max
0025 #endif
0026
0027 #include <limits>
0028
0029
0030 template<class T, int N>
0031 struct BVH_Bin
0032 {
0033
0034 BVH_Bin() : Count (0) {}
0035
0036 Standard_Integer Count;
0037 BVH_Box<T, N> Box;
0038 };
0039
0040
0041
0042
0043
0044
0045
0046 template<class T, int N, int Bins = BVH_Constants_NbBinsOptimal>
0047 class BVH_BinnedBuilder : public BVH_QueueBuilder<T, N>
0048 {
0049 public:
0050
0051
0052 typedef BVH_Bin<T, N> BVH_BinVector[Bins];
0053
0054
0055 struct BVH_SplitPlane
0056 {
0057 BVH_Bin<T, N> LftVoxel;
0058 BVH_Bin<T, N> RghVoxel;
0059 };
0060
0061
0062 typedef BVH_SplitPlane BVH_SplitPlanes[Bins + 1];
0063
0064 public:
0065
0066
0067 BVH_BinnedBuilder (const Standard_Integer theLeafNodeSize = BVH_Constants_LeafNodeSizeDefault,
0068 const Standard_Integer theMaxTreeDepth = BVH_Constants_MaxTreeDepth,
0069 const Standard_Boolean theDoMainSplits = Standard_False,
0070 const Standard_Integer theNumOfThreads = 1)
0071 : BVH_QueueBuilder<T, N> (theLeafNodeSize, theMaxTreeDepth, theNumOfThreads),
0072 myUseMainAxis (theDoMainSplits)
0073 {
0074
0075 }
0076
0077
0078 virtual ~BVH_BinnedBuilder() {}
0079
0080 protected:
0081
0082
0083 virtual typename BVH_QueueBuilder<T, N>::BVH_ChildNodes buildNode (BVH_Set<T, N>* theSet,
0084 BVH_Tree<T, N>* theBVH,
0085 const Standard_Integer theNode) const Standard_OVERRIDE;
0086
0087
0088 virtual void getSubVolumes (BVH_Set<T, N>* theSet,
0089 BVH_Tree<T, N>* theBVH,
0090 const Standard_Integer theNode,
0091 BVH_BinVector& theBins,
0092 const Standard_Integer theAxis) const;
0093
0094 private:
0095
0096 Standard_Boolean myUseMainAxis;
0097
0098 };
0099
0100
0101
0102
0103
0104 template<class T, int N, int Bins>
0105 void BVH_BinnedBuilder<T, N, Bins>::getSubVolumes (BVH_Set<T, N>* theSet,
0106 BVH_Tree<T, N>* theBVH,
0107 const Standard_Integer theNode,
0108 BVH_BinVector& theBins,
0109 const Standard_Integer theAxis) const
0110 {
0111 const T aMin = BVH::VecComp<T, N>::Get (theBVH->MinPoint (theNode), theAxis);
0112 const T aMax = BVH::VecComp<T, N>::Get (theBVH->MaxPoint (theNode), theAxis);
0113 const T anInverseStep = static_cast<T> (Bins) / (aMax - aMin);
0114 for (Standard_Integer anIdx = theBVH->BegPrimitive (theNode); anIdx <= theBVH->EndPrimitive (theNode); ++anIdx)
0115 {
0116 typename BVH_Set<T, N>::BVH_BoxNt aBox = theSet->Box (anIdx);
0117 Standard_Integer aBinIndex = BVH::IntFloor<T> ((theSet->Center (anIdx, theAxis) - aMin) * anInverseStep);
0118 if (aBinIndex < 0)
0119 {
0120 aBinIndex = 0;
0121 }
0122 else if (aBinIndex >= Bins)
0123 {
0124 aBinIndex = Bins - 1;
0125 }
0126
0127 theBins[aBinIndex].Count++;
0128 theBins[aBinIndex].Box.Combine (aBox);
0129 }
0130 }
0131
0132 namespace BVH
0133 {
0134 template<class T, int N>
0135 Standard_Integer SplitPrimitives (BVH_Set<T, N>* theSet,
0136 const BVH_Box<T, N>& theBox,
0137 const Standard_Integer theBeg,
0138 const Standard_Integer theEnd,
0139 const Standard_Integer theBin,
0140 const Standard_Integer theAxis,
0141 const Standard_Integer theBins)
0142 {
0143 const T aMin = BVH::VecComp<T, N>::Get (theBox.CornerMin(), theAxis);
0144 const T aMax = BVH::VecComp<T, N>::Get (theBox.CornerMax(), theAxis);
0145
0146 const T anInverseStep = static_cast<T> (theBins) / (aMax - aMin);
0147
0148 Standard_Integer aLftIdx (theBeg);
0149 Standard_Integer aRghIdx (theEnd);
0150
0151 do
0152 {
0153 while (BVH::IntFloor<T> ((theSet->Center (aLftIdx, theAxis) - aMin) * anInverseStep) <= theBin && aLftIdx < theEnd)
0154 {
0155 ++aLftIdx;
0156 }
0157 while (BVH::IntFloor<T> ((theSet->Center (aRghIdx, theAxis) - aMin) * anInverseStep) > theBin && aRghIdx > theBeg)
0158 {
0159 --aRghIdx;
0160 }
0161
0162 if (aLftIdx <= aRghIdx)
0163 {
0164 if (aLftIdx != aRghIdx)
0165 {
0166 theSet->Swap (aLftIdx, aRghIdx);
0167 }
0168
0169 ++aLftIdx;
0170 --aRghIdx;
0171 }
0172 } while (aLftIdx <= aRghIdx);
0173
0174 return aLftIdx;
0175 }
0176
0177 template<class T, int N>
0178 struct BVH_AxisSelector
0179 {
0180 typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
0181 static Standard_Integer MainAxis (const BVH_VecNt& theSize)
0182 {
0183 if (theSize.y() > theSize.x())
0184 {
0185 return theSize.y() > theSize.z() ? 1 : 2;
0186 }
0187 else
0188 {
0189 return theSize.z() > theSize.x() ? 2 : 0;
0190 }
0191 }
0192 };
0193
0194 template<class T>
0195 struct BVH_AxisSelector<T, 2>
0196 {
0197 typedef typename BVH::VectorType<T, 2>::Type BVH_VecNt;
0198 static Standard_Integer MainAxis (const BVH_VecNt& theSize)
0199 {
0200 return theSize.x() > theSize.y() ? 0 : 1;
0201 }
0202 };
0203 }
0204
0205
0206
0207
0208
0209 template<class T, int N, int Bins>
0210 typename BVH_QueueBuilder<T, N>::BVH_ChildNodes BVH_BinnedBuilder<T, N, Bins>::buildNode (BVH_Set<T, N>* theSet,
0211 BVH_Tree<T, N>* theBVH,
0212 const Standard_Integer theNode) const
0213 {
0214 const Standard_Integer aNodeBegPrimitive = theBVH->BegPrimitive (theNode);
0215 const Standard_Integer aNodeEndPrimitive = theBVH->EndPrimitive (theNode);
0216 if (aNodeEndPrimitive - aNodeBegPrimitive < BVH_Builder<T, N>::myLeafNodeSize)
0217 {
0218 return typename BVH_QueueBuilder<T, N>::BVH_ChildNodes();
0219 }
0220
0221 const BVH_Box<T, N> anAABB (theBVH->MinPoint (theNode),
0222 theBVH->MaxPoint (theNode));
0223 const typename BVH_Box<T, N>::BVH_VecNt aSize = anAABB.Size();
0224
0225
0226 Standard_Integer aMinSplitAxis = -1;
0227 Standard_Integer aMinSplitIndex = 0;
0228 Standard_Integer aMinSplitNumLft = 0;
0229 Standard_Integer aMinSplitNumRgh = 0;
0230
0231 BVH_Box<T, N> aMinSplitBoxLft;
0232 BVH_Box<T, N> aMinSplitBoxRgh;
0233
0234 Standard_Real aMinSplitCost = std::numeric_limits<Standard_Real>::max();
0235 const Standard_Integer aMainAxis = BVH::BVH_AxisSelector<T, N>::MainAxis (aSize);
0236
0237
0238 for (Standard_Integer anAxis = myUseMainAxis ? aMainAxis : 0; anAxis <= (myUseMainAxis ? aMainAxis : Min (N - 1, 2)); ++anAxis)
0239 {
0240 if (BVH::VecComp<T, N>::Get (aSize, anAxis) <= BVH::THE_NODE_MIN_SIZE)
0241 {
0242 continue;
0243 }
0244
0245 BVH_BinVector aBinVector;
0246 getSubVolumes (theSet, theBVH, theNode, aBinVector, anAxis);
0247
0248 BVH_SplitPlanes aSplitPlanes;
0249 for (Standard_Integer aLftSplit = 1, aRghSplit = Bins - 1; aLftSplit < Bins; ++aLftSplit, --aRghSplit)
0250 {
0251 aSplitPlanes[aLftSplit].LftVoxel.Count = aSplitPlanes[aLftSplit - 1].LftVoxel.Count + aBinVector[aLftSplit - 1].Count;
0252 aSplitPlanes[aRghSplit].RghVoxel.Count = aSplitPlanes[aRghSplit + 1].RghVoxel.Count + aBinVector[aRghSplit + 0].Count;
0253
0254 aSplitPlanes[aLftSplit].LftVoxel.Box = aSplitPlanes[aLftSplit - 1].LftVoxel.Box;
0255 aSplitPlanes[aRghSplit].RghVoxel.Box = aSplitPlanes[aRghSplit + 1].RghVoxel.Box;
0256
0257 aSplitPlanes[aLftSplit].LftVoxel.Box.Combine (aBinVector[aLftSplit - 1].Box);
0258 aSplitPlanes[aRghSplit].RghVoxel.Box.Combine (aBinVector[aRghSplit + 0].Box);
0259 }
0260
0261
0262 for (Standard_Integer aSplit = 1; aSplit < Bins; ++aSplit)
0263 {
0264
0265 Standard_Real aCost =
0266 (static_cast<Standard_Real> (aSplitPlanes[aSplit].LftVoxel.Box.Area()) ) * aSplitPlanes[aSplit].LftVoxel.Count
0267 + (static_cast<Standard_Real> (aSplitPlanes[aSplit].RghVoxel.Box.Area()) ) * aSplitPlanes[aSplit].RghVoxel.Count;
0268
0269 if (aCost <= aMinSplitCost)
0270 {
0271 aMinSplitCost = aCost;
0272 aMinSplitAxis = anAxis;
0273 aMinSplitIndex = aSplit;
0274 aMinSplitBoxLft = aSplitPlanes[aSplit].LftVoxel.Box;
0275 aMinSplitBoxRgh = aSplitPlanes[aSplit].RghVoxel.Box;
0276 aMinSplitNumLft = aSplitPlanes[aSplit].LftVoxel.Count;
0277 aMinSplitNumRgh = aSplitPlanes[aSplit].RghVoxel.Count;
0278 }
0279 }
0280 }
0281
0282 theBVH->SetInner (theNode);
0283 Standard_Integer aMiddle = -1;
0284 if (aMinSplitNumLft == 0 || aMinSplitNumRgh == 0 || aMinSplitAxis == -1)
0285 {
0286 aMinSplitBoxLft.Clear();
0287 aMinSplitBoxRgh.Clear();
0288
0289 aMiddle = std::max (aNodeBegPrimitive + 1,
0290 static_cast<Standard_Integer> ((aNodeBegPrimitive + aNodeEndPrimitive) / 2.f));
0291
0292 aMinSplitNumLft = aMiddle - aNodeBegPrimitive;
0293 for (Standard_Integer anIndex = aNodeBegPrimitive; anIndex < aMiddle; ++anIndex)
0294 {
0295 aMinSplitBoxLft.Combine (theSet->Box (anIndex));
0296 }
0297
0298 aMinSplitNumRgh = aNodeEndPrimitive - aMiddle + 1;
0299 for (Standard_Integer anIndex = aNodeEndPrimitive; anIndex >= aMiddle; --anIndex)
0300 {
0301 aMinSplitBoxRgh.Combine (theSet->Box (anIndex));
0302 }
0303 }
0304 else
0305 {
0306 aMiddle = BVH::SplitPrimitives<T, N> (theSet,
0307 anAABB,
0308 aNodeBegPrimitive,
0309 aNodeEndPrimitive,
0310 aMinSplitIndex - 1,
0311 aMinSplitAxis,
0312 Bins);
0313 }
0314
0315 typedef typename BVH_QueueBuilder<T, N>::BVH_PrimitiveRange Range;
0316 return typename BVH_QueueBuilder<T, N>::BVH_ChildNodes (aMinSplitBoxLft,
0317 aMinSplitBoxRgh,
0318 Range (aNodeBegPrimitive, aMiddle - 1),
0319 Range (aMiddle, aNodeEndPrimitive));
0320 }
0321
0322 #endif