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