29 #define GEO_BVH_INTERLEAVED 1
33 template<u
int NAXES,
typename SUBCLASS>
38 myPositions.setCapacity(0);
39 myRadii.setCapacity(0);
43 myHasCurvesOrPoints =
false;
46 template<
typename VectorType>
49 VectorType rel_origin,
const VectorType &
direction,
50 float radius,
float &t0,
float &t1)
56 float rayt = SYSsqrt(rel_origin.length2());
57 VectorType p = rel_origin + rayt*
direction;
60 float b = 2.0F *
dot(p, direction);
61 float c = p.length2() - radius*radius;
63 float d = b*b - 4.0F*
c;
78 template<u
int NAXES,
typename SUBCLASS>
79 template<
bool USE_TOLERANCE>
80 struct BVHBase<NAXES,SUBCLASS>::SingleHitFunctor
85 , myNestingArrayBase(hit_info.myNestedItemIndices ? hit_info.myNestedItemIndices->size() : 0)
89 myHitInfo.myItemIndex = -1;
90 myHitInfo.myUVW.assign(0,0,0);
91 myHitInfo.myT = -1.0f;
97 float &limit_t) noexcept
99 myHitInfo.myItemIndex =
index;
100 myHitInfo.myUVW = hit_uvw;
102 if (myHitInfo.myNestedItemIndices)
103 myHitInfo.myNestedItemIndices->setSize(myNestingArrayBase);
109 hit_info.myNestedItemIndices = myHitInfo.myNestedItemIndices;
113 return myHitInfo.myNestedItemIndices;
117 return myNestingArrayBase;
127 constexpr
static bool theAllHits =
false;
128 constexpr
static bool theNeedsNormal =
false;
129 constexpr
static bool theUseTolerance = USE_TOLERANCE;
138 template<u
int NAXES,
typename SUBCLASS>
139 template<
bool USE_TOLERANCE>
144 : myHitInfo(hit_info)
145 , myNestingArrayBase(hit_info.myNestedItemIndices ? hit_info.myNestedItemIndices->size() : 0)
149 myHitInfo.myItemIndex = -1;
150 myHitInfo.myUVW.assign(0,0,0);
151 myHitInfo.myT = -1.0f;
157 float &limit_t) noexcept
159 myHitInfo.myItemIndex =
index;
160 myHitInfo.myUVW = hit_uvw;
162 if (myHitInfo.myNestedItemIndices)
163 myHitInfo.myNestedItemIndices->setSize(myNestingArrayBase);
169 hit_info.myNestedItemIndices = myHitInfo.myNestedItemIndices;
173 return myHitInfo.myNestedItemIndices;
176 {
return hit_info.myNml; }
179 myHitInfo.myNml = nml;
183 hit_info.myNml = nml;
189 constexpr
static bool theAllHits =
false;
190 constexpr
static bool theNeedsNormal =
true;
191 constexpr
static bool theUseTolerance = USE_TOLERANCE;
200 template<u
int NAXES,
typename SUBCLASS>
201 template<
bool USE_TOLERANCE>
207 : myHitInfo(hit_info)
208 , myNestingTempArray(nesting_temp_array)
218 float &limit_t) noexcept
221 if (!myNestingTempArray || myNestingTempArray->isEmpty())
234 for (
exint i = 1; i <
n; ++i)
236 (*new_array)[i-1] = (*myNestingTempArray)[i];
238 (*new_array)[n-1] =
index;
240 hit_info.
myUVW = hit_uvw;
242 myHitInfo.append(hit_info);
247 return myNestingTempArray;
257 constexpr
static bool theAllHits =
true;
258 constexpr
static bool theNeedsNormal =
false;
259 constexpr
static bool theUseTolerance = USE_TOLERANCE;
269 template<u
int NAXES,
typename SUBCLASS>
270 template<
bool USE_TOLERANCE>
276 : myHitInfo(hit_info)
277 , myNestingTempArray(nesting_temp_array)
287 float &limit_t) noexcept
290 if (!myNestingTempArray || myNestingTempArray->isEmpty())
303 for (
exint i = 1; i <
n; ++i)
305 (*new_array)[i-1] = (*myNestingTempArray)[i];
307 (*new_array)[n-1] =
index;
309 hit_info.
myUVW = hit_uvw;
311 myHitInfo.append(hit_info);
316 return myNestingTempArray;
319 {
return hit_info.myNml; }
322 myHitInfo.last().myNml = nml;
326 hit_info.myNml = nml;
332 constexpr
static bool theAllHits =
true;
333 constexpr
static bool theNeedsNormal =
true;
334 constexpr
static bool theUseTolerance = USE_TOLERANCE;
344 template<u
int NAXES,
typename SUBCLASS>
345 template<
bool farthest,
bool rm_backface,
bool reverse,
typename HitInfoType>
349 HitInfoType &hit_info,
351 float outer_tmax)
const noexcept
354 sendRayGeneric<farthest,rm_backface,reverse>(origin,
direction, functor, outer_tmin, outer_tmax);
357 template<u
int NAXES,
typename SUBCLASS>
358 template<
bool farthest,
bool rm_backface,
bool reverse,
typename HitInfoType>
362 HitInfoType &hit_info,
363 float default_radius,
365 float outer_tmax)
const noexcept
367 if (!myHasCurvesOrPoints || !myRadii.isEmpty() || default_radius == 0)
370 sendRay<farthest,rm_backface,reverse>(origin,
direction, hit_info, outer_tmin, outer_tmax);
374 functor.myTolerance = default_radius;
375 sendRayGeneric<farthest,rm_backface,reverse>(origin,
direction, functor, outer_tmin, outer_tmax);
378 template<u
int NAXES,
typename SUBCLASS>
379 template<
bool rm_backface,
bool reverse,
bool sort,
typename HitInfoType>
385 float duplicate_tolerance,
387 float outer_tmax)
const noexcept
389 UT_ASSERT_MSG(
sort || duplicate_tolerance==0,
"Can't remove duplicates if we're not sorting!");
392 sendRayGeneric<false,rm_backface,reverse>(origin,
direction, functor, outer_tmin, outer_tmax);
394 if (!
sort || hit_info.size() <= 1)
407 if (duplicate_tolerance <= 0)
410 float prev_t = hit_info[0].myT;
412 for (
exint i = 1,
n = hit_info.size(); i <
n; ++i)
414 float t = hit_info[i].myT;
415 if (t-prev_t < duplicate_tolerance)
418 hit_info[desti] = hit_info[i];
421 hit_info.setSize(desti);
424 template<u
int NAXES,
typename SUBCLASS>
425 template<
bool rm_backface,
bool reverse,
bool sort,
typename HitInfoType>
430 float default_radius,
432 float duplicate_tolerance,
434 float outer_tmax)
const noexcept
436 if (!myHasCurvesOrPoints || !myRadii.isEmpty() || default_radius == 0)
439 sendRayAll<rm_backface,reverse,sort>(origin,
direction, hit_info, nesting_temp_array, duplicate_tolerance, outer_tmin, outer_tmax);
443 UT_ASSERT_MSG(
sort || duplicate_tolerance==0,
"Can't remove duplicates if we're not sorting!");
446 functor.myTolerance = default_radius;
447 sendRayGeneric<false,rm_backface,reverse>(origin,
direction, functor, outer_tmin, outer_tmax);
449 if (!
sort || hit_info.size() <= 1)
462 if (duplicate_tolerance <= 0)
465 float prev_t = hit_info[0].myT;
467 for (
exint i = 1,
n = hit_info.size(); i <
n; ++i)
469 float t = hit_info[i].myT;
470 if (t-prev_t < duplicate_tolerance)
473 hit_info[desti] = hit_info[i];
476 hit_info.setSize(desti);
479 template<u
int NAXES,
typename SUBCLASS>
480 template<
bool farthest,
bool rm_backface,
bool reverse,
typename FUNCTOR>
484 const NodeType *nodes = myTree.getNodes();
485 const uint nnodes = myTree.getNumNodes();
486 float length = direction.normalize();
489 if (nnodes == 0 || length == 0 || !
SYSisFinite(length) || !origin.isFinite())
495 const uint num_points = numPoints();
498 for (
int i = 0; i < NAXES; ++i)
499 sign[i] = (direction[i] < 0);
502 for (
int i = 0; i < NAXES; ++i)
526 #if GEO_BVH_INTERLEAVED
528 for (
uint axis = 0; axis < NAXES; ++axis)
530 vorigin[axis] =
v4uf(origin[axis]);
533 for (
uint axis = 0; axis < NAXES; ++axis)
535 vinverse_direction[axis] =
v4uf(inverse_direction[axis]);
538 if (hit_info.theUseTolerance)
539 vtolerance =
v4uf(hit_info.myTolerance);
541 const BoxType &box = myNodeBoxes[0];
542 box.
intersect(outer_tmin, outer_tmax, sign, origin, inverse_direction);
544 if (outer_tmin > outer_tmax)
556 #if GEO_BVH_INTERLEAVED
557 stack.
append(StackEntry(NodeType::markInternal(0),(!farthest) ? outer_tmin : outer_tmax));
559 stack.
append(StackEntry(0,outer_tmin));
564 StackEntry entry = stack.
last();
567 uint next_node = entry.myNode;
569 if ((!farthest) ? (entry.myTMin >= outer_tmax) : (entry.myTMin <= outer_tmin))
574 #if GEO_BVH_INTERLEAVED
575 if (NodeType::isInternal(next_node))
577 UT_ASSERT_MSG_P(next_node != NodeType::EMPTY,
"How did a ray hit an empty box?");
579 next_node = NodeType::getInternalNum(next_node);
580 const BoxType &box = myNodeBoxes[next_node];
581 v4uf tmin(outer_tmin);
v4uf tmax(outer_tmax);
582 if (!hit_info.theUseTolerance)
583 box.
intersect(tmin, tmax, sign, vorigin, vinverse_direction);
585 box.
intersectTol(tmin, tmax, sign, vorigin, vinverse_direction, vtolerance);
588 uint axis_sign = sign[0];
589 v4uf t1 = (box.
vals[0][axis_sign] - vorigin[0]) * vinverse_direction[0];
591 v4uf t2 = (box.
vals[0][axis_sign^1] - vorigin[0]) * vinverse_direction[0];
595 uint axis_sign = sign[1];
596 v4uf t1 = (box.
vals[1][axis_sign] - vorigin[1]) * vinverse_direction[1];
598 v4uf t2 = (box.
vals[1][axis_sign^1] - vorigin[1]) * vinverse_direction[1];
602 uint axis_sign = sign[2];
603 v4uf t1 = (box.
vals[2][axis_sign] - vorigin[2]) * vinverse_direction[2];
605 v4uf t2 = (box.
vals[2][axis_sign^1] - vorigin[2]) * vinverse_direction[2];
610 v4uu hit_mask = (tmin <= tmax);
614 const NodeType &node = nodes[next_node];
615 if (!(hit_bits & (hit_bits-1)))
618 uint local_index = SYSfirstBitSet(hit_bits);
620 next_node = node.child[local_index];
622 float local_tmin = tmins[local_index];
623 uint child_index = node.child[local_index];
624 if (!stack_size || ((!farthest) ? (stack_last->myTMin >= local_tmin) : (stack_last->myTMin <= local_tmin)))
625 next_node = child_index;
628 next_node = stack_last->myNode;
629 stack_last->myNode = child_index;
630 stack_last->myTMin = local_tmin;
637 StackEntry *stack_last = stack.
data()+stack_size-1;
647 while (stack_size != 0 && ((!farthest) ? (stack_last->myTMin >= outer_tmax) : (stack_last->myTMin <= outer_tmin)))
653 static constexpr
uint two_bit_indices[16][2] = {
654 {4, 4}, {4, 4}, {4, 4}, {0, 1},
655 {4, 4}, {0, 2}, {1, 2}, {0, 1},
656 {4, 4}, {0, 3}, {1, 3}, {0, 1},
657 {2, 3}, {0, 2}, {1, 2}, {0, 1}
659 static constexpr
uint third_bit_index[16] = {
666 union {
v4sf tminv;
float tmins[4]; };
668 uint local_index0 = two_bit_indices[hit_bits][0];
669 uint local_index1 = two_bit_indices[hit_bits][1];
670 if (third_bit_index[hit_bits] == 4)
673 float t0 = tmins[local_index0];
674 float t1 = tmins[local_index1];
675 uint child0 = node.child[local_index0];
676 uint child1 = node.child[local_index1];
677 if ((!farthest) ? (t0 > t1) : (t0 < t1))
679 uint childtmp = child0;
688 if (!stack_size || ((!farthest) ? (stack_last->myTMin >= t0) : (stack_last->myTMin <= t0)))
694 if (!stack_size || ((!farthest) ? (stack_last->myTMin >= t1) : (stack_last->myTMin <= t1)))
696 stack.
append(StackEntry(child1, t1));
704 for (i = stack_size-2; i >= limiti; --i)
706 if ((!farthest) ? (stack[i].myTMin >= t1) : (stack[i].myTMin <= t1))
708 stack.
insert(StackEntry(child1, t1), i+1);
714 stack.
insert(StackEntry(child1, t1), i+1);
720 next_node = stack_last->myNode;
721 stack_last->myNode = child1;
722 stack_last->myTMin = t1;
723 stack.
append(StackEntry(child0, t0));
729 uint nhit = (hit_bits == 0xF) ? 4 : 3;
730 uint local_index2 = third_bit_index[hit_bits];
731 uint children[BVH_N] = {
732 node.child[local_index0],
733 node.child[local_index1],
734 node.child[local_index2],
737 tmins[0] = tmins[local_index0];
738 tmins[1] = tmins[local_index1];
739 tmins[2] = tmins[local_index2];
743 if (!stack_size || ((!farthest) ? (stack_last->myTMin >= tmins[0]) : (stack_last->myTMin <= tmins[0])))
746 next_node = children[0];
750 new_tmin = stack_last->myTMin;
751 next_node = stack_last->myNode;
752 stack_last->myTMin = tmins[0];
753 stack_last->myNode = children[0];
755 for (
uint hit = 1; hit < nhit; ++hit)
757 float t = tmins[hit];
758 uint child = children[hit];
761 float tmpt = new_tmin;
762 uint tmpchild = next_node;
770 if (!stack_size || ((!farthest) ? (stack_last->myTMin >=
t) : (stack_last->myTMin <= t)))
772 stack.
append(StackEntry(child, t));
780 for (i = stack_size-2; i >= limiti; --i)
782 if ((!farthest) ? (stack[i].myTMin >= t) : (stack[i].myTMin <= t))
784 stack.
insert(StackEntry(child, t), i+1);
790 stack.
insert(StackEntry(child, t), i+1);
793 stack_last = stack.
data()+stack_size;
800 const NodeType &node = nodes[next_node];
801 uint children[BVH_N];
804 for (
uint i = 0; i < BVH_N; ++i)
806 const uint itemi = node.child[i];
807 if (NodeType::isInternal(itemi))
809 if (itemi == NodeType::EMPTY)
813 const uint childi = NodeType::getInternalNum(itemi);
814 const BoxType &box = myNodeBoxes[childi];
815 float tmin = outer_tmin;
float tmax = outer_tmax;
816 box.
intersect(tmin, tmax, sign, origin, inverse_direction);
821 children[nnodehits] = childi;
822 tmins[nnodehits] = tmin;
830 if (!SUBCLASS::theHasPrimitives || index < num_points)
834 if (!myRadii.isEmpty() || myRadAttrib.isValid() || hit_info.theUseTolerance)
838 exint ptarrayindex = (SUBCLASS::theReordersPositions) ?
exint(index) :
exint(myPoints(index));
839 const bool use_pos_array = !myPositions.isEmpty();
840 const VectorType pos = use_pos_array ? myPositions[ptarrayindex] : myPosAttrib.get(
GA_Offset(ptarrayindex));
842 if (hit_info.theUseTolerance)
843 radius = hit_info.myTolerance;
844 else if (myRadii.isEmpty())
845 radius = myRadAttrib.get(
GA_Offset(ptarrayindex));
847 radius = ((myRadii.size() == 1) ? myRadii[0] : myRadii[ptarrayindex]);
849 if (hit_info.theUseTolerance || radius != 0)
853 bool ishit = geoIntersectSphere(rel_origin, direction, radius, t0, t1);
855 #if GEO_BVH_INTERLEAVED
861 const float invradius = 1.0f/radius;
862 if ((t0 <= outer_tmax) && (t0 >= outer_tmin))
867 if (!rm_backface || (
dot(p,direction) <= 0) !=
reverse)
870 UT_Vector3(p[0], p[1], (NAXES==3) ? p[2] : 0),
872 (!farthest) ? outer_tmax : outer_tmin);
873 if (hit_info.theNeedsNormal)
874 hit_info.setNormal(p);
878 if ((t1 <= outer_tmax) && (t1 >= outer_tmin))
883 if (!rm_backface || (
dot(p,direction) <= 0) !=
reverse)
886 UT_Vector3(p[0], p[1], (NAXES==3) ? p[2] : 0),
888 (!farthest) ? outer_tmax : outer_tmin);
889 if (hit_info.theNeedsNormal)
890 hit_info.setNormal(p);
898 #if !GEO_BVH_INTERLEAVED
901 subclass()->template intersectPrim<farthest,rm_backface,reverse>(
902 index, origin,
direction, inverse_direction, max_dir, N0, N1,
903 outer_tmax, outer_tmin, hit_info);
904 #if !GEO_BVH_INTERLEAVED
909 #if GEO_BVH_INTERLEAVED
912 #if !GEO_BVH_INTERLEAVED
918 StackEntry *stack_last = stack.
data()+stack_size-1;
921 uint child_index = children[0];
922 if (!stack_size || stack_last->myTMin >= tmins[0])
923 next_node = child_index;
926 next_node = stack_last->myNode;
927 stack_last->myNode = child_index;
928 stack_last->myTMin = tmins[0];
931 else if (BVH_N == 2 || nnodehits == 2)
933 const uint local_index = (tmins[0] >= tmins[1]);
934 next_node = children[local_index];
935 const uint insert_node = children[!local_index];
936 const float insert_tmin = tmins[!local_index];
938 if (!stack_size || stack_last->myTMin <= insert_tmin)
940 stack.
append(StackEntry(insert_node, insert_tmin));
948 for (i = stack_size-2; i >= limiti; --i)
950 if (stack[i].myTMin <= insert_tmin)
952 stack.
insert(StackEntry(insert_node, insert_tmin), i+1);
958 stack.
insert(StackEntry(insert_node, insert_tmin), i+1);
975 hit_info.myItemIndex = hit_index;
976 hit_info.myUVW = hit_uvw;
977 hit_info.myT = (!farthest) ? outer_tmax : outer_tmin;
981 hit_info.myItemIndex = -1;
982 hit_info.myUVW.assign(0,0,0);
983 hit_info.myT = -1.0f;
988 template<u
int NAXES,
typename SUBCLASS>
989 template<
bool farthest,
typename QUERY_POINT>
991 const QUERY_POINT &query_point,
995 float max_dist_squared)
const noexcept
997 const v4uu* node_nitems_v = (
const v4uu*)myNodeNItems.get();
999 const bool use_pos_array = !myPositions.isEmpty();
1002 if (myRadii.size() == 0)
1004 if (myRadAttrib.isValid())
1006 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1007 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1008 myRadAttrib, max_points, max_dist_squared);
1012 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1013 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1017 else if (myRadii.size() == 1)
1019 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1020 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1025 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1026 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1027 myRadii, max_points, max_dist_squared);
1032 if (myRadii.size() == 0)
1034 if (myRadAttrib.isValid())
1036 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1037 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1038 myRadAttrib, max_points, max_dist_squared);
1042 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1043 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1047 else if (myRadii.size() == 1)
1049 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1050 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1055 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1056 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1057 myRadii, max_points, max_dist_squared);
1062 template<u
int NAXES,
typename SUBCLASS>
1065 const exint max_points,
const float max_dist_squared,
1073 findMaximalPointsCommon<false>(
1081 template<u
int NAXES,
typename SUBCLASS>
1084 const exint max_points,
const float max_dist_squared,
1092 findMaximalPointsCommon<false>(
1100 template<u
int NAXES,
typename SUBCLASS>
1108 const v4uu* node_nitems_v = (
const v4uu*)myNodeNItems.get();
1109 const bool use_pos_array = !myPositions.isEmpty();
1111 if (myRadii.size() == 0 && !myRadAttrib.isValid())
1118 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1119 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1120 radii, max_points, max_dist_squared);
1126 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1127 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1128 radii, max_points, max_dist_squared);
1131 else if (myRadii.size() == 1)
1138 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1139 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1140 radii, max_points, max_dist_squared);
1146 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1147 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1148 radii, max_points, max_dist_squared);
1151 else if (myRadii.size() > 1)
1157 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1158 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1159 myRadii, max_points, max_dist_squared);
1165 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1166 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1167 myRadii, max_points, max_dist_squared);
1176 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1177 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1178 myRadAttrib, max_points, max_dist_squared);
1184 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1185 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1186 myRadAttrib, max_points, max_dist_squared);
1191 template<u
int NAXES,
typename SUBCLASS>
1192 template<
bool farthest>
1196 const NodeType *nodes = myTree.getNodes();
1197 const uint nnodes = myTree.getNumNodes();
1199 if (nnodes == 0 || !origin.isFinite())
1202 hit_info.myItemIndex = -1;
1203 hit_info.myUVW.assign(0,0,0);
1204 hit_info.myDistSquared = -1.0f;
1210 exint nesting_array_base = nesting_array ? nesting_array->
size() : 0;
1212 const uint num_points = numPoints();
1217 float myDistSquared;
1226 #if GEO_BVH_INTERLEAVED
1228 for (
uint axis = 0; axis < NAXES; ++axis)
1230 vorigin[axis] =
v4uf(origin[axis]);
1233 const BoxType &box = myNodeBoxes[0];
1237 if ((!farthest) ? (dist2 > max_dist_squared) : (dist2 < max_dist_squared))
1240 hit_info.myItemIndex = -1;
1241 hit_info.myUVW.assign(0,0,0);
1242 hit_info.myDistSquared = -1.0f;
1249 exint hit_index = -1;
1256 #if GEO_BVH_INTERLEAVED
1259 stack.
append(StackEntry(0,dist2));
1264 StackEntry entry = stack.
last();
1267 uint next_node = entry.myNode;
1269 if ((!farthest) ? (entry.myDistSquared > max_dist_squared) : (entry.myDistSquared < max_dist_squared))
1274 #if GEO_BVH_INTERLEAVED
1275 if (NodeType::isInternal(next_node))
1277 if (next_node == NodeType::EMPTY)
1280 next_node = NodeType::getInternalNum(next_node);
1281 const BoxType &box = myNodeBoxes[next_node];
1283 v4uu hit_mask = (!farthest) ? (dist2 <= max_dist_squared) : (dist2 >= max_dist_squared);
1287 const NodeType &node = nodes[next_node];
1288 if (!(hit_bits & (hit_bits-1)))
1291 uint local_index = SYSfirstBitSet(hit_bits);
1293 next_node = node.child[local_index];
1295 float local_d2 = d2s[local_index];
1296 uint child_index = node.child[local_index];
1297 if (!stack_size || ((!farthest) ? (stack_last->myDistSquared >= local_d2) : (stack_last->myDistSquared <= local_d2)))
1298 next_node = child_index;
1301 next_node = stack_last->myNode;
1302 stack_last->myNode = child_index;
1303 stack_last->myDistSquared = local_d2;
1310 StackEntry *stack_last = stack.
data()+stack_size-1;
1320 while (stack_size != 0 && ((!farthest) ? (stack_last->myDistSquared > max_dist_squared) : (stack_last->myDistSquared < max_dist_squared)))
1326 static constexpr
uint two_bit_indices[16][2] = {
1327 {4, 4}, {4, 4}, {4, 4}, {0, 1},
1328 {4, 4}, {0, 2}, {1, 2}, {0, 1},
1329 {4, 4}, {0, 3}, {1, 3}, {0, 1},
1330 {2, 3}, {0, 2}, {1, 2}, {0, 1}
1332 static constexpr
uint third_bit_index[16] = {
1339 union {
v4sf d2v;
float d2s[4]; };
1341 uint local_index0 = two_bit_indices[hit_bits][0];
1342 uint local_index1 = two_bit_indices[hit_bits][1];
1343 if (third_bit_index[hit_bits] == 4)
1346 float d20 = d2s[local_index0];
1347 float d21 = d2s[local_index1];
1348 uint child0 = node.child[local_index0];
1349 uint child1 = node.child[local_index1];
1350 if ((!farthest) ? (d20 > d21) : (d20 < d21))
1352 uint childtmp = child0;
1360 if (!stack_size || ((!farthest) ? (stack_last->myDistSquared >= d20) : (stack_last->myDistSquared <= d20)))
1366 if (!stack_size || ((!farthest) ? (stack_last->myDistSquared >= d21) : (stack_last->myDistSquared <= d21)))
1368 stack.
append(StackEntry(child1, d21));
1376 for (i = stack_size-2; i >= limiti; --i)
1378 if ((!farthest) ? (stack[i].myDistSquared >= d21) : (stack[i].myDistSquared <= d21))
1380 stack.
insert(StackEntry(child1, d21), i+1);
1386 stack.
insert(StackEntry(child1, d21), i+1);
1392 next_node = stack_last->myNode;
1393 stack_last->myNode = child1;
1394 stack_last->myDistSquared = d21;
1395 stack.
append(StackEntry(child0, d20));
1401 uint nhit = (hit_bits == 0xF) ? 4 : 3;
1402 uint local_index2 = third_bit_index[hit_bits];
1403 uint children[BVH_N] = {
1404 node.child[local_index0],
1405 node.child[local_index1],
1406 node.child[local_index2],
1409 d2s[0] = d2s[local_index0];
1410 d2s[1] = d2s[local_index1];
1411 d2s[2] = d2s[local_index2];
1415 if (!stack_size || ((!farthest) ? (stack_last->myDistSquared >= d2s[0]) : (stack_last->myDistSquared <= d2s[0])))
1418 next_node = children[0];
1422 new_d2 = stack_last->myDistSquared;
1423 next_node = stack_last->myNode;
1424 stack_last->myDistSquared = d2s[0];
1425 stack_last->myNode = children[0];
1427 for (
uint hit = 1; hit < nhit; ++hit)
1429 float d2 = d2s[hit];
1430 uint child = children[hit];
1431 if ((!farthest) ? (d2 < new_d2) : (d2 > new_d2))
1433 float tmpd2 = new_d2;
1434 uint tmpchild = next_node;
1442 if (!stack_size || ((!farthest) ? (stack_last->myDistSquared >= d2) : (stack_last->myDistSquared <= d2)))
1444 stack.
append(StackEntry(child, d2));
1452 for (i = stack_size-2; i >= limiti; --i)
1454 if ((!farthest) ? (stack[i].myDistSquared >= d2) : (stack[i].myDistSquared <= d2))
1456 stack.
insert(StackEntry(child, d2), i+1);
1462 stack.
insert(StackEntry(child, d2), i+1);
1465 stack_last = stack.
data()+stack_size;
1472 const NodeType &node = nodes[next_node];
1473 uint children[BVH_N];
1476 for (
uint i = 0; i < BVH_N; ++i)
1478 const uint itemi = node.child[i];
1479 if (NodeType::isInternal(itemi))
1481 if (itemi == NodeType::EMPTY)
1485 const uint childi = NodeType::getInternalNum(itemi);
1486 const BoxType &box = myNodeBoxes[childi];
1488 if ((!farthest) ? (dist2 > min_dist_squared) : (dist2 < min_dist_squared))
1491 children[nnodehits] = childi;
1492 d2s[nnodehits] = dist2;
1500 if (!SUBCLASS::theHasPrimitives || index < num_points)
1505 exint ptarrayindex = (SUBCLASS::theReordersPositions) ?
exint(index) :
exint(myPoints(index));
1506 const bool use_pos_array = !myPositions.isEmpty();
1507 const VectorType pos = use_pos_array ? myPositions[ptarrayindex] : myPosAttrib.get(
GA_Offset(ptarrayindex));
1510 if (myRadii.isEmpty())
1511 radius = myRadAttrib.isValid() ? myRadAttrib.get(
GA_Offset(ptarrayindex)) : 0.0f;
1513 radius = ((myRadii.size() == 1) ? myRadii[0] : myRadii[ptarrayindex]);
1515 float d2 = displacement.length2();
1520 if ((!farthest) ? (d2 < max_dist_squared) : (d2 > max_dist_squared))
1522 max_dist_squared = d2;
1532 if ((!farthest) ? (d2 < max_dist_squared) : (d2 > max_dist_squared))
1534 max_dist_squared = d2;
1539 VectorType real_normal = (((radius > 0) != farthest) ? normal : -normal);
1540 hit_uvw[0] = real_normal[0];
1541 hit_uvw[1] = real_normal[1];
1542 hit_uvw[2] = (NAXES==3) ? real_normal[2] : 0;
1547 hit_position -= radius*normal;
1549 hit_position += radius*normal;
1555 subclass()->template closestPrim<farthest>(
1556 index, origin, max_dist_squared,
1557 hit_index, hit_uvw, hit_position,
1558 vorigin, nesting_array, nesting_array_base);
1560 #if GEO_BVH_INTERLEAVED
1568 StackEntry *stack_last = stack.
data()+stack_size-1;
1571 uint child_index = children[0];
1572 if (!stack_size || stack_last->myTMin >= tmins[0])
1573 next_node = child_index;
1576 next_node = stack_last->myNode;
1577 stack_last->myNode = child_index;
1578 stack_last->myTMin = tmins[0];
1581 else if (BVH_N == 2 || nnodehits == 2)
1583 const uint local_index = (tmins[0] >= tmins[1]);
1584 next_node = children[local_index];
1585 const uint insert_node = children[!local_index];
1586 const float insert_tmin = tmins[!local_index];
1588 if (!stack_size || stack_last->myTMin <= insert_tmin)
1590 stack.
append(StackEntry(insert_node, insert_tmin));
1598 for (i = stack_size-2; i >= limiti; --i)
1600 if (stack[i].myTMin <= insert_tmin)
1602 stack.
insert(StackEntry(insert_node, insert_tmin), i+1);
1608 stack.
insert(StackEntry(insert_node, insert_tmin), i+1);
1624 hit_info.myItemIndex = hit_index;
1625 hit_info.myUVW = hit_uvw;
1627 hit_info.myDistSquared = max_dist_squared;
1628 hit_info.myP = hit_position;
1632 hit_info.myItemIndex = -1;
1633 hit_info.myUVW.
assign(0,0,0);
1634 hit_info.myDistSquared = -1.0f;
1639 template<u
int NAXES,
typename SUBCLASS>
1646 template<u
int NAXES,
typename SUBCLASS>
1647 template<
bool normalize>
1650 if (!SUBCLASS::theHasPrimitives || hit_info.myItemIndex < numPoints())
1656 return subclass()->template primGeometricNormal<normalize>(hit_info);
1659 template<u
int NAXES,
typename SUBCLASS>
1662 if (!SUBCLASS::theHasPrimitives || hit_info.myItemIndex < numPoints())
1668 nml[0] = hit_info.myUVW[0];
1669 nml[1] = hit_info.myUVW[1];
1672 nml[2] = hit_info.myUVW[1];
1676 dP_dv[0] = -nml[2]*nmlxy[0];
1677 dP_dv[1] = -nml[2]*nmlxy[1];
1678 dP_dv[2] = lengthxy;
1681 dP_du[0] = -nml[1]*(2*
M_PI);
1682 dP_du[1] = nml[0]*(2*
M_PI);
1689 dP_du[0] = -nml[1]*(2*
M_PI);
1690 dP_du[1] = nml[0]*(2*
M_PI);
1696 subclass()->primDerivs(hit_info, dP_du, dP_dv);
1699 template<u
int NAXES,
typename SUBCLASS>
1702 float u = SYSatan(uvw[1], uvw[0]) / (
float)(2*
M_PI);
1720 template<u
int NAXES,
typename SUBCLASS>
1721 template<GA_AttributeOwner owner,
typename T,
typename DEST_T>
1733 if (!SUBCLASS::theHasPrimitives || index < numPoints())
1739 value = attrib.get(ptoff);
1742 return subclass()->template primAttribute<owner,T,DEST_T>(hit_info, attrib, detail,
value);
1747 #undef GEO_BVH_INTERLEAVED
SYS_FORCE_INLINE void setNestingArrayInto(HitInfo &hit_info) noexcept
SYS_FORCE_INLINE void insertHit(const UT_Vector3 &hit_uvw, const float t, const uint index, float &limit_t) noexcept
SYS_FORCE_INLINE UT_Vector3 & lastUVW() noexcept
#define SYS_STATIC_ASSERT(expr)
SYS_FORCE_INLINE void insertHit(const UT_Vector3 &hit_uvw, const float t, const uint index, float &limit_t) noexcept
void sendRay(const VectorType &origin, const VectorType &direction, HitInfoType &hit_info, float tmin=0, float tmax=std::numeric_limits< float >::max()) const noexcept
SYS_FORCE_INLINE UT_Array< exint > * nestingArray() noexcept
SYS_FORCE_INLINE UT_Array< HitInfo > * getHitArray() noexcept
SIM_API const UT_StringHolder angle
#define SYS_STATIC_ASSERT_MSG(expr, msg)
void getDerivs(const CommonHitInfo &hit_info, VectorType &dP_du, VectorType &dP_dv) const noexcept
Fills in the values of dP/du and dP/dv for the hit surface.
void findClosest(VectorType origin, MinInfo &min_info, float max_dist_squared=std::numeric_limits< float >::max()) const noexcept
SYS_FORCE_INLINE void removeLast()
VectorType getGeometricNormal(const CommonHitInfo &hit_info) const noexcept
SYS_FORCE_INLINE exint nestingArrayBase() noexcept
IMF_EXPORT IMATH_NAMESPACE::V3f direction(const IMATH_NAMESPACE::Box2i &dataWindow, const IMATH_NAMESPACE::V2f &pixelPosition)
SYS_FORCE_INLINE UT_Array< HitInfoAndNormal > * getHitArray() noexcept
SYS_FORCE_INLINE void noHit() noexcept
SYS_FORCE_INLINE void setNestingArrayInto(HitInfoAndNormal &hit_info) noexcept
GLsizei const GLfloat * value
bool SYSisFinite(fpreal64 f)
void setSizeNoInit(exint newsize)
UT_Array< exint > *const myNestingTempArray
SYS_FORCE_INLINE VectorType getNormal(const HitInfoAndNormal &hit_info) const noexcept
UT_Vector3T< float > UT_Vector3
SYS_FORCE_INLINE exint nestingArrayBase() const noexcept
SYS_FORCE_INLINE void setNormal(const VectorType &nml) noexcept
GLboolean GLboolean GLboolean GLboolean a
void reverse(I begin, I end)
GLuint GLsizei GLsizei * length
SYS_FORCE_INLINE void setNormal(const VectorType &nml) noexcept
void findClosestInCone(VectorType origin, VectorType direction, const float angle, const exint max_points, const float max_dist_squared, UT::BVHOrderedStack &output_queue) const noexcept
#define UT_ASSERT_MSG_P(ZZ,...)
void findClosestToSegment(VectorType p0, VectorType p1, const exint max_points, const float max_dist_squared, UT::BVHOrderedStack &output_queue) const noexcept
Finds the closest points to the line segment with endpoints p0 and p1.
SYS_FORCE_INLINE const VectorType & getNormal(const HitInfoAndNormal &hit_info) const noexcept
SYS_FORCE_INLINE void setNormal(const VectorType &nml) noexcept
SYS_FORCE_INLINE UT_Array< exint > * nestingArray() noexcept
SYS_FORCE_INLINE void setNormal(HitInfoAndNormal &hit_info, const VectorType &nml) const noexcept
UT_Array< HitInfoAndNormal > & myHitInfo
GEO::BVHBase< NAXES, SUBCLASS > BVHBase
SYS_FORCE_INLINE T minDistance2(const UT_FixedVector< T, NAXES > &p) const noexcept
#define UT_ASSERT_MSG(ZZ,...)
SYS_FORCE_INLINE AllHitsAndNormalsFunctor(UT_Array< HitInfoAndNormal > &hit_info, UT_Array< exint > *nesting_temp_array) noexcept
SYS_FORCE_INLINE void setNormal(HitInfo &hit_info, const VectorType &nml) const noexcept
bool getAttribute(const CommonHitInfo &hit_info, const GA_ROHandleT< T > &attrib, const GEO_Detail &detail, DEST_T &value) const noexcept
void findClosestToLine(VectorType origin, VectorType direction, const exint max_points, const float max_dist_squared, UT::BVHOrderedStack &output_queue) const noexcept
Finds the closest points to the infinite line containing origin with direction direction.
SYS_FORCE_INLINE UT_Array< HitInfo > * getHitArray() noexcept
IMATH_NAMESPACE::V2f float
SYS_FORCE_INLINE UT_Array< exint > * nestingArray() noexcept
SYS_FORCE_INLINE UT_Array< HitInfoAndNormal > * getHitArray() noexcept
SYS_FORCE_INLINE UT_Vector3 & lastUVW() noexcept
SYS_FORCE_INLINE VectorType getNormal(const HitInfo &hit_info) const noexcept
void getIntersectingBoxes(const SingleBoxType &query_box, UT_Array< exint > &box_indices) const noexcept
SYS_FORCE_INLINE T maxDistance2(const UT_FixedVector< T, NAXES > &p) const noexcept
fpreal64 dot(const CE_VectorT< T > &a, const CE_VectorT< T > &b)
SYS_FORCE_INLINE void noHit() noexcept
typename SYS_SelectType< UT_FixedVector< uint, 2 >, UT_FixedVector< uint, 3 >, NAXES==3 >::type UintVectorType
static void pointUVWToPolar(VectorType &uvw) noexcept
HitInfoAndNormal & myHitInfo
SYS_FORCE_INLINE void insertHit(const UT_Vector3 &hit_uvw, const float t, const uint index, float &limit_t) noexcept
void sendRayAllRad(const VectorType &origin, const VectorType &direction, UT_Array< HitInfoType > &hit_info, float default_radius, UT_Array< exint > *nesting_temp_array=nullptr, float duplicate_tolerance=0, float tmin=0, float tmax=std::numeric_limits< float >::max()) const noexcept
SYS_FORCE_INLINE exint nestingArrayBase() const noexcept
IMATH_HOSTDEVICE constexpr int sign(T a) IMATH_NOEXCEPT
SYS_FORCE_INLINE exint nestingArrayBase() const noexcept
GLboolean GLboolean GLboolean b
SYS_FORCE_INLINE void setNestingArrayInto(HitInfoAndNormal &hit_info) noexcept
SYS_FORCE_INLINE VectorType getNormal(const HitInfo &hit_info) const noexcept
void sendRayGeneric(VectorType origin, VectorType direction, FUNCTOR &hit_info, float tmin=0, float tmax=std::numeric_limits< float >::max()) const noexcept
SYS_FORCE_INLINE void setNormal(HitInfoAndNormal &hit_info, const VectorType &nml) const noexcept
void assign(T xx=0.0f, T yy=0.0f, T zz=0.0f)
Set the values of the vector components.
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.
SYS_FORCE_INLINE void setNormal(HitInfo &hit_info, const VectorType &nml) const noexcept
typename SYS_SelectType< UT_Vector2, UT_Vector3, NAXES==3 >::type VectorType
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
SYS_FORCE_INLINE UT_Array< exint > * nestingArray() 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
void findMaximalPointsCommon(const QUERY_POINT &query_point, UT::BVHOrderedStack &stack, UT::BVHOrderedStack &output_queue, exint max_points, float max_dist_squared) const noexcept
SYS_FORCE_INLINE AllHitsFunctor(UT_Array< HitInfo > &hit_info, UT_Array< exint > *nesting_temp_array) 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
SYS_FORCE_INLINE SingleHitFunctor(HitInfo &hit_info) noexcept
SIM_API const UT_StringHolder distance
void sendRayAll(const VectorType &origin, const VectorType &direction, UT_Array< HitInfoType > &hit_info, UT_Array< exint > *nesting_temp_array=nullptr, float duplicate_tolerance=0, float tmin=0, float tmax=std::numeric_limits< float >::max()) const noexcept
SYS_FORCE_INLINE SingleHitAndNormalFunctor(HitInfoAndNormal &hit_info) noexcept
SYS_FORCE_INLINE UT_Vector3 & lastUVW() noexcept
SYS_FORCE_INLINE UT_StorageMathFloat_t< T > normalize() noexcept
void sort(I begin, I end, const Pred &pred)
SYS_FORCE_INLINE void insertHit(const UT_Vector3 &hit_uvw, const float t, const uint index, float &limit_t) noexcept
void sendRayRad(const VectorType &origin, const VectorType &direction, HitInfoType &hit_info, float default_radius, float tmin=0, float tmax=std::numeric_limits< float >::max()) const noexcept
SYS_FORCE_INLINE exint nestingArrayBase() const noexcept
UT_Array< exint > * myNestedItemIndices
This can be used for packed primitive hits.
SYS_FORCE_INLINE void noHit() noexcept
exint insert(exint index)
SYS_FORCE_INLINE void noHit() noexcept
UT_Array< HitInfo > & myHitInfo
SYS_FORCE_INLINE void setNormal(const VectorType &nml) noexcept
SYS_FORCE_INLINE UT_Vector3 & lastUVW() noexcept
SYS_FORCE_INLINE void setNestingArrayInto(HitInfo &hit_info) noexcept
UT_Array< exint > *const myNestingTempArray
bool isEmpty() const
Returns true iff there are no occupied elements in the array.