diff --git a/src/BVH/BVH_BinaryTree.hxx b/src/BVH/BVH_BinaryTree.hxx index 52b898434c..80d36aca17 100644 --- a/src/BVH/BVH_BinaryTree.hxx +++ b/src/BVH/BVH_BinaryTree.hxx @@ -18,6 +18,9 @@ #include <BVH_QuadTree.hxx> +#include <deque> +#include <tuple> + //! Specialization of binary BVH tree. template<class T, int N> class BVH_Tree<T, N, BVH_BinaryTree> : public BVH_TreeBase<T, N> @@ -32,59 +35,101 @@ public: //! @name methods for accessing individual nodes BVH_Tree() : BVH_TreeBase<T, N>() { } //! Sets node type to 'outer'. - void SetOuter (const int theNodeIndex); + void SetOuter (const int theNodeIndex) { BVH::Array<int, 4>::ChangeValue (this->myNodeInfoBuffer, theNodeIndex).x() = 1; } //! Sets node type to 'inner'. - void SetInner (const int theNodeIndex); + void SetInner (const int theNodeIndex) { BVH::Array<int, 4>::ChangeValue (this->myNodeInfoBuffer, theNodeIndex).x() = 0; } //! Returns index of the K-th child of the given inner node. //! \tparam K the index of node child (0 or 1) template<int K> - int Child (const int theNodeIndex) const; + int Child (const int theNodeIndex) const { return BVH::Array<int, 4>::Value (this->myNodeInfoBuffer, theNodeIndex)[K + 1]; } //! Returns index of the K-th child of the given inner node. //! \tparam K the index of node child (0 or 1) template<int K> - int& Child (const int theNodeIndex); + int& ChangeChild (const int theNodeIndex) { return BVH::Array<int, 4>::ChangeValue (this->myNodeInfoBuffer, theNodeIndex)[K + 1]; } + + //! Returns index of the K-th child of the given inner node. + //! \tparam K the index of node child (0 or 1) + template<int K> + int& Child (const int theNodeIndex) { return BVH::Array<int, 4>::ChangeValue (this->myNodeInfoBuffer, theNodeIndex)[K + 1]; } public: //! @name methods for adding/removing tree nodes //! Removes all nodes from the tree. - void Clear(); + void Clear() + { + this->myDepth = 0; + BVH::Array<T, N>::Clear (this->myMinPointBuffer); + BVH::Array<T, N>::Clear (this->myMaxPointBuffer); + BVH::Array<int, 4>::Clear(this->myNodeInfoBuffer); + } //! Reserves internal BVH storage, so that it //! can contain the given number of BVH nodes. - void Reserve (const int theNbNodes); + void Reserve (const int theNbNodes) + { + BVH::Array<T, N>::Reserve (this->myMinPointBuffer, theNbNodes); + BVH::Array<T, N>::Reserve (this->myMaxPointBuffer, theNbNodes); + BVH::Array<int, 4>::Reserve (this->myNodeInfoBuffer, theNbNodes); + } //! Adds new leaf node to the BVH. int AddLeafNode (const BVH_VecNt& theMinPoint, const BVH_VecNt& theMaxPoint, const int theBegElem, - const int theEndElem); + const int theEndElem) + { + BVH::Array<T, N>::Append (this->myMinPointBuffer, theMinPoint); + BVH::Array<T, N>::Append (this->myMaxPointBuffer, theMaxPoint); + BVH::Array<int, 4>::Append (this->myNodeInfoBuffer, BVH_Vec4i (1, theBegElem, theEndElem, 0)); + return BVH::Array<int, 4>::Size (this->myNodeInfoBuffer) - 1; + } //! Adds new inner node to the BVH. int AddInnerNode (const BVH_VecNt& theMinPoint, const BVH_VecNt& theMaxPoint, const int theLftChild, - const int theRghChild); + const int theRghChild) + { + BVH::Array<T, N>::Append (this->myMinPointBuffer, theMinPoint); + BVH::Array<T, N>::Append (this->myMaxPointBuffer, theMaxPoint); + BVH::Array<int, 4>::Append (this->myNodeInfoBuffer, BVH_Vec4i (0, theLftChild, theRghChild, 0)); + return BVH::Array<int, 4>::Size (this->myNodeInfoBuffer) - 1; + } //! Adds new leaf node to the BVH. int AddLeafNode (const BVH_Box<T, N>& theAABB, const int theBegElem, - const int theEndElem); + const int theEndElem) + { + return AddLeafNode (theAABB.CornerMin(), theAABB.CornerMax(), theBegElem, theEndElem); + } //! Adds new inner node to the BVH. int AddInnerNode (const BVH_Box<T, N>& theAABB, const int theLftChild, - const int theRghChild); + const int theRghChild) + { + return AddInnerNode (theAABB.CornerMin(), theAABB.CornerMax(), theLftChild, theRghChild); + } //! Adds new leaf node to the BVH with UNINITIALIZED bounds. int AddLeafNode (const int theBegElem, - const int theEndElem); + const int theEndElem) + { + BVH::Array<int, 4>::Append (this->myNodeInfoBuffer, BVH_Vec4i (1, theBegElem, theEndElem, 0)); + return BVH::Array<int, 4>::Size (this->myNodeInfoBuffer) - 1; + } //! Adds new inner node to the BVH with UNINITIALIZED bounds. int AddInnerNode (const int theLftChild, - const int theRghChild); + const int theRghChild) + { + BVH::Array<int, 4>::Append (this->myNodeInfoBuffer, BVH_Vec4i (0, theLftChild, theRghChild, 0)); + return BVH::Array<int, 4>::Size (this->myNodeInfoBuffer) - 1; + } public: //! @name methods specific to binary BVH @@ -99,6 +144,130 @@ public: //! @name methods specific to binary BVH }; -#include <BVH_BinaryTree.lxx> +namespace BVH +{ + //! Internal function for recursive calculation of + //! surface area heuristic (SAH) of the given tree. + template<class T, int N> + void EstimateSAH (const BVH_Tree<T, N, BVH_BinaryTree>* theTree, const int theNode, T theProb, T& theSAH) + { + BVH_Box<T, N> aBox (theTree->MinPoint (theNode), + theTree->MaxPoint (theNode)); + + if (theTree->IsOuter (theNode)) + { + theSAH += theProb * (theTree->EndPrimitive (theNode) - theTree->BegPrimitive (theNode) + 1); + } + else + { + theSAH += theProb * static_cast<T> (2.0); + + BVH_Box<T, N> aLftBox (theTree->MinPoint (theTree->template Child<0> (theNode)), + theTree->MaxPoint (theTree->template Child<0> (theNode))); + + if (theProb > 0.0) + { + EstimateSAH (theTree, theTree->template Child<0> (theNode), + theProb * aLftBox.Area() / aBox.Area(), theSAH); + } + + BVH_Box<T, N> aRghBox (theTree->MinPoint (theTree->template Child<1> (theNode)), + theTree->MaxPoint (theTree->template Child<1> (theNode))); + + if (theProb > 0.0) + { + EstimateSAH (theTree, theTree->template Child<1> (theNode), + theProb * aRghBox.Area() / aBox.Area(), theSAH); + } + } + } +} + +// ======================================================================= +// function : EstimateSAH +// purpose : +// ======================================================================= +template<class T, int N> +T BVH_Tree<T, N, BVH_BinaryTree>::EstimateSAH() const +{ + T aSAH = static_cast<T> (0.0); + BVH::EstimateSAH<T, N> (this, 0, static_cast<T> (1.0), aSAH); + return aSAH; +} + +// ======================================================================= +// function : CollapseToQuadTree +// purpose : +// ======================================================================= +template<class T, int N> +BVH_Tree<T, N, BVH_QuadTree>* BVH_Tree<T, N, BVH_BinaryTree>::CollapseToQuadTree() const +{ + BVH_Tree<T, N, BVH_QuadTree>* aQBVH = new BVH_Tree<T, N, BVH_QuadTree>; + + if (this->Length() == 0) + { + return aQBVH; + } + + std::deque<std::pair<int, int> > aQueue (1, std::make_pair (0, 0)); + + for (int aNbNodes = 1; !aQueue.empty();) + { + const std::pair<int, int> aNode = aQueue.front(); + + BVH::Array<T, N>::Append (aQBVH->myMinPointBuffer, BVH::Array<T, N>::Value (this->myMinPointBuffer, std::get<0> (aNode))); + BVH::Array<T, N>::Append (aQBVH->myMaxPointBuffer, BVH::Array<T, N>::Value (this->myMaxPointBuffer, std::get<0> (aNode))); + + BVH_Vec4i aNodeInfo; + if (this->IsOuter (std::get<0> (aNode))) // is leaf node + { + aNodeInfo = BVH_Vec4i (1 /* leaf flag */, + this->BegPrimitive (std::get<0> (aNode)), this->EndPrimitive (std::get<0> (aNode)), std::get<1> (aNode) /* level */); + } + else + { + NCollection_Vector<int> aGrandChildNodes; + + const int aLftChild = Child<0> (std::get<0> (aNode)); + const int aRghChild = Child<1> (std::get<0> (aNode)); + if (this->IsOuter (aLftChild)) // is leaf node + { + aGrandChildNodes.Append (aLftChild); + } + else + { + aGrandChildNodes.Append (Child<0> (aLftChild)); + aGrandChildNodes.Append (Child<1> (aLftChild)); + } + + if (this->IsOuter (aRghChild)) // is leaf node + { + aGrandChildNodes.Append (aRghChild); + } + else + { + aGrandChildNodes.Append (Child<0> (aRghChild)); + aGrandChildNodes.Append (Child<1> (aRghChild)); + } + + for (int aNodeIdx = 0; aNodeIdx < aGrandChildNodes.Size(); ++aNodeIdx) + { + aQueue.push_back (std::make_pair (aGrandChildNodes (aNodeIdx), std::get<1> (aNode) + 1)); + } + + aNodeInfo = BVH_Vec4i (0 /* inner flag */, + aNbNodes, aGrandChildNodes.Size() - 1, std::get<1> (aNode) /* level */); + + aQBVH->myDepth = Max (aQBVH->myDepth, std::get<1> (aNode) + 1); + + aNbNodes += aGrandChildNodes.Size(); + } + + BVH::Array<int, 4>::Append (aQBVH->myNodeInfoBuffer, aNodeInfo); + aQueue.pop_front(); // node processing completed + } + + return aQBVH; +} #endif // _BVH_BinaryTree_Header diff --git a/src/BVH/BVH_BinaryTree.lxx b/src/BVH/BVH_BinaryTree.lxx deleted file mode 100644 index 54a036da80..0000000000 --- a/src/BVH/BVH_BinaryTree.lxx +++ /dev/null @@ -1,307 +0,0 @@ -// Created on: 2016-06-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2016 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include <deque> -#include <tuple> - -// ======================================================================= -// function : Child -// purpose : Returns index of the K-th child of the given inner node -// ======================================================================= -template<class T, int N> template<int K> -int& BVH_Tree<T, N, BVH_BinaryTree>::Child (const int theNodeIndex) -{ - return BVH::Array<int, 4>::ChangeValue (this->myNodeInfoBuffer, theNodeIndex)[K + 1]; -} - -// ======================================================================= -// function : Child -// purpose : Returns index of the K-th child of the given inner node -// ======================================================================= -template<class T, int N> template<int K> -int BVH_Tree<T, N, BVH_BinaryTree>::Child (const int theNodeIndex) const -{ - return BVH::Array<int, 4>::Value (this->myNodeInfoBuffer, theNodeIndex)[K + 1]; -} - -// ======================================================================= -// function : SetOuter -// purpose : Sets node type to 'outer' -// ======================================================================= -template<class T, int N> -void BVH_Tree<T, N, BVH_BinaryTree>::SetOuter (const int theNodeIndex) -{ - BVH::Array<int, 4>::ChangeValue (this->myNodeInfoBuffer, theNodeIndex).x() = 1; -} - -// ======================================================================= -// function : SetOuter -// purpose : Sets node type to 'inner' -// ======================================================================= -template<class T, int N> -void BVH_Tree<T, N, BVH_BinaryTree>::SetInner (const int theNodeIndex) -{ - BVH::Array<int, 4>::ChangeValue (this->myNodeInfoBuffer, theNodeIndex).x() = 0; -} - -// ======================================================================= -// function : Clear -// purpose : Removes all BVH nodes -// ======================================================================= -template<class T, int N> -void BVH_Tree<T, N, BVH_BinaryTree>::Clear() -{ - this->myDepth = 0; - - BVH::Array<T, N>::Clear (this->myMinPointBuffer); - BVH::Array<T, N>::Clear (this->myMaxPointBuffer); - - BVH::Array<int, 4>::Clear (this->myNodeInfoBuffer); -} - -// ======================================================================= -// function : AddLeafNode -// purpose : Adds new leaf node to the BVH -// ======================================================================= -template<class T, int N> -int BVH_Tree<T, N, BVH_BinaryTree>::AddLeafNode (const int theBegElem, - const int theEndElem) -{ - BVH::Array<int, 4>::Append (this->myNodeInfoBuffer, BVH_Vec4i (1, theBegElem, theEndElem, 0)); - - return BVH::Array<int, 4>::Size (this->myNodeInfoBuffer) - 1; -} - -// ======================================================================= -// function : AddInnerNode -// purpose : Adds new inner node to the BVH -// ======================================================================= -template<class T, int N> -int BVH_Tree<T, N, BVH_BinaryTree>::AddInnerNode (const int theLftChild, - const int theRghChild) -{ - BVH::Array<int, 4>::Append (this->myNodeInfoBuffer, BVH_Vec4i (0, theLftChild, theRghChild, 0)); - - return BVH::Array<int, 4>::Size (this->myNodeInfoBuffer) - 1; -} - -// ======================================================================= -// function : AddLeafNode -// purpose : Adds new leaf node to the BVH -// ======================================================================= -template<class T, int N> -int BVH_Tree<T, N, BVH_BinaryTree>::AddLeafNode (const BVH_VecNt& theMinPoint, - const BVH_VecNt& theMaxPoint, - const int theBegElem, - const int theEndElem) -{ - BVH::Array<T, N>::Append (this->myMinPointBuffer, theMinPoint); - BVH::Array<T, N>::Append (this->myMaxPointBuffer, theMaxPoint); - - BVH::Array<int, 4>::Append (this->myNodeInfoBuffer, BVH_Vec4i (1, theBegElem, theEndElem, 0)); - - return BVH::Array<int, 4>::Size (this->myNodeInfoBuffer) - 1; -} - -// ======================================================================= -// function : AddInnerNode -// purpose : Adds new inner node to the BVH -// ======================================================================= -template<class T, int N> -int BVH_Tree<T, N, BVH_BinaryTree>::AddInnerNode (const BVH_VecNt& theMinPoint, - const BVH_VecNt& theMaxPoint, - const int theLftChild, - const int theRghChild) -{ - BVH::Array<T, N>::Append (this->myMinPointBuffer, theMinPoint); - BVH::Array<T, N>::Append (this->myMaxPointBuffer, theMaxPoint); - - BVH::Array<int, 4>::Append (this->myNodeInfoBuffer, BVH_Vec4i (0, theLftChild, theRghChild, 0)); - - return BVH::Array<int, 4>::Size (this->myNodeInfoBuffer) - 1; -} - -// ======================================================================= -// function : AddLeafNode -// purpose : Adds new leaf node to the BVH -// ======================================================================= -template<class T, int N> -int BVH_Tree<T, N, BVH_BinaryTree>::AddLeafNode (const BVH_Box<T, N>& theAABB, - const int theBegElem, - const int theEndElem) -{ - return AddLeafNode (theAABB.CornerMin(), - theAABB.CornerMax(), - theBegElem, - theEndElem); -} - -// ======================================================================= -// function : AddInnerNode -// purpose : Adds new inner node to the BVH -// ======================================================================= -template<class T, int N> -int BVH_Tree<T, N, BVH_BinaryTree>::AddInnerNode (const BVH_Box<T, N>& theAABB, - const int theLftChild, - const int theRghChild) -{ - return AddInnerNode (theAABB.CornerMin(), - theAABB.CornerMax(), - theLftChild, - theRghChild); -} - -namespace BVH -{ - //! Internal function for recursive calculation of - //! surface area heuristic (SAH) of the given tree. - template<class T, int N> - void EstimateSAH (const BVH_Tree<T, N, BVH_BinaryTree>* theTree, const int theNode, T theProb, T& theSAH) - { - BVH_Box<T, N> aBox (theTree->MinPoint (theNode), - theTree->MaxPoint (theNode)); - - if (theTree->IsOuter (theNode)) - { - theSAH += theProb * (theTree->EndPrimitive (theNode) - theTree->BegPrimitive (theNode) + 1); - } - else - { - theSAH += theProb * static_cast<T> (2.0); - - BVH_Box<T, N> aLftBox (theTree->MinPoint (theTree->template Child<0> (theNode)), - theTree->MaxPoint (theTree->template Child<0> (theNode))); - - if (theProb > 0.0) - { - EstimateSAH (theTree, theTree->template Child<0> (theNode), - theProb * aLftBox.Area() / aBox.Area(), theSAH); - } - - BVH_Box<T, N> aRghBox (theTree->MinPoint (theTree->template Child<1> (theNode)), - theTree->MaxPoint (theTree->template Child<1> (theNode))); - - if (theProb > 0.0) - { - EstimateSAH (theTree, theTree->template Child<1> (theNode), - theProb * aRghBox.Area() / aBox.Area(), theSAH); - } - } - } -} - -// ======================================================================= -// function : EstimateSAH -// purpose : -// ======================================================================= -template<class T, int N> -T BVH_Tree<T, N, BVH_BinaryTree>::EstimateSAH() const -{ - T aSAH = static_cast<T> (0.0); - - BVH::EstimateSAH<T, N> (this, 0, static_cast<T> (1.0), aSAH); - - return aSAH; -} - -// ======================================================================= -// function : Reserve -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_Tree<T, N, BVH_BinaryTree>::Reserve (const int theNbNodes) -{ - BVH::Array<T, N>::Reserve (this->myMinPointBuffer, theNbNodes); - BVH::Array<T, N>::Reserve (this->myMaxPointBuffer, theNbNodes); - BVH::Array<int, 4>::Reserve (this->myNodeInfoBuffer, theNbNodes); -} - -// ======================================================================= -// function : CollapseToQuadTree -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Tree<T, N, BVH_QuadTree>* BVH_Tree<T, N, BVH_BinaryTree>::CollapseToQuadTree() const -{ - BVH_Tree<T, N, BVH_QuadTree>* aQBVH = new BVH_Tree<T, N, BVH_QuadTree>; - - if (this->Length() == 0) - { - return aQBVH; - } - - std::deque<std::pair<int, int> > aQueue (1, std::make_pair (0, 0)); - - for (int aNbNodes = 1; !aQueue.empty();) - { - const std::pair<int, int> aNode = aQueue.front(); - - BVH::Array<T, N>::Append (aQBVH->myMinPointBuffer, BVH::Array<T, N>::Value (this->myMinPointBuffer, std::get<0> (aNode))); - BVH::Array<T, N>::Append (aQBVH->myMaxPointBuffer, BVH::Array<T, N>::Value (this->myMaxPointBuffer, std::get<0> (aNode))); - - BVH_Vec4i aNodeInfo; - - if (this->IsOuter (std::get<0> (aNode))) // is leaf node - { - aNodeInfo = BVH_Vec4i (1 /* leaf flag */, - this->BegPrimitive (std::get<0> (aNode)), this->EndPrimitive (std::get<0> (aNode)), std::get<1> (aNode) /* level */); - } - else - { - NCollection_Vector<int> aGrandChildNodes; - - const int aLftChild = Child<0> (std::get<0> (aNode)); - const int aRghChild = Child<1> (std::get<0> (aNode)); - - if (this->IsOuter (aLftChild)) // is leaf node - { - aGrandChildNodes.Append (aLftChild); - } - else - { - aGrandChildNodes.Append (Child<0> (aLftChild)); - aGrandChildNodes.Append (Child<1> (aLftChild)); - } - - if (this->IsOuter (aRghChild)) // is leaf node - { - aGrandChildNodes.Append (aRghChild); - } - else - { - aGrandChildNodes.Append (Child<0> (aRghChild)); - aGrandChildNodes.Append (Child<1> (aRghChild)); - } - - for (int aNodeIdx = 0; aNodeIdx < aGrandChildNodes.Size(); ++aNodeIdx) - { - aQueue.push_back (std::make_pair (aGrandChildNodes (aNodeIdx), std::get<1> (aNode) + 1)); - } - - aNodeInfo = BVH_Vec4i (0 /* inner flag */, - aNbNodes, aGrandChildNodes.Size() - 1, std::get<1> (aNode) /* level */); - - aQBVH->myDepth = Max (aQBVH->myDepth, std::get<1> (aNode) + 1); - - aNbNodes += aGrandChildNodes.Size(); - } - - BVH::Array<int, 4>::Append (aQBVH->myNodeInfoBuffer, aNodeInfo); - - aQueue.pop_front(); // node processing completed - } - - return aQBVH; -} diff --git a/src/BVH/BVH_BinnedBuilder.hxx b/src/BVH/BVH_BinnedBuilder.hxx index 011295f8a5..eb21a8d256 100644 --- a/src/BVH/BVH_BinnedBuilder.hxx +++ b/src/BVH/BVH_BinnedBuilder.hxx @@ -20,6 +20,12 @@ #include <algorithm> +#if defined (_WIN32) && defined (max) + #undef max +#endif + +#include <limits> + //! Stores parameters of single bin (slice of AABB). template<class T, int N> struct BVH_Bin @@ -61,24 +67,29 @@ public: BVH_BinnedBuilder (const Standard_Integer theLeafNodeSize = 5, const Standard_Integer theMaxTreeDepth = 32, const Standard_Boolean theDoMainSplits = 0, - const Standard_Integer theNumOfThreads = 1); + const Standard_Integer theNumOfThreads = 1) + : BVH_QueueBuilder<T, N> (theLeafNodeSize, theMaxTreeDepth, theNumOfThreads), + myUseMainAxis (theDoMainSplits) + { + // + } //! Releases resources of binned SAH BVH builder. - virtual ~BVH_BinnedBuilder(); + virtual ~BVH_BinnedBuilder() {} protected: //! Performs splitting of the given BVH node. - typename BVH_QueueBuilder<T, N>::BVH_ChildNodes BuildNode (BVH_Set<T, N>* theSet, - BVH_Tree<T, N>* theBVH, - const Standard_Integer theNode); + virtual typename BVH_QueueBuilder<T, N>::BVH_ChildNodes buildNode (BVH_Set<T, N>* theSet, + BVH_Tree<T, N>* theBVH, + const Standard_Integer theNode) const Standard_OVERRIDE; //! Arranges node primitives into bins. - virtual void GetSubVolumes (BVH_Set<T, N>* theSet, + virtual void getSubVolumes (BVH_Set<T, N>* theSet, BVH_Tree<T, N>* theBVH, const Standard_Integer theNode, BVH_BinVector& theBins, - const Standard_Integer theAxis); + const Standard_Integer theAxis) const; private: @@ -86,6 +97,226 @@ private: }; -#include <BVH_BinnedBuilder.lxx> +// ======================================================================= +// function : getSubVolumes +// purpose : +// ======================================================================= +template<class T, int N, int Bins> +void BVH_BinnedBuilder<T, N, Bins>::getSubVolumes (BVH_Set<T, N>* theSet, + BVH_Tree<T, N>* theBVH, + const Standard_Integer theNode, + BVH_BinVector& theBins, + const Standard_Integer theAxis) const +{ + const T aMin = BVH::VecComp<T, N>::Get (theBVH->MinPoint (theNode), theAxis); + const T aMax = BVH::VecComp<T, N>::Get (theBVH->MaxPoint (theNode), theAxis); + const T anInverseStep = static_cast<T> (Bins) / (aMax - aMin); + for (Standard_Integer anIdx = theBVH->BegPrimitive (theNode); anIdx <= theBVH->EndPrimitive (theNode); ++anIdx) + { + typename BVH_Set<T, N>::BVH_BoxNt aBox = theSet->Box (anIdx); + Standard_Integer aBinIndex = BVH::IntFloor<T> ((theSet->Center (anIdx, theAxis) - aMin) * anInverseStep); + if (aBinIndex < 0) + { + aBinIndex = 0; + } + else if (aBinIndex >= Bins) + { + aBinIndex = Bins - 1; + } + + theBins[aBinIndex].Count++; + theBins[aBinIndex].Box.Combine (aBox); + } +} + +namespace BVH +{ + template<class T, int N> + Standard_Integer SplitPrimitives (BVH_Set<T, N>* theSet, + const BVH_Box<T, N>& theBox, + const Standard_Integer theBeg, + const Standard_Integer theEnd, + const Standard_Integer theBin, + const Standard_Integer theAxis, + const Standard_Integer theBins) + { + const T aMin = BVH::VecComp<T, N>::Get (theBox.CornerMin(), theAxis); + const T aMax = BVH::VecComp<T, N>::Get (theBox.CornerMax(), theAxis); + + const T anInverseStep = static_cast<T> (theBins) / (aMax - aMin); + + Standard_Integer aLftIdx (theBeg); + Standard_Integer aRghIdx (theEnd); + + do + { + while (BVH::IntFloor<T> ((theSet->Center (aLftIdx, theAxis) - aMin) * anInverseStep) <= theBin && aLftIdx < theEnd) + { + ++aLftIdx; + } + while (BVH::IntFloor<T> ((theSet->Center (aRghIdx, theAxis) - aMin) * anInverseStep) > theBin && aRghIdx > theBeg) + { + --aRghIdx; + } + + if (aLftIdx <= aRghIdx) + { + if (aLftIdx != aRghIdx) + { + theSet->Swap (aLftIdx, aRghIdx); + } + + ++aLftIdx; + --aRghIdx; + } + } while (aLftIdx <= aRghIdx); + + return aLftIdx; + } + + template<class T, int N> + struct BVH_AxisSelector + { + typedef typename BVH::VectorType<T, N>::Type BVH_VecNt; + static Standard_Integer MainAxis (const BVH_VecNt& theSize) + { + if (theSize.y() > theSize.x()) + { + return theSize.y() > theSize.z() ? 1 : 2; + } + else + { + return theSize.z() > theSize.x() ? 2 : 0; + } + } + }; + + template<class T> + struct BVH_AxisSelector<T, 2> + { + typedef typename BVH::VectorType<T, 2>::Type BVH_VecNt; + static Standard_Integer MainAxis (const BVH_VecNt& theSize) + { + return theSize.x() > theSize.y() ? 0 : 1; + } + }; +} + +// ======================================================================= +// function : buildNode +// purpose : +// ======================================================================= +template<class T, int N, int Bins> +typename BVH_QueueBuilder<T, N>::BVH_ChildNodes BVH_BinnedBuilder<T, N, Bins>::buildNode (BVH_Set<T, N>* theSet, + BVH_Tree<T, N>* theBVH, + const Standard_Integer theNode) const +{ + const Standard_Integer aNodeBegPrimitive = theBVH->BegPrimitive (theNode); + const Standard_Integer aNodeEndPrimitive = theBVH->EndPrimitive (theNode); + if (aNodeEndPrimitive - aNodeBegPrimitive < BVH_Builder<T, N>::myLeafNodeSize) + { + return typename BVH_QueueBuilder<T, N>::BVH_ChildNodes(); // node does not require partitioning + } + + const BVH_Box<T, N> anAABB (theBVH->MinPoint (theNode), + theBVH->MaxPoint (theNode)); + const typename BVH_Box<T, N>::BVH_VecNt aSize = anAABB.Size(); + + // Parameters for storing best split + Standard_Integer aMinSplitAxis = -1; + Standard_Integer aMinSplitIndex = 0; + Standard_Integer aMinSplitNumLft = 0; + Standard_Integer aMinSplitNumRgh = 0; + + BVH_Box<T, N> aMinSplitBoxLft; + BVH_Box<T, N> aMinSplitBoxRgh; + + Standard_Real aMinSplitCost = std::numeric_limits<Standard_Real>::max(); + const Standard_Integer aMainAxis = BVH::BVH_AxisSelector<T, N>::MainAxis (aSize); + + // Find best split + for (Standard_Integer anAxis = myUseMainAxis ? aMainAxis : 0; anAxis <= (myUseMainAxis ? aMainAxis : Min (N - 1, 2)); ++anAxis) + { + if (BVH::VecComp<T, N>::Get (aSize, anAxis) <= BVH::THE_NODE_MIN_SIZE) + { + continue; + } + + BVH_BinVector aBinVector; + getSubVolumes (theSet, theBVH, theNode, aBinVector, anAxis); + + BVH_SplitPlanes aSplitPlanes; + for (Standard_Integer aLftSplit = 1, aRghSplit = Bins - 1; aLftSplit < Bins; ++aLftSplit, --aRghSplit) + { + aSplitPlanes[aLftSplit].LftVoxel.Count = aSplitPlanes[aLftSplit - 1].LftVoxel.Count + aBinVector[aLftSplit - 1].Count; + aSplitPlanes[aRghSplit].RghVoxel.Count = aSplitPlanes[aRghSplit + 1].RghVoxel.Count + aBinVector[aRghSplit + 0].Count; + + aSplitPlanes[aLftSplit].LftVoxel.Box = aSplitPlanes[aLftSplit - 1].LftVoxel.Box; + aSplitPlanes[aRghSplit].RghVoxel.Box = aSplitPlanes[aRghSplit + 1].RghVoxel.Box; + + aSplitPlanes[aLftSplit].LftVoxel.Box.Combine (aBinVector[aLftSplit - 1].Box); + aSplitPlanes[aRghSplit].RghVoxel.Box.Combine (aBinVector[aRghSplit + 0].Box); + } + + // Choose the best split (with minimum SAH cost) + for (Standard_Integer aSplit = 1; aSplit < Bins; ++aSplit) + { + // Simple SAH evaluation + Standard_Real aCost = + (static_cast<Standard_Real> (aSplitPlanes[aSplit].LftVoxel.Box.Area()) /* / S(N) */) * aSplitPlanes[aSplit].LftVoxel.Count + + (static_cast<Standard_Real> (aSplitPlanes[aSplit].RghVoxel.Box.Area()) /* / S(N) */) * aSplitPlanes[aSplit].RghVoxel.Count; + + if (aCost <= aMinSplitCost) + { + aMinSplitCost = aCost; + aMinSplitAxis = anAxis; + aMinSplitIndex = aSplit; + aMinSplitBoxLft = aSplitPlanes[aSplit].LftVoxel.Box; + aMinSplitBoxRgh = aSplitPlanes[aSplit].RghVoxel.Box; + aMinSplitNumLft = aSplitPlanes[aSplit].LftVoxel.Count; + aMinSplitNumRgh = aSplitPlanes[aSplit].RghVoxel.Count; + } + } + } + + theBVH->SetInner (theNode); + Standard_Integer aMiddle = -1; + if (aMinSplitNumLft == 0 || aMinSplitNumRgh == 0 || aMinSplitAxis == -1) // case of objects with the same center + { + aMinSplitBoxLft.Clear(); + aMinSplitBoxRgh.Clear(); + + aMiddle = std::max (aNodeBegPrimitive + 1, + static_cast<Standard_Integer> ((aNodeBegPrimitive + aNodeEndPrimitive) / 2.f)); + + aMinSplitNumLft = aMiddle - aNodeBegPrimitive; + for (Standard_Integer anIndex = aNodeBegPrimitive; anIndex < aMiddle; ++anIndex) + { + aMinSplitBoxLft.Combine (theSet->Box (anIndex)); + } + + aMinSplitNumRgh = aNodeEndPrimitive - aMiddle + 1; + for (Standard_Integer anIndex = aNodeEndPrimitive; anIndex >= aMiddle; --anIndex) + { + aMinSplitBoxRgh.Combine (theSet->Box (anIndex)); + } + } + else + { + aMiddle = BVH::SplitPrimitives<T, N> (theSet, + anAABB, + aNodeBegPrimitive, + aNodeEndPrimitive, + aMinSplitIndex - 1, + aMinSplitAxis, + Bins); + } + + typedef typename BVH_QueueBuilder<T, N>::BVH_PrimitiveRange Range; + return typename BVH_QueueBuilder<T, N>::BVH_ChildNodes (aMinSplitBoxLft, + aMinSplitBoxRgh, + Range (aNodeBegPrimitive, aMiddle - 1), + Range (aMiddle, aNodeEndPrimitive)); +} #endif // _BVH_BinnedBuilder_Header diff --git a/src/BVH/BVH_BinnedBuilder.lxx b/src/BVH/BVH_BinnedBuilder.lxx deleted file mode 100644 index 5be6c34e97..0000000000 --- a/src/BVH/BVH_BinnedBuilder.lxx +++ /dev/null @@ -1,299 +0,0 @@ -// Created on: 2013-12-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -// ======================================================================= -// function : BVH_BinnedBuilder -// purpose : -// ======================================================================= -template<class T, int N, int Bins> -BVH_BinnedBuilder<T, N, Bins>::BVH_BinnedBuilder (const Standard_Integer theLeafNodeSize, - const Standard_Integer theMaxTreeDepth, - const Standard_Boolean theDoMainSplits, - const Standard_Integer theNumOfThreads) -: BVH_QueueBuilder<T, N> (theLeafNodeSize, - theMaxTreeDepth, - theNumOfThreads), - myUseMainAxis (theDoMainSplits) -{ - // -} - -// ======================================================================= -// function : ~BVH_BinnedBuilder -// purpose : -// ======================================================================= -template<class T, int N, int Bins> -BVH_BinnedBuilder<T, N, Bins>::~BVH_BinnedBuilder() -{ - // -} - -// ======================================================================= -// function : GetSubVolumes -// purpose : -// ======================================================================= -template<class T, int N, int Bins> -void BVH_BinnedBuilder<T, N, Bins>::GetSubVolumes (BVH_Set<T, N>* theSet, - BVH_Tree<T, N>* theBVH, - const Standard_Integer theNode, - BVH_BinVector& theBins, - const Standard_Integer theAxis) -{ - const T aMin = BVH::VecComp<T, N>::Get (theBVH->MinPoint (theNode), theAxis); - const T aMax = BVH::VecComp<T, N>::Get (theBVH->MaxPoint (theNode), theAxis); - - const T anInverseStep = static_cast<T> (Bins) / (aMax - aMin); - - for (Standard_Integer anIdx = theBVH->BegPrimitive (theNode); anIdx <= theBVH->EndPrimitive (theNode); ++anIdx) - { - typename BVH_Set<T, N>::BVH_BoxNt aBox = theSet->Box (anIdx); - - Standard_Integer aBinIndex = BVH::IntFloor<T> ( - (theSet->Center (anIdx, theAxis) - aMin) * anInverseStep); - - if (aBinIndex < 0) - { - aBinIndex = 0; - } - else if (aBinIndex >= Bins) - { - aBinIndex = Bins - 1; - } - - theBins[aBinIndex].Count++; - theBins[aBinIndex].Box.Combine (aBox); - } -} - -namespace BVH -{ - // ======================================================================= - // function : SplitPrimitives - // purpose : - // ======================================================================= - template<class T, int N> - Standard_Integer SplitPrimitives (BVH_Set<T, N>* theSet, - const BVH_Box<T, N>& theBox, - const Standard_Integer theBeg, - const Standard_Integer theEnd, - const Standard_Integer theBin, - const Standard_Integer theAxis, - const Standard_Integer theBins) - { - const T aMin = BVH::VecComp<T, N>::Get (theBox.CornerMin(), theAxis); - const T aMax = BVH::VecComp<T, N>::Get (theBox.CornerMax(), theAxis); - - const T anInverseStep = static_cast<T> (theBins) / (aMax - aMin); - - Standard_Integer aLftIdx (theBeg); - Standard_Integer aRghIdx (theEnd); - - do - { - while (BVH::IntFloor<T> ((theSet->Center (aLftIdx, theAxis) - aMin) * anInverseStep) <= theBin && aLftIdx < theEnd) - { - ++aLftIdx; - } - while (BVH::IntFloor<T> ((theSet->Center (aRghIdx, theAxis) - aMin) * anInverseStep) > theBin && aRghIdx > theBeg) - { - --aRghIdx; - } - - if (aLftIdx <= aRghIdx) - { - if (aLftIdx != aRghIdx) - { - theSet->Swap (aLftIdx, aRghIdx); - } - - ++aLftIdx; - --aRghIdx; - } - } while (aLftIdx <= aRghIdx); - - return aLftIdx; - } -} - -#if defined (_WIN32) && defined (max) - #undef max -#endif - -#include <limits> - -namespace BVH -{ - template<class T, int N> - struct BVH_AxisSelector - { - typedef typename BVH::VectorType<T, N>::Type BVH_VecNt; - - // ======================================================================= - // function : MainAxis - // purpose : - // ======================================================================= - static Standard_Integer MainAxis (const BVH_VecNt& theSize) - { - if (theSize.y() > theSize.x()) - { - return theSize.y() > theSize.z() ? 1 : 2; - } - else - { - return theSize.z() > theSize.x() ? 2 : 0; - } - } - }; - - template<class T> - struct BVH_AxisSelector<T, 2> - { - typedef typename BVH::VectorType<T, 2>::Type BVH_VecNt; - - // ======================================================================= - // function : MainAxis - // purpose : - // ======================================================================= - static Standard_Integer MainAxis (const BVH_VecNt& theSize) - { - return theSize.x() > theSize.y() ? 0 : 1; - } - }; -} - -// ======================================================================= -// function : BuildNode -// purpose : -// ======================================================================= -template<class T, int N, int Bins> -typename BVH_QueueBuilder<T, N>::BVH_ChildNodes BVH_BinnedBuilder<T, N, Bins>::BuildNode (BVH_Set<T, N>* theSet, - BVH_Tree<T, N>* theBVH, - const Standard_Integer theNode) -{ - const Standard_Integer aNodeBegPrimitive = theBVH->BegPrimitive (theNode); - const Standard_Integer aNodeEndPrimitive = theBVH->EndPrimitive (theNode); - - if (aNodeEndPrimitive - aNodeBegPrimitive < BVH_Builder<T, N>::myLeafNodeSize) - { - return typename BVH_QueueBuilder<T, N>::BVH_ChildNodes(); // node does not require partitioning - } - - const BVH_Box<T, N> anAABB (theBVH->MinPoint (theNode), - theBVH->MaxPoint (theNode)); - - const typename BVH_Box<T, N>::BVH_VecNt aSize = anAABB.Size(); - - // Parameters for storing best split - Standard_Integer aMinSplitAxis = -1; - Standard_Integer aMinSplitIndex = 0; - Standard_Integer aMinSplitNumLft = 0; - Standard_Integer aMinSplitNumRgh = 0; - - BVH_Box<T, N> aMinSplitBoxLft; - BVH_Box<T, N> aMinSplitBoxRgh; - - Standard_Real aMinSplitCost = std::numeric_limits<Standard_Real>::max(); - - const Standard_Integer aMainAxis = BVH::BVH_AxisSelector<T, N>::MainAxis (aSize); - - // Find best split - for (Standard_Integer anAxis = myUseMainAxis ? aMainAxis : 0; anAxis <= (myUseMainAxis ? aMainAxis : Min (N - 1, 2)); ++anAxis) - { - if (BVH::VecComp<T, N>::Get (aSize, anAxis) <= BVH::THE_NODE_MIN_SIZE) - { - continue; - } - - BVH_BinVector aBinVector; - GetSubVolumes (theSet, theBVH, theNode, aBinVector, anAxis); - - BVH_SplitPlanes aSplitPlanes; - for (Standard_Integer aLftSplit = 1, aRghSplit = Bins - 1; aLftSplit < Bins; ++aLftSplit, --aRghSplit) - { - aSplitPlanes[aLftSplit].LftVoxel.Count = aSplitPlanes[aLftSplit - 1].LftVoxel.Count + aBinVector[aLftSplit - 1].Count; - aSplitPlanes[aRghSplit].RghVoxel.Count = aSplitPlanes[aRghSplit + 1].RghVoxel.Count + aBinVector[aRghSplit + 0].Count; - - aSplitPlanes[aLftSplit].LftVoxel.Box = aSplitPlanes[aLftSplit - 1].LftVoxel.Box; - aSplitPlanes[aRghSplit].RghVoxel.Box = aSplitPlanes[aRghSplit + 1].RghVoxel.Box; - - aSplitPlanes[aLftSplit].LftVoxel.Box.Combine (aBinVector[aLftSplit - 1].Box); - aSplitPlanes[aRghSplit].RghVoxel.Box.Combine (aBinVector[aRghSplit + 0].Box); - } - - // Choose the best split (with minimum SAH cost) - for (Standard_Integer aSplit = 1; aSplit < Bins; ++aSplit) - { - // Simple SAH evaluation - Standard_Real aCost = - (static_cast<Standard_Real> (aSplitPlanes[aSplit].LftVoxel.Box.Area()) /* / S(N) */) * aSplitPlanes[aSplit].LftVoxel.Count - + (static_cast<Standard_Real> (aSplitPlanes[aSplit].RghVoxel.Box.Area()) /* / S(N) */) * aSplitPlanes[aSplit].RghVoxel.Count; - - if (aCost <= aMinSplitCost) - { - aMinSplitCost = aCost; - aMinSplitAxis = anAxis; - aMinSplitIndex = aSplit; - aMinSplitBoxLft = aSplitPlanes[aSplit].LftVoxel.Box; - aMinSplitBoxRgh = aSplitPlanes[aSplit].RghVoxel.Box; - aMinSplitNumLft = aSplitPlanes[aSplit].LftVoxel.Count; - aMinSplitNumRgh = aSplitPlanes[aSplit].RghVoxel.Count; - } - } - } - - theBVH->SetInner (theNode); - - Standard_Integer aMiddle = -1; - - if (aMinSplitNumLft == 0 || aMinSplitNumRgh == 0 || aMinSplitAxis == -1) // case of objects with the same center - { - aMinSplitBoxLft.Clear(); - aMinSplitBoxRgh.Clear(); - - aMiddle = std::max (aNodeBegPrimitive + 1, - static_cast<Standard_Integer> ((aNodeBegPrimitive + aNodeEndPrimitive) / 2.f)); - - aMinSplitNumLft = aMiddle - aNodeBegPrimitive; - - for (Standard_Integer anIndex = aNodeBegPrimitive; anIndex < aMiddle; ++anIndex) - { - aMinSplitBoxLft.Combine (theSet->Box (anIndex)); - } - - aMinSplitNumRgh = aNodeEndPrimitive - aMiddle + 1; - - for (Standard_Integer anIndex = aNodeEndPrimitive; anIndex >= aMiddle; --anIndex) - { - aMinSplitBoxRgh.Combine (theSet->Box (anIndex)); - } - } - else - { - aMiddle = BVH::SplitPrimitives<T, N> (theSet, - anAABB, - aNodeBegPrimitive, - aNodeEndPrimitive, - aMinSplitIndex - 1, - aMinSplitAxis, - Bins); - } - - typedef typename BVH_QueueBuilder<T, N>::BVH_PrimitiveRange Range; - - return typename BVH_QueueBuilder<T, N>::BVH_ChildNodes (aMinSplitBoxLft, - aMinSplitBoxRgh, - Range (aNodeBegPrimitive, aMiddle - 1), - Range (aMiddle, aNodeEndPrimitive)); -} diff --git a/src/BVH/BVH_Box.hxx b/src/BVH/BVH_Box.hxx index 838fb90352..537b4f7a94 100644 --- a/src/BVH/BVH_Box.hxx +++ b/src/BVH/BVH_Box.hxx @@ -17,6 +17,7 @@ #define _BVH_Box_Header #include <BVH_Types.hxx> +#include <Standard_ShortReal.hxx> #include <limits> @@ -57,38 +58,51 @@ public: public: //! Clears bounding box. - void Clear(); + void Clear() { myIsInited = Standard_False; } //! Is bounding box valid? - Standard_Boolean IsValid() const; + Standard_Boolean IsValid() const { return myIsInited; } //! Appends new point to the bounding box. - void Add (const BVH_VecNt& thePoint); + void Add (const BVH_VecNt& thePoint) + { + if (!myIsInited) + { + myMinPoint = thePoint; + myMaxPoint = thePoint; + myIsInited = Standard_True; + } + else + { + myMinPoint = myMinPoint.cwiseMin (thePoint); + myMaxPoint = myMaxPoint.cwiseMax (thePoint); + } + } //! Combines bounding box with another one. - void Combine (const BVH_Box& theVolume); + void Combine (const BVH_Box& theBox); //! Returns minimum point of bounding box. - const BVH_VecNt& CornerMin() const; + const BVH_VecNt& CornerMin() const { return myMinPoint; } //! Returns maximum point of bounding box. - const BVH_VecNt& CornerMax() const; + const BVH_VecNt& CornerMax() const { return myMaxPoint; } //! Returns minimum point of bounding box. - BVH_VecNt& CornerMin(); + BVH_VecNt& CornerMin() { return myMinPoint; } //! Returns maximum point of bounding box. - BVH_VecNt& CornerMax(); + BVH_VecNt& CornerMax() { return myMaxPoint; } //! Returns surface area of bounding box. //! If the box is degenerated into line, returns the perimeter instead. T Area() const; //! Returns diagonal of bounding box. - BVH_VecNt Size() const; + BVH_VecNt Size() const { return myMaxPoint - myMinPoint; } //! Returns center of bounding box. - BVH_VecNt Center() const; + BVH_VecNt Center() const { return (myMinPoint + myMaxPoint) * static_cast<T> (0.5); } //! Returns center of bounding box along the given axis. T Center (const Standard_Integer theAxis) const; @@ -279,6 +293,47 @@ namespace BVH }; } -#include <BVH_Box.lxx> +// ======================================================================= +// function : Combine +// purpose : +// ======================================================================= +template<class T, int N> +void BVH_Box<T, N>::Combine (const BVH_Box& theBox) +{ + if (theBox.myIsInited) + { + if (!myIsInited) + { + myMinPoint = theBox.myMinPoint; + myMaxPoint = theBox.myMaxPoint; + myIsInited = Standard_True; + } + else + { + BVH::BoxMinMax<T, N>::CwiseMin (myMinPoint, theBox.myMinPoint); + BVH::BoxMinMax<T, N>::CwiseMax (myMaxPoint, theBox.myMaxPoint); + } + } +} + +// ======================================================================= +// function : Area +// purpose : +// ======================================================================= +template<class T, int N> +T BVH_Box<T, N>::Area() const +{ + return !myIsInited ? static_cast<T> (0.0) : BVH::SurfaceCalculator<T, N>::Area (myMaxPoint - myMinPoint); +} + +// ======================================================================= +// function : Center +// purpose : +// ======================================================================= +template<class T, int N> +T BVH_Box<T, N>::Center (const Standard_Integer theAxis) const +{ + return BVH::CenterAxis<T, N>::Center (*this, theAxis); +} #endif // _BVH_Box_Header diff --git a/src/BVH/BVH_Box.lxx b/src/BVH/BVH_Box.lxx deleted file mode 100644 index 5082c66f73..0000000000 --- a/src/BVH/BVH_Box.lxx +++ /dev/null @@ -1,162 +0,0 @@ -// Created on: 2013-12-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include <Standard_ShortReal.hxx> - -// ======================================================================= -// function : Clear -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_Box<T, N>::Clear() -{ - myIsInited = Standard_False; -} - -// ======================================================================= -// function : Clear -// purpose : -// ======================================================================= -template<class T, int N> -Standard_Boolean BVH_Box<T, N>::IsValid() const -{ - return myIsInited; -} - -// ======================================================================= -// function : Add -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_Box<T, N>::Add (const BVH_VecNt& thePoint) -{ - if (!myIsInited) - { - myMinPoint = thePoint; - myMaxPoint = thePoint; - - myIsInited = Standard_True; - } - else - { - myMinPoint = myMinPoint.cwiseMin (thePoint); - myMaxPoint = myMaxPoint.cwiseMax (thePoint); - } -} - -// ======================================================================= -// function : Combine -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_Box<T, N>::Combine (const BVH_Box& theBox) -{ - if (theBox.myIsInited) - { - if (!myIsInited) - { - myMinPoint = theBox.myMinPoint; - myMaxPoint = theBox.myMaxPoint; - - myIsInited = Standard_True; - } - else - { - BVH::BoxMinMax<T, N>::CwiseMin (myMinPoint, theBox.myMinPoint); - BVH::BoxMinMax<T, N>::CwiseMax (myMaxPoint, theBox.myMaxPoint); - } - } -} - -// ======================================================================= -// function : Area -// purpose : -// ======================================================================= -template<class T, int N> -T BVH_Box<T, N>::Area() const -{ - return !myIsInited ? static_cast<T> (0.0) : - BVH::SurfaceCalculator<T, N>::Area (myMaxPoint - myMinPoint); -} - -// ======================================================================= -// function : CornerMin -// purpose : -// ======================================================================= -template<class T, int N> -const typename BVH_Box<T, N>::BVH_VecNt& BVH_Box<T, N>::CornerMin() const -{ - return myMinPoint; -} - -// ======================================================================= -// function : CornerMax -// purpose : -// ======================================================================= -template<class T, int N> -const typename BVH_Box<T, N>::BVH_VecNt& BVH_Box<T, N>::CornerMax() const -{ - return myMaxPoint; -} - -// ======================================================================= -// function : CornerMin -// purpose : -// ======================================================================= -template<class T, int N> -typename BVH_Box<T, N>::BVH_VecNt& BVH_Box<T, N>::CornerMin() -{ - return myMinPoint; -} - -// ======================================================================= -// function : CornerMax -// purpose : -// ======================================================================= -template<class T, int N> -typename BVH_Box<T, N>::BVH_VecNt& BVH_Box<T, N>::CornerMax() -{ - return myMaxPoint; -} - -// ======================================================================= -// function : Size -// purpose : -// ======================================================================= -template<class T, int N> -typename BVH_Box<T, N>::BVH_VecNt BVH_Box<T, N>::Size() const -{ - return myMaxPoint - myMinPoint; -} - -// ======================================================================= -// function : Center -// purpose : -// ======================================================================= -template<class T, int N> -typename BVH_Box<T, N>::BVH_VecNt BVH_Box<T, N>::Center() const -{ - return (myMinPoint + myMaxPoint) * static_cast<T> (0.5); -} - -// ======================================================================= -// function : Center -// purpose : -// ======================================================================= -template<class T, int N> -T BVH_Box<T, N>::Center (const Standard_Integer theAxis) const -{ - return BVH::CenterAxis<T, N>::Center (*this, theAxis); -} diff --git a/src/BVH/BVH_Builder.hxx b/src/BVH/BVH_Builder.hxx index 27fbc83e39..571767e791 100644 --- a/src/BVH/BVH_Builder.hxx +++ b/src/BVH/BVH_Builder.hxx @@ -36,21 +36,23 @@ public: //! Creates new abstract BVH builder. BVH_Builder (const Standard_Integer theLeafNodeSize, - const Standard_Integer theMaxTreeDepth); + const Standard_Integer theMaxTreeDepth) + : myMaxTreeDepth (theMaxTreeDepth), + myLeafNodeSize (theLeafNodeSize) {} //! Releases resources of BVH builder. - virtual ~BVH_Builder(); + virtual ~BVH_Builder() {} //! Builds BVH using specific algorithm. virtual void Build (BVH_Set<T, N>* theSet, BVH_Tree<T, N>* theBVH, - const BVH_Box<T, N>& theBox) = 0; + const BVH_Box<T, N>& theBox) const = 0; protected: //! Updates depth of constructed BVH tree. - void UpdateDepth (BVH_Tree<T, N>* theBVH, - const Standard_Integer theLevel) + void updateDepth (BVH_Tree<T, N>* theBVH, + const Standard_Integer theLevel) const { if (theLevel > theBVH->myDepth) { @@ -65,6 +67,4 @@ protected: }; -#include <BVH_Builder.lxx> - #endif // _BVH_Builder_Header diff --git a/src/BVH/BVH_Builder.lxx b/src/BVH/BVH_Builder.lxx deleted file mode 100644 index ebb173a550..0000000000 --- a/src/BVH/BVH_Builder.lxx +++ /dev/null @@ -1,37 +0,0 @@ -// Created on: 2013-12-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -// ======================================================================= -// function : BVH_Builder -// purpose : Creates abstract BVH builder -// ======================================================================= -template<class T, int N> -BVH_Builder<T, N>::BVH_Builder (const Standard_Integer theLeafNodeSize, - const Standard_Integer theMaxTreeDepth) -: myMaxTreeDepth (theMaxTreeDepth), - myLeafNodeSize (theLeafNodeSize) -{ - // -} - -// ======================================================================= -// function : ~BVH_Builder -// purpose : Releases resources of BVH builder -// ======================================================================= -template<class T, int N> -BVH_Builder<T, N>::~BVH_Builder() -{ - // -} diff --git a/src/BVH/BVH_Geometry.hxx b/src/BVH/BVH_Geometry.hxx index ee33154197..8cf2162df6 100644 --- a/src/BVH/BVH_Geometry.hxx +++ b/src/BVH/BVH_Geometry.hxx @@ -18,6 +18,7 @@ #include <BVH_ObjectSet.hxx> #include <BVH_Builder.hxx> +#include <BVH_BinnedBuilder.hxx> //! BVH geometry as a set of abstract geometric objects //! organized with bounding volume hierarchy (BVH). @@ -29,35 +30,66 @@ class BVH_Geometry : public BVH_ObjectSet<T, N> public: //! Creates uninitialized BVH geometry. - BVH_Geometry(); + BVH_Geometry() + : myIsDirty (Standard_False), + myBVH (new BVH_Tree<T, N>()) + { + // Set default builder - binned SAH split + myBuilder = new BVH_BinnedBuilder<T, N, 32> (1 /* primitive per leaf */); + } //! Releases resources of BVH geometry. - virtual ~BVH_Geometry(); + virtual ~BVH_Geometry() + { + myBVH.Nullify(); + myBuilder.Nullify(); + } public: //! Marks geometry as outdated. - virtual void MarkDirty(); + virtual void MarkDirty() { myIsDirty = Standard_True; } //! Returns AABB of the given object. using BVH_ObjectSet<T, N>::Box; //! Returns AABB of the whole geometry. - virtual BVH_Box<T, N> Box() const; + virtual BVH_Box<T, N> Box() const Standard_OVERRIDE + { + if (myIsDirty) + { + myBox = BVH_Set<T, N>::Box(); + } + return myBox; + } //! Returns BVH tree (and builds it if necessary). - virtual const NCollection_Handle<BVH_Tree<T, N> >& BVH(); + virtual const NCollection_Handle<BVH_Tree<T, N> >& BVH() + { + if (myIsDirty) + { + Update(); + } + return myBVH; + } //! Returns the method (builder) used to construct BVH. - virtual const NCollection_Handle<BVH_Builder<T, N> >& Builder() const; + virtual const NCollection_Handle<BVH_Builder<T, N> >& Builder() const { return myBuilder; } //! Sets the method (builder) used to construct BVH. - virtual void SetBuilder (NCollection_Handle<BVH_Builder<T, N> >& theBuilder); + virtual void SetBuilder (const NCollection_Handle<BVH_Builder<T, N> >& theBuilder) { myBuilder = theBuilder; } protected: //! Updates internal geometry state. - virtual void Update(); + virtual void Update() + { + if (myIsDirty) + { + myBuilder->Build (this, myBVH.operator->(), Box()); + myIsDirty = Standard_False; + } + } protected: @@ -69,6 +101,4 @@ protected: }; -#include <BVH_Geometry.lxx> - #endif // _BVH_Geometry_Header diff --git a/src/BVH/BVH_Geometry.lxx b/src/BVH/BVH_Geometry.lxx deleted file mode 100644 index 9f610a1d85..0000000000 --- a/src/BVH/BVH_Geometry.lxx +++ /dev/null @@ -1,118 +0,0 @@ -// Created on: 2013-12-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include <BVH_BinnedBuilder.hxx> - -// ======================================================================= -// function : BVH_Geometry -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Geometry<T, N>::BVH_Geometry() -: myIsDirty (Standard_False), - myBVH (new BVH_Tree<T, N>()) -{ - // Set default builder - binned SAH split - myBuilder = new BVH_BinnedBuilder<T, N, 32> (1 /* primitive per leaf */); -} - -// ======================================================================= -// function : ~BVH_Geometry -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Geometry<T, N>::~BVH_Geometry() -{ - myBVH.Nullify(); - myBuilder.Nullify(); -} - -// ======================================================================= -// function : MarkDirty -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_Geometry<T, N>::MarkDirty() -{ - myIsDirty = Standard_True; -} - -// ======================================================================= -// function : Box -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Box<T, N> BVH_Geometry<T, N>::Box() const -{ - if (!myIsDirty) - { - return myBox; - } - - myBox = BVH_Set<T, N>::Box(); - return myBox; -} - -// ======================================================================= -// function : BVH -// purpose : -// ======================================================================= -template<class T, int N> -const NCollection_Handle<BVH_Tree<T, N> >& BVH_Geometry<T, N>::BVH() -{ - if (myIsDirty) - { - Update(); - } - - return myBVH; -} - -// ======================================================================= -// function : Update -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_Geometry<T, N>::Update() -{ - if (!myIsDirty) - { - return; - } - - myBuilder->Build (this, myBVH.operator->(), Box()); - - myIsDirty = Standard_False; -} - -// ======================================================================= -// function : Builder -// purpose : -// ======================================================================= -template<class T, int N> -const NCollection_Handle<BVH_Builder<T, N> >& BVH_Geometry<T, N>::Builder() const -{ - return myBuilder; -} - -// ======================================================================= -// function : SetBuilder -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_Geometry<T, N>::SetBuilder (NCollection_Handle<BVH_Builder<T, N> >& theBuilder) -{ - myBuilder = theBuilder; -} diff --git a/src/BVH/BVH_LinearBuilder.hxx b/src/BVH/BVH_LinearBuilder.hxx index 1bb6fc0079..3dd7c4fb49 100644 --- a/src/BVH/BVH_LinearBuilder.hxx +++ b/src/BVH/BVH_LinearBuilder.hxx @@ -17,6 +17,7 @@ #define _BVH_LinearBuilder_Header #include <BVH_RadixSorter.hxx> +#include <Standard_Assert.hxx> //! Performs fast BVH construction using LBVH building approach. //! Algorithm uses spatial Morton codes to reduce the BVH construction @@ -45,35 +46,308 @@ public: virtual ~BVH_LinearBuilder(); //! Builds BVH. - void Build (BVH_Set<T, N>* theSet, - BVH_Tree<T, N>* theBVH, - const BVH_Box<T, N>& theBox); + virtual void Build (BVH_Set<T, N>* theSet, + BVH_Tree<T, N>* theBVH, + const BVH_Box<T, N>& theBox) const Standard_OVERRIDE; protected: - typedef NCollection_Array1<BVH_EncodedLink>::iterator LinkIterator; + typedef NCollection_Array1<BVH_EncodedLink>::iterator LinkIterator; protected: //! Emits hierarchy from sorted Morton codes. - Standard_Integer EmitHierachy (BVH_Tree<T, N>* theBVH, + Standard_Integer emitHierachy (BVH_Tree<T, N>* theBVH, + const NCollection_Array1<BVH_EncodedLink>& theEncodedLinks, const Standard_Integer theBit, const Standard_Integer theShift, const Standard_Integer theStart, - const Standard_Integer theFinal); + const Standard_Integer theFinal) const; //! Returns index of the first element which does not compare less than the given one. - Standard_Integer LowerBound (Standard_Integer theStart, + Standard_Integer lowerBound (const NCollection_Array1<BVH_EncodedLink>& theEncodedLinks, + Standard_Integer theStart, Standard_Integer theFinal, - Standard_Integer theDigit); - -protected: - - //! Tool object to perform radix sort of BVH primitives. - NCollection_Handle<BVH_RadixSorter<T, N> > myRadixSorter; + Standard_Integer theDigit) const; }; -#include <BVH_LinearBuilder.lxx> +// ======================================================================= +// function : BVH_LinearBuilder +// purpose : +// ======================================================================= +template<class T, int N> +BVH_LinearBuilder<T, N>::BVH_LinearBuilder (const Standard_Integer theLeafNodeSize, + const Standard_Integer theMaxTreeDepth) +: BVH_Builder<T, N> (theLeafNodeSize, + theMaxTreeDepth) +{ + // +} + +// ======================================================================= +// function : ~BVH_LinearBuilder +// purpose : +// ======================================================================= +template<class T, int N> +BVH_LinearBuilder<T, N>::~BVH_LinearBuilder() +{ + // +} + +// ======================================================================= +// function : lowerBound +// purpose : Returns index of first element greater than the given one +// ======================================================================= +template<class T, int N> +Standard_Integer BVH_LinearBuilder<T, N>::lowerBound (const NCollection_Array1<BVH_EncodedLink>& theEncodedLinks, + Standard_Integer theStart, + Standard_Integer theFinal, + Standard_Integer theDigit) const +{ + Standard_Integer aNbPrims = theFinal - theStart; + while (aNbPrims > 0) + { + const Standard_Integer aStep = aNbPrims / 2; + if (theEncodedLinks.Value (theStart + aStep).first & (1 << theDigit)) + { + aNbPrims = aStep; + } + else + { + theStart += aStep + 1; + aNbPrims -= aStep + 1; + } + } + + return theStart; +} + +// ======================================================================= +// function : emitHierachy +// purpose : Emits hierarchy from sorted Morton codes +// ======================================================================= +template<class T, int N> +Standard_Integer BVH_LinearBuilder<T, N>::emitHierachy (BVH_Tree<T, N>* theBVH, + const NCollection_Array1<BVH_EncodedLink>& theEncodedLinks, + const Standard_Integer theBit, + const Standard_Integer theShift, + const Standard_Integer theStart, + const Standard_Integer theFinal) const +{ + if (theFinal - theStart > BVH_Builder<T, N>::myLeafNodeSize) + { + const Standard_Integer aPosition = theBit < 0 ? + (theStart + theFinal) / 2 : lowerBound (theEncodedLinks, theStart, theFinal, theBit); + if (aPosition == theStart || aPosition == theFinal) + { + return emitHierachy (theBVH, theEncodedLinks, theBit - 1, theShift, theStart, theFinal); + } + + // Build inner node + const Standard_Integer aNode = theBVH->AddInnerNode (0, 0); + const Standard_Integer aRghNode = theShift + aPosition - theStart; + + const Standard_Integer aLftChild = emitHierachy (theBVH, theEncodedLinks, theBit - 1, theShift, theStart, aPosition); + const Standard_Integer aRghChild = emitHierachy (theBVH, theEncodedLinks, theBit - 1, aRghNode, aPosition, theFinal); + + theBVH->NodeInfoBuffer()[aNode].y() = aLftChild; + theBVH->NodeInfoBuffer()[aNode].z() = aRghChild; + return aNode; + } + else + { + // Build leaf node + return theBVH->AddLeafNode (theShift, theShift + theFinal - theStart - 1); + } +} + +namespace BVH +{ + //! Calculates bounding boxes (AABBs) for the given BVH tree. + template<class T, int N> + Standard_Integer UpdateBounds (BVH_Set<T, N>* theSet, BVH_Tree<T, N>* theTree, const Standard_Integer theNode = 0) + { + const BVH_Vec4i aData = theTree->NodeInfoBuffer()[theNode]; + if (aData.x() == 0) + { + const Standard_Integer aLftChild = theTree->NodeInfoBuffer()[theNode].y(); + const Standard_Integer aRghChild = theTree->NodeInfoBuffer()[theNode].z(); + + const Standard_Integer aLftDepth = UpdateBounds (theSet, theTree, aLftChild); + const Standard_Integer aRghDepth = UpdateBounds (theSet, theTree, aRghChild); + + typename BVH_Box<T, N>::BVH_VecNt aLftMinPoint = theTree->MinPointBuffer()[aLftChild]; + typename BVH_Box<T, N>::BVH_VecNt aLftMaxPoint = theTree->MaxPointBuffer()[aLftChild]; + typename BVH_Box<T, N>::BVH_VecNt aRghMinPoint = theTree->MinPointBuffer()[aRghChild]; + typename BVH_Box<T, N>::BVH_VecNt aRghMaxPoint = theTree->MaxPointBuffer()[aRghChild]; + + BVH::BoxMinMax<T, N>::CwiseMin (aLftMinPoint, aRghMinPoint); + BVH::BoxMinMax<T, N>::CwiseMax (aLftMaxPoint, aRghMaxPoint); + + theTree->MinPointBuffer()[theNode] = aLftMinPoint; + theTree->MaxPointBuffer()[theNode] = aLftMaxPoint; + return Max (aLftDepth, aRghDepth) + 1; + } + else + { + typename BVH_Box<T, N>::BVH_VecNt& aMinPoint = theTree->MinPointBuffer()[theNode]; + typename BVH_Box<T, N>::BVH_VecNt& aMaxPoint = theTree->MaxPointBuffer()[theNode]; + for (Standard_Integer aPrimIdx = aData.y(); aPrimIdx <= aData.z(); ++aPrimIdx) + { + const BVH_Box<T, N> aBox = theSet->Box (aPrimIdx); + if (aPrimIdx == aData.y()) + { + aMinPoint = aBox.CornerMin(); + aMaxPoint = aBox.CornerMax(); + } + else + { + BVH::BoxMinMax<T, N>::CwiseMin (aMinPoint, aBox.CornerMin()); + BVH::BoxMinMax<T, N>::CwiseMax (aMaxPoint, aBox.CornerMax()); + } + } + } + return 0; + } + +#ifdef HAVE_TBB + + //! TBB task for parallel bounds updating. + template<class T, int N> + class UpdateBoundTask: public tbb::task + { + + BVH_Set<T, N>* mySet; //!< Set of geometric objects + BVH_Tree<T, N>* myBVH; //!< BVH tree built over the set + Standard_Integer myNode; //!< BVH node to update bounding box + Standard_Integer myLevel; //!< Level of the processed BVH node + Standard_Integer* myHeight; //!< Height of the processed BVH node + + public: + + //! Creates new TBB parallel bound update task. + UpdateBoundTask (BVH_Set<T, N>* theSet, + BVH_Tree<T, N>* theBVH, + Standard_Integer theNode, + Standard_Integer theLevel, + Standard_Integer* theHeight) + : mySet (theSet), myBVH (theBVH), myNode (theNode), myLevel (theLevel), myHeight (theHeight) {} + + //! Executes the task. + tbb::task* execute() + { + if (myBVH->IsOuter (myNode) || myLevel > 2) + { + *myHeight = BVH::UpdateBounds (mySet, myBVH, myNode); + } + else + { + Standard_Integer aLftHeight = 0; + Standard_Integer aRghHeight = 0; + + const Standard_Integer aLftChild = myBVH->NodeInfoBuffer()[myNode].y(); + const Standard_Integer aRghChild = myBVH->NodeInfoBuffer()[myNode].z(); + + Standard_Integer aCount = 1; + tbb::task_list aList; + if (!myBVH->IsOuter (aLftChild)) + { + ++aCount; + aList.push_back (*new ( allocate_child() ) + UpdateBoundTask (mySet, myBVH, aLftChild, myLevel + 1, &aLftHeight)); + } + else + { + aLftHeight = BVH::UpdateBounds (mySet, myBVH, aLftChild); + } + + if (!myBVH->IsOuter (aRghChild)) + { + ++aCount; + aList.push_back (*new( allocate_child() ) + UpdateBoundTask (mySet, myBVH, aRghChild, myLevel + 1, &aRghHeight)); + } + else + { + aRghHeight = BVH::UpdateBounds (mySet, myBVH, aRghChild); + } + + if (aCount > 1) + { + set_ref_count (aCount); + spawn_and_wait_for_all (aList); + } + + typename BVH_Box<T, N>::BVH_VecNt aLftMinPoint = myBVH->MinPointBuffer()[aLftChild]; + typename BVH_Box<T, N>::BVH_VecNt aLftMaxPoint = myBVH->MaxPointBuffer()[aLftChild]; + typename BVH_Box<T, N>::BVH_VecNt aRghMinPoint = myBVH->MinPointBuffer()[aRghChild]; + typename BVH_Box<T, N>::BVH_VecNt aRghMaxPoint = myBVH->MaxPointBuffer()[aRghChild]; + + BVH::BoxMinMax<T, N>::CwiseMin (aLftMinPoint, aRghMinPoint); + BVH::BoxMinMax<T, N>::CwiseMax (aLftMaxPoint, aRghMaxPoint); + + myBVH->MinPointBuffer()[myNode] = aLftMinPoint; + myBVH->MaxPointBuffer()[myNode] = aLftMaxPoint; + + *myHeight = Max (aLftHeight, aRghHeight) + 1; + } + return NULL; + } + }; + +#endif +} + +// ======================================================================= +// function : Build +// purpose : +// ======================================================================= +template<class T, int N> +void BVH_LinearBuilder<T, N>::Build (BVH_Set<T, N>* theSet, + BVH_Tree<T, N>* theBVH, + const BVH_Box<T, N>& theBox) const +{ + Standard_STATIC_ASSERT (N == 3 || N == 4); + const Standard_Integer aSetSize = theSet->Size(); + if (theBVH == NULL || aSetSize == 0) + { + return; + } + + theBVH->Clear(); + + // Step 0 -- Initialize parameter of virtual grid + BVH_RadixSorter<T, N> aRadixSorter (theBox); + + // Step 1 - Perform radix sorting of primitive set + aRadixSorter.Perform (theSet); + + // Step 2 -- Emitting BVH hierarchy from sorted Morton codes + emitHierachy (theBVH, aRadixSorter.EncodedLinks(), 29, 0, 0, theSet->Size()); + + // Step 3 -- Compute bounding boxes of BVH nodes + theBVH->MinPointBuffer().resize (theBVH->NodeInfoBuffer().size()); + theBVH->MaxPointBuffer().resize (theBVH->NodeInfoBuffer().size()); + + Standard_Integer aHeight = 0; + +#ifdef HAVE_TBB + + // Note: Although TBB tasks are allocated using placement + // new, we do not need to delete them explicitly + BVH::UpdateBoundTask<T, N>& aRootTask = *new ( tbb::task::allocate_root() ) + BVH::UpdateBoundTask<T, N> (theSet, theBVH, 0, 0, &aHeight); + + tbb::task::spawn_root_and_wait (aRootTask); + +#else + + aHeight = BVH::UpdateBounds (theSet, theBVH, 0); + +#endif + + BVH_Builder<T, N>::updateDepth (theBVH, aHeight); +} #endif // _BVH_LinearBuilder_Header diff --git a/src/BVH/BVH_LinearBuilder.lxx b/src/BVH/BVH_LinearBuilder.lxx deleted file mode 100644 index e616590253..0000000000 --- a/src/BVH/BVH_LinearBuilder.lxx +++ /dev/null @@ -1,320 +0,0 @@ -// Created on: 2014-09-11 -// Created by: Danila ULYANOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include <Standard_Assert.hxx> - -// ======================================================================= -// function : BVH_LinearBuilder -// purpose : -// ======================================================================= -template<class T, int N> -BVH_LinearBuilder<T, N>::BVH_LinearBuilder (const Standard_Integer theLeafNodeSize, - const Standard_Integer theMaxTreeDepth) -: BVH_Builder<T, N> (theLeafNodeSize, - theMaxTreeDepth) -{ - // -} - -// ======================================================================= -// function : ~BVH_LinearBuilder -// purpose : -// ======================================================================= -template<class T, int N> -BVH_LinearBuilder<T, N>::~BVH_LinearBuilder() -{ - // -} - -// ======================================================================= -// function : LowerBound -// purpose : Returns index of first element greater than the given one -// ======================================================================= -template<class T, int N> -Standard_Integer BVH_LinearBuilder<T, N>::LowerBound (Standard_Integer theStart, - Standard_Integer theFinal, - Standard_Integer theDigit) -{ - Standard_Integer aNbPrims = theFinal - theStart; - - while (aNbPrims > 0) - { - const Standard_Integer aStep = aNbPrims / 2; - - if (myRadixSorter->EncodedLinks().Value (theStart + aStep).first & (1 << theDigit)) - { - aNbPrims = aStep; - } - else - { - theStart += aStep + 1; - aNbPrims -= aStep + 1; - } - } - - return theStart; -} - -// ======================================================================= -// function : EmitHierachy -// purpose : Emits hierarchy from sorted Morton codes -// ======================================================================= -template<class T, int N> -Standard_Integer BVH_LinearBuilder<T, N>::EmitHierachy (BVH_Tree<T, N>* theBVH, - const Standard_Integer theBit, - const Standard_Integer theShift, - const Standard_Integer theStart, - const Standard_Integer theFinal) -{ - if (theFinal - theStart > BVH_Builder<T, N>::myLeafNodeSize) - { - const Standard_Integer aPosition = theBit < 0 ? - (theStart + theFinal) / 2 : LowerBound (theStart, theFinal, theBit); - - if (aPosition == theStart || aPosition == theFinal) - { - return EmitHierachy (theBVH, theBit - 1, theShift, theStart, theFinal); - } - - // Build inner node - const Standard_Integer aNode = theBVH->AddInnerNode (0, 0); - - const Standard_Integer aRghNode = theShift + aPosition - theStart; - - const Standard_Integer aLftChild = EmitHierachy (theBVH, theBit - 1, theShift, theStart, aPosition); - const Standard_Integer aRghChild = EmitHierachy (theBVH, theBit - 1, aRghNode, aPosition, theFinal); - - theBVH->NodeInfoBuffer()[aNode].y() = aLftChild; - theBVH->NodeInfoBuffer()[aNode].z() = aRghChild; - - return aNode; - } - else - { - // Build leaf node - return theBVH->AddLeafNode (theShift, theShift + theFinal - theStart - 1); - } -} - -namespace BVH -{ - //! Calculates bounding boxes (AABBs) for the given BVH tree. - template<class T, int N> - Standard_Integer UpdateBounds (BVH_Set<T, N>* theSet, BVH_Tree<T, N>* theTree, const Standard_Integer theNode = 0) - { - const BVH_Vec4i aData = theTree->NodeInfoBuffer()[theNode]; - - if (aData.x() == 0) - { - const Standard_Integer aLftChild = theTree->NodeInfoBuffer()[theNode].y(); - const Standard_Integer aRghChild = theTree->NodeInfoBuffer()[theNode].z(); - - const Standard_Integer aLftDepth = UpdateBounds (theSet, theTree, aLftChild); - const Standard_Integer aRghDepth = UpdateBounds (theSet, theTree, aRghChild); - - typename BVH_Box<T, N>::BVH_VecNt aLftMinPoint = theTree->MinPointBuffer()[aLftChild]; - typename BVH_Box<T, N>::BVH_VecNt aLftMaxPoint = theTree->MaxPointBuffer()[aLftChild]; - typename BVH_Box<T, N>::BVH_VecNt aRghMinPoint = theTree->MinPointBuffer()[aRghChild]; - typename BVH_Box<T, N>::BVH_VecNt aRghMaxPoint = theTree->MaxPointBuffer()[aRghChild]; - - BVH::BoxMinMax<T, N>::CwiseMin (aLftMinPoint, aRghMinPoint); - BVH::BoxMinMax<T, N>::CwiseMax (aLftMaxPoint, aRghMaxPoint); - - theTree->MinPointBuffer()[theNode] = aLftMinPoint; - theTree->MaxPointBuffer()[theNode] = aLftMaxPoint; - - return Max (aLftDepth, aRghDepth) + 1; - } - else - { - typename BVH_Box<T, N>::BVH_VecNt& aMinPoint = theTree->MinPointBuffer()[theNode]; - typename BVH_Box<T, N>::BVH_VecNt& aMaxPoint = theTree->MaxPointBuffer()[theNode]; - - for (Standard_Integer aPrimIdx = aData.y(); aPrimIdx <= aData.z(); ++aPrimIdx) - { - const BVH_Box<T, N> aBox = theSet->Box (aPrimIdx); - - if (aPrimIdx == aData.y()) - { - aMinPoint = aBox.CornerMin(); - aMaxPoint = aBox.CornerMax(); - } - else - { - BVH::BoxMinMax<T, N>::CwiseMin (aMinPoint, aBox.CornerMin()); - BVH::BoxMinMax<T, N>::CwiseMax (aMaxPoint, aBox.CornerMax()); - } - } - } - - return 0; - } - -#ifdef HAVE_TBB - - //! TBB task for parallel bounds updating. - template<class T, int N> - class UpdateBoundTask: public tbb::task - { - //! Set of geometric objects. - BVH_Set<T, N>* mySet; - - //! BVH tree built over the set. - BVH_Tree<T, N>* myBVH; - - //! BVH node to update bounding box. - Standard_Integer myNode; - - //! Level of the processed BVH node. - Standard_Integer myLevel; - - //! Height of the processed BVH node. - Standard_Integer* myHeight; - - public: - - //! Creates new TBB parallel bound update task. - UpdateBoundTask (BVH_Set<T, N>* theSet, - BVH_Tree<T, N>* theBVH, - Standard_Integer theNode, - Standard_Integer theLevel, - Standard_Integer* theHeight) - : mySet (theSet), - myBVH (theBVH), - myNode (theNode), - myLevel (theLevel), - myHeight (theHeight) - { - // - } - - //! Executes the task. - tbb::task* execute() - { - if (myBVH->IsOuter (myNode) || myLevel > 2) - { - *myHeight = BVH::UpdateBounds (mySet, myBVH, myNode); - } - else - { - Standard_Integer aLftHeight = 0; - Standard_Integer aRghHeight = 0; - - tbb::task_list aList; - - const Standard_Integer aLftChild = myBVH->NodeInfoBuffer()[myNode].y(); - const Standard_Integer aRghChild = myBVH->NodeInfoBuffer()[myNode].z(); - - Standard_Integer aCount = 1; - - if (!myBVH->IsOuter (aLftChild)) - { - ++aCount; - aList.push_back (*new ( allocate_child() ) - UpdateBoundTask (mySet, myBVH, aLftChild, myLevel + 1, &aLftHeight)); - } - else - { - aLftHeight = BVH::UpdateBounds (mySet, myBVH, aLftChild); - } - - if (!myBVH->IsOuter (aRghChild)) - { - ++aCount; - aList.push_back (*new( allocate_child() ) - UpdateBoundTask (mySet, myBVH, aRghChild, myLevel + 1, &aRghHeight)); - } - else - { - aRghHeight = BVH::UpdateBounds (mySet, myBVH, aRghChild); - } - - if (aCount > 1) - { - set_ref_count (aCount); - spawn_and_wait_for_all (aList); - } - - typename BVH_Box<T, N>::BVH_VecNt aLftMinPoint = myBVH->MinPointBuffer()[aLftChild]; - typename BVH_Box<T, N>::BVH_VecNt aLftMaxPoint = myBVH->MaxPointBuffer()[aLftChild]; - typename BVH_Box<T, N>::BVH_VecNt aRghMinPoint = myBVH->MinPointBuffer()[aRghChild]; - typename BVH_Box<T, N>::BVH_VecNt aRghMaxPoint = myBVH->MaxPointBuffer()[aRghChild]; - - BVH::BoxMinMax<T, N>::CwiseMin (aLftMinPoint, aRghMinPoint); - BVH::BoxMinMax<T, N>::CwiseMax (aLftMaxPoint, aRghMaxPoint); - - myBVH->MinPointBuffer()[myNode] = aLftMinPoint; - myBVH->MaxPointBuffer()[myNode] = aLftMaxPoint; - - *myHeight = Max (aLftHeight, aRghHeight) + 1; - } - - return NULL; - } - }; - -#endif -} - -// ======================================================================= -// function : Build -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_LinearBuilder<T, N>::Build (BVH_Set<T, N>* theSet, - BVH_Tree<T, N>* theBVH, - const BVH_Box<T, N>& theBox) -{ - Standard_STATIC_ASSERT (N == 3 || N == 4); - const Standard_Integer aSetSize = theSet->Size(); - if (theBVH == NULL || aSetSize == 0) - { - return; - } - - theBVH->Clear(); - - // Step 0 -- Initialize parameter of virtual grid - myRadixSorter = new BVH_RadixSorter<T, N> (theBox); - - // Step 1 - Perform radix sorting of primitive set - myRadixSorter->Perform (theSet); - - // Step 2 -- Emitting BVH hierarchy from sorted Morton codes - EmitHierachy (theBVH, 29, 0, 0, theSet->Size()); - - // Step 3 -- Compute bounding boxes of BVH nodes - theBVH->MinPointBuffer().resize (theBVH->NodeInfoBuffer().size()); - theBVH->MaxPointBuffer().resize (theBVH->NodeInfoBuffer().size()); - - Standard_Integer aHeight = 0; - -#ifdef HAVE_TBB - - // Note: Although TBB tasks are allocated using placement - // new, we do not need to delete them explicitly - BVH::UpdateBoundTask<T, N>& aRootTask = *new ( tbb::task::allocate_root() ) - BVH::UpdateBoundTask<T, N> (theSet, theBVH, 0, 0, &aHeight); - - tbb::task::spawn_root_and_wait (aRootTask); - -#else - - aHeight = BVH::UpdateBounds (theSet, theBVH, 0); - -#endif - - BVH_Builder<T, N>::UpdateDepth (theBVH, aHeight); -} diff --git a/src/BVH/BVH_Object.hxx b/src/BVH/BVH_Object.hxx index 2c36cea0fb..0a265ff2cc 100644 --- a/src/BVH/BVH_Object.hxx +++ b/src/BVH/BVH_Object.hxx @@ -30,7 +30,7 @@ class BVH_Object public: //! Creates new abstract geometric object. - BVH_Object(); + BVH_Object() : myIsDirty (Standard_False) {} //! Releases resources of geometric object. virtual ~BVH_Object() = 0; @@ -41,13 +41,13 @@ public: virtual BVH_Box<T, N> Box() const = 0; //! Returns properties of the geometric object. - virtual const NCollection_Handle<BVH_Properties>& Properties() const; + virtual const NCollection_Handle<BVH_Properties>& Properties() const { return myProperties; } //! Sets properties of the geometric object. - virtual void SetProperties (const NCollection_Handle<BVH_Properties>& theProperties); + virtual void SetProperties (const NCollection_Handle<BVH_Properties>& theProperties) { myProperties = theProperties; } //! Marks object state as outdated (needs BVH rebuilding). - virtual void MarkDirty(); + virtual void MarkDirty() { myIsDirty = Standard_True; } protected: @@ -56,6 +56,14 @@ protected: }; -#include <BVH_Object.lxx> +// ======================================================================= +// function : ~BVH_Object +// purpose : +// ======================================================================= +template<class T, int N> +BVH_Object<T, N>::~BVH_Object() +{ + // +} #endif // _BVH_Object_Header diff --git a/src/BVH/BVH_Object.lxx b/src/BVH/BVH_Object.lxx deleted file mode 100644 index 0025bbc8ff..0000000000 --- a/src/BVH/BVH_Object.lxx +++ /dev/null @@ -1,65 +0,0 @@ -// Created on: 2013-12-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -// ======================================================================= -// function : BVH_Object -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Object<T, N>::BVH_Object() -: myIsDirty (Standard_False) -{ - // -} - -// ======================================================================= -// function : ~BVH_Object -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Object<T, N>::~BVH_Object() -{ - // -} - -// ======================================================================= -// function : Properties -// purpose : -// ======================================================================= -template<class T, int N> -const NCollection_Handle<BVH_Properties>& BVH_Object<T, N>::Properties() const -{ - return myProperties; -} - -// ======================================================================= -// function : SetProperties -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_Object<T, N>::SetProperties (const NCollection_Handle<BVH_Properties>& theProperties) -{ - myProperties = theProperties; -} - -// ======================================================================= -// function : MarkDirty -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_Object<T, N>::MarkDirty() -{ - myIsDirty = Standard_True; -} diff --git a/src/BVH/BVH_ObjectSet.hxx b/src/BVH/BVH_ObjectSet.hxx index e776c088bd..9cbd9ae791 100644 --- a/src/BVH/BVH_ObjectSet.hxx +++ b/src/BVH/BVH_ObjectSet.hxx @@ -33,38 +33,53 @@ public: public: //! Creates new set of geometric objects. - BVH_ObjectSet(); + BVH_ObjectSet() {} //! Releases resources of set of geometric objects. - virtual ~BVH_ObjectSet(); + virtual ~BVH_ObjectSet() {} public: //! Removes all geometric objects. - virtual void Clear(); + virtual void Clear() + { + for (typename BVH_ObjectList::Iterator anObjectIter (myObjects); anObjectIter.More(); anObjectIter.Next()) + { + anObjectIter.ChangeValue().Nullify(); + } + myObjects.Clear(); + } //! Returns reference to the array of geometric objects. - BVH_ObjectList& Objects(); + BVH_ObjectList& Objects() { return myObjects; } //! Returns reference to the array of geometric objects. - const BVH_ObjectList& Objects() const; + const BVH_ObjectList& Objects() const { return myObjects; } public: //! Return total number of objects. - virtual Standard_Integer Size() const; + virtual Standard_Integer Size() const Standard_OVERRIDE { return myObjects.Size(); } //! Returns AABB of entire set of objects. using BVH_Set<T, N>::Box; //! Returns AABB of the given object. - virtual BVH_Box<T, N> Box (const Standard_Integer theIndex) const; + virtual BVH_Box<T, N> Box (const Standard_Integer theIndex) const Standard_OVERRIDE { return myObjects.Value (theIndex)->Box(); } //! Returns centroid position along the given axis. - virtual T Center (const Standard_Integer theIndex, const Standard_Integer theAxis) const; + virtual T Center (const Standard_Integer theIndex, const Standard_Integer theAxis) const Standard_OVERRIDE + { + // Note: general implementation, not optimal + return BVH::CenterAxis<T, N>::Center (myObjects.Value (theIndex)->Box(), theAxis); + } //! Performs transposing the two given objects in the set. - virtual void Swap (const Standard_Integer theIndex1, const Standard_Integer theIndex2); + virtual void Swap (const Standard_Integer theIndex1, const Standard_Integer theIndex2) Standard_OVERRIDE + { + std::swap (myObjects.ChangeValue (theIndex1), + myObjects.ChangeValue (theIndex2)); + } protected: @@ -72,6 +87,4 @@ protected: }; -#include <BVH_ObjectSet.lxx> - #endif // _BVH_ObjectSet_Header diff --git a/src/BVH/BVH_ObjectSet.lxx b/src/BVH/BVH_ObjectSet.lxx deleted file mode 100644 index 87d93528d6..0000000000 --- a/src/BVH/BVH_ObjectSet.lxx +++ /dev/null @@ -1,112 +0,0 @@ -// Created on: 2013-12-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -// ======================================================================= -// function : BVH_ObjectSet -// purpose : -// ======================================================================= -template<class T, int N> -BVH_ObjectSet<T, N>::BVH_ObjectSet() -{ - // -} - -// ======================================================================= -// function : ~BVH_ObjectSet -// purpose : -// ======================================================================= -template<class T, int N> -BVH_ObjectSet<T, N>::~BVH_ObjectSet() -{ - // -} - -// ======================================================================= -// function : Clears all geometric objects -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_ObjectSet<T, N>::Clear() -{ - for (Standard_Integer anObjectIdx = 0; anObjectIdx < myObjects.Size(); ++anObjectIdx) - { - myObjects.ChangeValue (anObjectIdx).Nullify(); - } - myObjects.Clear(); -} - -// ======================================================================= -// function : Objects -// purpose : -// ======================================================================= -template<class T, int N> -typename BVH_ObjectSet<T, N>::BVH_ObjectList& BVH_ObjectSet<T, N>::Objects() -{ - return myObjects; -} - -// ======================================================================= -// function : Objects -// purpose : -// ======================================================================= -template<class T, int N> -const typename BVH_ObjectSet<T, N>::BVH_ObjectList& BVH_ObjectSet<T, N>::Objects() const -{ - return myObjects; -} - -// ======================================================================= -// function : Size -// purpose : -// ======================================================================= -template<class T, int N> -Standard_Integer BVH_ObjectSet<T, N>::Size() const -{ - return myObjects.Size(); -} - -// ======================================================================= -// function : Box -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Box<T, N> BVH_ObjectSet<T, N>::Box (const Standard_Integer theIndex) const -{ - return myObjects.Value (theIndex)->Box(); -} - -// ======================================================================= -// function : Center -// purpose : -// ======================================================================= -template<class T, int N> -T BVH_ObjectSet<T, N>::Center (const Standard_Integer theIndex, - const Standard_Integer theAxis) const -{ - // Note: general implementation, not optimal - return BVH::CenterAxis<T, N>::Center (myObjects.Value (theIndex)->Box(), theAxis); -} - -// ======================================================================= -// function : Swap -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_ObjectSet<T, N>::Swap (const Standard_Integer theIndex1, - const Standard_Integer theIndex2) -{ - std::swap (myObjects.ChangeValue (theIndex1), - myObjects.ChangeValue (theIndex2)); -} diff --git a/src/BVH/BVH_PrimitiveSet.hxx b/src/BVH/BVH_PrimitiveSet.hxx index 265b402e90..3ed9b577d1 100644 --- a/src/BVH/BVH_PrimitiveSet.hxx +++ b/src/BVH/BVH_PrimitiveSet.hxx @@ -18,6 +18,7 @@ #include <BVH_Object.hxx> #include <BVH_Builder.hxx> +#include <BVH_BinnedBuilder.hxx> //! Set of abstract geometric primitives organized with bounding //! volume hierarchy (BVH). Unlike an object set, this collection @@ -38,29 +39,59 @@ public: static const Standard_Integer MaxTreeDepth = 32; //! Creates set of abstract primitives. - BVH_PrimitiveSet(); + BVH_PrimitiveSet() + : myBVH (new BVH_Tree<T, N>()) + { + // Set default builder - binned SAH split + myBuilder = new BVH_BinnedBuilder<T, N, 48> (5, MaxTreeDepth); + } //! Releases resources of set of abstract primitives. - virtual ~BVH_PrimitiveSet(); + virtual ~BVH_PrimitiveSet() + { + myBVH.Nullify(); + myBuilder.Nullify(); + } public: //! Returns AABB of primitive set. - virtual BVH_Box<T, N> Box() const; + virtual BVH_Box<T, N> Box() const Standard_OVERRIDE + { + if (BVH_Object<T, N>::myIsDirty) + { + myBox = BVH_Set<T, N>::Box(); + } + return myBox; + } //! Returns BVH tree (and builds it if necessary). - virtual const NCollection_Handle<BVH_Tree<T, N> >& BVH(); + virtual const NCollection_Handle<BVH_Tree<T, N> >& BVH() + { + if (BVH_Object<T, N>::myIsDirty) + { + Update(); + } + return myBVH; + } //! Returns the method (builder) used to construct BVH. - virtual const NCollection_Handle<BVH_Builder<T, N> >& Builder() const; + virtual const NCollection_Handle<BVH_Builder<T, N> >& Builder() const { return myBuilder; } //! Sets the method (builder) used to construct BVH. - virtual void SetBuilder (NCollection_Handle<BVH_Builder<T, N> >& theBuilder); + virtual void SetBuilder (const NCollection_Handle<BVH_Builder<T, N> >& theBuilder) { myBuilder = theBuilder; } protected: //! Updates BVH of primitive set. - virtual void Update(); + virtual void Update() + { + if (BVH_Object<T, N>::myIsDirty) + { + myBuilder->Build (this, myBVH.operator->(), Box()); + BVH_Object<T, N>::myIsDirty = Standard_False; + } + } protected: @@ -71,6 +102,4 @@ protected: }; -#include <BVH_PrimitiveSet.lxx> - #endif // _BVH_PrimitiveSet_Header diff --git a/src/BVH/BVH_PrimitiveSet.lxx b/src/BVH/BVH_PrimitiveSet.lxx deleted file mode 100644 index 00231a635a..0000000000 --- a/src/BVH/BVH_PrimitiveSet.lxx +++ /dev/null @@ -1,106 +0,0 @@ -// Created on: 2013-12-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include <BVH_BinnedBuilder.hxx> - -// ======================================================================= -// function : BVH_PrimitiveSet -// purpose : -// ======================================================================= -template<class T, int N> -BVH_PrimitiveSet<T, N>::BVH_PrimitiveSet() -: myBVH (new BVH_Tree<T, N>()) -{ - // Set default builder - binned SAH split - myBuilder = new BVH_BinnedBuilder<T, N, 48> (5, MaxTreeDepth); -} - -// ======================================================================= -// function : ~BVH_PrimitiveSet -// purpose : -// ======================================================================= -template<class T, int N> -BVH_PrimitiveSet<T, N>::~BVH_PrimitiveSet() -{ - myBVH.Nullify(); - myBuilder.Nullify(); -} - -// ======================================================================= -// function : BVH -// purpose : -// ======================================================================= -template<class T, int N> -const NCollection_Handle<BVH_Tree<T, N> >& BVH_PrimitiveSet<T, N>::BVH() -{ - if (BVH_Object<T, N>::myIsDirty) - { - Update(); - } - - return myBVH; -} - -// ======================================================================= -// function : Box -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Box<T, N> BVH_PrimitiveSet<T, N>::Box() const -{ - if (!BVH_Object<T, N>::myIsDirty) - { - return myBox; - } - - myBox = BVH_Set<T, N>::Box(); - return myBox; -} - -// ======================================================================= -// function : Update -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_PrimitiveSet<T, N>::Update() -{ - if (!BVH_Object<T, N>::myIsDirty) - { - return; - } - - myBuilder->Build (this, myBVH.operator->(), Box()); - BVH_Object<T, N>::myIsDirty = Standard_False; -} - -// ======================================================================= -// function : Builder -// purpose : -// ======================================================================= -template<class T, int N> -const NCollection_Handle<BVH_Builder<T, N> >& BVH_PrimitiveSet<T, N>::Builder() const -{ - return myBuilder; -} - -// ======================================================================= -// function : SetBuilder -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_PrimitiveSet<T, N>::SetBuilder (NCollection_Handle<BVH_Builder<T, N> >& theBuilder) -{ - myBuilder = theBuilder; -} diff --git a/src/BVH/BVH_Properties.hxx b/src/BVH/BVH_Properties.hxx index 6cb6e2c216..9a0e9238e9 100644 --- a/src/BVH/BVH_Properties.hxx +++ b/src/BVH/BVH_Properties.hxx @@ -42,22 +42,22 @@ public: public: //! Creates new identity transformation. - BVH_Transform(); + BVH_Transform() {} //! Creates new transformation with specified matrix. - BVH_Transform (const BVH_MatNt& theTransform); + BVH_Transform (const BVH_MatNt& theTransform) : myTransform (theTransform) {} //! Releases resources of transformation properties. - virtual ~BVH_Transform(); + virtual ~BVH_Transform() {} //! Returns transformation matrix. - const BVH_MatNt& Transform() const; + const BVH_MatNt& Transform() const { return myTransform; } //! Sets new transformation matrix. void SetTransform (const BVH_MatNt& theTransform); //! Returns inversed transformation matrix. - const BVH_MatNt& Inversed() const; + const BVH_MatNt& Inversed() const { return myTransformInversed; } //! Applies transformation matrix to bounding box. BVH_Box<T, N> Apply (const BVH_Box<T, N>& theBox) const; @@ -69,6 +69,105 @@ protected: }; -#include <BVH_Properties.lxx> +namespace BVH +{ + template<class T, int N> struct MatrixOp + { + // Not implemented + }; + + template<class T> struct MatrixOp<T, 4> + { + typedef typename BVH::MatrixType<T, 4>::Type BVH_Mat4t; + + static void Inverse (const BVH_Mat4t& theIn, + BVH_Mat4t& theOut) + { + theIn.Inverted (theOut); + } + + typedef typename BVH::VectorType<T, 4>::Type BVH_Vec4t; + + static BVH_Vec4t Multiply (const BVH_Mat4t& theMat, + const BVH_Vec4t& theVec) + { + BVH_Vec4t aOut = theMat * theVec; + return aOut * static_cast<T> (1.0 / aOut.w()); + } + }; + + template<class T, int N> + struct UnitVector + { + // Not implemented + }; + + template<class T> + struct UnitVector<T, 2> + { + typedef typename BVH::VectorType<T, 2>::Type BVH_Vec2t; + static BVH_Vec2t DX() { return BVH_Vec2t (static_cast<T> (1.0), static_cast<T> (0.0)); } + static BVH_Vec2t DY() { return BVH_Vec2t (static_cast<T> (0.0), static_cast<T> (1.0)); } + static BVH_Vec2t DZ() { return BVH_Vec2t (static_cast<T> (0.0), static_cast<T> (0.0)); } + }; + + template<class T> + struct UnitVector<T, 3> + { + typedef typename BVH::VectorType<T, 3>::Type BVH_Vec3t; + static BVH_Vec3t DX() { return BVH_Vec3t (static_cast<T> (1.0), static_cast<T> (0.0), static_cast<T> (0.0)); } + static BVH_Vec3t DY() { return BVH_Vec3t (static_cast<T> (0.0), static_cast<T> (1.0), static_cast<T> (0.0)); } + static BVH_Vec3t DZ() { return BVH_Vec3t (static_cast<T> (0.0), static_cast<T> (0.0), static_cast<T> (1.0)); } + }; + + template<class T> + struct UnitVector<T, 4> + { + typedef typename BVH::VectorType<T, 4>::Type BVH_Vec4t; + static BVH_Vec4t DX() { return BVH_Vec4t (static_cast<T> (1.0), static_cast<T> (0.0), static_cast<T> (0.0), static_cast<T> (0.0)); } + static BVH_Vec4t DY() { return BVH_Vec4t (static_cast<T> (0.0), static_cast<T> (1.0), static_cast<T> (0.0), static_cast<T> (0.0)); } + static BVH_Vec4t DZ() { return BVH_Vec4t (static_cast<T> (0.0), static_cast<T> (0.0), static_cast<T> (1.0), static_cast<T> (0.0)); } + }; +} + +// ======================================================================= +// function : SetTransform +// purpose : +// ======================================================================= +template<class T, int N> +void BVH_Transform<T, N>::SetTransform (const BVH_MatNt& theTransform) +{ + myTransform = theTransform; + BVH::MatrixOp<T, N>::Inverse (myTransform, myTransformInversed); +} + +// ======================================================================= +// function : Apply +// purpose : +// ======================================================================= +template<class T, int N> +BVH_Box<T, N> BVH_Transform<T, N>::Apply (const BVH_Box<T, N>& theBox) const +{ + typename BVH_Box<T, N>::BVH_VecNt aSize = theBox.Size(); + + BVH_Box<T, N> aBox; + for (Standard_Integer aX = 0; aX <= 1; ++aX) + { + for (Standard_Integer aY = 0; aY <= 1; ++aY) + { + for (Standard_Integer aZ = 0; aZ <= 1; ++aZ) + { + typename BVH_Box<T, N>::BVH_VecNt aCorner = theBox.CornerMin() + + BVH::UnitVector<T, N>::DX() * aSize * static_cast<T> (aX) + + BVH::UnitVector<T, N>::DY() * aSize * static_cast<T> (aY) + + BVH::UnitVector<T, N>::DZ() * aSize * static_cast<T> (aZ); + + aBox.Add (BVH::MatrixOp<T, N>::Multiply (myTransform, aCorner)); + } + } + } + + return aBox; +} #endif // _BVH_Properties_Header diff --git a/src/BVH/BVH_Properties.lxx b/src/BVH/BVH_Properties.lxx deleted file mode 100644 index 0fed18914d..0000000000 --- a/src/BVH/BVH_Properties.lxx +++ /dev/null @@ -1,223 +0,0 @@ -// Created on: 2013-12-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -// ======================================================================= -// function : BVH_Transform -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Transform<T, N>::BVH_Transform() -{ - // -} - -// ======================================================================= -// function : BVH_Transform -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Transform<T, N>::BVH_Transform (const BVH_MatNt& theTransform) -: myTransform (theTransform) -{ - // -} - -// ======================================================================= -// function : ~BVH_Transform -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Transform<T, N>::~BVH_Transform() -{ - // -} - -// ======================================================================= -// function : Transform -// purpose : -// ======================================================================= -template<class T, int N> -const typename BVH_Transform<T, N>::BVH_MatNt& BVH_Transform<T, N>::Transform() const -{ - return myTransform; -} - -namespace BVH -{ - template<class T, int N> struct MatrixOp - { - // Not implemented - }; - - template<class T> struct MatrixOp<T, 4> - { - typedef typename BVH::MatrixType<T, 4>::Type BVH_Mat4t; - - static void Inverse (const BVH_Mat4t& theIn, - BVH_Mat4t& theOut) - { - theIn.Inverted (theOut); - } - - typedef typename BVH::VectorType<T, 4>::Type BVH_Vec4t; - - static BVH_Vec4t Multiply (const BVH_Mat4t& theMat, - const BVH_Vec4t& theVec) - { - BVH_Vec4t aOut = theMat * theVec; - return aOut * static_cast<T> (1.0 / aOut.w()); - } - }; -} - -// ======================================================================= -// function : SetTransform -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_Transform<T, N>::SetTransform (const BVH_MatNt& theTransform) -{ - myTransform = theTransform; - BVH::MatrixOp<T, N>::Inverse (myTransform, myTransformInversed); -} - -// ======================================================================= -// function : Inversed -// purpose : -// ======================================================================= -template<class T, int N> -const typename BVH_Transform<T, N>::BVH_MatNt& BVH_Transform<T, N>::Inversed() const -{ - return myTransformInversed; -} - -namespace BVH -{ - template<class T, int N> - struct UnitVector - { - // Not implemented - }; - - template<class T> - struct UnitVector<T, 2> - { - typedef typename BVH::VectorType<T, 2>::Type BVH_Vec2t; - - static BVH_Vec2t DX() - { - return BVH_Vec2t (static_cast<T> (1.0), - static_cast<T> (0.0)); - } - - static BVH_Vec2t DY() - { - return BVH_Vec2t (static_cast<T> (0.0), - static_cast<T> (1.0)); - } - - static BVH_Vec2t DZ() - { - return BVH_Vec2t (static_cast<T> (0.0), - static_cast<T> (0.0)); - } - }; - - template<class T> - struct UnitVector<T, 3> - { - typedef typename BVH::VectorType<T, 3>::Type BVH_Vec3t; - - static BVH_Vec3t DX() - { - return BVH_Vec3t (static_cast<T> (1.0), - static_cast<T> (0.0), - static_cast<T> (0.0)); - } - - static BVH_Vec3t DY() - { - return BVH_Vec3t (static_cast<T> (0.0), - static_cast<T> (1.0), - static_cast<T> (0.0)); - } - - static BVH_Vec3t DZ() - { - return BVH_Vec3t (static_cast<T> (0.0), - static_cast<T> (0.0), - static_cast<T> (1.0)); - } - }; - - template<class T> - struct UnitVector<T, 4> - { - typedef typename BVH::VectorType<T, 4>::Type BVH_Vec4t; - - static BVH_Vec4t DX() - { - return BVH_Vec4t (static_cast<T> (1.0), - static_cast<T> (0.0), - static_cast<T> (0.0), - static_cast<T> (0.0)); - } - - static BVH_Vec4t DY() - { - return BVH_Vec4t (static_cast<T> (0.0), - static_cast<T> (1.0), - static_cast<T> (0.0), - static_cast<T> (0.0)); - } - - static BVH_Vec4t DZ() - { - return BVH_Vec4t (static_cast<T> (0.0), - static_cast<T> (0.0), - static_cast<T> (1.0), - static_cast<T> (0.0)); - } - }; -} - -// ======================================================================= -// function : Apply -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Box<T, N> BVH_Transform<T, N>::Apply (const BVH_Box<T, N>& theBox) const -{ - typename BVH_Box<T, N>::BVH_VecNt aSize = theBox.Size(); - - BVH_Box<T, N> aBox; - for (Standard_Integer aX = 0; aX <= 1; ++aX) - { - for (Standard_Integer aY = 0; aY <= 1; ++aY) - { - for (Standard_Integer aZ = 0; aZ <= 1; ++aZ) - { - typename BVH_Box<T, N>::BVH_VecNt aCorner = theBox.CornerMin() + - BVH::UnitVector<T, N>::DX() * aSize * static_cast<T> (aX) + - BVH::UnitVector<T, N>::DY() * aSize * static_cast<T> (aY) + - BVH::UnitVector<T, N>::DZ() * aSize * static_cast<T> (aZ); - - aBox.Add (BVH::MatrixOp<T, N>::Multiply (myTransform, aCorner)); - } - } - } - - return aBox; -} diff --git a/src/BVH/BVH_QuadTree.hxx b/src/BVH/BVH_QuadTree.hxx index e49ede6d32..bc348770f0 100644 --- a/src/BVH/BVH_QuadTree.hxx +++ b/src/BVH/BVH_QuadTree.hxx @@ -30,10 +30,11 @@ public: //! @name general methods //! Returns index of the K-th child of the given inner node. //! \tparam K the index of node child (from 0 to 3) template<int K> - int Child (const int theNodeIndex) const; + int Child (const int theNodeIndex) const + { + return BVH::Array<int, 4>::Value (this->myNodeInfoBuffer, theNodeIndex).y() + K; + } }; -#include <BVH_QuadTree.lxx> - #endif // _BVH_QuadTree_Header diff --git a/src/BVH/BVH_QuadTree.lxx b/src/BVH/BVH_QuadTree.lxx deleted file mode 100644 index 82adbef034..0000000000 --- a/src/BVH/BVH_QuadTree.lxx +++ /dev/null @@ -1,24 +0,0 @@ -// Created on: 2016-06-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2016 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -// ======================================================================= -// function : Child -// purpose : Returns index of the K-th child of the given inner node -// ======================================================================= -template<class T, int N> template<int K> -int BVH_Tree<T, N, BVH_QuadTree>::Child (const int theNodeIndex) const -{ - return BVH::Array<int, 4>::Value (this->myNodeInfoBuffer, theNodeIndex).y() + K; -} diff --git a/src/BVH/BVH_QueueBuilder.hxx b/src/BVH/BVH_QueueBuilder.hxx index a27ef13651..c7c4bf34ec 100644 --- a/src/BVH/BVH_QueueBuilder.hxx +++ b/src/BVH/BVH_QueueBuilder.hxx @@ -38,7 +38,10 @@ public: //! Creates new BVH queue based builder. BVH_QueueBuilder (const Standard_Integer theLeafNodeSize, const Standard_Integer theMaxTreeDepth, - const Standard_Integer theNumOfThreads = 1); + const Standard_Integer theNumOfThreads = 1) + : BVH_Builder<T, N> (theLeafNodeSize, + theMaxTreeDepth), + myNumOfThreads (theNumOfThreads) {} //! Releases resources of BVH queue based builder. virtual ~BVH_QueueBuilder() = 0; @@ -48,7 +51,7 @@ public: //! Builds BVH using specific algorithm. virtual void Build (BVH_Set<T, N>* theSet, BVH_Tree<T, N>* theBVH, - const BVH_Box<T, N>& theBox); + const BVH_Box<T, N>& theBox) const Standard_OVERRIDE; protected: @@ -126,58 +129,173 @@ protected: public: //! Creates new BVH build thread. - BVH_TypedBuildTool (BVH_Set<T, N>* theSet, - BVH_Tree<T, N>* theBVH, - BVH_Builder<T, N>* theAlgo) + BVH_TypedBuildTool (BVH_Set<T, N>* theSet, + BVH_Tree<T, N>* theBVH, + BVH_BuildQueue& theBuildQueue, + const BVH_QueueBuilder<T, N>* theAlgo) : mySet (theSet), - myBVH (theBVH) + myBVH (theBVH), + myBuildQueue (&theBuildQueue), + myAlgo (theAlgo) { - myAlgo = dynamic_cast<BVH_QueueBuilder<T, N>* > (theAlgo); - - Standard_ASSERT_RAISE (myAlgo != NULL, - "Error! BVH builder should be queue based"); + Standard_ASSERT_RAISE (myAlgo != NULL, "Error! BVH builder should be queue based"); } //! Performs splitting of the given BVH node. - virtual void Perform (const Standard_Integer theNode) + virtual void Perform (const Standard_Integer theNode) Standard_OVERRIDE { - const typename BVH_QueueBuilder<T, N>::BVH_ChildNodes aChildren = myAlgo->BuildNode (mySet, myBVH, theNode); - - myAlgo->AddChildren (myBVH, theNode, aChildren); + const typename BVH_QueueBuilder<T, N>::BVH_ChildNodes aChildren = myAlgo->buildNode (mySet, myBVH, theNode); + myAlgo->addChildren (myBVH, *myBuildQueue, theNode, aChildren); } protected: - //! Primitive set to build BVH. - BVH_Set<T, N>* mySet; + BVH_Set<T, N>* mySet; //!< Primitive set to build BVH + BVH_Tree<T, N>* myBVH; //!< Output BVH tree for the set + BVH_BuildQueue* myBuildQueue; + const BVH_QueueBuilder<T, N>* myAlgo; //!< Queue based BVH builder to use - //! Output BVH tree for the set. - BVH_Tree<T, N>* myBVH; - - //! Queue based BVH builder to use. - BVH_QueueBuilder<T, N>* myAlgo; }; protected: //! Performs splitting of the given BVH node. - virtual typename BVH_QueueBuilder<T, N>::BVH_ChildNodes BuildNode (BVH_Set<T, N>* theSet, + virtual typename BVH_QueueBuilder<T, N>::BVH_ChildNodes buildNode (BVH_Set<T, N>* theSet, BVH_Tree<T, N>* theBVH, - const Standard_Integer theNode) = 0; + const Standard_Integer theNode) const = 0; //! Processes child nodes of the splitted BVH node. - virtual void AddChildren (BVH_Tree<T, N>* theBVH, - const Standard_Integer theNode, - const BVH_ChildNodes& theSubNodes); + virtual void addChildren (BVH_Tree<T, N>* theBVH, + BVH_BuildQueue& theBuildQueue, + const Standard_Integer theNode, + const BVH_ChildNodes& theSubNodes) const; protected: - BVH_BuildQueue myBuildQueue; //!< Queue to manage BVH node building tasks - Standard_Integer myNumOfThreads; //!< Number of threads used to build BVH }; -#include <BVH_QueueBuilder.lxx> +// ======================================================================= +// function : addChildren +// purpose : +// ======================================================================= +template<class T, int N> +void BVH_QueueBuilder<T, N>::addChildren (BVH_Tree<T, N>* theBVH, + BVH_BuildQueue& theBuildQueue, + const Standard_Integer theNode, + const typename BVH_QueueBuilder<T, N>::BVH_ChildNodes& theSubNodes) const +{ + Standard_Integer aChildren[] = { -1, -1 }; + if (!theSubNodes.IsValid()) + { + return; + } + + // Add child nodes + { + Standard_Mutex::Sentry aSentry (theBuildQueue.myMutex); + + for (Standard_Integer anIdx = 0; anIdx < 2; ++anIdx) + { + aChildren[anIdx] = theBVH->AddLeafNode (theSubNodes.Boxes[anIdx], + theSubNodes.Ranges[anIdx].Start, + theSubNodes.Ranges[anIdx].Final); + } + + BVH_Builder<T, N>::updateDepth (theBVH, theBVH->Level (theNode) + 1); + } + + // Set parameters of child nodes and generate new tasks + for (Standard_Integer anIdx = 0; anIdx < 2; ++anIdx) + { + const Standard_Integer aChildIndex = aChildren[anIdx]; + + theBVH->Level (aChildIndex) = theBVH->Level (theNode) + 1; + + (anIdx == 0 ? theBVH->template Child<0> (theNode) + : theBVH->template Child<1> (theNode)) = aChildIndex; + + // Check to see if the child node must be split + const Standard_Boolean isLeaf = theSubNodes.NbPrims (anIdx) <= BVH_Builder<T, N>::myLeafNodeSize + || theBVH->Level (aChildIndex) >= BVH_Builder<T, N>::myMaxTreeDepth; + + if (!isLeaf) + { + theBuildQueue.Enqueue (aChildIndex); + } + } +} + +// ======================================================================= +// function : Build +// purpose : Builds BVH using specific algorithm +// ======================================================================= +template<class T, int N> +void BVH_QueueBuilder<T, N>::Build (BVH_Set<T, N>* theSet, + BVH_Tree<T, N>* theBVH, + const BVH_Box<T, N>& theBox) const +{ + Standard_ASSERT_RETURN (theBVH != NULL, + "Error! BVH tree to construct is NULL", ); + + theBVH->Clear(); + const Standard_Integer aSetSize = theSet->Size(); + if (aSetSize == 0) + { + return; + } + + const Standard_Integer aRoot = theBVH->AddLeafNode (theBox, 0, aSetSize - 1); + if (theSet->Size() == 1) + { + return; + } + + BVH_BuildQueue aBuildQueue; + aBuildQueue.Enqueue (aRoot); + + BVH_TypedBuildTool aBuildTool (theSet, theBVH, aBuildQueue, this); + if (myNumOfThreads > 1) + { + // Reserve the maximum possible number of nodes in the BVH + theBVH->Reserve (2 * aSetSize - 1); + + NCollection_Vector<Handle(BVH_BuildThread)> aThreads; + + // Run BVH build threads + for (Standard_Integer aThreadIndex = 0; aThreadIndex < myNumOfThreads; ++aThreadIndex) + { + aThreads.Append (new BVH_BuildThread (aBuildTool, aBuildQueue)); + aThreads.Last()->Run(); + } + + // Wait until all threads finish their work + for (Standard_Integer aThreadIndex = 0; aThreadIndex < myNumOfThreads; ++aThreadIndex) + { + aThreads.ChangeValue (aThreadIndex)->Wait(); + } + + // Free unused memory + theBVH->Reserve (theBVH->Length()); + } + else + { + BVH_BuildThread aThread (aBuildTool, aBuildQueue); + + // Execute thread function inside current thread + aThread.execute(); + } +} + +// ======================================================================= +// function : ~BVH_QueueBuilder +// purpose : +// ======================================================================= +template<class T, int N> +BVH_QueueBuilder<T, N>::~BVH_QueueBuilder() +{ + // +} #endif // _BVH_QueueBuilder_Header diff --git a/src/BVH/BVH_QueueBuilder.lxx b/src/BVH/BVH_QueueBuilder.lxx deleted file mode 100644 index 07cc2a84dd..0000000000 --- a/src/BVH/BVH_QueueBuilder.lxx +++ /dev/null @@ -1,153 +0,0 @@ -// Created on: 2014-09-15 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include <NCollection_Vector.hxx> - -// ======================================================================= -// function : BVH_QueueBuilder -// purpose : Creates new BVH queue based builder -// ======================================================================= -template<class T, int N> -BVH_QueueBuilder<T, N>::BVH_QueueBuilder (const Standard_Integer theLeafNodeSize, - const Standard_Integer theMaxTreeDepth, - const Standard_Integer theNumOfThreads) -: BVH_Builder<T, N> (theLeafNodeSize, - theMaxTreeDepth), - myNumOfThreads (theNumOfThreads) -{ - // -} - -// ======================================================================= -// function : ~BVH_QueueBuilder -// purpose : Releases resources of BVH queue based builder -// ======================================================================= -template<class T, int N> -BVH_QueueBuilder<T, N>::~BVH_QueueBuilder() -{ - // -} - -// ======================================================================= -// function : AddChildren -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_QueueBuilder<T, N>::AddChildren (BVH_Tree<T, N>* theBVH, - const Standard_Integer theNode, - const typename BVH_QueueBuilder<T, N>::BVH_ChildNodes& theSubNodes) -{ - Standard_Integer aChildren[] = { -1, -1 }; - - if (!theSubNodes.IsValid()) - { - return; - } - - // Add child nodes - { - Standard_Mutex::Sentry aSentry (myBuildQueue.myMutex); - - for (Standard_Integer anIdx = 0; anIdx < 2; ++anIdx) - { - aChildren[anIdx] = theBVH->AddLeafNode (theSubNodes.Boxes[anIdx], - theSubNodes.Ranges[anIdx].Start, - theSubNodes.Ranges[anIdx].Final); - } - - BVH_Builder<T, N>::UpdateDepth (theBVH, theBVH->Level (theNode) + 1); - } - - // Set parameters of child nodes and generate new tasks - for (Standard_Integer anIdx = 0; anIdx < 2; ++anIdx) - { - const Standard_Integer aChildIndex = aChildren[anIdx]; - - theBVH->Level (aChildIndex) = theBVH->Level (theNode) + 1; - - (anIdx == 0 ? theBVH->template Child<0> (theNode) - : theBVH->template Child<1> (theNode)) = aChildIndex; - - // Check to see if the child node must be split - const Standard_Boolean isLeaf = theSubNodes.NbPrims (anIdx) <= BVH_Builder<T, N>::myLeafNodeSize - || theBVH->Level (aChildIndex) >= BVH_Builder<T, N>::myMaxTreeDepth; - - if (!isLeaf) - { - myBuildQueue.Enqueue (aChildIndex); - } - } -} - -// ======================================================================= -// function : Build -// purpose : Builds BVH using specific algorithm -// ======================================================================= -template<class T, int N> -void BVH_QueueBuilder<T, N>::Build (BVH_Set<T, N>* theSet, - BVH_Tree<T, N>* theBVH, - const BVH_Box<T, N>& theBox) -{ - Standard_ASSERT_RETURN (theBVH != NULL, - "Error! BVH tree to construct is NULL", ); - - theBVH->Clear(); - const Standard_Integer aSetSize = theSet->Size(); - if (aSetSize == 0) - { - return; - } - - const Standard_Integer aRoot = theBVH->AddLeafNode (theBox, 0, aSetSize - 1); - if (theSet->Size() == 1) - { - return; - } - - myBuildQueue.Enqueue (aRoot); - - BVH_TypedBuildTool aBuildTool (theSet, theBVH, this); - - if (myNumOfThreads > 1) - { - // Reserve the maximum possible number of nodes in the BVH - theBVH->Reserve (2 * aSetSize - 1); - - NCollection_Vector<Handle(BVH_BuildThread)> aThreads; - - // Run BVH build threads - for (Standard_Integer aThreadIndex = 0; aThreadIndex < myNumOfThreads; ++aThreadIndex) - { - aThreads.Append (new BVH_BuildThread (aBuildTool, myBuildQueue)); - aThreads.Last()->Run(); - } - - // Wait until all threads finish their work - for (Standard_Integer aThreadIndex = 0; aThreadIndex < myNumOfThreads; ++aThreadIndex) - { - aThreads.ChangeValue (aThreadIndex)->Wait(); - } - - // Free unused memory - theBVH->Reserve (theBVH->Length()); - } - else - { - BVH_BuildThread aThread (aBuildTool, myBuildQueue); - - // Execute thread function inside current thread - aThread.execute(); - } -} diff --git a/src/BVH/BVH_QuickSorter.hxx b/src/BVH/BVH_QuickSorter.hxx index b39da74a24..35834a7845 100644 --- a/src/BVH/BVH_QuickSorter.hxx +++ b/src/BVH/BVH_QuickSorter.hxx @@ -29,10 +29,51 @@ public: BVH_QuickSorter (const Standard_Integer theAxis = 0) : myAxis (theAxis) { } //! Sorts the set. - virtual void Perform (BVH_Set<T, N>* theSet); + virtual void Perform (BVH_Set<T, N>* theSet) Standard_OVERRIDE + { + Perform (theSet, 0, theSet->Size() - 1); + } //! Sorts the given (inclusive) range in the set. - virtual void Perform (BVH_Set<T, N>* theSet, const Standard_Integer theStart, const Standard_Integer theFinal); + virtual void Perform (BVH_Set<T, N>* theSet, const Standard_Integer theStart, const Standard_Integer theFinal) Standard_OVERRIDE + { + Standard_Integer aLft = theStart; + Standard_Integer aRgh = theFinal; + + T aPivot = theSet->Center ((aRgh + aLft) / 2, myAxis); + while (aLft < aRgh) + { + while (theSet->Center (aLft, myAxis) < aPivot && aLft < theFinal) + { + ++aLft; + } + + while (theSet->Center (aRgh, myAxis) > aPivot && aRgh > theStart) + { + --aRgh; + } + + if (aLft <= aRgh) + { + if (aLft != aRgh) + { + theSet->Swap (aLft, aRgh); + } + ++aLft; + --aRgh; + } + } + + if (aRgh > theStart) + { + Perform (theSet, theStart, aRgh); + } + + if (aLft < theFinal) + { + Perform (theSet, aLft, theFinal); + } + } protected: @@ -41,6 +82,4 @@ protected: }; -#include <BVH_QuickSorter.lxx> - #endif // _BVH_QuickSorter_Header diff --git a/src/BVH/BVH_QuickSorter.lxx b/src/BVH/BVH_QuickSorter.lxx deleted file mode 100644 index b6161af1aa..0000000000 --- a/src/BVH/BVH_QuickSorter.lxx +++ /dev/null @@ -1,71 +0,0 @@ -// Created on: 2016-04-13 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2016 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -// ======================================================================= -// function : Perform -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_QuickSorter<T, N>::Perform (BVH_Set<T, N>* theSet) -{ - Perform (theSet, 0, theSet->Size() - 1); -} - -// ======================================================================= -// function : Perform -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_QuickSorter<T, N>::Perform (BVH_Set<T, N>* theSet, const Standard_Integer theStart, const Standard_Integer theFinal) -{ - Standard_Integer aLft = theStart; - Standard_Integer aRgh = theFinal; - - T aPivot = theSet->Center ((aRgh + aLft) / 2, myAxis); - - while (aLft < aRgh) - { - while (theSet->Center (aLft, myAxis) < aPivot && aLft < theFinal) - { - ++aLft; - } - - while (theSet->Center (aRgh, myAxis) > aPivot && aRgh > theStart) - { - --aRgh; - } - - if (aLft <= aRgh) - { - if (aLft != aRgh) - { - theSet->Swap (aLft, aRgh); - } - - ++aLft; - --aRgh; - } - } - - if (aRgh > theStart) - { - Perform (theSet, theStart, aRgh); - } - - if (aLft < theFinal) - { - Perform (theSet, aLft, theFinal); - } -} diff --git a/src/BVH/BVH_RadixSorter.hxx b/src/BVH/BVH_RadixSorter.hxx index 1d97b7ef4d..a3cec78547 100644 --- a/src/BVH/BVH_RadixSorter.hxx +++ b/src/BVH/BVH_RadixSorter.hxx @@ -18,10 +18,23 @@ #include <BVH_Sorter.hxx> #include <BVH_Builder.hxx> - #include <NCollection_Handle.hxx> #include <NCollection_Array1.hxx> +#include <algorithm> + +#ifdef HAVE_TBB + // On Windows, function TryEnterCriticalSection has appeared in Windows NT + // and is surrounded by #ifdef in MS VC++ 7.1 headers. + // Thus to use it we need to define appropriate macro saying that we will + // run on Windows NT 4.0 at least + #if defined(_WIN32) && !defined(_WIN32_WINNT) + #define _WIN32_WINNT 0x0501 + #endif + + #include <tbb/parallel_invoke.h> +#endif + //! Pair of Morton code and primitive ID. typedef std::pair<Standard_Integer, Standard_Integer> BVH_EncodedLink; @@ -40,10 +53,10 @@ public: BVH_RadixSorter (const BVH_Box<T, N>& theBox) : myBox (theBox) { } //! Sorts the set. - virtual void Perform (BVH_Set<T, N>* theSet); + virtual void Perform (BVH_Set<T, N>* theSet) Standard_OVERRIDE { Perform (theSet, 0, theSet->Size() - 1); } //! Sorts the given (inclusive) range in the set. - virtual void Perform (BVH_Set<T, N>* theSet, const Standard_Integer theStart, const Standard_Integer theFinal); + virtual void Perform (BVH_Set<T, N>* theSet, const Standard_Integer theStart, const Standard_Integer theFinal) Standard_OVERRIDE; //! Returns Morton codes assigned to BVH primitives. const NCollection_Array1<BVH_EncodedLink>& EncodedLinks() const { return *myEncodedLinks; } @@ -58,6 +71,180 @@ protected: }; -#include <BVH_RadixSorter.lxx> +namespace BVH +{ + // Radix sort STL predicate for 32-bit integer. + struct BitPredicate + { + Standard_Integer myBit; + + //! Creates new radix sort predicate. + BitPredicate (const Standard_Integer theBit) : myBit (theBit) {} + + //! Returns predicate value. + bool operator() (const BVH_EncodedLink theLink) const + { + const Standard_Integer aMask = 1 << myBit; + return !(theLink.first & aMask); // 0-bit to the left side + } + }; + + //! STL compare tool used in binary search algorithm. + struct BitComparator + { + Standard_Integer myBit; + + //! Creates new STL comparator. + BitComparator (const Standard_Integer theBit) : myBit (theBit) {} + + //! Checks left value for the given bit. + bool operator() (BVH_EncodedLink theLink1, BVH_EncodedLink /*theLink2*/) + { + return !(theLink1.first & (1 << myBit)); + } + }; + + //! Tool object for sorting link array using radix sort algorithm. + class RadixSorter + { + public: + + typedef NCollection_Array1<BVH_EncodedLink>::iterator LinkIterator; + + private: + + //! TBB functor class to run sorting. + struct Functor + { + LinkIterator myStart; //!< Start element of exclusive sorting range + LinkIterator myFinal; //!< Final element of exclusive sorting range + Standard_Integer myDigit; //!< Bit number used for partition operation + + //! Creates new sorting functor. + Functor (LinkIterator theStart, LinkIterator theFinal, Standard_Integer theDigit) + : myStart (theStart), myFinal (theFinal), myDigit (theDigit) {} + + //! Runs sorting function for the given range. + void operator() () const + { + RadixSorter::Sort (myStart, myFinal, myDigit); + } + }; + + public: + + static void Sort (LinkIterator theStart, LinkIterator theFinal, Standard_Integer theDigit) + { + #ifdef HAVE_TBB + if (theDigit < 24) + { + BVH::RadixSorter::perform (theStart, theFinal, theDigit); + } + else + { + LinkIterator anOffset = std::partition (theStart, theFinal, BitPredicate (theDigit)); + tbb::parallel_invoke (Functor (theStart, anOffset, theDigit - 1), + Functor (anOffset, theFinal, theDigit - 1)); + } + #else + BVH::RadixSorter::perform (theStart, theFinal, theDigit); + #endif + } + + protected: + + // Performs MSD (most significant digit) radix sort. + static void perform (LinkIterator theStart, LinkIterator theFinal, Standard_Integer theBit = 29) + { + while (theStart != theFinal && theBit >= 0) + { + LinkIterator anOffset = std::partition (theStart, theFinal, BitPredicate (theBit--)); + perform (theStart, anOffset, theBit); + theStart = anOffset; + } + } + }; +} + +// ======================================================================= +// function : Perform +// purpose : +// ======================================================================= +template<class T, int N> +void BVH_RadixSorter<T, N>::Perform (BVH_Set<T, N>* theSet, const Standard_Integer theStart, const Standard_Integer theFinal) +{ + Standard_STATIC_ASSERT (N == 3 || N == 4); + + const Standard_Integer aDimensionX = 1024; + const Standard_Integer aDimensionY = 1024; + const Standard_Integer aDimensionZ = 1024; + + const BVH_VecNt aSceneMin = myBox.CornerMin(); + const BVH_VecNt aSceneMax = myBox.CornerMax(); + + const T aReverseSizeX = static_cast<T> (aDimensionX) / Max (static_cast<T> (BVH::THE_NODE_MIN_SIZE), aSceneMax.x() - aSceneMin.x()); + const T aReverseSizeY = static_cast<T> (aDimensionY) / Max (static_cast<T> (BVH::THE_NODE_MIN_SIZE), aSceneMax.y() - aSceneMin.y()); + const T aReverseSizeZ = static_cast<T> (aDimensionZ) / Max (static_cast<T> (BVH::THE_NODE_MIN_SIZE), aSceneMax.z() - aSceneMin.z()); + + myEncodedLinks = new NCollection_Array1<BVH_EncodedLink> (theStart, theFinal); + + // Step 1 -- Assign Morton code to each primitive + for (Standard_Integer aPrimIdx = theStart; aPrimIdx <= theFinal; ++aPrimIdx) + { + const BVH_VecNt aCenter = theSet->Box (aPrimIdx).Center(); + + Standard_Integer aVoxelX = BVH::IntFloor ((aCenter.x() - aSceneMin.x()) * aReverseSizeX); + Standard_Integer aVoxelY = BVH::IntFloor ((aCenter.y() - aSceneMin.y()) * aReverseSizeY); + Standard_Integer aVoxelZ = BVH::IntFloor ((aCenter.z() - aSceneMin.z()) * aReverseSizeZ); + + aVoxelX = Max (0, Min (aVoxelX, aDimensionX - 1)); + aVoxelY = Max (0, Min (aVoxelY, aDimensionY - 1)); + aVoxelZ = Max (0, Min (aVoxelZ, aDimensionZ - 1)); + + aVoxelX = (aVoxelX | (aVoxelX << 16)) & 0x030000FF; + aVoxelX = (aVoxelX | (aVoxelX << 8)) & 0x0300F00F; + aVoxelX = (aVoxelX | (aVoxelX << 4)) & 0x030C30C3; + aVoxelX = (aVoxelX | (aVoxelX << 2)) & 0x09249249; + + aVoxelY = (aVoxelY | (aVoxelY << 16)) & 0x030000FF; + aVoxelY = (aVoxelY | (aVoxelY << 8)) & 0x0300F00F; + aVoxelY = (aVoxelY | (aVoxelY << 4)) & 0x030C30C3; + aVoxelY = (aVoxelY | (aVoxelY << 2)) & 0x09249249; + + aVoxelZ = (aVoxelZ | (aVoxelZ << 16)) & 0x030000FF; + aVoxelZ = (aVoxelZ | (aVoxelZ << 8)) & 0x0300F00F; + aVoxelZ = (aVoxelZ | (aVoxelZ << 4)) & 0x030C30C3; + aVoxelZ = (aVoxelZ | (aVoxelZ << 2)) & 0x09249249; + + myEncodedLinks->ChangeValue (aPrimIdx) = BVH_EncodedLink ( + aVoxelX | (aVoxelY << 1) | (aVoxelZ << 2), aPrimIdx); + } + + // Step 2 -- Sort primitives by their Morton codes using radix sort + BVH::RadixSorter::Sort (myEncodedLinks->begin(), myEncodedLinks->end(), 29); + + NCollection_Array1<Standard_Integer> aLinkMap (theStart, theFinal); + for (Standard_Integer aLinkIdx = theStart; aLinkIdx <= theFinal; ++aLinkIdx) + { + aLinkMap (myEncodedLinks->Value (aLinkIdx).second) = aLinkIdx; + } + + // Step 3 -- Rearranging primitive list according to Morton codes (in place) + Standard_Integer aPrimIdx = theStart; + while (aPrimIdx <= theFinal) + { + const Standard_Integer aSortIdx = aLinkMap (aPrimIdx); + if (aPrimIdx != aSortIdx) + { + theSet->Swap (aPrimIdx, aSortIdx); + std::swap (aLinkMap (aPrimIdx), + aLinkMap (aSortIdx)); + } + else + { + ++aPrimIdx; + } + } +} #endif // _BVH_RadixSorter_Header diff --git a/src/BVH/BVH_RadixSorter.lxx b/src/BVH/BVH_RadixSorter.lxx deleted file mode 100644 index 3cfa5740e8..0000000000 --- a/src/BVH/BVH_RadixSorter.lxx +++ /dev/null @@ -1,241 +0,0 @@ -// Created on: 2016-04-13 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2016 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include <algorithm> - -#ifdef HAVE_TBB - // On Windows, function TryEnterCriticalSection has appeared in Windows NT - // and is surrounded by #ifdef in MS VC++ 7.1 headers. - // Thus to use it we need to define appropriate macro saying that we will - // run on Windows NT 4.0 at least - #if defined(_WIN32) && !defined(_WIN32_WINNT) - #define _WIN32_WINNT 0x0501 - #endif - - #include <tbb/parallel_invoke.h> -#endif - -// ======================================================================= -// function : Perform -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_RadixSorter<T, N>::Perform (BVH_Set<T, N>* theSet) -{ - Perform (theSet, 0, theSet->Size() - 1); -} - -namespace BVH -{ - // Radix sort STL predicate for 32-bit integer. - class BitPredicate - { - Standard_Integer myBit; - - public: - - //! Creates new radix sort predicate. - BitPredicate (const Standard_Integer theBit) : myBit (theBit) - { - // - } - - //! Returns predicate value. - bool operator() (const BVH_EncodedLink theLink) const - { - const Standard_Integer aMask = 1 << myBit; - - return !(theLink.first & aMask); // 0-bit to the left side - } - }; - - //! STL compare tool used in binary search algorithm. - class BitComparator - { - Standard_Integer myBit; - - public: - - //! Creates new STL comparator. - BitComparator (const Standard_Integer theBit) : myBit (theBit) - { - // - } - - //! Checks left value for the given bit. - bool operator() (BVH_EncodedLink theLink1, BVH_EncodedLink /*theLink2*/) - { - return !(theLink1.first & (1 << myBit)); - } - }; - - //! Tool object for sorting link array using radix sort algorithm. - class RadixSorter - { - public: - - typedef NCollection_Array1<BVH_EncodedLink>::iterator LinkIterator; - - private: - - //! TBB functor class to run sorting. - class Functor - { - //! Start element of exclusive sorting range. - LinkIterator myStart; - - //! Final element of exclusive sorting range. - LinkIterator myFinal; - - //! Bit number used for partition operation. - Standard_Integer myDigit; - - public: - - //! Creates new sorting functor. - Functor (LinkIterator theStart, LinkIterator theFinal, Standard_Integer theDigit) - : myStart (theStart), - myFinal (theFinal), - myDigit (theDigit) { } - - //! Runs sorting function for the given range. - void operator() () const - { - RadixSorter::Sort (myStart, myFinal, myDigit); - } - }; - - public: - - static void Sort (LinkIterator theStart, LinkIterator theFinal, Standard_Integer theDigit) - { -#ifdef HAVE_TBB - if (theDigit < 24) - { - BVH::RadixSorter::perform (theStart, theFinal, theDigit); - } - else - { - LinkIterator anOffset = std::partition (theStart, theFinal, BitPredicate (theDigit)); - - tbb::parallel_invoke (Functor (theStart, anOffset, theDigit - 1), - Functor (anOffset, theFinal, theDigit - 1)); - } -#else - BVH::RadixSorter::perform (theStart, theFinal, theDigit); -#endif - } - - protected: - - // Performs MSD (most significant digit) radix sort. - static void perform (LinkIterator theStart, LinkIterator theFinal, Standard_Integer theBit = 29) - { - while (theStart != theFinal && theBit >= 0) - { - LinkIterator anOffset = std::partition (theStart, theFinal, BitPredicate (theBit--)); - - perform (theStart, anOffset, theBit); - - theStart = anOffset; - } - } - }; -} - -// ======================================================================= -// function : Perform -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_RadixSorter<T, N>::Perform (BVH_Set<T, N>* theSet, const Standard_Integer theStart, const Standard_Integer theFinal) -{ - Standard_STATIC_ASSERT (N == 3 || N == 4); - - const Standard_Integer aDimensionX = 1024; - const Standard_Integer aDimensionY = 1024; - const Standard_Integer aDimensionZ = 1024; - - const BVH_VecNt aSceneMin = myBox.CornerMin(); - const BVH_VecNt aSceneMax = myBox.CornerMax(); - - const T aReverseSizeX = static_cast<T> (aDimensionX) / Max (static_cast<T> (BVH::THE_NODE_MIN_SIZE), aSceneMax.x() - aSceneMin.x()); - const T aReverseSizeY = static_cast<T> (aDimensionY) / Max (static_cast<T> (BVH::THE_NODE_MIN_SIZE), aSceneMax.y() - aSceneMin.y()); - const T aReverseSizeZ = static_cast<T> (aDimensionZ) / Max (static_cast<T> (BVH::THE_NODE_MIN_SIZE), aSceneMax.z() - aSceneMin.z()); - - myEncodedLinks = new NCollection_Array1<BVH_EncodedLink> (theStart, theFinal); - - // Step 1 -- Assign Morton code to each primitive - for (Standard_Integer aPrimIdx = theStart; aPrimIdx <= theFinal; ++aPrimIdx) - { - const BVH_VecNt aCenter = theSet->Box (aPrimIdx).Center(); - - Standard_Integer aVoxelX = BVH::IntFloor ((aCenter.x() - aSceneMin.x()) * aReverseSizeX); - Standard_Integer aVoxelY = BVH::IntFloor ((aCenter.y() - aSceneMin.y()) * aReverseSizeY); - Standard_Integer aVoxelZ = BVH::IntFloor ((aCenter.z() - aSceneMin.z()) * aReverseSizeZ); - - aVoxelX = Max (0, Min (aVoxelX, aDimensionX - 1)); - aVoxelY = Max (0, Min (aVoxelY, aDimensionY - 1)); - aVoxelZ = Max (0, Min (aVoxelZ, aDimensionZ - 1)); - - aVoxelX = (aVoxelX | (aVoxelX << 16)) & 0x030000FF; - aVoxelX = (aVoxelX | (aVoxelX << 8)) & 0x0300F00F; - aVoxelX = (aVoxelX | (aVoxelX << 4)) & 0x030C30C3; - aVoxelX = (aVoxelX | (aVoxelX << 2)) & 0x09249249; - - aVoxelY = (aVoxelY | (aVoxelY << 16)) & 0x030000FF; - aVoxelY = (aVoxelY | (aVoxelY << 8)) & 0x0300F00F; - aVoxelY = (aVoxelY | (aVoxelY << 4)) & 0x030C30C3; - aVoxelY = (aVoxelY | (aVoxelY << 2)) & 0x09249249; - - aVoxelZ = (aVoxelZ | (aVoxelZ << 16)) & 0x030000FF; - aVoxelZ = (aVoxelZ | (aVoxelZ << 8)) & 0x0300F00F; - aVoxelZ = (aVoxelZ | (aVoxelZ << 4)) & 0x030C30C3; - aVoxelZ = (aVoxelZ | (aVoxelZ << 2)) & 0x09249249; - - myEncodedLinks->ChangeValue (aPrimIdx) = BVH_EncodedLink ( - aVoxelX | (aVoxelY << 1) | (aVoxelZ << 2), aPrimIdx); - } - - // Step 2 -- Sort primitives by their Morton codes using radix sort - BVH::RadixSorter::Sort (myEncodedLinks->begin(), myEncodedLinks->end(), 29); - - NCollection_Array1<Standard_Integer> aLinkMap (theStart, theFinal); - - for (Standard_Integer aLinkIdx = theStart; aLinkIdx <= theFinal; ++aLinkIdx) - { - aLinkMap (myEncodedLinks->Value (aLinkIdx).second) = aLinkIdx; - } - - // Step 3 -- Rearranging primitive list according to Morton codes (in place) - Standard_Integer aPrimIdx = theStart; - - while (aPrimIdx <= theFinal) - { - const Standard_Integer aSortIdx = aLinkMap (aPrimIdx); - - if (aPrimIdx != aSortIdx) - { - theSet->Swap (aPrimIdx, aSortIdx); - - std::swap (aLinkMap (aPrimIdx), - aLinkMap (aSortIdx)); - } - else - { - ++aPrimIdx; - } - } -} diff --git a/src/BVH/BVH_Set.hxx b/src/BVH/BVH_Set.hxx index 274f09f41a..2d0950cb2b 100644 --- a/src/BVH/BVH_Set.hxx +++ b/src/BVH/BVH_Set.hxx @@ -32,13 +32,22 @@ public: public: //! Creates new abstract set of objects. - BVH_Set(); + BVH_Set() {} //! Releases resources of set of objects. virtual ~BVH_Set() = 0; //! Returns AABB of the entire set of objects. - virtual BVH_Box<T, N> Box() const; + virtual BVH_Box<T, N> Box() const + { + BVH_Box<T, N> aBox; + const Standard_Integer aSize = Size(); + for (Standard_Integer anIndex = 0; anIndex < aSize; ++anIndex) + { + aBox.Combine (Box (anIndex)); + } + return aBox; + } public: @@ -58,6 +67,14 @@ public: }; -#include <BVH_Set.lxx> +// ======================================================================= +// function : ~BVH_Set +// purpose : +// ======================================================================= +template<class T, int N> +BVH_Set<T, N>::~BVH_Set() +{ + // +} #endif // _BVH_Set_Header diff --git a/src/BVH/BVH_Set.lxx b/src/BVH/BVH_Set.lxx deleted file mode 100644 index 7453a35d2d..0000000000 --- a/src/BVH/BVH_Set.lxx +++ /dev/null @@ -1,50 +0,0 @@ -// Created on: 2013-12-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -// ======================================================================= -// function : BVH_Set -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Set<T, N>::BVH_Set() -{ - // -} - -// ======================================================================= -// function : ~BVH_Set -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Set<T, N>::~BVH_Set() -{ - // -} - -// ======================================================================= -// function : Box -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Box<T, N> BVH_Set<T, N>::Box() const -{ - BVH_Box<T, N> aBox; - const Standard_Integer aSize = Size(); - for (Standard_Integer anIndex = 0; anIndex < aSize; ++anIndex) - { - aBox.Combine (Box (anIndex)); - } - return aBox; -} diff --git a/src/BVH/BVH_SpatialMedianBuilder.hxx b/src/BVH/BVH_SpatialMedianBuilder.hxx index 5c7726ab37..503c35720e 100644 --- a/src/BVH/BVH_SpatialMedianBuilder.hxx +++ b/src/BVH/BVH_SpatialMedianBuilder.hxx @@ -17,6 +17,7 @@ #define _BVH_SpatialMedianBuilder_Header #include <BVH_BinnedBuilder.hxx> +#include <BVH_Box.hxx> //! Performs building of BVH tree using spatial median split algorithm. template<class T, int N> @@ -27,13 +28,14 @@ public: //! Creates spatial median split builder. BVH_SpatialMedianBuilder (const Standard_Integer theLeafNodeSize = 5, const Standard_Integer theMaxTreeDepth = 32, - const Standard_Boolean theToUseMainAxis = Standard_False); + const Standard_Boolean theToUseMainAxis = Standard_False) + : BVH_BinnedBuilder<T, N, 2> (theLeafNodeSize, + theMaxTreeDepth, + theToUseMainAxis) {} //! Releases resources of spatial median split builder. - virtual ~BVH_SpatialMedianBuilder(); + virtual ~BVH_SpatialMedianBuilder() {} }; -#include <BVH_SpatialMedianBuilder.lxx> - #endif // _BVH_SpatialMedianBuilder_Header diff --git a/src/BVH/BVH_SpatialMedianBuilder.lxx b/src/BVH/BVH_SpatialMedianBuilder.lxx deleted file mode 100644 index 7be3a73615..0000000000 --- a/src/BVH/BVH_SpatialMedianBuilder.lxx +++ /dev/null @@ -1,41 +0,0 @@ -// Created on: 2013-12-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include <BVH_Box.hxx> - -// ======================================================================= -// function : BVH_SpatialMedianBuilder -// purpose : -// ======================================================================= -template<class T, int N> -BVH_SpatialMedianBuilder<T, N>::BVH_SpatialMedianBuilder (const Standard_Integer theLeafNodeSize, - const Standard_Integer theMaxTreeDepth, - const Standard_Boolean theToUseMainAxis) -: BVH_BinnedBuilder<T, N, 2> (theLeafNodeSize, - theMaxTreeDepth, - theToUseMainAxis) -{ - // -} - -// ======================================================================= -// function : ~BVH_SpatialMedianBuilder -// purpose : -// ======================================================================= -template<class T, int N> -BVH_SpatialMedianBuilder<T, N>::~BVH_SpatialMedianBuilder() -{ - // -} diff --git a/src/BVH/BVH_SweepPlaneBuilder.hxx b/src/BVH/BVH_SweepPlaneBuilder.hxx index ab802ca63d..63921a8abe 100644 --- a/src/BVH/BVH_SweepPlaneBuilder.hxx +++ b/src/BVH/BVH_SweepPlaneBuilder.hxx @@ -17,6 +17,8 @@ #define _BVH_SweepPlaneBuilder_Header #include <BVH_QueueBuilder.hxx> +#include <BVH_QuickSorter.hxx> +#include <NCollection_Array1.hxx> //! Performs building of BVH tree using sweep plane SAH algorithm. template<class T, int N> @@ -27,20 +29,114 @@ public: //! Creates sweep plane SAH BVH builder. BVH_SweepPlaneBuilder (const Standard_Integer theLeafNodeSize = 5, const Standard_Integer theMaxTreeDepth = 32, - const Standard_Integer theNumOfThreads = 1); + const Standard_Integer theNumOfThreads = 1) + : BVH_QueueBuilder<T, N> (theLeafNodeSize, + theMaxTreeDepth, + theNumOfThreads) {} //! Releases resources of sweep plane SAH BVH builder. - virtual ~BVH_SweepPlaneBuilder(); + virtual ~BVH_SweepPlaneBuilder() {} protected: //! Performs splitting of the given BVH node. - typename BVH_QueueBuilder<T, N>::BVH_ChildNodes BuildNode (BVH_Set<T, N>* theSet, + typename BVH_QueueBuilder<T, N>::BVH_ChildNodes buildNode (BVH_Set<T, N>* theSet, BVH_Tree<T, N>* theBVH, - const Standard_Integer theNode); + const Standard_Integer theNode) const Standard_OVERRIDE + { + const Standard_Integer aNodeBegPrimitive = theBVH->BegPrimitive (theNode); + const Standard_Integer aNodeEndPrimitive = theBVH->EndPrimitive (theNode); + const Standard_Integer aNodeNbPrimitives = theBVH->NbPrimitives (theNode); + if (aNodeEndPrimitive - aNodeBegPrimitive < BVH_Builder<T, N>::myLeafNodeSize) + { + return typename BVH_QueueBuilder<T, N>::BVH_ChildNodes(); // node does not require partitioning + } + + // Parameters for storing best split + Standard_Integer aMinSplitAxis = -1; + Standard_Integer aMinSplitIndex = 0; + + NCollection_Array1<Standard_Real> aLftSet (0, aNodeNbPrimitives - 1); + NCollection_Array1<Standard_Real> aRghSet (0, aNodeNbPrimitives - 1); + Standard_Real aMinSplitCost = std::numeric_limits<Standard_Real>::max(); + + // Find best split + for (Standard_Integer anAxis = 0; anAxis < (N < 4 ? N : 3); ++anAxis) + { + const T aNodeSize = BVH::VecComp<T, N>::Get (theBVH->MaxPoint (theNode), anAxis) - + BVH::VecComp<T, N>::Get (theBVH->MinPoint (theNode), anAxis); + if (aNodeSize <= BVH::THE_NODE_MIN_SIZE) + { + continue; + } + + BVH_QuickSorter<T, N> (anAxis).Perform (theSet, aNodeBegPrimitive, aNodeEndPrimitive); + BVH_Box<T, N> aLftBox; + BVH_Box<T, N> aRghBox; + aLftSet.ChangeFirst() = std::numeric_limits<T>::max(); + aRghSet.ChangeFirst() = std::numeric_limits<T>::max(); + + // Sweep from left + for (Standard_Integer anIndex = 1; anIndex < aNodeNbPrimitives; ++anIndex) + { + aLftBox.Combine (theSet->Box (anIndex + aNodeBegPrimitive - 1)); + aLftSet (anIndex) = static_cast<Standard_Real> (aLftBox.Area()); + } + + // Sweep from right + for (Standard_Integer anIndex = 1; anIndex < aNodeNbPrimitives; ++anIndex) + { + aRghBox.Combine (theSet->Box (aNodeEndPrimitive - anIndex + 1)); + aRghSet (anIndex) = static_cast<Standard_Real> (aRghBox.Area()); + } + + // Find best split using simplified SAH + for (Standard_Integer aNbLft = 1, aNbRgh = aNodeNbPrimitives - 1; aNbLft < aNodeNbPrimitives; ++aNbLft, --aNbRgh) + { + Standard_Real aCost = (aLftSet (aNbLft) /* / aNodeArea */) * aNbLft + + (aRghSet (aNbRgh) /* / aNodeArea */) * aNbRgh; + if (aCost < aMinSplitCost) + { + aMinSplitCost = aCost; + aMinSplitAxis = anAxis; + aMinSplitIndex = aNbLft; + } + } + } + + if (aMinSplitAxis == -1) + { + return typename BVH_QueueBuilder<T, N>::BVH_ChildNodes(); // failed to find split axis + } + + theBVH->SetInner (theNode); + if (aMinSplitAxis != (N < 4 ? N - 1 : 2)) + { + BVH_QuickSorter<T, N> (aMinSplitAxis).Perform (theSet, aNodeBegPrimitive, aNodeEndPrimitive); + } + + BVH_Box<T, N> aMinSplitBoxLft; + BVH_Box<T, N> aMinSplitBoxRgh; + + // Compute bounding boxes for selected split plane + for (Standard_Integer anIndex = aNodeBegPrimitive; anIndex < aMinSplitIndex + aNodeBegPrimitive; ++anIndex) + { + aMinSplitBoxLft.Combine (theSet->Box (anIndex)); + } + + for (Standard_Integer anIndex = aNodeEndPrimitive; anIndex >= aMinSplitIndex + aNodeBegPrimitive; --anIndex) + { + aMinSplitBoxRgh.Combine (theSet->Box (anIndex)); + } + + const Standard_Integer aMiddle = aNodeBegPrimitive + aMinSplitIndex; + typedef typename BVH_QueueBuilder<T, N>::BVH_PrimitiveRange Range; + return typename BVH_QueueBuilder<T, N>::BVH_ChildNodes (aMinSplitBoxLft, + aMinSplitBoxRgh, + Range (aNodeBegPrimitive, aMiddle - 1), + Range (aMiddle, aNodeEndPrimitive)); + } }; -#include <BVH_SweepPlaneBuilder.lxx> - #endif // _BVH_SweepPlaneBuilder_Header diff --git a/src/BVH/BVH_SweepPlaneBuilder.lxx b/src/BVH/BVH_SweepPlaneBuilder.lxx deleted file mode 100644 index 1b3fed2bd8..0000000000 --- a/src/BVH/BVH_SweepPlaneBuilder.lxx +++ /dev/null @@ -1,155 +0,0 @@ -// Created on: 2014-01-09 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include <BVH_QuickSorter.hxx> - -#include <NCollection_Array1.hxx> - -// ======================================================================= -// function : BVH_SweepPlaneBuilder -// purpose : -// ======================================================================= -template<class T, int N> -BVH_SweepPlaneBuilder<T, N>::BVH_SweepPlaneBuilder (const Standard_Integer theLeafNodeSize, - const Standard_Integer theMaxTreeDepth, - const Standard_Integer theNumOfThreads) -: BVH_QueueBuilder<T, N> (theLeafNodeSize, - theMaxTreeDepth, - theNumOfThreads) -{ - // -} - -// ======================================================================= -// function : ~BVH_SweepPlaneBuilder -// purpose : -// ======================================================================= -template<class T, int N> -BVH_SweepPlaneBuilder<T, N>::~BVH_SweepPlaneBuilder() -{ - // -} - -// ======================================================================= -// function : BuildNode -// purpose : -// ======================================================================= -template<class T, int N> -typename BVH_QueueBuilder<T, N>::BVH_ChildNodes BVH_SweepPlaneBuilder<T, N>::BuildNode (BVH_Set<T, N>* theSet, - BVH_Tree<T, N>* theBVH, - const Standard_Integer theNode) -{ - const Standard_Integer aNodeBegPrimitive = theBVH->BegPrimitive (theNode); - const Standard_Integer aNodeEndPrimitive = theBVH->EndPrimitive (theNode); - const Standard_Integer aNodeNbPrimitives = theBVH->NbPrimitives (theNode); - - if (aNodeEndPrimitive - aNodeBegPrimitive < BVH_Builder<T, N>::myLeafNodeSize) - { - return typename BVH_QueueBuilder<T, N>::BVH_ChildNodes(); // node does not require partitioning - } - - // Parameters for storing best split - Standard_Integer aMinSplitAxis = -1; - Standard_Integer aMinSplitIndex = 0; - - NCollection_Array1<Standard_Real> aLftSet (0, aNodeNbPrimitives - 1); - NCollection_Array1<Standard_Real> aRghSet (0, aNodeNbPrimitives - 1); - - Standard_Real aMinSplitCost = std::numeric_limits<Standard_Real>::max(); - - // Find best split - for (Standard_Integer anAxis = 0; anAxis < (N < 4 ? N : 3); ++anAxis) - { - const T aNodeSize = BVH::VecComp<T, N>::Get (theBVH->MaxPoint (theNode), anAxis) - - BVH::VecComp<T, N>::Get (theBVH->MinPoint (theNode), anAxis); - if (aNodeSize <= BVH::THE_NODE_MIN_SIZE) - { - continue; - } - - BVH_QuickSorter<T, N> (anAxis).Perform (theSet, aNodeBegPrimitive, aNodeEndPrimitive); - - BVH_Box<T, N> aLftBox; - BVH_Box<T, N> aRghBox; - - aLftSet.ChangeFirst() = std::numeric_limits<T>::max(); - aRghSet.ChangeFirst() = std::numeric_limits<T>::max(); - - // Sweep from left - for (Standard_Integer anIndex = 1; anIndex < aNodeNbPrimitives; ++anIndex) - { - aLftBox.Combine (theSet->Box (anIndex + aNodeBegPrimitive - 1)); - - aLftSet (anIndex) = static_cast<Standard_Real> (aLftBox.Area()); - } - - // Sweep from right - for (Standard_Integer anIndex = 1; anIndex < aNodeNbPrimitives; ++anIndex) - { - aRghBox.Combine (theSet->Box (aNodeEndPrimitive - anIndex + 1)); - - aRghSet (anIndex) = static_cast<Standard_Real> (aRghBox.Area()); - } - - // Find best split using simplified SAH - for (Standard_Integer aNbLft = 1, aNbRgh = aNodeNbPrimitives - 1; aNbLft < aNodeNbPrimitives; ++aNbLft, --aNbRgh) - { - Standard_Real aCost = (aLftSet (aNbLft) /* / aNodeArea */) * aNbLft + - (aRghSet (aNbRgh) /* / aNodeArea */) * aNbRgh; - - if (aCost < aMinSplitCost) - { - aMinSplitCost = aCost; - aMinSplitAxis = anAxis; - aMinSplitIndex = aNbLft; - } - } - } - - if (aMinSplitAxis == -1) - { - return typename BVH_QueueBuilder<T, N>::BVH_ChildNodes(); // failed to find split axis - } - - theBVH->SetInner (theNode); - - if (aMinSplitAxis != (N < 4 ? N - 1 : 2)) - { - BVH_QuickSorter<T, N> (aMinSplitAxis).Perform (theSet, aNodeBegPrimitive, aNodeEndPrimitive); - } - - BVH_Box<T, N> aMinSplitBoxLft; - BVH_Box<T, N> aMinSplitBoxRgh; - - // Compute bounding boxes for selected split plane - for (Standard_Integer anIndex = aNodeBegPrimitive; anIndex < aMinSplitIndex + aNodeBegPrimitive; ++anIndex) - { - aMinSplitBoxLft.Combine (theSet->Box (anIndex)); - } - - for (Standard_Integer anIndex = aNodeEndPrimitive; anIndex >= aMinSplitIndex + aNodeBegPrimitive; --anIndex) - { - aMinSplitBoxRgh.Combine (theSet->Box (anIndex)); - } - - const Standard_Integer aMiddle = aNodeBegPrimitive + aMinSplitIndex; - - typedef typename BVH_QueueBuilder<T, N>::BVH_PrimitiveRange Range; - - return typename BVH_QueueBuilder<T, N>::BVH_ChildNodes (aMinSplitBoxLft, - aMinSplitBoxRgh, - Range (aNodeBegPrimitive, aMiddle - 1), - Range (aMiddle, aNodeEndPrimitive)); -} diff --git a/src/BVH/BVH_Tree.hxx b/src/BVH/BVH_Tree.hxx index bf59c635fe..076b9f02ed 100644 --- a/src/BVH/BVH_Tree.hxx +++ b/src/BVH/BVH_Tree.hxx @@ -43,7 +43,7 @@ public: //! @name general methods BVH_TreeBase() : myDepth (0) { } //! Releases resources of BVH tree. - virtual ~BVH_TreeBase(); + virtual ~BVH_TreeBase() {} //! Returns depth (height) of BVH tree. int Depth() const @@ -198,6 +198,4 @@ class BVH_Tree // Invalid type }; -#include <BVH_Tree.lxx> - #endif // _BVH_TreeBase_Header diff --git a/src/BVH/BVH_Tree.lxx b/src/BVH/BVH_Tree.lxx deleted file mode 100644 index ec6473db34..0000000000 --- a/src/BVH/BVH_Tree.lxx +++ /dev/null @@ -1,24 +0,0 @@ -// Created on: 2013-12-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -// ======================================================================= -// function : ~BVH_TreeBase -// purpose : Releases resources of BVH tree -// ======================================================================= -template<class T, int N> -BVH_TreeBase<T, N>::~BVH_TreeBase() -{ - // -} \ No newline at end of file diff --git a/src/BVH/BVH_Triangulation.hxx b/src/BVH/BVH_Triangulation.hxx index ea6bce2b01..9a33e03533 100644 --- a/src/BVH/BVH_Triangulation.hxx +++ b/src/BVH/BVH_Triangulation.hxx @@ -31,10 +31,10 @@ public: public: //! Creates empty triangulation. - BVH_Triangulation(); + BVH_Triangulation() {} //! Releases resources of triangulation. - virtual ~BVH_Triangulation(); + virtual ~BVH_Triangulation() {} public: @@ -47,24 +47,55 @@ public: public: //! Returns total number of triangles. - virtual Standard_Integer Size() const; + virtual Standard_Integer Size() const Standard_OVERRIDE + { + return BVH::Array<Standard_Integer, 4>::Size (Elements); + } //! Returns AABB of entire set of objects. using BVH_PrimitiveSet<T, N>::Box; //! Returns AABB of the given triangle. - virtual BVH_Box<T, N> Box (const Standard_Integer theIndex) const; + virtual BVH_Box<T, N> Box (const Standard_Integer theIndex) const Standard_OVERRIDE + { + const BVH_Vec4i& anIndex = BVH::Array<Standard_Integer, 4>::Value (Elements, theIndex); + + const BVH_VecNt& aPoint0 = BVH::Array<T, N>::Value (Vertices, anIndex.x()); + const BVH_VecNt& aPoint1 = BVH::Array<T, N>::Value (Vertices, anIndex.y()); + const BVH_VecNt& aPoint2 = BVH::Array<T, N>::Value (Vertices, anIndex.z()); + + BVH_VecNt aMinPoint (aPoint0), aMaxPoint (aPoint0); + + BVH::BoxMinMax<T, N>::CwiseMin (aMinPoint, aPoint1); + BVH::BoxMinMax<T, N>::CwiseMin (aMinPoint, aPoint2); + BVH::BoxMinMax<T, N>::CwiseMax (aMaxPoint, aPoint1); + BVH::BoxMinMax<T, N>::CwiseMax (aMaxPoint, aPoint2); + return BVH_Box<T, N> (aMinPoint, aMaxPoint); + } //! Returns centroid position along the given axis. virtual T Center (const Standard_Integer theIndex, - const Standard_Integer theAxis) const; + const Standard_Integer theAxis) const Standard_OVERRIDE + { + const BVH_Vec4i& anIndex = BVH::Array<Standard_Integer, 4>::Value (Elements, theIndex); + + const BVH_VecNt& aPoint0 = BVH::Array<T, N>::Value (Vertices, anIndex.x()); + const BVH_VecNt& aPoint1 = BVH::Array<T, N>::Value (Vertices, anIndex.y()); + const BVH_VecNt& aPoint2 = BVH::Array<T, N>::Value (Vertices, anIndex.z()); + return (BVH::VecComp<T, N>::Get (aPoint0, theAxis) + + BVH::VecComp<T, N>::Get (aPoint1, theAxis) + + BVH::VecComp<T, N>::Get (aPoint2, theAxis)) * static_cast<T> (1.0 / 3.0); + } //! Performs transposing the two given triangles in the set. virtual void Swap (const Standard_Integer theIndex1, - const Standard_Integer theIndex2); + const Standard_Integer theIndex2) Standard_OVERRIDE + { + BVH_Vec4i& anIndices1 = BVH::Array<Standard_Integer, 4>::ChangeValue (Elements, theIndex1); + BVH_Vec4i& anIndices2 = BVH::Array<Standard_Integer, 4>::ChangeValue (Elements, theIndex2); + std::swap (anIndices1, anIndices2); + } }; -#include <BVH_Triangulation.lxx> - #endif // _BVH_Triangulation_Header diff --git a/src/BVH/BVH_Triangulation.lxx b/src/BVH/BVH_Triangulation.lxx deleted file mode 100644 index 19ff30f49c..0000000000 --- a/src/BVH/BVH_Triangulation.lxx +++ /dev/null @@ -1,101 +0,0 @@ -// Created on: 2013-12-20 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -// ======================================================================= -// function : BVH_Triangulation -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Triangulation<T, N>::BVH_Triangulation() -{ - // -} - -// ======================================================================= -// function : ~BVH_Triangulation -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Triangulation<T, N>::~BVH_Triangulation() -{ - // -} - -// ======================================================================= -// function : Size -// purpose : -// ======================================================================= -template<class T, int N> -Standard_Integer BVH_Triangulation<T, N>::Size() const -{ - return BVH::Array<Standard_Integer, 4>::Size (Elements); -} - -// ======================================================================= -// function : Box -// purpose : -// ======================================================================= -template<class T, int N> -BVH_Box<T, N> BVH_Triangulation<T, N>::Box (const Standard_Integer theIndex) const -{ - const BVH_Vec4i& anIndex = BVH::Array<Standard_Integer, 4>::Value (Elements, theIndex); - - const BVH_VecNt& aPoint0 = BVH::Array<T, N>::Value (Vertices, anIndex.x()); - const BVH_VecNt& aPoint1 = BVH::Array<T, N>::Value (Vertices, anIndex.y()); - const BVH_VecNt& aPoint2 = BVH::Array<T, N>::Value (Vertices, anIndex.z()); - - BVH_VecNt aMinPoint = aPoint0; - BVH_VecNt aMaxPoint = aPoint0; - - BVH::BoxMinMax<T, N>::CwiseMin (aMinPoint, aPoint1); - BVH::BoxMinMax<T, N>::CwiseMin (aMinPoint, aPoint2); - BVH::BoxMinMax<T, N>::CwiseMax (aMaxPoint, aPoint1); - BVH::BoxMinMax<T, N>::CwiseMax (aMaxPoint, aPoint2); - - return BVH_Box<T, N> (aMinPoint, aMaxPoint); -} - -// ======================================================================= -// function : Center -// purpose : -// ======================================================================= -template<class T, int N> -T BVH_Triangulation<T, N>::Center (const Standard_Integer theIndex, - const Standard_Integer theAxis) const -{ - const BVH_Vec4i& anIndex = BVH::Array<Standard_Integer, 4>::Value (Elements, theIndex); - - const BVH_VecNt& aPoint0 = BVH::Array<T, N>::Value (Vertices, anIndex.x()); - const BVH_VecNt& aPoint1 = BVH::Array<T, N>::Value (Vertices, anIndex.y()); - const BVH_VecNt& aPoint2 = BVH::Array<T, N>::Value (Vertices, anIndex.z()); - - return ( BVH::VecComp<T, N>::Get (aPoint0, theAxis) + - BVH::VecComp<T, N>::Get (aPoint1, theAxis) + - BVH::VecComp<T, N>::Get (aPoint2, theAxis) ) * static_cast<T> (1.0 / 3.0); -} - -// ======================================================================= -// function : Swap -// purpose : -// ======================================================================= -template<class T, int N> -void BVH_Triangulation<T, N>::Swap (const Standard_Integer theIndex1, - const Standard_Integer theIndex2) -{ - BVH_Vec4i& anIndices1 = BVH::Array<Standard_Integer, 4>::ChangeValue (Elements, theIndex1); - BVH_Vec4i& anIndices2 = BVH::Array<Standard_Integer, 4>::ChangeValue (Elements, theIndex2); - - std::swap (anIndices1, anIndices2); -} diff --git a/src/BVH/FILES b/src/BVH/FILES index 88ff44dca1..0bab64bd55 100644 --- a/src/BVH/FILES +++ b/src/BVH/FILES @@ -1,10 +1,7 @@ BVH.cxx BVH_BinnedBuilder.hxx -BVH_BinnedBuilder.lxx BVH_Box.hxx -BVH_Box.lxx BVH_Builder.hxx -BVH_Builder.lxx BVH_BuildQueue.hxx BVH_BuildQueue.cxx BVH_BuildThread.hxx @@ -12,37 +9,21 @@ BVH_BuildThread.cxx BVH_DistanceField.hxx BVH_DistanceField.lxx BVH_Geometry.hxx -BVH_Geometry.lxx BVH_LinearBuilder.hxx -BVH_LinearBuilder.lxx BVH_Object.hxx -BVH_Object.lxx BVH_ObjectSet.hxx -BVH_ObjectSet.lxx BVH_PrimitiveSet.hxx -BVH_PrimitiveSet.lxx BVH_Properties.cxx BVH_Properties.hxx -BVH_Properties.lxx BVH_QueueBuilder.hxx -BVH_QueueBuilder.lxx BVH_Set.hxx -BVH_Set.lxx BVH_Sorter.hxx BVH_QuickSorter.hxx -BVH_QuickSorter.lxx BVH_RadixSorter.hxx -BVH_RadixSorter.lxx BVH_SpatialMedianBuilder.hxx -BVH_SpatialMedianBuilder.lxx BVH_SweepPlaneBuilder.hxx -BVH_SweepPlaneBuilder.lxx BVH_Tree.hxx -BVH_Tree.lxx BVH_BinaryTree.hxx -BVH_BinaryTree.lxx BVH_QuadTree.hxx -BVH_QuadTree.lxx BVH_Triangulation.hxx -BVH_Triangulation.lxx BVH_Types.hxx diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx index bbf6ccb565..03a710f84e 100644 --- a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx +++ b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx @@ -35,18 +35,18 @@ public: OpenGl_BVHClipPrimitiveSet(); //! Returns total number of structures. - virtual Standard_Integer Size() const; + virtual Standard_Integer Size() const Standard_OVERRIDE; //! Returns AABB of the structure. - virtual Graphic3d_BndBox3d Box (const Standard_Integer theIdx) const; + virtual Graphic3d_BndBox3d Box (const Standard_Integer theIdx) const Standard_OVERRIDE; //! Calculates center of the AABB along given axis. virtual Standard_Real Center (const Standard_Integer theIdx, - const Standard_Integer theAxis) const; + const Standard_Integer theAxis) const Standard_OVERRIDE; //! Swaps structures with the given indices. virtual void Swap (const Standard_Integer theIdx1, - const Standard_Integer theIdx2); + const Standard_Integer theIdx2) Standard_OVERRIDE; //! Adds structure to the set. //! @return true if structure added, otherwise returns false (structure already in the set). diff --git a/src/OpenGl/OpenGl_SceneGeometry.hxx b/src/OpenGl/OpenGl_SceneGeometry.hxx index 427ed303d5..e467030096 100755 --- a/src/OpenGl/OpenGl_SceneGeometry.hxx +++ b/src/OpenGl/OpenGl_SceneGeometry.hxx @@ -283,7 +283,7 @@ public: } //! Clears ray-tracing geometry. - void Clear(); + virtual void Clear() Standard_OVERRIDE; public: //! @name methods related to acceleration structure