mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-04 18:06:22 +03:00
0028793: Visualization, TKV3d - make BVH_Builder::Build() const for propagating builder by value
Added const for method BVH_Builder::Build(). Added missing Standard_OVERRIDE to overridden methods. Merged code from .lxx in BVH package directly into .hxx headers.
This commit is contained in:
parent
edfa30deef
commit
e28f12b304
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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,
|
||||
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_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
|
||||
|
@ -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));
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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()
|
||||
{
|
||||
//
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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,9 +46,9 @@ public:
|
||||
virtual ~BVH_LinearBuilder();
|
||||
|
||||
//! Builds BVH.
|
||||
void Build (BVH_Set<T, N>* theSet,
|
||||
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:
|
||||
|
||||
@ -56,24 +57,297 @@ protected:
|
||||
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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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:
|
||||
|
||||
@ -128,56 +131,171 @@ protected:
|
||||
//! Creates new BVH build thread.
|
||||
BVH_TypedBuildTool (BVH_Set<T, N>* theSet,
|
||||
BVH_Tree<T, N>* theBVH,
|
||||
BVH_Builder<T, N>* theAlgo)
|
||||
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,
|
||||
virtual void addChildren (BVH_Tree<T, N>* theBVH,
|
||||
BVH_BuildQueue& theBuildQueue,
|
||||
const Standard_Integer theNode,
|
||||
const BVH_ChildNodes& theSubNodes);
|
||||
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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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()
|
||||
{
|
||||
//
|
||||
}
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
@ -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
|
||||
|
@ -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()
|
||||
{
|
||||
//
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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).
|
||||
|
@ -283,7 +283,7 @@ public:
|
||||
}
|
||||
|
||||
//! Clears ray-tracing geometry.
|
||||
void Clear();
|
||||
virtual void Clear() Standard_OVERRIDE;
|
||||
|
||||
public: //! @name methods related to acceleration structure
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user