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_QueueBuilder_Header
0017 #define _BVH_QueueBuilder_Header
0018
0019 #include <BVH_Builder.hxx>
0020 #include <BVH_BuildThread.hxx>
0021 #include <NCollection_Vector.hxx>
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 template<class T, int N>
0034 class BVH_QueueBuilder : public BVH_Builder<T, N>
0035 {
0036 public:
0037
0038
0039 BVH_QueueBuilder (const Standard_Integer theLeafNodeSize,
0040 const Standard_Integer theMaxTreeDepth,
0041 const Standard_Integer theNumOfThreads = 1)
0042 : BVH_Builder<T, N> (theLeafNodeSize,
0043 theMaxTreeDepth),
0044 myNumOfThreads (theNumOfThreads) {}
0045
0046
0047 virtual ~BVH_QueueBuilder() {}
0048
0049 public:
0050
0051
0052 virtual void Build (BVH_Set<T, N>* theSet,
0053 BVH_Tree<T, N>* theBVH,
0054 const BVH_Box<T, N>& theBox) const Standard_OVERRIDE;
0055
0056 protected:
0057
0058
0059 struct BVH_PrimitiveRange
0060 {
0061 Standard_Integer Start;
0062 Standard_Integer Final;
0063
0064
0065 BVH_PrimitiveRange (Standard_Integer theStart = -1,
0066 Standard_Integer theFinal = -1)
0067 : Start (theStart),
0068 Final (theFinal)
0069 {
0070
0071 }
0072
0073
0074 Standard_Integer Size() const
0075 {
0076 return Final - Start + 1;
0077 }
0078
0079
0080 Standard_Boolean IsValid() const
0081 {
0082 return Start != -1;
0083 }
0084 };
0085
0086
0087 struct BVH_ChildNodes
0088 {
0089
0090 BVH_Box<T, N> Boxes[2];
0091
0092
0093 BVH_PrimitiveRange Ranges[2];
0094
0095
0096 BVH_ChildNodes()
0097 {
0098
0099 }
0100
0101
0102 BVH_ChildNodes (const BVH_Box<T, N>& theLftBox,
0103 const BVH_Box<T, N>& theRghBox,
0104 const BVH_PrimitiveRange& theLftRange,
0105 const BVH_PrimitiveRange& theRghRange)
0106 {
0107 Boxes[0] = theLftBox;
0108 Boxes[1] = theRghBox;
0109 Ranges[0] = theLftRange;
0110 Ranges[1] = theRghRange;
0111 }
0112
0113
0114 Standard_Integer NbPrims (const Standard_Integer theChild) const
0115 {
0116 return Ranges[theChild].Size();
0117 }
0118
0119
0120 Standard_Boolean IsValid() const
0121 {
0122 return Ranges[0].IsValid() && Ranges[1].IsValid();
0123 }
0124 };
0125
0126
0127 class BVH_TypedBuildTool : public BVH_BuildTool
0128 {
0129 public:
0130
0131
0132 BVH_TypedBuildTool (BVH_Set<T, N>* theSet,
0133 BVH_Tree<T, N>* theBVH,
0134 BVH_BuildQueue& theBuildQueue,
0135 const BVH_QueueBuilder<T, N>* theAlgo)
0136 : mySet (theSet),
0137 myBVH (theBVH),
0138 myBuildQueue (&theBuildQueue),
0139 myAlgo (theAlgo)
0140 {
0141 Standard_ASSERT_RAISE (myAlgo != NULL, "Error! BVH builder should be queue based");
0142 }
0143
0144
0145 virtual void Perform (const Standard_Integer theNode) Standard_OVERRIDE
0146 {
0147 const typename BVH_QueueBuilder<T, N>::BVH_ChildNodes aChildren = myAlgo->buildNode (mySet, myBVH, theNode);
0148 myAlgo->addChildren (myBVH, *myBuildQueue, theNode, aChildren);
0149 }
0150
0151 protected:
0152
0153 BVH_Set<T, N>* mySet;
0154 BVH_Tree<T, N>* myBVH;
0155 BVH_BuildQueue* myBuildQueue;
0156 const BVH_QueueBuilder<T, N>* myAlgo;
0157
0158 };
0159
0160 protected:
0161
0162
0163 virtual typename BVH_QueueBuilder<T, N>::BVH_ChildNodes buildNode (BVH_Set<T, N>* theSet,
0164 BVH_Tree<T, N>* theBVH,
0165 const Standard_Integer theNode) const = 0;
0166
0167
0168 virtual void addChildren (BVH_Tree<T, N>* theBVH,
0169 BVH_BuildQueue& theBuildQueue,
0170 const Standard_Integer theNode,
0171 const BVH_ChildNodes& theSubNodes) const;
0172
0173 protected:
0174
0175 Standard_Integer myNumOfThreads;
0176
0177 };
0178
0179
0180
0181
0182
0183 template<class T, int N>
0184 void BVH_QueueBuilder<T, N>::addChildren (BVH_Tree<T, N>* theBVH,
0185 BVH_BuildQueue& theBuildQueue,
0186 const Standard_Integer theNode,
0187 const typename BVH_QueueBuilder<T, N>::BVH_ChildNodes& theSubNodes) const
0188 {
0189 Standard_Integer aChildren[] = { -1, -1 };
0190 if (!theSubNodes.IsValid())
0191 {
0192 return;
0193 }
0194
0195
0196 {
0197 Standard_Mutex::Sentry aSentry (theBuildQueue.myMutex);
0198
0199 for (Standard_Integer anIdx = 0; anIdx < 2; ++anIdx)
0200 {
0201 aChildren[anIdx] = theBVH->AddLeafNode (theSubNodes.Boxes[anIdx],
0202 theSubNodes.Ranges[anIdx].Start,
0203 theSubNodes.Ranges[anIdx].Final);
0204 }
0205
0206 BVH_Builder<T, N>::updateDepth (theBVH, theBVH->Level (theNode) + 1);
0207 }
0208
0209
0210 for (Standard_Integer anIdx = 0; anIdx < 2; ++anIdx)
0211 {
0212 const Standard_Integer aChildIndex = aChildren[anIdx];
0213
0214 theBVH->Level (aChildIndex) = theBVH->Level (theNode) + 1;
0215
0216 (anIdx == 0 ? theBVH->template Child<0> (theNode)
0217 : theBVH->template Child<1> (theNode)) = aChildIndex;
0218
0219
0220 const Standard_Boolean isLeaf = theSubNodes.NbPrims (anIdx) <= BVH_Builder<T, N>::myLeafNodeSize
0221 || theBVH->Level (aChildIndex) >= BVH_Builder<T, N>::myMaxTreeDepth;
0222
0223 if (!isLeaf)
0224 {
0225 theBuildQueue.Enqueue (aChildIndex);
0226 }
0227 }
0228 }
0229
0230
0231
0232
0233
0234 template<class T, int N>
0235 void BVH_QueueBuilder<T, N>::Build (BVH_Set<T, N>* theSet,
0236 BVH_Tree<T, N>* theBVH,
0237 const BVH_Box<T, N>& theBox) const
0238 {
0239 Standard_ASSERT_RETURN (theBVH != NULL,
0240 "Error! BVH tree to construct is NULL", );
0241
0242 theBVH->Clear();
0243 const Standard_Integer aSetSize = theSet->Size();
0244 if (aSetSize == 0)
0245 {
0246 return;
0247 }
0248
0249 const Standard_Integer aRoot = theBVH->AddLeafNode (theBox, 0, aSetSize - 1);
0250 if (theSet->Size() == 1)
0251 {
0252 return;
0253 }
0254
0255 BVH_BuildQueue aBuildQueue;
0256 aBuildQueue.Enqueue (aRoot);
0257
0258 BVH_TypedBuildTool aBuildTool (theSet, theBVH, aBuildQueue, this);
0259 if (myNumOfThreads > 1)
0260 {
0261
0262 theBVH->Reserve (2 * aSetSize - 1);
0263
0264 NCollection_Vector<Handle(BVH_BuildThread)> aThreads;
0265
0266
0267 for (Standard_Integer aThreadIndex = 0; aThreadIndex < myNumOfThreads; ++aThreadIndex)
0268 {
0269 aThreads.Append (new BVH_BuildThread (aBuildTool, aBuildQueue));
0270 aThreads.Last()->Run();
0271 }
0272
0273
0274 for (Standard_Integer aThreadIndex = 0; aThreadIndex < myNumOfThreads; ++aThreadIndex)
0275 {
0276 aThreads.ChangeValue (aThreadIndex)->Wait();
0277 }
0278
0279
0280 theBVH->Reserve (theBVH->Length());
0281 }
0282 else
0283 {
0284 BVH_BuildThread aThread (aBuildTool, aBuildQueue);
0285
0286
0287 aThread.execute();
0288 }
0289 }
0290
0291 #endif