28 #define BVH_TRY_ALL_AXES 0
36 template<
typename T,u
int NAXES>
49 "UT::Box should be POD, for better performance in UT_Array, etc.");
51 for (
uint axis = 0; axis < NAXES; ++axis) {
52 vals[axis][0] =
T(other.vals[axis][0]);
53 vals[axis][1] =
T(other.vals[axis][1]);
57 template<
typename TS >
62 for (
uint axis = 0; axis < NAXES; ++axis) {
63 vals[axis][0] = pt[axis];
64 vals[axis][1] = pt[axis];
70 for (
uint axis = 0; axis < NAXES; ++axis) {
71 vals[axis][0] =
T(other.vals[axis][0]);
72 vals[axis][1] =
T(other.vals[axis][1]);
87 for (
uint axis = 0; axis < NAXES; ++axis) {
96 for (
uint axis = 0; axis < NAXES; ++axis) {
97 vals[axis][0] =
src.vals[axis][0];
98 vals[axis][1] =
src.vals[axis][1];
105 for (
uint axis = 0; axis < NAXES; ++axis) {
106 vals[axis][0] =
SYSmin(src0.vals[axis][0], src1.vals[axis][0]);
107 vals[axis][1] =
SYSmax(src0.vals[axis][1], src1.vals[axis][1]);
111 for (
uint axis = 0; axis < NAXES; ++axis) {
112 T& minv =
vals[axis][0];
113 T& maxv =
vals[axis][1];
114 const T curminv =
src.vals[axis][0];
115 const T curmaxv =
src.vals[axis][1];
116 minv = (minv < curminv) ? minv : curminv;
117 maxv = (maxv > curmaxv) ? maxv : curmaxv;
124 template<
typename TS >
130 for (
uint axis = 0; axis < NAXES; ++axis) {
131 vals[axis][0] = pt[axis];
132 vals[axis][1] = pt[axis];
136 template<
typename TS >
145 for (
uint axis = 0; axis < NAXES; ++axis) {
151 template<
typename TS >
157 for (
uint axis = 0; axis < NAXES; ++axis) {
163 template<
typename TS >
169 for (
uint axis = 0; axis < NAXES; ++axis) {
175 template<
typename TS >
186 for (
uint axis = 0; axis < NAXES; ++axis) {
187 v[axis] =
vals[axis][0];
195 for (
uint axis = 0; axis < NAXES; ++axis) {
196 v[axis] =
vals[axis][1];
204 for (
uint axis = 1; axis < NAXES; ++axis) {
205 diff = (
vals[axis][1]-
vals[axis][0]);
212 for (
uint axis = 1; axis < NAXES; ++axis) {
213 product *= (
vals[axis][1]-
vals[axis][0]);
233 return d0*d1 + d1*d2 + d2*d0;
241 const T d0d1 = d0*d1;
242 const T d2d3 = d2*d3;
243 return d0d1*(d2+d3) + d2d3*(d0+d1);
247 for (
uint skipped_axis = 0; skipped_axis < NAXES; ++skipped_axis) {
249 for (
uint axis = 0; axis < NAXES; ++axis) {
250 if (axis != skipped_axis) {
251 product *= (
vals[axis][1]-
vals[axis][0]);
260 for (
uint axis = 1; axis < NAXES; ++axis) {
261 sum += (
vals[axis][1]-
vals[axis][0]);
273 for (
int axis = 0; axis < NAXES; ++axis)
276 T t1 = (
vals[axis][
sign] - origin[axis]) * inverse_direction[axis];
277 T t2 = (
vals[axis][sign^1] - origin[axis]) * inverse_direction[axis];
278 box_tmin =
SYSmax(t1, box_tmin);
279 box_tmax =
SYSmin(t2, box_tmax);
291 for (
int axis = 0; axis < NAXES; ++axis)
295 vals[axis][0] - tolerance,
296 vals[axis][1] + tolerance
298 T t1 = (local_vals[
sign] - origin[axis]) * inverse_direction[axis];
299 T t2 = (local_vals[sign^1] - origin[axis]) * inverse_direction[axis];
300 box_tmin =
SYSmax(t1, box_tmin);
301 box_tmax =
SYSmin(t2, box_tmax);
305 for (
int axis = 0; axis < NAXES; ++axis)
307 dest.vals[axis][0] =
SYSmax(
vals[axis][0], other.vals[axis][0]);
308 dest.vals[axis][1] =
SYSmin(
vals[axis][1], other.vals[axis][1]);
317 for (
int axis = 1; axis < NAXES; ++axis)
330 for (
int axis = 1; axis < NAXES; ++axis)
338 template<
typename TS >
339 auto isInside(
const TS &pt)
const noexcept -> decltype(
vals[0][0] <= pt[0])
345 vals[0][0] <= pt[0] &&
vals[0][1] >= pt[0] &&
346 vals[1][0] <= pt[1] && vals[1][1] >= pt[1] &&
347 vals[2][0] <= pt[2] && vals[2][1] >= pt[2];
436 template<BVH_Heuristic H,
typename T,u
int NAXES,
typename BOX_TYPE,
typename SRC_INT_TYPE=INT_TYPE>
437 void init(
const BOX_TYPE* boxes,
const INT_TYPE nboxes, SRC_INT_TYPE*
indices=
nullptr,
bool reorder_indices=
false,
INT_TYPE max_items_per_leaf=1) noexcept;
440 void init(
Box<T,NAXES> axes_minmax, const BOX_TYPE* boxes,
INT_TYPE nboxes, SRC_INT_TYPE*
indices=
nullptr,
bool reorder_indices=false,
INT_TYPE max_items_per_leaf=1) noexcept;
477 template<
typename LOCAL_DATA,
typename FUNCTORS>
480 LOCAL_DATA *data_for_parent=
nullptr) const noexcept;
488 template<typename LOCAL_DATA,typename FUNCTORS>
492 LOCAL_DATA *data_for_parent=
nullptr) const noexcept;
508 template<typename LOCAL_DATA,typename FUNCTORS>
511 LOCAL_DATA *data_for_parent=
nullptr) const noexcept;
516 template<typename SRC_INT_TYPE>
520 template<typename LOCAL_DATA,typename FUNCTORS>
525 LOCAL_DATA *data_for_parent=
nullptr) const noexcept;
527 template<typename LOCAL_DATA,typename FUNCTORS>
528 void traverseParallelHelper(
534 LOCAL_DATA *data_for_parent=
nullptr) const noexcept;
536 template<typename LOCAL_DATA,typename FUNCTORS>
537 void traverseVectorHelper(
541 LOCAL_DATA *data_for_parent=
nullptr) const noexcept;
543 template<typename T,
uint NAXES,typename BOX_TYPE,typename SRC_INT_TYPE>
544 static
void computeFullBoundingBox(
Box<T,NAXES>& axes_minmax, const BOX_TYPE* boxes, const
INT_TYPE nboxes, SRC_INT_TYPE* indices) noexcept;
546 template<
BVH_Heuristic H,typename T,
uint NAXES,typename BOX_TYPE,typename SRC_INT_TYPE>
547 static
void initNode(
UT_Array<
Node>& nodes,
Node &node, const
Box<T,NAXES>& axes_minmax, const BOX_TYPE* boxes, SRC_INT_TYPE* indices, const
INT_TYPE nboxes) noexcept;
549 template<
BVH_Heuristic H,typename T,
uint NAXES,typename BOX_TYPE,typename SRC_INT_TYPE>
550 static
void initNodeReorder(
UT_Array<
Node>& nodes,
Node &node, const
Box<T,NAXES>& axes_minmax, const BOX_TYPE* boxes, SRC_INT_TYPE* indices, const
INT_TYPE nboxes, const
INT_TYPE indices_offset, const
INT_TYPE max_items_per_leaf) noexcept;
552 template<
BVH_Heuristic H,typename T,
uint NAXES,typename BOX_TYPE,typename SRC_INT_TYPE>
553 static
void multiSplit(const
Box<T,NAXES>& axes_minmax, const BOX_TYPE* boxes, SRC_INT_TYPE* indices,
INT_TYPE nboxes, SRC_INT_TYPE* sub_indices[
N+1],
Box<T,NAXES> sub_boxes[N]) noexcept;
555 template<
BVH_Heuristic H,typename T,
uint NAXES,typename BOX_TYPE,typename SRC_INT_TYPE>
556 static
void split(const
Box<T,NAXES>& axes_minmax, const BOX_TYPE* boxes, SRC_INT_TYPE* indices,
INT_TYPE nboxes, SRC_INT_TYPE*& split_indices,
Box<T,NAXES>* split_boxes) noexcept;
559 template<BVH_Heuristic H,
typename T,u
int NAXES,
typename BOX_TYPE,
typename SRC_INT_TYPE>
560 static void splitMiddleCountAxis(
const INT_TYPE axis, T &best_heuristic,
const BOX_TYPE* boxes, SRC_INT_TYPE* indices,
INT_TYPE nboxes, SRC_INT_TYPE*& split_indices,
Box<T,NAXES>* split_boxes) noexcept;
562 template<BVH_Heuristic H,
typename T,u
int NAXES,
typename BOX_TYPE,
typename SRC_INT_TYPE>
563 static void splitLargeCountAxis(
564 const INT_TYPE axis,
const T axis_min,
const T axis_length,
571 const BOX_TYPE* boxes, SRC_INT_TYPE* indices,
INT_TYPE nboxes) noexcept;
574 template<INT_TYPE PARALLEL_THRESHOLD,
typename SRC_INT_TYPE>
577 template<
typename T,
typename BOX_TYPE,
typename SRC_INT_TYPE>
578 static void nthElement(
const BOX_TYPE* boxes, SRC_INT_TYPE* indices,
const SRC_INT_TYPE* indices_end,
const uint axis, SRC_INT_TYPE*
const nth) noexcept;
580 template<
typename T,
typename BOX_TYPE,
typename SRC_INT_TYPE>
581 static void partitionByCentre(
const BOX_TYPE* boxes, SRC_INT_TYPE*
const indices,
const SRC_INT_TYPE*
const indices_end,
const uint axis,
const T pivotx2, SRC_INT_TYPE*& ppivot_start, SRC_INT_TYPE*& ppivot_end) noexcept;
589 return nboxes/2 + nboxes/(2*(N-1));
592 template<BVH_Heuristic H,
typename T, u
int NAXES>
595 return box.axis_sum();
598 return box.half_surface_area();
604 T diameter2 = box.diameter2();
605 return SYSsqrt(diameter2);
608 return box.diameter2();
611 T diameter2 = box.diameter2();
612 return diameter2*SYSsqrt(diameter2);
614 UT_ASSERT_MSG(0,
"BVH_Heuristic::MEDIAN_MAX_AXIS should be handled separately by caller!");
618 int getMaxDepthHelper(
INT_TYPE curnode,
int depth)
const noexcept;
619 int getPureInternalDepthHelper(
INT_TYPE curnode,
int depth)
const noexcept;
622 static constexpr
INT_TYPE NSPANS = 16;
623 static constexpr
INT_TYPE NSPLITS = NSPANS-1;
626 static constexpr
INT_TYPE MIN_FRACTION = 16;
632 template<u
int BVH_N,
typename ITEM_BOX,
typename NODE_BOX>
635 const ITEM_BOX* item_boxes,
636 NODE_BOX* node_boxes) noexcept;
641 template<u
int NAXES,
typename T,u
int BVH_N,
typename ITEM_BOX,
typename NODE_BOX>
644 const ITEM_BOX* item_boxes,
645 NODE_BOX* node_boxes,
646 float expand_factor=0.0
f) noexcept;
651 template<
uint NAXES,typename T,typename ITEM_BOX,typename NODE_BOX,typename INT_TYPE0=
uint>
653 const UT::BVH<4>& bvh,
654 const ITEM_BOX* item_boxes,
655 NODE_BOX* node_boxes,
656 const
v4uu* node_nitems,
657 const INT_TYPE0* indices_mapping=
nullptr) noexcept;
666 template<
uint NAXES,typename INT_TYPE>
668 const UT::
BVH<4>& bvh,
669 const UT::
Box<
v4uf,NAXES>* node_boxes,
670 const UT::
Box<
float,NAXES>& query_box,
674 template<
uint NAXES,typename INT_TYPE>
676 const UT::
BVH<4>& bvh,
677 const UT::
Box<v4uf,NAXES>* node_boxes,
678 const UT::
Box<
float,NAXES>& query_box,
682 template<
uint NAXES,typename INT_TYPE>
684 const UT::
BVH<4>& bvh,
685 const UT::
Box<v4uf,NAXES>* node_boxes,
686 const UT::
Box<
float,NAXES>& query_box,
690 template<
uint NAXES,typename INT_TYPE,
int BATCH_SIZE>
692 const UT::
BVH<4>& bvh,
693 const UT::
Box<v4uf,NAXES>* node_boxes,
694 const UT::
Box<
float,NAXES> *query_box,
700 const UT::
BVH<4>& bvh,
702 exint nitems) noexcept;
709 SYS_FORCE_INLINE BVHOrderedStackEntry(const BVHOrderedStackEntry& other) noexcept = default;
710 SYS_FORCE_INLINE BVHOrderedStackEntry(BVHOrderedStackEntry&& other) noexcept = default;
711 SYS_FORCE_INLINE BVHOrderedStackEntry& operator=(const BVHOrderedStackEntry& other) noexcept = default;
712 SYS_FORCE_INLINE BVHOrderedStackEntry& operator=(BVHOrderedStackEntry&& other) noexcept = default;
714 : myDistSquared(dist_squared)
738 return !(*
this == other);
770 constexpr
bool allRadiiZero(
const T*
const array) noexcept {
return !array; }
772 template<
typename QUERY_POINT>
792 template<
typename POSITION,
typename RADIUS_ARRAY>
795 return myQueryPoint.queryDistance2(tree_point, radii, index);
801 template<
bool farthest,u
int NAXES>
804 return myQueryPoint.template boxHitAndDist2<farthest>(boxes, max_dist_squared, internal_node_num, dist2);
816 template<
bool farthest,
bool reordered,
bool use_max_po
ints,u
int NAXES,
typename QUERY_POINT,
typename INT_TYPE0,
typename POSITION_ARRAY,
typename RADIUS_ARRAY>
820 const v4uu* node_nitems,
821 const INT_TYPE0* indices_mapping,
822 const POSITION_ARRAY& positions,
823 QUERY_POINT& query_point,
826 const RADIUS_ARRAY& radii = ZeroRadiiWrapper(),
835 #undef BVH_TRY_ALL_AXES
SYS_FORCE_INLINE bool operator==(const BVHOrderedStackEntry &other) const
SYS_FORCE_INLINE uint boxHitAndDist2(const UT::Box< v4uf, NAXES > &boxes, const float max_dist_squared, const uint internal_node_num, v4uf &dist2) const
#define SYS_STATIC_ASSERT(expr)
GLsizei GLenum const void * indices
constexpr bool allRadiiZero(const T &array) noexcept
static constexpr INT_TYPE EMPTY
void findClosestPoints(const UT::BVH< 4 > &bvh, const UT::Box< v4uf, NAXES > *node_boxes, const v4uu *node_nitems, const INT_TYPE0 *indices_mapping, const POSITION_ARRAY &positions, QUERY_POINT &query_point, BVHOrderedStack &stack, BVHOrderedStack &output_queue, const RADIUS_ARRAY &radii=ZeroRadiiWrapper(), exint max_points=std::numeric_limits< exint >::max(), float max_dist_squared=std::numeric_limits< float >::max()) noexcept
SYS_FORCE_INLINE void combine(const TS &pt) noexcept
SYS_FORCE_INLINE void intersect(const Box &other, Box &dest) const noexcept
void traverseParallel(INT_TYPE parallel_threshold, FUNCTORS &functors, LOCAL_DATA *data_for_parent=nullptr) const noexcept
#define SYS_STATIC_ASSERT_MSG(expr, msg)
T half_surface_area() const noexcept
static SYS_FORCE_INLINE INT_TYPE markInternal(INT_TYPE internal_node_num) noexcept
int getPureInternalDepth() const noexcept
Returns the minimum depth of the first non-internal node.
SYS_FORCE_INLINE bool operator!=(const BVHOrderedStackEntry &other) const
SYS_FORCE_INLINE void initBounds(const Box< T, NAXES > &src) noexcept
SYS_FORCE_INLINE UT_FixedVector< T, NAXES > getMin() const noexcept
SYS_FORCE_INLINE constexpr SingleRadiusWrapper(const float radius)
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
SYS_FORCE_INLINE void initBounds() noexcept
SYS_FORCE_INLINE void enlargeBounds(const TS &pt) noexcept
SYS_FORCE_INLINE BVHQueryPointWrapper(QUERY_POINT &query_point)
SYS_FORCE_INLINE UT_FixedVector< T, NAXES > getMax() const noexcept
SYS_FORCE_INLINE bool operator>(const BVHOrderedStackEntry &other) const
int getMaxDepth() const noexcept
Returns the maximum depth of any leaf.
SYS_FORCE_INLINE constexpr float operator[](exint i) const noexcept
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
void getIntersectingBoxesFromStack(const UT::BVH< 4 > &bvh, const UT::Box< v4uf, NAXES > *node_boxes, const UT::Box< float, NAXES > &query_box, UT_Array< INT_TYPE > &box_indices, BVHUnorderedStack &stack) noexcept
SYS_FORCE_INLINE T minDistance2(const UT_FixedVector< T, NAXES > &p) const noexcept
#define UT_ASSERT_MSG(ZZ,...)
SYS_FORCE_INLINE void clear() noexcept
SYS_FORCE_INLINE T * operator[](const size_t axis) noexcept
T axis_sum() const noexcept
UT::BVH< 4 >::INT_TYPE myNode
void computeNodeNItems(const UT::BVH< 4 > &bvh, v4uu *node_nitems, exint nitems) noexcept
Computes the number of items per node entry and fills in node_nitems.
SYS_FORCE_INLINE void initBounds(const TS &min, const TS &max) noexcept
void getIntersectingNodes(const UT::BVH< 4 > &bvh, const UT::Box< v4uf, NAXES > *node_boxes, const UT::Box< float, NAXES > &query_box, UT_Array< INT_TYPE > &box_indices, BVHUnorderedStack &stack) noexcept
QUERY_POINT & myQueryPoint
SYS_FORCE_INLINE Box() noexcept=default
SYS_FORCE_INLINE bool operator>=(const BVHOrderedStackEntry &other) const
SYS_FORCE_INLINE T maxDistance2(const UT_FixedVector< T, NAXES > &p) const noexcept
SYS_FORCE_INLINE bool operator<=(const BVHOrderedStackEntry &other) const
SYS_FORCE_INLINE const Node * getNodes() const noexcept
void debugDump() const
Prints a text representation of the tree to stdout.
SYS_FORCE_INLINE BVH() noexcept
T diameter2() const noexcept
SYS_FORCE_INLINE void createBVHNodeBoxes(const UT::BVH< BVH_N > &bvh, const ITEM_BOX *item_boxes, NODE_BOX *node_boxes) noexcept
SYS_FORCE_INLINE void createBVHInterleavedBoxes(const UT::BVH< BVH_N > &bvh, const ITEM_BOX *item_boxes, NODE_BOX *node_boxes, float expand_factor=0.0f) noexcept
STATIC_INLINE uint64_t H(uint64_t x, uint64_t y, uint64_t mul, int r)
IMATH_HOSTDEVICE constexpr int sign(T a) IMATH_NOEXCEPT
auto isInside(const TS &pt) const noexcept-> decltype(vals[0][0]<=pt[0])
GLint GLint GLsizei GLsizei GLsizei depth
void init(const BOX_TYPE *boxes, const INT_TYPE nboxes, SRC_INT_TYPE *indices=nullptr, bool reorder_indices=false, INT_TYPE max_items_per_leaf=1) noexcept
void traverse(FUNCTORS &functors, LOCAL_DATA *data_for_parent=nullptr) const noexcept
static void createTrivialIndices(SRC_INT_TYPE *indices, const INT_TYPE n) noexcept
static constexpr bool theAllPointsValid
isValid() doesn't need to be called if theAllPointsValid is true.
static SYS_FORCE_INLINE INT_TYPE getInternalNum(INT_TYPE node_int) noexcept
SYS_FORCE_INLINE float queryDistance2(const POSITION &tree_point, const RADIUS_ARRAY &radii, uint index) const
This must be the exact distance squared.
SYS_FORCE_INLINE Box & operator=(const Box< S, NAXES > &other) noexcept
SYS_FORCE_INLINE void intersectTol(T &box_tmin, T &box_tmax, const UT_FixedVector< uint, NAXES > &signs, const UT_FixedVector< T, NAXES > &origin, const UT_FixedVector< T, NAXES > &inverse_direction, T tolerance) const noexcept
Intersect the box expanded by the specified tolerance in all axes.
void getIntersectingBoxesBatch(const UT::BVH< 4 > &bvh, const UT::Box< v4uf, NAXES > *node_boxes, const UT::Box< float, NAXES > *query_box, UT_Array< INT_TYPE > *box_indices, BVHUnorderedStack &stack) noexcept
UT_Array< BVHOrderedStackEntry > BVHOrderedStack
SYS_FORCE_INLINE void initBounds(const TS &pt) noexcept
SYS_FORCE_INLINE INT_TYPE getNumNodes() const noexcept
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
GA_API const UT_StringHolder N
SYS_FORCE_INLINE void initBoundsUnordered(const TS &p0, const TS &p1) noexcept
SYS_FORCE_INLINE void intersect(T &box_tmin, T &box_tmax, const UT_FixedVector< uint, NAXES > &signs, const UT_FixedVector< T, NAXES > &origin, const UT_FixedVector< T, NAXES > &inverse_direction) const noexcept
static constexpr INT_TYPE INTERNAL_BIT
static constexpr INT_TYPE theN
SYS_FORCE_INLINE void initBoundsUnordered(const Box< T, NAXES > &src0, const Box< T, NAXES > &src1) noexcept
T volume() const noexcept
void getIntersectingBoxes(const UT::BVH< 4 > &bvh, const UT::Box< v4uf, NAXES > *node_boxes, const UT::Box< float, NAXES > &query_box, UT_Array< INT_TYPE > &box_indices, BVHUnorderedStack &stack) noexcept
constexpr float operator[](exint i) const noexcept
static SYS_FORCE_INLINE bool isInternal(INT_TYPE node_int) noexcept
SYS_FORCE_INLINE Box(const TS &pt) noexcept
SYS_FORCE_INLINE bool operator<(const BVHOrderedStackEntry &other) const
SYS_FORCE_INLINE void enlargeBounds(const Box< T, NAXES > &src) noexcept
SYS_FORCE_INLINE void combine(const Box< T, NAXES > &src) noexcept
void traverseVector(FUNCTORS &functors, LOCAL_DATA *data_for_parent=nullptr) const noexcept
SYS_FORCE_INLINE const T * operator[](const size_t axis) const noexcept
constexpr ZeroRadiiWrapper()=default
SYS_FORCE_INLINE bool isValid(uint tree_point_index) const