File indexing completed on 2026-05-30 08:45:56
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef _BVH_LinearBuilder_Header
0017 #define _BVH_LinearBuilder_Header
0018
0019 #include <BVH_RadixSorter.hxx>
0020 #include <Standard_Assert.hxx>
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 template <class T, int N>
0033 class BVH_LinearBuilder : public BVH_Builder<T, N>
0034 {
0035 public:
0036 typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
0037
0038 public:
0039
0040 BVH_LinearBuilder(const Standard_Integer theLeafNodeSize = BVH_Constants_LeafNodeSizeDefault,
0041 const Standard_Integer theMaxTreeDepth = BVH_Constants_MaxTreeDepth);
0042
0043
0044 virtual ~BVH_LinearBuilder();
0045
0046
0047 virtual void Build(BVH_Set<T, N>* theSet,
0048 BVH_Tree<T, N>* theBVH,
0049 const BVH_Box<T, N>& theBox) const Standard_OVERRIDE;
0050
0051 protected:
0052 typedef NCollection_Array1<BVH_EncodedLink>::iterator LinkIterator;
0053
0054 protected:
0055
0056 Standard_Integer emitHierachy(BVH_Tree<T, N>* theBVH,
0057 const NCollection_Array1<BVH_EncodedLink>& theEncodedLinks,
0058 const Standard_Integer theBit,
0059 const Standard_Integer theShift,
0060 const Standard_Integer theStart,
0061 const Standard_Integer theFinal) const;
0062
0063
0064 Standard_Integer lowerBound(const NCollection_Array1<BVH_EncodedLink>& theEncodedLinks,
0065 Standard_Integer theStart,
0066 Standard_Integer theFinal,
0067 Standard_Integer theDigit) const;
0068 };
0069
0070
0071
0072
0073
0074 template <class T, int N>
0075 BVH_LinearBuilder<T, N>::BVH_LinearBuilder(const Standard_Integer theLeafNodeSize,
0076 const Standard_Integer theMaxTreeDepth)
0077 : BVH_Builder<T, N>(theLeafNodeSize, theMaxTreeDepth)
0078 {
0079
0080 }
0081
0082
0083
0084
0085
0086 template <class T, int N>
0087 BVH_LinearBuilder<T, N>::~BVH_LinearBuilder()
0088 {
0089
0090 }
0091
0092
0093
0094
0095
0096 template <class T, int N>
0097 Standard_Integer BVH_LinearBuilder<T, N>::lowerBound(
0098 const NCollection_Array1<BVH_EncodedLink>& theEncodedLinks,
0099 Standard_Integer theStart,
0100 Standard_Integer theFinal,
0101 Standard_Integer theDigit) const
0102 {
0103 Standard_Integer aNbPrims = theFinal - theStart;
0104 unsigned int aBit = 1U << theDigit;
0105 while (aNbPrims > 0)
0106 {
0107 const Standard_Integer aStep = aNbPrims / 2;
0108 if (theEncodedLinks.Value(theStart + aStep).first & aBit)
0109 {
0110 aNbPrims = aStep;
0111 }
0112 else
0113 {
0114 theStart += aStep + 1;
0115 aNbPrims -= aStep + 1;
0116 }
0117 }
0118
0119 return theStart;
0120 }
0121
0122
0123
0124
0125
0126 template <class T, int N>
0127 Standard_Integer BVH_LinearBuilder<T, N>::emitHierachy(
0128 BVH_Tree<T, N>* theBVH,
0129 const NCollection_Array1<BVH_EncodedLink>& theEncodedLinks,
0130 const Standard_Integer theDigit,
0131 const Standard_Integer theShift,
0132 const Standard_Integer theStart,
0133 const Standard_Integer theFinal) const
0134 {
0135 if (theFinal - theStart > BVH_Builder<T, N>::myLeafNodeSize)
0136 {
0137 const Standard_Integer aPosition =
0138 theDigit < 0 ? (theStart + theFinal) / 2
0139 : lowerBound(theEncodedLinks, theStart, theFinal, theDigit);
0140 if (aPosition == theStart || aPosition == theFinal)
0141 {
0142 return emitHierachy(theBVH, theEncodedLinks, theDigit - 1, theShift, theStart, theFinal);
0143 }
0144
0145
0146 const Standard_Integer aNode = theBVH->AddInnerNode(0, 0);
0147 const Standard_Integer aRghNode = theShift + aPosition - theStart;
0148
0149 const Standard_Integer aLftChild =
0150 emitHierachy(theBVH, theEncodedLinks, theDigit - 1, theShift, theStart, aPosition);
0151 const Standard_Integer aRghChild =
0152 emitHierachy(theBVH, theEncodedLinks, theDigit - 1, aRghNode, aPosition, theFinal);
0153
0154 theBVH->NodeInfoBuffer()[aNode].y() = aLftChild;
0155 theBVH->NodeInfoBuffer()[aNode].z() = aRghChild;
0156 return aNode;
0157 }
0158 else
0159 {
0160
0161 return theBVH->AddLeafNode(theShift, theShift + theFinal - theStart - 1);
0162 }
0163 }
0164
0165 namespace BVH
0166 {
0167
0168 template <class T, int N>
0169 Standard_Integer UpdateBounds(BVH_Set<T, N>* theSet,
0170 BVH_Tree<T, N>* theTree,
0171 const Standard_Integer theNode = 0)
0172 {
0173 const BVH_Vec4i aData = theTree->NodeInfoBuffer()[theNode];
0174 if (aData.x() == 0)
0175 {
0176 const Standard_Integer aLftChild = theTree->NodeInfoBuffer()[theNode].y();
0177 const Standard_Integer aRghChild = theTree->NodeInfoBuffer()[theNode].z();
0178
0179 const Standard_Integer aLftDepth = UpdateBounds(theSet, theTree, aLftChild);
0180 const Standard_Integer aRghDepth = UpdateBounds(theSet, theTree, aRghChild);
0181
0182 typename BVH_Box<T, N>::BVH_VecNt aLftMinPoint = theTree->MinPointBuffer()[aLftChild];
0183 typename BVH_Box<T, N>::BVH_VecNt aLftMaxPoint = theTree->MaxPointBuffer()[aLftChild];
0184 typename BVH_Box<T, N>::BVH_VecNt aRghMinPoint = theTree->MinPointBuffer()[aRghChild];
0185 typename BVH_Box<T, N>::BVH_VecNt aRghMaxPoint = theTree->MaxPointBuffer()[aRghChild];
0186
0187 BVH::BoxMinMax<T, N>::CwiseMin(aLftMinPoint, aRghMinPoint);
0188 BVH::BoxMinMax<T, N>::CwiseMax(aLftMaxPoint, aRghMaxPoint);
0189
0190 theTree->MinPointBuffer()[theNode] = aLftMinPoint;
0191 theTree->MaxPointBuffer()[theNode] = aLftMaxPoint;
0192 return Max(aLftDepth, aRghDepth) + 1;
0193 }
0194 else
0195 {
0196 typename BVH_Box<T, N>::BVH_VecNt& aMinPoint = theTree->MinPointBuffer()[theNode];
0197 typename BVH_Box<T, N>::BVH_VecNt& aMaxPoint = theTree->MaxPointBuffer()[theNode];
0198 for (Standard_Integer aPrimIdx = aData.y(); aPrimIdx <= aData.z(); ++aPrimIdx)
0199 {
0200 const BVH_Box<T, N> aBox = theSet->Box(aPrimIdx);
0201 if (aPrimIdx == aData.y())
0202 {
0203 aMinPoint = aBox.CornerMin();
0204 aMaxPoint = aBox.CornerMax();
0205 }
0206 else
0207 {
0208 BVH::BoxMinMax<T, N>::CwiseMin(aMinPoint, aBox.CornerMin());
0209 BVH::BoxMinMax<T, N>::CwiseMax(aMaxPoint, aBox.CornerMax());
0210 }
0211 }
0212 }
0213 return 0;
0214 }
0215
0216 template <class T, int N>
0217 struct BoundData
0218 {
0219 BVH_Set<T, N>* mySet;
0220 BVH_Tree<T, N>* myBVH;
0221 Standard_Integer myNode;
0222 Standard_Integer myLevel;
0223 Standard_Integer* myHeight;
0224 };
0225
0226
0227 template <class T, int N>
0228 class UpdateBoundTask
0229 {
0230 public:
0231 UpdateBoundTask(const Standard_Boolean isParallel)
0232 : myIsParallel(isParallel)
0233 {
0234 }
0235
0236
0237 void operator()(const BoundData<T, N>& theData) const
0238 {
0239 if (theData.myBVH->IsOuter(theData.myNode) || theData.myLevel > 2)
0240 {
0241 *theData.myHeight = BVH::UpdateBounds(theData.mySet, theData.myBVH, theData.myNode);
0242 }
0243 else
0244 {
0245 Standard_Integer aLftHeight = 0;
0246 Standard_Integer aRghHeight = 0;
0247
0248 const Standard_Integer aLftChild = theData.myBVH->NodeInfoBuffer()[theData.myNode].y();
0249 const Standard_Integer aRghChild = theData.myBVH->NodeInfoBuffer()[theData.myNode].z();
0250
0251 std::vector<BoundData<T, N>> aList;
0252 aList.reserve(2);
0253 if (!theData.myBVH->IsOuter(aLftChild))
0254 {
0255 BoundData<T, N> aBoundData = {theData.mySet,
0256 theData.myBVH,
0257 aLftChild,
0258 theData.myLevel + 1,
0259 &aLftHeight};
0260 aList.push_back(aBoundData);
0261 }
0262 else
0263 {
0264 aLftHeight = BVH::UpdateBounds(theData.mySet, theData.myBVH, aLftChild);
0265 }
0266
0267 if (!theData.myBVH->IsOuter(aRghChild))
0268 {
0269 BoundData<T, N> aBoundData = {theData.mySet,
0270 theData.myBVH,
0271 aRghChild,
0272 theData.myLevel + 1,
0273 &aRghHeight};
0274 aList.push_back(aBoundData);
0275 }
0276 else
0277 {
0278 aRghHeight = BVH::UpdateBounds(theData.mySet, theData.myBVH, aRghChild);
0279 }
0280
0281 if (!aList.empty())
0282 {
0283 OSD_Parallel::ForEach(aList.begin(),
0284 aList.end(),
0285 UpdateBoundTask<T, N>(myIsParallel),
0286 !myIsParallel);
0287 }
0288
0289 typename BVH_Box<T, N>::BVH_VecNt aLftMinPoint = theData.myBVH->MinPointBuffer()[aLftChild];
0290 typename BVH_Box<T, N>::BVH_VecNt aLftMaxPoint = theData.myBVH->MaxPointBuffer()[aLftChild];
0291 typename BVH_Box<T, N>::BVH_VecNt aRghMinPoint = theData.myBVH->MinPointBuffer()[aRghChild];
0292 typename BVH_Box<T, N>::BVH_VecNt aRghMaxPoint = theData.myBVH->MaxPointBuffer()[aRghChild];
0293
0294 BVH::BoxMinMax<T, N>::CwiseMin(aLftMinPoint, aRghMinPoint);
0295 BVH::BoxMinMax<T, N>::CwiseMax(aLftMaxPoint, aRghMaxPoint);
0296
0297 theData.myBVH->MinPointBuffer()[theData.myNode] = aLftMinPoint;
0298 theData.myBVH->MaxPointBuffer()[theData.myNode] = aLftMaxPoint;
0299
0300 *theData.myHeight = Max(aLftHeight, aRghHeight) + 1;
0301 }
0302 }
0303
0304 private:
0305 Standard_Boolean myIsParallel;
0306 };
0307 }
0308
0309
0310
0311
0312
0313 template <class T, int N>
0314 void BVH_LinearBuilder<T, N>::Build(BVH_Set<T, N>* theSet,
0315 BVH_Tree<T, N>* theBVH,
0316 const BVH_Box<T, N>& theBox) const
0317 {
0318 Standard_STATIC_ASSERT(N == 2 || N == 3 || N == 4);
0319 const Standard_Integer aSetSize = theSet->Size();
0320 if (theBVH == NULL || aSetSize == 0)
0321 {
0322 return;
0323 }
0324
0325 theBVH->Clear();
0326
0327
0328 BVH_RadixSorter<T, N> aRadixSorter(theBox);
0329 aRadixSorter.SetParallel(this->IsParallel());
0330
0331
0332 aRadixSorter.Perform(theSet);
0333
0334
0335 emitHierachy(theBVH, aRadixSorter.EncodedLinks(), 29, 0, 0, theSet->Size());
0336
0337
0338 theBVH->MinPointBuffer().resize(theBVH->NodeInfoBuffer().size());
0339 theBVH->MaxPointBuffer().resize(theBVH->NodeInfoBuffer().size());
0340
0341 Standard_Integer aHeight = 0;
0342 BVH::BoundData<T, N> aBoundData = {theSet, theBVH, 0, 0, &aHeight};
0343 BVH::UpdateBoundTask<T, N> aBoundTask(this->IsParallel());
0344 aBoundTask(aBoundData);
0345
0346 BVH_Builder<T, N>::updateDepth(theBVH, aHeight);
0347 }
0348
0349 #endif