9 #ifndef CUBBYFLOW_BVH3_IMPL_H 10 #define CUBBYFLOW_BVH3_IMPL_H 17 BVH3<T>::Node::Node() : flags(0)
19 child = std::numeric_limits<size_t>::max();
23 void BVH3<T>::Node::InitLeaf(
size_t it,
const BoundingBox3D& b)
31 void BVH3<T>::Node::InitInternal(uint8_t axis,
size_t c,
const BoundingBox3D& b)
39 bool BVH3<T>::Node::IsLeaf()
const 52 const std::vector<BoundingBox3D>& itemsBounds)
55 m_itemBounds = itemsBounds;
64 for (
size_t i = 0; i < m_items.size(); ++i)
66 m_bound.Merge(m_itemBounds[i]);
69 std::vector<size_t> itemIndices(m_items.size());
70 std::iota(std::begin(itemIndices), std::end(itemIndices), 0);
72 Build(0, itemIndices.data(), m_items.size(), 0);
90 best.
distance = std::numeric_limits<double>::max();
94 static const int maxTreeDepth = 8 *
sizeof(size_t);
95 const Node* todo[maxTreeDepth];
99 const Node* node = m_nodes.data();
100 while (node !=
nullptr)
104 double dist = distanceFunc(m_items[node->item], pt);
108 best.
item = &m_items[node->item];
116 node = todo[todoPos];
127 const Node* left = node + 1;
128 const Node* right = &m_nodes[node->child];
134 Vector3D closestLeft = left->bound.Clamp(pt);
135 Vector3D closestRight = right->bound.Clamp(pt);
140 bool shouldVisitLeft = distMinLeftSqr < bestDistSqr;
141 bool shouldVisitRight = distMinRightSqr < bestDistSqr;
143 const Node* firstChild;
144 const Node* secondChild;
146 if (shouldVisitLeft && shouldVisitRight)
148 if (distMinLeftSqr < distMinRightSqr)
160 todo[todoPos] = secondChild;
164 else if (shouldVisitLeft)
168 else if (shouldVisitRight)
178 node = todo[todoPos];
191 template <
typename T>
195 if (!m_bound.Overlaps(box))
201 static const int maxTreeDepth = 8 *
sizeof(size_t);
202 const Node* todo[maxTreeDepth];
206 const Node* node = m_nodes.data();
208 while (node !=
nullptr)
212 if (testFunc(m_items[node->item], box))
222 node = todo[todoPos];
232 const Node* firstChild = node + 1;
233 const Node* secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
236 if (!firstChild->bound.Overlaps(box))
240 else if (!secondChild->bound.Overlaps(box))
247 todo[todoPos] = secondChild;
257 template <
typename T>
261 if (!m_bound.Intersects(ray))
267 static const int maxTreeDepth = 8 *
sizeof(size_t);
268 const Node* todo[maxTreeDepth];
272 const Node* node = m_nodes.data();
274 while (node !=
nullptr)
278 if (testFunc(m_items[node->item], ray))
288 node = todo[todoPos];
298 const Node* firstChild;
299 const Node* secondChild;
303 firstChild = node + 1;
304 secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
308 firstChild =
const_cast<Node*
>(&m_nodes[node->child]);
309 secondChild = node + 1;
313 if (!firstChild->bound.Intersects(ray))
317 else if (!secondChild->bound.Intersects(ray))
324 todo[todoPos] = secondChild;
334 template <
typename T>
339 if (!m_bound.Overlaps(box))
345 static const int maxTreeDepth = 8 *
sizeof(size_t);
346 const Node* todo[maxTreeDepth];
350 const Node* node = m_nodes.data();
352 while (node !=
nullptr)
356 if (testFunc(m_items[node->item], box))
358 visitorFunc(m_items[node->item]);
366 node = todo[todoPos];
376 const Node* firstChild = node + 1;
377 const Node* secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
380 if (!firstChild->bound.Overlaps(box))
384 else if (!secondChild->bound.Overlaps(box))
391 todo[todoPos] = secondChild;
399 template <
typename T>
404 if (!m_bound.Intersects(ray))
410 static const int maxTreeDepth = 8 *
sizeof(size_t);
411 const Node* todo[maxTreeDepth];
415 const Node* node = m_nodes.data();
417 while (node !=
nullptr)
421 if (testFunc(m_items[node->item], ray))
423 visitorFunc(m_items[node->item]);
431 node = todo[todoPos];
441 const Node* firstChild;
442 const Node* secondChild;
446 firstChild = node + 1;
447 secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
451 firstChild =
const_cast<Node*
>(&m_nodes[node->child]);
452 secondChild = node + 1;
456 if (!firstChild->bound.Intersects(ray))
460 else if (!secondChild->bound.Intersects(ray))
467 todo[todoPos] = secondChild;
475 template <
typename T>
480 best.
distance = std::numeric_limits<double>::max();
483 if (!m_bound.Intersects(ray))
489 static const int maxTreeDepth = 8 *
sizeof(size_t);
490 const Node* todo[maxTreeDepth];
494 const Node* node = m_nodes.data();
496 while (node !=
nullptr)
500 double dist = testFunc(m_items[node->item], ray);
504 best.
item = m_items.data() + node->item;
512 node = todo[todoPos];
522 const Node* firstChild;
523 const Node* secondChild;
527 firstChild = node + 1;
528 secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
532 firstChild =
const_cast<Node*
>(&m_nodes[node->child]);
533 secondChild = node + 1;
537 if (!firstChild->bound.Intersects(ray))
541 else if (!secondChild->bound.Intersects(ray))
548 todo[todoPos] = secondChild;
558 template <
typename T>
564 template <
typename T>
567 return m_items.
begin();
570 template <
typename T>
573 return m_items.
end();
576 template <
typename T>
579 return m_items.
begin();
582 template <
typename T>
585 return m_items.
end();
588 template <
typename T>
591 return m_items.size();
594 template <
typename T>
600 template <
typename T>
601 size_t BVH3<T>::Build(
size_t nodeIndex,
size_t* itemIndices,
size_t nItems,
size_t currentDepth)
604 m_nodes.push_back(Node());
609 m_nodes[nodeIndex].InitLeaf(itemIndices[0], m_itemBounds[itemIndices[0]]);
610 return currentDepth + 1;
615 for (
size_t i = 0; i < nItems; ++i)
617 nodeBound.Merge(m_itemBounds[itemIndices[i]]);
620 Vector3D d = nodeBound.upperCorner - nodeBound.lowerCorner;
624 if (d.x > d.y && d.x > d.z)
630 axis = (d.y > d.z) ? 1 : 2;
633 double pivot = 0.5 * (nodeBound.upperCorner[axis] + nodeBound.lowerCorner[axis]);
636 size_t midPoint = QSplit(itemIndices, nItems, pivot, axis);
639 size_t d0 = Build(nodeIndex + 1, itemIndices, midPoint, currentDepth + 1);
640 m_nodes[nodeIndex].InitInternal(axis, m_nodes.size(), nodeBound);
641 size_t d1 = Build(m_nodes[nodeIndex].child, itemIndices + midPoint, nItems - midPoint, currentDepth + 1);
643 return std::max(d0, d1);
646 template <
typename T>
647 size_t BVH3<T>::QSplit(
size_t* itemIndices,
size_t numItems,
double pivot, uint8_t axis)
651 for (
size_t i = 0; i < numItems; ++i)
654 double centroid = 0.5f * (b.lowerCorner[axis] + b.upperCorner[axis]);
656 if (centroid < pivot)
658 std::swap(itemIndices[i], itemIndices[ret]);
663 if (ret == 0 || ret == numItems)
3-D vector class.
Definition: Vector3.h:26
Bounding Volume Hierarchy (BVH) in 3D.
Definition: BVH3.h:26
typename ContainerType::iterator Iterator
Definition: BVH3.h:30
Vector3< T > direction
The direction of the ray.
Definition: Ray3.h:32
const T * item
Definition: NearestNeighborQueryEngine3.h:20
Iterator begin()
Returns the begin iterator of the item.
Definition: BVH3-Impl.h:565
std::function< bool(const T &, const BoundingBox3D &)> BoxIntersectionTestFunc3
Box-item intersection test function.
Definition: IntersectionQueryEngine3.h:31
T DistanceSquaredTo(const Vector &other) const
Returns the squared distance to the other vector.
Definition: Vector3-Impl.h:332
const T * item
Definition: IntersectionQueryEngine3.h:21
BoundingBox3< double > BoundingBox3D
Double-type 3-D BoundingBox.
Definition: BoundingBox3.h:129
std::function< double(const T &, const Ray3D &)> GetRayIntersectionFunc3
Ray-item closest intersection evaluation function.
Definition: IntersectionQueryEngine3.h:39
double distance
Definition: IntersectionQueryEngine3.h:22
Definition: pybind11Utils.h:24
3-D axis-aligned bounding box class.
Definition: BoundingBox3.h:44
Closest intersection query result.
Definition: IntersectionQueryEngine3.h:19
Iterator end()
Returns the end iterator of the item.
Definition: BVH3-Impl.h:571
double distance
Definition: NearestNeighborQueryEngine3.h:21
std::function< void(const T &)> IntersectionVisitorFunc3
Visitor function which is invoked for each intersecting item.
Definition: IntersectionQueryEngine3.h:43
std::function< bool(const T &, const Ray3D &)> RayIntersectionTestFunc3
Ray-item intersection test function.
Definition: IntersectionQueryEngine3.h:35
typename ContainerType::const_iterator ConstIterator
Definition: BVH3.h:31
Nearest neighbor query result.
Definition: NearestNeighborQueryEngine3.h:18
Class for 3-D ray.
Definition: Ray3.h:23
Vector3< double > Vector3D
Double-type 3D vector.
Definition: Vector3.h:353
std::function< double(const T &, const Vector3D &)> NearestNeighborDistanceFunc3
Nearest neighbor distance measure function.
Definition: NearestNeighborQueryEngine3.h:26