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;
98 bool should_clear_nesting =
true) noexcept
100 myHitInfo.myItemIndex = index;
101 myHitInfo.myUVW = hit_uvw;
103 if (should_clear_nesting && myHitInfo.myNestedItemIndices)
104 myHitInfo.myNestedItemIndices->setSize(myNestingArrayBase);
110 hit_info.myNestedItemIndices = myHitInfo.myNestedItemIndices;
114 return myHitInfo.myNestedItemIndices;
118 return myNestingArrayBase;
128 constexpr
static bool theAllHits =
false;
129 constexpr
static bool theNeedsNormal =
false;
130 constexpr
static bool theUseTolerance = USE_TOLERANCE;
139 template<u
int NAXES,
typename SUBCLASS>
140 template<
bool USE_TOLERANCE>
145 : myHitInfo(hit_info)
146 , myNestingArrayBase(hit_info.myNestedItemIndices ? hit_info.myNestedItemIndices->size() : 0)
150 myHitInfo.myItemIndex = -1;
151 myHitInfo.myUVW.assign(0,0,0);
152 myHitInfo.myT = -1.0f;
159 bool should_clear_nesting =
true) noexcept
161 myHitInfo.myItemIndex = index;
162 myHitInfo.myUVW = hit_uvw;
164 if (should_clear_nesting && myHitInfo.myNestedItemIndices)
165 myHitInfo.myNestedItemIndices->setSize(myNestingArrayBase);
171 hit_info.myNestedItemIndices = myHitInfo.myNestedItemIndices;
175 return myHitInfo.myNestedItemIndices;
178 {
return hit_info.myNml; }
181 myHitInfo.myNml = nml;
185 hit_info.myNml = nml;
191 constexpr
static bool theAllHits =
false;
192 constexpr
static bool theNeedsNormal =
true;
193 constexpr
static bool theUseTolerance = USE_TOLERANCE;
202 template<u
int NAXES,
typename SUBCLASS>
203 template<
bool USE_TOLERANCE>
209 : myHitInfo(hit_info)
210 , myNestingTempArray(nesting_temp_array)
220 float &limit_t) noexcept
223 if (!myNestingTempArray || myNestingTempArray->isEmpty())
236 for (
exint i = 1; i <
n; ++i)
238 (*new_array)[i-1] = (*myNestingTempArray)[i];
240 (*new_array)[n-1] =
index;
242 hit_info.
myUVW = hit_uvw;
244 myHitInfo.append(hit_info);
249 return myNestingTempArray;
259 constexpr
static bool theAllHits =
true;
260 constexpr
static bool theNeedsNormal =
false;
261 constexpr
static bool theUseTolerance = USE_TOLERANCE;
271 template<u
int NAXES,
typename SUBCLASS>
272 template<
bool USE_TOLERANCE>
278 : myHitInfo(hit_info)
279 , myNestingTempArray(nesting_temp_array)
289 float &limit_t) noexcept
292 if (!myNestingTempArray || myNestingTempArray->isEmpty())
305 for (
exint i = 1; i <
n; ++i)
307 (*new_array)[i-1] = (*myNestingTempArray)[i];
309 (*new_array)[n-1] =
index;
311 hit_info.
myUVW = hit_uvw;
313 myHitInfo.append(hit_info);
318 return myNestingTempArray;
321 {
return hit_info.myNml; }
324 myHitInfo.last().myNml = nml;
328 hit_info.myNml = nml;
334 constexpr
static bool theAllHits =
true;
335 constexpr
static bool theNeedsNormal =
true;
336 constexpr
static bool theUseTolerance = USE_TOLERANCE;
346 template<u
int NAXES,
typename SUBCLASS>
347 template<
bool farthest,
bool rm_backface,
bool reverse,
typename HitInfoType>
351 HitInfoType &hit_info,
353 float outer_tmax)
const noexcept
356 sendRayGeneric<farthest,rm_backface,reverse>(origin,
direction, functor, outer_tmin, outer_tmax);
359 template<u
int NAXES,
typename SUBCLASS>
360 template<
bool farthest,
bool rm_backface,
bool reverse,
typename HitInfoType>
364 HitInfoType &hit_info,
365 float default_radius,
367 float outer_tmax)
const noexcept
369 if (!myHasCurvesOrPoints || !myRadii.isEmpty() || default_radius == 0)
372 sendRay<farthest,rm_backface,reverse>(origin,
direction, hit_info, outer_tmin, outer_tmax);
376 functor.myTolerance = default_radius;
377 sendRayGeneric<farthest,rm_backface,reverse>(origin,
direction, functor, outer_tmin, outer_tmax);
380 template<u
int NAXES,
typename SUBCLASS>
381 template<
bool rm_backface,
bool reverse,
bool sort,
typename HitInfoType>
387 float duplicate_tolerance,
389 float outer_tmax)
const noexcept
391 UT_ASSERT_MSG(
sort || duplicate_tolerance==0,
"Can't remove duplicates if we're not sorting!");
394 sendRayGeneric<false,rm_backface,reverse>(origin,
direction, functor, outer_tmin, outer_tmax);
396 if (!
sort || hit_info.size() <= 1)
409 if (duplicate_tolerance <= 0)
412 float prev_t = hit_info[0].myT;
414 for (
exint i = 1,
n = hit_info.size(); i <
n; ++i)
416 float t = hit_info[i].myT;
417 if (t-prev_t < duplicate_tolerance)
420 hit_info[desti] = hit_info[i];
423 hit_info.setSize(desti);
426 template<u
int NAXES,
typename SUBCLASS>
427 template<
bool rm_backface,
bool reverse,
bool sort,
typename HitInfoType>
432 float default_radius,
434 float duplicate_tolerance,
436 float outer_tmax)
const noexcept
438 if (!myHasCurvesOrPoints || !myRadii.isEmpty() || default_radius == 0)
441 sendRayAll<rm_backface,reverse,sort>(origin,
direction, hit_info, nesting_temp_array, duplicate_tolerance, outer_tmin, outer_tmax);
445 UT_ASSERT_MSG(
sort || duplicate_tolerance==0,
"Can't remove duplicates if we're not sorting!");
448 functor.myTolerance = default_radius;
449 sendRayGeneric<false,rm_backface,reverse>(origin,
direction, functor, outer_tmin, outer_tmax);
451 if (!
sort || hit_info.size() <= 1)
464 if (duplicate_tolerance <= 0)
467 float prev_t = hit_info[0].myT;
469 for (
exint i = 1,
n = hit_info.size(); i <
n; ++i)
471 float t = hit_info[i].myT;
472 if (t-prev_t < duplicate_tolerance)
475 hit_info[desti] = hit_info[i];
478 hit_info.setSize(desti);
481 template<u
int NAXES,
typename SUBCLASS>
482 template<
bool farthest,
bool rm_backface,
bool reverse,
typename FUNCTOR>
486 const NodeType *nodes = myTree.getNodes();
487 const uint nnodes = myTree.getNumNodes();
488 float length = direction.normalize();
491 if (nnodes == 0 || length == 0 || !
SYSisFinite(length) || !origin.isFinite())
497 const uint num_points = numPoints();
500 for (
int i = 0; i < NAXES; ++i)
501 sign[i] = (direction[i] < 0);
504 for (
int i = 0; i < NAXES; ++i)
528 #if GEO_BVH_INTERLEAVED
530 for (
uint axis = 0; axis < NAXES; ++axis)
532 vorigin[axis] =
v4uf(origin[axis]);
535 for (
uint axis = 0; axis < NAXES; ++axis)
537 vinverse_direction[axis] =
v4uf(inverse_direction[axis]);
540 if (hit_info.theUseTolerance)
541 vtolerance =
v4uf(hit_info.myTolerance);
543 const BoxType &box = myNodeBoxes[0];
544 box.
intersect(outer_tmin, outer_tmax, sign, origin, inverse_direction);
546 if (outer_tmin > outer_tmax)
558 #if GEO_BVH_INTERLEAVED
559 stack.
append(StackEntry(NodeType::markInternal(0),(!farthest) ? outer_tmin : outer_tmax));
561 stack.
append(StackEntry(0,outer_tmin));
566 StackEntry entry = stack.
last();
569 uint next_node = entry.myNode;
571 if ((!farthest) ? (entry.myTMin >= outer_tmax) : (entry.myTMin <= outer_tmin))
576 #if GEO_BVH_INTERLEAVED
577 if (NodeType::isInternal(next_node))
579 UT_ASSERT_MSG_P(next_node != NodeType::EMPTY,
"How did a ray hit an empty box?");
581 next_node = NodeType::getInternalNum(next_node);
582 const BoxType &box = myNodeBoxes[next_node];
583 v4uf tmin(outer_tmin);
v4uf tmax(outer_tmax);
584 if (!hit_info.theUseTolerance)
585 box.
intersect(tmin, tmax, sign, vorigin, vinverse_direction);
587 box.
intersectTol(tmin, tmax, sign, vorigin, vinverse_direction, vtolerance);
590 uint axis_sign = sign[0];
591 v4uf t1 = (box.
vals[0][axis_sign] - vorigin[0]) * vinverse_direction[0];
593 v4uf t2 = (box.
vals[0][axis_sign^1] - vorigin[0]) * vinverse_direction[0];
597 uint axis_sign = sign[1];
598 v4uf t1 = (box.
vals[1][axis_sign] - vorigin[1]) * vinverse_direction[1];
600 v4uf t2 = (box.
vals[1][axis_sign^1] - vorigin[1]) * vinverse_direction[1];
604 uint axis_sign = sign[2];
605 v4uf t1 = (box.
vals[2][axis_sign] - vorigin[2]) * vinverse_direction[2];
607 v4uf t2 = (box.
vals[2][axis_sign^1] - vorigin[2]) * vinverse_direction[2];
612 v4uu hit_mask = (tmin <= tmax);
616 const NodeType &node = nodes[next_node];
617 if (!(hit_bits & (hit_bits-1)))
620 uint local_index = SYSfirstBitSet(hit_bits);
622 next_node = node.child[local_index];
624 float local_tmin = tmins[local_index];
625 uint child_index = node.child[local_index];
626 if (!stack_size || ((!farthest) ? (stack_last->myTMin >= local_tmin) : (stack_last->myTMin <= local_tmin)))
627 next_node = child_index;
630 next_node = stack_last->myNode;
631 stack_last->myNode = child_index;
632 stack_last->myTMin = local_tmin;
639 StackEntry *stack_last = stack.
data()+stack_size-1;
649 while (stack_size != 0 && ((!farthest) ? (stack_last->myTMin >= outer_tmax) : (stack_last->myTMin <= outer_tmin)))
655 static constexpr
uint two_bit_indices[16][2] = {
656 {4, 4}, {4, 4}, {4, 4}, {0, 1},
657 {4, 4}, {0, 2}, {1, 2}, {0, 1},
658 {4, 4}, {0, 3}, {1, 3}, {0, 1},
659 {2, 3}, {0, 2}, {1, 2}, {0, 1}
661 static constexpr
uint third_bit_index[16] = {
668 union {
v4sf tminv;
float tmins[4]; };
670 uint local_index0 = two_bit_indices[hit_bits][0];
671 uint local_index1 = two_bit_indices[hit_bits][1];
672 if (third_bit_index[hit_bits] == 4)
675 float t0 = tmins[local_index0];
676 float t1 = tmins[local_index1];
677 uint child0 = node.child[local_index0];
678 uint child1 = node.child[local_index1];
679 if ((!farthest) ? (t0 > t1) : (t0 < t1))
681 uint childtmp = child0;
690 if (!stack_size || ((!farthest) ? (stack_last->myTMin >= t0) : (stack_last->myTMin <= t0)))
696 if (!stack_size || ((!farthest) ? (stack_last->myTMin >= t1) : (stack_last->myTMin <= t1)))
698 stack.
append(StackEntry(child1, t1));
706 for (i = stack_size-2; i >= limiti; --i)
708 if ((!farthest) ? (stack[i].myTMin >= t1) : (stack[i].myTMin <= t1))
710 stack.
insert(StackEntry(child1, t1), i+1);
716 stack.
insert(StackEntry(child1, t1), i+1);
722 next_node = stack_last->myNode;
723 stack_last->myNode = child1;
724 stack_last->myTMin = t1;
725 stack.
append(StackEntry(child0, t0));
731 uint nhit = (hit_bits == 0xF) ? 4 : 3;
732 uint local_index2 = third_bit_index[hit_bits];
733 uint children[BVH_N] = {
734 node.child[local_index0],
735 node.child[local_index1],
736 node.child[local_index2],
739 tmins[0] = tmins[local_index0];
740 tmins[1] = tmins[local_index1];
741 tmins[2] = tmins[local_index2];
745 if (!stack_size || ((!farthest) ? (stack_last->myTMin >= tmins[0]) : (stack_last->myTMin <= tmins[0])))
748 next_node = children[0];
752 new_tmin = stack_last->myTMin;
753 next_node = stack_last->myNode;
754 stack_last->myTMin = tmins[0];
755 stack_last->myNode = children[0];
757 for (
uint hit = 1; hit < nhit; ++hit)
759 float t = tmins[hit];
760 uint child = children[hit];
763 float tmpt = new_tmin;
764 uint tmpchild = next_node;
772 if (!stack_size || ((!farthest) ? (stack_last->myTMin >=
t) : (stack_last->myTMin <= t)))
774 stack.
append(StackEntry(child, t));
782 for (i = stack_size-2; i >= limiti; --i)
784 if ((!farthest) ? (stack[i].myTMin >= t) : (stack[i].myTMin <= t))
786 stack.
insert(StackEntry(child, t), i+1);
792 stack.
insert(StackEntry(child, t), i+1);
795 stack_last = stack.
data()+stack_size;
802 const NodeType &node = nodes[next_node];
803 uint children[BVH_N];
806 for (
uint i = 0; i < BVH_N; ++i)
808 const uint itemi = node.child[i];
809 if (NodeType::isInternal(itemi))
811 if (itemi == NodeType::EMPTY)
815 const uint childi = NodeType::getInternalNum(itemi);
816 const BoxType &box = myNodeBoxes[childi];
817 float tmin = outer_tmin;
float tmax = outer_tmax;
818 box.
intersect(tmin, tmax, sign, origin, inverse_direction);
823 children[nnodehits] = childi;
824 tmins[nnodehits] = tmin;
832 if (!SUBCLASS::theHasPrimitives || index < num_points)
836 if (!myRadii.isEmpty() || myRadAttrib.isValid() || hit_info.theUseTolerance)
840 exint ptarrayindex = (SUBCLASS::theReordersPositions) ?
exint(index) :
exint(myPoints(index));
841 const bool use_pos_array = !myPositions.isEmpty();
842 const VectorType pos = use_pos_array ? myPositions[ptarrayindex] : myPosAttrib.get(
GA_Offset(ptarrayindex));
844 if (hit_info.theUseTolerance)
845 radius = hit_info.myTolerance;
846 else if (myRadii.isEmpty())
847 radius = myRadAttrib.get(
GA_Offset(ptarrayindex));
849 radius = ((myRadii.size() == 1) ? myRadii[0] : myRadii[ptarrayindex]);
851 if (hit_info.theUseTolerance || radius != 0)
855 bool ishit = geoIntersectSphere(rel_origin, direction, radius, t0, t1);
857 #if GEO_BVH_INTERLEAVED
863 const float invradius = 1.0f/radius;
864 if ((t0 <= outer_tmax) && (t0 >= outer_tmin))
869 if (!rm_backface || (
dot(p,direction) <= 0) !=
reverse)
872 UT_Vector3(p[0], p[1], (NAXES==3) ? p[2] : 0),
874 (!farthest) ? outer_tmax : outer_tmin);
875 if (hit_info.theNeedsNormal)
876 hit_info.setNormal(p);
880 if ((t1 <= outer_tmax) && (t1 >= outer_tmin))
885 if (!rm_backface || (
dot(p,direction) <= 0) !=
reverse)
888 UT_Vector3(p[0], p[1], (NAXES==3) ? p[2] : 0),
890 (!farthest) ? outer_tmax : outer_tmin);
891 if (hit_info.theNeedsNormal)
892 hit_info.setNormal(p);
900 #if !GEO_BVH_INTERLEAVED
903 subclass()->template intersectPrim<farthest,rm_backface,reverse>(
904 index, origin,
direction, inverse_direction, max_dir, N0, N1,
905 outer_tmax, outer_tmin, hit_info);
906 #if !GEO_BVH_INTERLEAVED
911 #if GEO_BVH_INTERLEAVED
914 #if !GEO_BVH_INTERLEAVED
920 StackEntry *stack_last = stack.
data()+stack_size-1;
923 uint child_index = children[0];
924 if (!stack_size || stack_last->myTMin >= tmins[0])
925 next_node = child_index;
928 next_node = stack_last->myNode;
929 stack_last->myNode = child_index;
930 stack_last->myTMin = tmins[0];
933 else if (BVH_N == 2 || nnodehits == 2)
935 const uint local_index = (tmins[0] >= tmins[1]);
936 next_node = children[local_index];
937 const uint insert_node = children[!local_index];
938 const float insert_tmin = tmins[!local_index];
940 if (!stack_size || stack_last->myTMin <= insert_tmin)
942 stack.
append(StackEntry(insert_node, insert_tmin));
950 for (i = stack_size-2; i >= limiti; --i)
952 if (stack[i].myTMin <= insert_tmin)
954 stack.
insert(StackEntry(insert_node, insert_tmin), i+1);
960 stack.
insert(StackEntry(insert_node, insert_tmin), i+1);
977 hit_info.myItemIndex = hit_index;
978 hit_info.myUVW = hit_uvw;
979 hit_info.myT = (!farthest) ? outer_tmax : outer_tmin;
983 hit_info.myItemIndex = -1;
984 hit_info.myUVW.assign(0,0,0);
985 hit_info.myT = -1.0f;
990 template<u
int NAXES,
typename SUBCLASS>
991 template<
bool farthest,
typename QUERY_POINT>
993 const QUERY_POINT &query_point,
997 float max_dist_squared)
const noexcept
999 const v4uu* node_nitems_v = (
const v4uu*)myNodeNItems.get();
1001 const bool use_pos_array = !myPositions.isEmpty();
1004 if (myRadii.size() == 0)
1006 if (myRadAttrib.isValid())
1008 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1009 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1010 myRadAttrib, max_points, max_dist_squared);
1014 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1015 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1019 else if (myRadii.size() == 1)
1021 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1022 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1027 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1028 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1029 myRadii, max_points, max_dist_squared);
1034 if (myRadii.size() == 0)
1036 if (myRadAttrib.isValid())
1038 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1039 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1040 myRadAttrib, max_points, max_dist_squared);
1044 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1045 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1049 else if (myRadii.size() == 1)
1051 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1052 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1057 UT::findClosestPoints<farthest,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1058 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1059 myRadii, max_points, max_dist_squared);
1064 template<u
int NAXES,
typename SUBCLASS>
1067 const exint max_points,
const float max_dist_squared,
1075 findMaximalPointsCommon<false>(
1083 template<u
int NAXES,
typename SUBCLASS>
1086 const exint max_points,
const float max_dist_squared,
1094 findMaximalPointsCommon<false>(
1102 template<u
int NAXES,
typename SUBCLASS>
1110 const v4uu* node_nitems_v = (
const v4uu*)myNodeNItems.get();
1111 const bool use_pos_array = !myPositions.isEmpty();
1113 if (myRadii.size() == 0 && !myRadAttrib.isValid())
1120 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1121 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1122 radii, max_points, max_dist_squared);
1128 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1129 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1130 radii, max_points, max_dist_squared);
1133 else if (myRadii.size() == 1)
1140 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1141 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1142 radii, max_points, max_dist_squared);
1148 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1149 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1150 radii, max_points, max_dist_squared);
1153 else if (myRadii.size() > 1)
1159 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1160 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1161 myRadii, max_points, max_dist_squared);
1167 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1168 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1169 myRadii, max_points, max_dist_squared);
1178 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1179 myPoints.getArray(), myPositions, query_point, stack, output_queue,
1180 myRadAttrib, max_points, max_dist_squared);
1186 UT::findClosestPoints<false,true,true>(myTree, myNodeBoxes.get(), node_nitems_v,
1187 myPoints.getArray(), myPosAttrib, query_point, stack, output_queue,
1188 myRadAttrib, max_points, max_dist_squared);
1193 template<u
int NAXES,
typename SUBCLASS>
1194 template<
bool farthest>
1198 const NodeType *nodes = myTree.getNodes();
1199 const uint nnodes = myTree.getNumNodes();
1201 if (nnodes == 0 || !origin.isFinite())
1204 hit_info.myItemIndex = -1;
1205 hit_info.myUVW.assign(0,0,0);
1206 hit_info.myDistSquared = -1.0f;
1212 exint nesting_array_base = nesting_array ? nesting_array->
size() : 0;
1214 const uint num_points = numPoints();
1219 float myDistSquared;
1228 #if GEO_BVH_INTERLEAVED
1230 for (
uint axis = 0; axis < NAXES; ++axis)
1232 vorigin[axis] =
v4uf(origin[axis]);
1235 const BoxType &box = myNodeBoxes[0];
1239 if ((!farthest) ? (dist2 > max_dist_squared) : (dist2 < max_dist_squared))
1242 hit_info.myItemIndex = -1;
1243 hit_info.myUVW.assign(0,0,0);
1244 hit_info.myDistSquared = -1.0f;
1251 exint hit_index = -1;
1258 #if GEO_BVH_INTERLEAVED
1261 stack.
append(StackEntry(0,dist2));
1266 StackEntry entry = stack.
last();
1269 uint next_node = entry.myNode;
1271 if ((!farthest) ? (entry.myDistSquared > max_dist_squared) : (entry.myDistSquared < max_dist_squared))
1276 #if GEO_BVH_INTERLEAVED
1277 if (NodeType::isInternal(next_node))
1279 if (next_node == NodeType::EMPTY)
1282 next_node = NodeType::getInternalNum(next_node);
1283 const BoxType &box = myNodeBoxes[next_node];
1285 v4uu hit_mask = (!farthest) ? (dist2 <= max_dist_squared) : (dist2 >= max_dist_squared);
1289 const NodeType &node = nodes[next_node];
1290 if (!(hit_bits & (hit_bits-1)))
1293 uint local_index = SYSfirstBitSet(hit_bits);
1295 next_node = node.child[local_index];
1297 float local_d2 = d2s[local_index];
1298 uint child_index = node.child[local_index];
1299 if (!stack_size || ((!farthest) ? (stack_last->myDistSquared >= local_d2) : (stack_last->myDistSquared <= local_d2)))
1300 next_node = child_index;
1303 next_node = stack_last->myNode;
1304 stack_last->myNode = child_index;
1305 stack_last->myDistSquared = local_d2;
1312 StackEntry *stack_last = stack.
data()+stack_size-1;
1322 while (stack_size != 0 && ((!farthest) ? (stack_last->myDistSquared > max_dist_squared) : (stack_last->myDistSquared < max_dist_squared)))
1328 static constexpr
uint two_bit_indices[16][2] = {
1329 {4, 4}, {4, 4}, {4, 4}, {0, 1},
1330 {4, 4}, {0, 2}, {1, 2}, {0, 1},
1331 {4, 4}, {0, 3}, {1, 3}, {0, 1},
1332 {2, 3}, {0, 2}, {1, 2}, {0, 1}
1334 static constexpr
uint third_bit_index[16] = {
1341 union {
v4sf d2v;
float d2s[4]; };
1343 uint local_index0 = two_bit_indices[hit_bits][0];
1344 uint local_index1 = two_bit_indices[hit_bits][1];
1345 if (third_bit_index[hit_bits] == 4)
1348 float d20 = d2s[local_index0];
1349 float d21 = d2s[local_index1];
1350 uint child0 = node.child[local_index0];
1351 uint child1 = node.child[local_index1];
1352 if ((!farthest) ? (d20 > d21) : (d20 < d21))
1354 uint childtmp = child0;
1362 if (!stack_size || ((!farthest) ? (stack_last->myDistSquared >= d20) : (stack_last->myDistSquared <= d20)))
1368 if (!stack_size || ((!farthest) ? (stack_last->myDistSquared >= d21) : (stack_last->myDistSquared <= d21)))
1370 stack.
append(StackEntry(child1, d21));
1378 for (i = stack_size-2; i >= limiti; --i)
1380 if ((!farthest) ? (stack[i].myDistSquared >= d21) : (stack[i].myDistSquared <= d21))
1382 stack.
insert(StackEntry(child1, d21), i+1);
1388 stack.
insert(StackEntry(child1, d21), i+1);
1394 next_node = stack_last->myNode;
1395 stack_last->myNode = child1;
1396 stack_last->myDistSquared = d21;
1397 stack.
append(StackEntry(child0, d20));
1403 uint nhit = (hit_bits == 0xF) ? 4 : 3;
1404 uint local_index2 = third_bit_index[hit_bits];
1405 uint children[BVH_N] = {
1406 node.child[local_index0],
1407 node.child[local_index1],
1408 node.child[local_index2],
1411 d2s[0] = d2s[local_index0];
1412 d2s[1] = d2s[local_index1];
1413 d2s[2] = d2s[local_index2];
1417 if (!stack_size || ((!farthest) ? (stack_last->myDistSquared >= d2s[0]) : (stack_last->myDistSquared <= d2s[0])))
1420 next_node = children[0];
1424 new_d2 = stack_last->myDistSquared;
1425 next_node = stack_last->myNode;
1426 stack_last->myDistSquared = d2s[0];
1427 stack_last->myNode = children[0];
1429 for (
uint hit = 1; hit < nhit; ++hit)
1431 float d2 = d2s[hit];
1432 uint child = children[hit];
1433 if ((!farthest) ? (d2 < new_d2) : (d2 > new_d2))
1435 float tmpd2 = new_d2;
1436 uint tmpchild = next_node;
1444 if (!stack_size || ((!farthest) ? (stack_last->myDistSquared >= d2) : (stack_last->myDistSquared <= d2)))
1446 stack.
append(StackEntry(child, d2));
1454 for (i = stack_size-2; i >= limiti; --i)
1456 if ((!farthest) ? (stack[i].myDistSquared >= d2) : (stack[i].myDistSquared <= d2))
1458 stack.
insert(StackEntry(child, d2), i+1);
1464 stack.
insert(StackEntry(child, d2), i+1);
1467 stack_last = stack.
data()+stack_size;
1474 const NodeType &node = nodes[next_node];
1475 uint children[BVH_N];
1478 for (
uint i = 0; i < BVH_N; ++i)
1480 const uint itemi = node.child[i];
1481 if (NodeType::isInternal(itemi))
1483 if (itemi == NodeType::EMPTY)
1487 const uint childi = NodeType::getInternalNum(itemi);
1488 const BoxType &box = myNodeBoxes[childi];
1490 if ((!farthest) ? (dist2 > min_dist_squared) : (dist2 < min_dist_squared))
1493 children[nnodehits] = childi;
1494 d2s[nnodehits] = dist2;
1502 if (!SUBCLASS::theHasPrimitives || index < num_points)
1507 exint ptarrayindex = (SUBCLASS::theReordersPositions) ?
exint(index) :
exint(myPoints(index));
1508 const bool use_pos_array = !myPositions.isEmpty();
1509 const VectorType pos = use_pos_array ? myPositions[ptarrayindex] : myPosAttrib.get(
GA_Offset(ptarrayindex));
1512 if (myRadii.isEmpty())
1513 radius = myRadAttrib.isValid() ? myRadAttrib.get(
GA_Offset(ptarrayindex)) : 0.0f;
1515 radius = ((myRadii.size() == 1) ? myRadii[0] : myRadii[ptarrayindex]);
1517 float d2 = displacement.length2();
1522 if ((!farthest) ? (d2 < max_dist_squared) : (d2 > max_dist_squared))
1524 max_dist_squared = d2;
1534 if ((!farthest) ? (d2 < max_dist_squared) : (d2 > max_dist_squared))
1536 max_dist_squared = d2;
1541 VectorType real_normal = (((radius > 0) != farthest) ? normal : -normal);
1542 hit_uvw[0] = real_normal[0];
1543 hit_uvw[1] = real_normal[1];
1544 hit_uvw[2] = (NAXES==3) ? real_normal[2] : 0;
1549 hit_position -= radius*normal;
1551 hit_position += radius*normal;
1557 subclass()->template closestPrim<farthest>(
1558 index, origin, max_dist_squared,
1559 hit_index, hit_uvw, hit_position,
1560 vorigin, nesting_array, nesting_array_base);
1562 #if GEO_BVH_INTERLEAVED
1570 StackEntry *stack_last = stack.
data()+stack_size-1;
1573 uint child_index = children[0];
1574 if (!stack_size || stack_last->myTMin >= tmins[0])
1575 next_node = child_index;
1578 next_node = stack_last->myNode;
1579 stack_last->myNode = child_index;
1580 stack_last->myTMin = tmins[0];
1583 else if (BVH_N == 2 || nnodehits == 2)
1585 const uint local_index = (tmins[0] >= tmins[1]);
1586 next_node = children[local_index];
1587 const uint insert_node = children[!local_index];
1588 const float insert_tmin = tmins[!local_index];
1590 if (!stack_size || stack_last->myTMin <= insert_tmin)
1592 stack.
append(StackEntry(insert_node, insert_tmin));
1600 for (i = stack_size-2; i >= limiti; --i)
1602 if (stack[i].myTMin <= insert_tmin)
1604 stack.
insert(StackEntry(insert_node, insert_tmin), i+1);
1610 stack.
insert(StackEntry(insert_node, insert_tmin), i+1);
1626 hit_info.myItemIndex = hit_index;
1627 hit_info.myUVW = hit_uvw;
1629 hit_info.myDistSquared = max_dist_squared;
1630 hit_info.myP = hit_position;
1634 hit_info.myItemIndex = -1;
1635 hit_info.myUVW.
assign(0,0,0);
1636 hit_info.myDistSquared = -1.0f;
1641 template<u
int NAXES,
typename SUBCLASS>
1648 template<u
int NAXES,
typename SUBCLASS>
1649 template<
bool normalize>
1652 if (!SUBCLASS::theHasPrimitives || hit_info.myItemIndex < numPoints())
1658 return subclass()->template primGeometricNormal<normalize>(hit_info);
1661 template<u
int NAXES,
typename SUBCLASS>
1664 if (!SUBCLASS::theHasPrimitives || hit_info.myItemIndex < numPoints())
1670 nml[0] = hit_info.myUVW[0];
1671 nml[1] = hit_info.myUVW[1];
1674 nml[2] = hit_info.myUVW[1];
1678 dP_dv[0] = -nml[2]*nmlxy[0];
1679 dP_dv[1] = -nml[2]*nmlxy[1];
1680 dP_dv[2] = lengthxy;
1683 dP_du[0] = -nml[1]*(2*
M_PI);
1684 dP_du[1] = nml[0]*(2*
M_PI);
1691 dP_du[0] = -nml[1]*(2*
M_PI);
1692 dP_du[1] = nml[0]*(2*
M_PI);
1698 subclass()->primDerivs(hit_info, dP_du, dP_dv);
1701 template<u
int NAXES,
typename SUBCLASS>
1704 float u = SYSatan(uvw[1], uvw[0]) / (
float)(2*
M_PI);
1722 template<u
int NAXES,
typename SUBCLASS>
1723 template<GA_AttributeOwner owner,
typename T,
typename DEST_T>
1735 if (!SUBCLASS::theHasPrimitives || index < numPoints())
1741 value = attrib.get(ptoff);
1744 return subclass()->template primAttribute<owner,T,DEST_T>(hit_info, attrib, detail,
value);
1749 #undef GEO_BVH_INTERLEAVED
SYS_FORCE_INLINE void setNestingArrayInto(HitInfo &hit_info) 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
PUGI__FN void reverse(I begin, I end)
GLuint GLsizei GLsizei * length
PUGI__FN void sort(I begin, I end, const Pred &pred)
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
GLint GLint GLsizei GLint GLenum GLenum type
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
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.
IMATH_NAMESPACE::V2f IMATH_NAMESPACE::Box2i std::string this attribute is obsolete as of OpenEXR v3 float
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
SYS_FORCE_INLINE void insertHit(const UT_Vector3 &hit_uvw, const float t, const uint index, float &limit_t, bool should_clear_nesting=true) 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
SYS_FORCE_INLINE void insertHit(const UT_Vector3 &hit_uvw, const float t, const uint index, float &limit_t, bool should_clear_nesting=true) 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.