File indexing completed on 2026-05-18 08:29:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef _BVH_BinaryTree_Header
0017 #define _BVH_BinaryTree_Header
0018
0019 #include <BVH_QuadTree.hxx>
0020
0021 #include <deque>
0022 #include <tuple>
0023
0024
0025 template <class T, int N>
0026 class BVH_Tree<T, N, BVH_BinaryTree> : public BVH_TreeBase<T, N>
0027 {
0028 public:
0029 typedef typename BVH_TreeBase<T, N>::BVH_VecNt BVH_VecNt;
0030
0031 public:
0032
0033 BVH_Tree()
0034 : BVH_TreeBase<T, N>()
0035 {
0036 }
0037
0038
0039 void SetOuter(const int theNodeIndex)
0040 {
0041 BVH::Array<int, 4>::ChangeValue(this->myNodeInfoBuffer, theNodeIndex).x() = 1;
0042 }
0043
0044
0045 void SetInner(const int theNodeIndex)
0046 {
0047 BVH::Array<int, 4>::ChangeValue(this->myNodeInfoBuffer, theNodeIndex).x() = 0;
0048 }
0049
0050
0051
0052 template <int K>
0053 int Child(const int theNodeIndex) const
0054 {
0055 return BVH::Array<int, 4>::Value(this->myNodeInfoBuffer, theNodeIndex)[K + 1];
0056 }
0057
0058
0059
0060 template <int K>
0061 int& ChangeChild(const int theNodeIndex)
0062 {
0063 return BVH::Array<int, 4>::ChangeValue(this->myNodeInfoBuffer, theNodeIndex)[K + 1];
0064 }
0065
0066
0067
0068 template <int K>
0069 int& Child(const int theNodeIndex)
0070 {
0071 return BVH::Array<int, 4>::ChangeValue(this->myNodeInfoBuffer, theNodeIndex)[K + 1];
0072 }
0073
0074 public:
0075
0076 void Clear()
0077 {
0078 this->myDepth = 0;
0079 BVH::Array<T, N>::Clear(this->myMinPointBuffer);
0080 BVH::Array<T, N>::Clear(this->myMaxPointBuffer);
0081 BVH::Array<int, 4>::Clear(this->myNodeInfoBuffer);
0082 }
0083
0084
0085
0086 void Reserve(const int theNbNodes)
0087 {
0088 BVH::Array<T, N>::Reserve(this->myMinPointBuffer, theNbNodes);
0089 BVH::Array<T, N>::Reserve(this->myMaxPointBuffer, theNbNodes);
0090 BVH::Array<int, 4>::Reserve(this->myNodeInfoBuffer, theNbNodes);
0091 }
0092
0093
0094 int AddLeafNode(const BVH_VecNt& theMinPoint,
0095 const BVH_VecNt& theMaxPoint,
0096 const int theBegElem,
0097 const int theEndElem)
0098 {
0099 BVH::Array<T, N>::Append(this->myMinPointBuffer, theMinPoint);
0100 BVH::Array<T, N>::Append(this->myMaxPointBuffer, theMaxPoint);
0101 BVH::Array<int, 4>::Append(this->myNodeInfoBuffer, BVH_Vec4i(1, theBegElem, theEndElem, 0));
0102 return BVH::Array<int, 4>::Size(this->myNodeInfoBuffer) - 1;
0103 }
0104
0105
0106 int AddInnerNode(const BVH_VecNt& theMinPoint,
0107 const BVH_VecNt& theMaxPoint,
0108 const int theLftChild,
0109 const int theRghChild)
0110 {
0111 BVH::Array<T, N>::Append(this->myMinPointBuffer, theMinPoint);
0112 BVH::Array<T, N>::Append(this->myMaxPointBuffer, theMaxPoint);
0113 BVH::Array<int, 4>::Append(this->myNodeInfoBuffer, BVH_Vec4i(0, theLftChild, theRghChild, 0));
0114 return BVH::Array<int, 4>::Size(this->myNodeInfoBuffer) - 1;
0115 }
0116
0117
0118 int AddLeafNode(const BVH_Box<T, N>& theAABB, const int theBegElem, const int theEndElem)
0119 {
0120 return AddLeafNode(theAABB.CornerMin(), theAABB.CornerMax(), theBegElem, theEndElem);
0121 }
0122
0123
0124 int AddInnerNode(const BVH_Box<T, N>& theAABB, const int theLftChild, const int theRghChild)
0125 {
0126 return AddInnerNode(theAABB.CornerMin(), theAABB.CornerMax(), theLftChild, theRghChild);
0127 }
0128
0129
0130 int AddLeafNode(const int theBegElem, const int theEndElem)
0131 {
0132 BVH::Array<int, 4>::Append(this->myNodeInfoBuffer, BVH_Vec4i(1, theBegElem, theEndElem, 0));
0133 return BVH::Array<int, 4>::Size(this->myNodeInfoBuffer) - 1;
0134 }
0135
0136
0137 int AddInnerNode(const int theLftChild, const int theRghChild)
0138 {
0139 BVH::Array<int, 4>::Append(this->myNodeInfoBuffer, BVH_Vec4i(0, theLftChild, theRghChild, 0));
0140 return BVH::Array<int, 4>::Size(this->myNodeInfoBuffer) - 1;
0141 }
0142
0143 public:
0144
0145
0146
0147 T EstimateSAH() const;
0148
0149
0150
0151 BVH_Tree<T, N, BVH_QuadTree>* CollapseToQuadTree() const;
0152 };
0153
0154 namespace BVH
0155 {
0156
0157
0158 template <class T, int N>
0159 void EstimateSAH(const BVH_Tree<T, N, BVH_BinaryTree>* theTree,
0160 const int theNode,
0161 T theProb,
0162 T& theSAH)
0163 {
0164 BVH_Box<T, N> aBox(theTree->MinPoint(theNode), theTree->MaxPoint(theNode));
0165
0166 if (theTree->IsOuter(theNode))
0167 {
0168 theSAH += theProb * (theTree->EndPrimitive(theNode) - theTree->BegPrimitive(theNode) + 1);
0169 }
0170 else
0171 {
0172 theSAH += theProb * static_cast<T>(2.0);
0173
0174 BVH_Box<T, N> aLftBox(theTree->MinPoint(theTree->template Child<0>(theNode)),
0175 theTree->MaxPoint(theTree->template Child<0>(theNode)));
0176
0177 if (theProb > 0.0)
0178 {
0179 EstimateSAH(theTree,
0180 theTree->template Child<0>(theNode),
0181 theProb * aLftBox.Area() / aBox.Area(),
0182 theSAH);
0183 }
0184
0185 BVH_Box<T, N> aRghBox(theTree->MinPoint(theTree->template Child<1>(theNode)),
0186 theTree->MaxPoint(theTree->template Child<1>(theNode)));
0187
0188 if (theProb > 0.0)
0189 {
0190 EstimateSAH(theTree,
0191 theTree->template Child<1>(theNode),
0192 theProb * aRghBox.Area() / aBox.Area(),
0193 theSAH);
0194 }
0195 }
0196 }
0197 }
0198
0199
0200
0201
0202
0203 template <class T, int N>
0204 T BVH_Tree<T, N, BVH_BinaryTree>::EstimateSAH() const
0205 {
0206 T aSAH = static_cast<T>(0.0);
0207 BVH::EstimateSAH<T, N>(this, 0, static_cast<T>(1.0), aSAH);
0208 return aSAH;
0209 }
0210
0211
0212
0213
0214
0215 template <class T, int N>
0216 BVH_Tree<T, N, BVH_QuadTree>* BVH_Tree<T, N, BVH_BinaryTree>::CollapseToQuadTree() const
0217 {
0218 BVH_Tree<T, N, BVH_QuadTree>* aQBVH = new BVH_Tree<T, N, BVH_QuadTree>;
0219
0220 if (this->Length() == 0)
0221 {
0222 return aQBVH;
0223 }
0224
0225 std::deque<std::pair<int, int>> aQueue(1, std::make_pair(0, 0));
0226
0227 for (int aNbNodes = 1; !aQueue.empty();)
0228 {
0229 const std::pair<int, int> aNode = aQueue.front();
0230
0231 BVH::Array<T, N>::Append(aQBVH->myMinPointBuffer,
0232 BVH::Array<T, N>::Value(this->myMinPointBuffer, std::get<0>(aNode)));
0233 BVH::Array<T, N>::Append(aQBVH->myMaxPointBuffer,
0234 BVH::Array<T, N>::Value(this->myMaxPointBuffer, std::get<0>(aNode)));
0235
0236 BVH_Vec4i aNodeInfo;
0237 if (this->IsOuter(std::get<0>(aNode)))
0238 {
0239 aNodeInfo = BVH_Vec4i(1 ,
0240 this->BegPrimitive(std::get<0>(aNode)),
0241 this->EndPrimitive(std::get<0>(aNode)),
0242 std::get<1>(aNode) );
0243 }
0244 else
0245 {
0246 NCollection_Vector<int> aGrandChildNodes;
0247
0248 const int aLftChild = Child<0>(std::get<0>(aNode));
0249 const int aRghChild = Child<1>(std::get<0>(aNode));
0250 if (this->IsOuter(aLftChild))
0251 {
0252 aGrandChildNodes.Append(aLftChild);
0253 }
0254 else
0255 {
0256 aGrandChildNodes.Append(Child<0>(aLftChild));
0257 aGrandChildNodes.Append(Child<1>(aLftChild));
0258 }
0259
0260 if (this->IsOuter(aRghChild))
0261 {
0262 aGrandChildNodes.Append(aRghChild);
0263 }
0264 else
0265 {
0266 aGrandChildNodes.Append(Child<0>(aRghChild));
0267 aGrandChildNodes.Append(Child<1>(aRghChild));
0268 }
0269
0270 for (int aNodeIdx = 0; aNodeIdx < aGrandChildNodes.Size(); ++aNodeIdx)
0271 {
0272 aQueue.push_back(std::make_pair(aGrandChildNodes(aNodeIdx), std::get<1>(aNode) + 1));
0273 }
0274
0275 aNodeInfo = BVH_Vec4i(0 ,
0276 aNbNodes,
0277 aGrandChildNodes.Size() - 1,
0278 std::get<1>(aNode) );
0279
0280 aQBVH->myDepth = Max(aQBVH->myDepth, std::get<1>(aNode) + 1);
0281
0282 aNbNodes += aGrandChildNodes.Size();
0283 }
0284
0285 BVH::Array<int, 4>::Append(aQBVH->myNodeInfoBuffer, aNodeInfo);
0286 aQueue.pop_front();
0287 }
0288
0289 return aQBVH;
0290 }
0291
0292 #endif