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