40 #define SOLID_ANGLE_TIME_PRECOMPUTE 0
42 #if SOLID_ANGLE_TIME_PRECOMPUTE
46 #define SOLID_ANGLE_DEBUG 0
51 using namespace UT::Literal;
53 #define TAYLOR_SERIES_ORDER 2
55 namespace HDK_Sample {
57 template<
typename T,
typename S>
63 memset(
this,0,
sizeof(*
this));
78 #if TAYLOR_SERIES_ORDER >= 1
88 #if TAYLOR_SERIES_ORDER >= 2
103 template<
typename T,
typename S>
110 , myTrianglePoints(nullptr)
112 , myPositions(nullptr)
115 template<
typename T,
typename S>
123 template<
typename T,
typename S>
125 const int ntriangles,
126 const int *
const triangle_points,
131 #if SOLID_ANGLE_DEBUG
134 UTdebugFormat(
"Building BVH for {} ntriangles on {} points:", ntriangles, npoints);
137 myNTriangles = ntriangles;
138 myTrianglePoints = triangle_points;
140 myPositions = positions;
142 #if SOLID_ANGLE_TIME_PRECOMPUTE
148 if (ntriangles < 16*1024)
150 const int *cur_triangle_points = triangle_points;
151 for (
int i = 0; i < ntriangles; ++i, cur_triangle_points += 3)
154 box.
initBounds(positions[cur_triangle_points[0]]);
163 const int *cur_triangle_points = triangle_points +
exint(r.begin())*3;
164 for (
int i = r.begin(),
end = r.end(); i <
end; ++i, cur_triangle_points += 3)
167 box.
initBounds(positions[cur_triangle_points[0]]);
173 #if SOLID_ANGLE_TIME_PRECOMPUTE
178 myTree.template init<UT::BVH_Heuristic::BOX_AREA,S,3>(triangle_boxes.
array(), ntriangles);
179 #if SOLID_ANGLE_TIME_PRECOMPUTE
181 UTdebugFormat(
"{} s to initialize UT_BVH structure. {} nodes", time, myTree.getNumNodes());
186 const int nnodes = myTree.getNumNodes();
190 myData.reset(box_data);
206 #if TAYLOR_SERIES_ORDER >= 1
214 #if TAYLOR_SERIES_ORDER >= 2
226 struct PrecomputeFunctors
230 const int *
const myTrianglePoints;
237 const int *triangle_points,
240 : myBoxData(box_data)
241 , myTriangleBoxes(triangle_boxes)
242 , myTrianglePoints(triangle_points)
243 , myPositions(positions)
246 constexpr
SYS_FORCE_INLINE bool pre(
const int nodei, LocalData *data_for_parent)
const
250 void item(
const int itemi,
const int parent_nodei, LocalData &data_for_parent)
const
253 const int *
const cur_triangle_points = myTrianglePoints + 3*itemi;
260 const UT::Box<S,3> &triangle_box = myTriangleBoxes[itemi];
262 data_for_parent.myBox.initBounds(
263 vector3TFromFixed( triangle_box.
getMin() ),
264 vector3TFromFixed( triangle_box.
getMax() )
270 const T area = SYSsqrt(area2);
272 data_for_parent.myAverageP = P;
273 data_for_parent.myAreaP = P*
area;
274 data_for_parent.myN =
N;
275 #if SOLID_ANGLE_DEBUG
277 UTdebugFormat(
"Triangle {}: P = {}; N = {}; area = {}", itemi, P, N, area);
281 data_for_parent.myArea =
area;
282 #if TAYLOR_SERIES_ORDER >= 1
289 data_for_parent.myNijDiag =
T(0);
290 data_for_parent.myNxy = 0; data_for_parent.myNyx = 0;
291 data_for_parent.myNyz = 0; data_for_parent.myNzy = 0;
292 data_for_parent.myNzx = 0; data_for_parent.myNxz = 0;
295 #if TAYLOR_SERIES_ORDER >= 2
302 data_for_parent.myNijkDiag =
T(0);
303 data_for_parent.mySumPermuteNxyz = 0;
304 data_for_parent.my2Nxxy_Nyxx = 0;
305 data_for_parent.my2Nxxz_Nzxx = 0;
306 data_for_parent.my2Nyyz_Nzyy = 0;
307 data_for_parent.my2Nyyx_Nxyy = 0;
308 data_for_parent.my2Nzzx_Nxzz = 0;
309 data_for_parent.my2Nzzy_Nyzz = 0;
320 int order_x[3] = {0,1,2};
323 if (values[order_x[0]].
x() > c.
x())
325 if (values[order_x[1]].
x() > values[order_x[2]].
x())
327 T dx = values[order_x[2]].
x() - values[order_x[0]].
x();
329 int order_y[3] = {0,1,2};
332 if (values[order_y[0]].
y() > c.
y())
334 if (values[order_y[1]].
y() > values[order_y[2]].
y())
336 T dy = values[order_y[2]].
y() - values[order_y[0]].
y();
338 int order_z[3] = {0,1,2};
341 if (values[order_z[0]].
z() > c.
z())
343 if (values[order_z[1]].
z() > values[order_z[2]].
z())
345 T dz = values[order_z[2]].
z() - values[order_z[0]].
z();
347 auto &&compute_integrals = [](
357 #if SOLID_ANGLE_DEBUG
358 UTdebugFormat(
" Splitting on {}; a = {}; b = {}; c = {}",
char(
'x'+i), a, b, c);
365 UT_ASSERT_MSG_P(oac[i] > 0,
"This should have been checked by the caller.");
366 const T t = oab[i]/oac[i];
367 UT_ASSERT_MSG_P(t >= 0 && t <= 1,
"Either sorting must have gone wrong, or there are input NaNs.");
369 const int j = (i==2) ? 0 : (i+1);
370 const int k = (j==2) ? 0 : (j+1);
371 const T jdiff = t*oac[
j] - oab[
j];
372 const T kdiff = t*oac[k] - oab[k];
373 const UT_Vector3T<T> cross_a(jdiff*oab[k] - kdiff*oab[j], kdiff*oab[i], jdiff*oab[i]);
374 const UT_Vector3T<T> cross_c(jdiff*ocb[k] - kdiff*ocb[j], kdiff*ocb[i], jdiff*ocb[i]);
375 const T area_scale_a = cross_a.
length();
376 const T area_scale_c = cross_c.
length();
377 const T Pai = a[i] - P[i];
378 const T Pci = c[i] - P[i];
383 const T int_ii_a = area_scale_a*(
T(0.5)*Pai*Pai +
T(2.0/3.0)*Pai*oab[i] +
T(0.25)*oab[i]*oab[i]);
384 const T int_ii_c = area_scale_c*(
T(0.5)*Pci*Pci +
T(2.0/3.0)*Pci*ocb[i] +
T(0.25)*ocb[i]*ocb[i]);
385 *integral_ii = int_ii_a + int_ii_c;
386 #if SOLID_ANGLE_DEBUG
387 UTdebugFormat(
" integral_{}{}_a = {}; integral_{}{}_c = {}",
char(
'x'+i),
char(
'x'+i), int_ii_a,
char(
'x'+i),
char(
'x'+i), int_ii_c);
391 T *integral = integral_ij;
397 T obmidj = b[jk] +
T(0.5)*diff;
398 T oabmidj = obmidj - a[jk];
399 T ocbmidj = obmidj - c[jk];
400 T Paj = a[jk] - P[jk];
401 T Pcj = c[jk] - P[jk];
403 const T int_ij_a = area_scale_a*(
T(0.5)*Pai*Paj +
T(1.0/3.0)*Pai*oabmidj +
T(1.0/3.0)*Paj*oab[i] +
T(0.25)*oab[i]*oabmidj);
404 const T int_ij_c = area_scale_c*(
T(0.5)*Pci*Pcj +
T(1.0/3.0)*Pci*ocbmidj +
T(1.0/3.0)*Pcj*ocb[i] +
T(0.25)*ocb[i]*ocbmidj);
405 *integral = int_ij_a + int_ij_c;
406 #if SOLID_ANGLE_DEBUG
407 UTdebugFormat(
" integral_{}{}_a = {}; integral_{}{}_c = {}",
char(
'x'+i),
char(
'x'+jk), int_ij_a,
char(
'x'+i),
char(
'x'+jk), int_ij_c);
413 integral = integral_ik;
430 values[order_x[0]], values[order_x[1]], values[order_x[2]], P,
431 &integral_xx, ((dx >= dy && dy > 0) ? &integral_xy :
nullptr), ((dx >= dz && dz > 0) ? &integral_zx :
nullptr), 0);
436 values[order_y[0]], values[order_y[1]], values[order_y[2]], P,
437 &integral_yy, ((dy >= dz && dz > 0) ? &integral_yz :
nullptr), ((dx < dy && dx > 0) ? &integral_xy :
nullptr), 1);
442 values[order_z[0]], values[order_z[1]], values[order_z[2]], P,
443 &integral_zz, ((dx < dz && dx > 0) ? &integral_zx :
nullptr), ((dy < dz && dy > 0) ? &integral_yz :
nullptr), 2);
447 data_for_parent.myNijkDiag = Niii;
448 data_for_parent.mySumPermuteNxyz = 2*
dot(n,
UT_Vector3T<T>(integral_yz, integral_zx, integral_xy));
449 T Nxxy = n.
x()*integral_xy;
450 T Nxxz = n.
x()*integral_zx;
451 T Nyyz = n.
y()*integral_yz;
452 T Nyyx = n.
y()*integral_xy;
453 T Nzzx = n.
z()*integral_zx;
454 T Nzzy = n.
z()*integral_yz;
455 data_for_parent.my2Nxxy_Nyxx = 2*Nxxy + n.
y()*integral_xx;
456 data_for_parent.my2Nxxz_Nzxx = 2*Nxxz + n.
z()*integral_xx;
457 data_for_parent.my2Nyyz_Nzyy = 2*Nyyz + n.
z()*integral_yy;
458 data_for_parent.my2Nyyx_Nxyy = 2*Nyyx + n.
x()*integral_yy;
459 data_for_parent.my2Nzzx_Nxzz = 2*Nzzx + n.
x()*integral_zz;
460 data_for_parent.my2Nzzy_Nyzz = 2*Nzzy + n.
y()*integral_zz;
461 #if SOLID_ANGLE_DEBUG
462 UTdebugFormat(
" integral_xx = {}; yy = {}; zz = {}", integral_xx, integral_yy, integral_zz);
463 UTdebugFormat(
" integral_xy = {}; yz = {}; zx = {}", integral_xy, integral_yz, integral_zx);
468 void post(
const int nodei,
const int parent_nodei, LocalData *data_for_parent,
const int nchildren,
const LocalData *child_data_array)
const
473 BoxData ¤t_box_data = myBoxData[nodei];
476 ((
T*)¤t_box_data.
myN[0])[0] = N[0];
477 ((
T*)¤t_box_data.
myN[1])[0] = N[1];
478 ((
T*)¤t_box_data.
myN[2])[0] = N[2];
480 T area = child_data_array[0].myArea;
482 ((
T*)¤t_box_data.
myAverageP[0])[0] = local_P[0];
483 ((
T*)¤t_box_data.
myAverageP[1])[0] = local_P[1];
484 ((
T*)¤t_box_data.
myAverageP[2])[0] = local_P[2];
485 for (
int i = 1; i < nchildren; ++i)
489 ((
T*)¤t_box_data.
myN[0])[i] = local_N[0];
490 ((
T*)¤t_box_data.
myN[1])[i] = local_N[1];
491 ((
T*)¤t_box_data.
myN[2])[i] = local_N[2];
492 areaP += child_data_array[i].myAreaP;
493 area += child_data_array[i].myArea;
495 ((
T*)¤t_box_data.
myAverageP[0])[i] = local_P[0];
496 ((
T*)¤t_box_data.
myAverageP[1])[i] = local_P[1];
497 ((
T*)¤t_box_data.
myAverageP[2])[i] = local_P[2];
499 for (
int i = nchildren; i < BVH_N; ++i)
502 ((
T*)¤t_box_data.
myN[0])[i] = 0;
503 ((
T*)¤t_box_data.
myN[1])[i] = 0;
504 ((
T*)¤t_box_data.
myN[2])[i] = 0;
509 data_for_parent->myN =
N;
510 data_for_parent->myAreaP = areaP;
511 data_for_parent->myArea =
area;
514 for (
int i = 1; i < nchildren; ++i)
520 averageP = areaP/
area;
523 data_for_parent->myAverageP = averageP;
525 data_for_parent->myBox = box;
527 for (
int i = 0; i < nchildren; ++i)
534 for (
int i = nchildren; i < BVH_N; ++i)
538 ((
T*)¤t_box_data.
myMaxPDist2)[i] = std::numeric_limits<T>::infinity();
541 #if TAYLOR_SERIES_ORDER >= 1
546 data_for_parent->myNijDiag = child_data_array[0].myNijDiag;
547 data_for_parent->myNxy = 0;
548 data_for_parent->myNyx = 0;
549 data_for_parent->myNyz = 0;
550 data_for_parent->myNzy = 0;
551 data_for_parent->myNzx = 0;
552 data_for_parent->myNxz = 0;
553 #if TAYLOR_SERIES_ORDER >= 2
554 data_for_parent->myNijkDiag = child_data_array[0].myNijkDiag;
555 data_for_parent->mySumPermuteNxyz = child_data_array[0].mySumPermuteNxyz;
556 data_for_parent->my2Nxxy_Nyxx = child_data_array[0].my2Nxxy_Nyxx;
557 data_for_parent->my2Nxxz_Nzxx = child_data_array[0].my2Nxxz_Nzxx;
558 data_for_parent->my2Nyyz_Nzyy = child_data_array[0].my2Nyyz_Nzyy;
559 data_for_parent->my2Nyyx_Nxyy = child_data_array[0].my2Nyyx_Nxyy;
560 data_for_parent->my2Nzzx_Nxzz = child_data_array[0].my2Nzzx_Nxzz;
561 data_for_parent->my2Nzzy_Nyzz = child_data_array[0].my2Nzzy_Nyzz;
564 for (
int i = 1; i < nchildren; ++i)
566 data_for_parent->myNijDiag += child_data_array[i].myNijDiag;
567 #if TAYLOR_SERIES_ORDER >= 2
568 data_for_parent->myNijkDiag += child_data_array[i].myNijkDiag;
569 data_for_parent->mySumPermuteNxyz += child_data_array[i].mySumPermuteNxyz;
570 data_for_parent->my2Nxxy_Nyxx += child_data_array[i].my2Nxxy_Nyxx;
571 data_for_parent->my2Nxxz_Nzxx += child_data_array[i].my2Nxxz_Nzxx;
572 data_for_parent->my2Nyyz_Nzyy += child_data_array[i].my2Nyyz_Nzyy;
573 data_for_parent->my2Nyyx_Nxyy += child_data_array[i].my2Nyyx_Nxyy;
574 data_for_parent->my2Nzzx_Nxzz += child_data_array[i].my2Nzzx_Nxzz;
575 data_for_parent->my2Nzzy_Nyzz += child_data_array[i].my2Nzzy_Nyzz;
578 for (
int j = 0;
j < 3; ++
j)
579 ((
T*)¤t_box_data.
myNijDiag[
j])[0] = child_data_array[0].myNijDiag[
j];
580 ((
T*)¤t_box_data.
myNxy_Nyx)[0] = child_data_array[0].myNxy + child_data_array[0].myNyx;
581 ((
T*)¤t_box_data.
myNyz_Nzy)[0] = child_data_array[0].myNyz + child_data_array[0].myNzy;
582 ((
T*)¤t_box_data.
myNzx_Nxz)[0] = child_data_array[0].myNzx + child_data_array[0].myNxz;
583 for (
int j = 0;
j < 3; ++
j)
584 ((
T*)¤t_box_data.
myNijkDiag[
j])[0] = child_data_array[0].myNijkDiag[
j];
585 ((
T*)¤t_box_data.
mySumPermuteNxyz)[0] = child_data_array[0].mySumPermuteNxyz;
586 ((
T*)¤t_box_data.
my2Nxxy_Nyxx)[0] = child_data_array[0].my2Nxxy_Nyxx;
587 ((
T*)¤t_box_data.
my2Nxxz_Nzxx)[0] = child_data_array[0].my2Nxxz_Nzxx;
588 ((
T*)¤t_box_data.
my2Nyyz_Nzyy)[0] = child_data_array[0].my2Nyyz_Nzyy;
589 ((
T*)¤t_box_data.
my2Nyyx_Nxyy)[0] = child_data_array[0].my2Nyyx_Nxyy;
590 ((
T*)¤t_box_data.
my2Nzzx_Nxzz)[0] = child_data_array[0].my2Nzzx_Nxzz;
591 ((
T*)¤t_box_data.
my2Nzzy_Nyzz)[0] = child_data_array[0].my2Nzzy_Nyzz;
592 for (
int i = 1; i < nchildren; ++i)
594 for (
int j = 0;
j < 3; ++
j)
595 ((
T*)¤t_box_data.
myNijDiag[
j])[i] = child_data_array[i].myNijDiag[
j];
596 ((
T*)¤t_box_data.
myNxy_Nyx)[i] = child_data_array[i].myNxy + child_data_array[i].myNyx;
597 ((
T*)¤t_box_data.
myNyz_Nzy)[i] = child_data_array[i].myNyz + child_data_array[i].myNzy;
598 ((
T*)¤t_box_data.
myNzx_Nxz)[i] = child_data_array[i].myNzx + child_data_array[i].myNxz;
599 for (
int j = 0;
j < 3; ++
j)
600 ((
T*)¤t_box_data.
myNijkDiag[
j])[i] = child_data_array[i].myNijkDiag[
j];
601 ((
T*)¤t_box_data.
mySumPermuteNxyz)[i] = child_data_array[i].mySumPermuteNxyz;
602 ((
T*)¤t_box_data.
my2Nxxy_Nyxx)[i] = child_data_array[i].my2Nxxy_Nyxx;
603 ((
T*)¤t_box_data.
my2Nxxz_Nzxx)[i] = child_data_array[i].my2Nxxz_Nzxx;
604 ((
T*)¤t_box_data.
my2Nyyz_Nzyy)[i] = child_data_array[i].my2Nyyz_Nzyy;
605 ((
T*)¤t_box_data.
my2Nyyx_Nxyy)[i] = child_data_array[i].my2Nyyx_Nxyy;
606 ((
T*)¤t_box_data.
my2Nzzx_Nxzz)[i] = child_data_array[i].my2Nzzx_Nxzz;
607 ((
T*)¤t_box_data.
my2Nzzy_Nyzz)[i] = child_data_array[i].my2Nzzy_Nyzz;
609 for (
int i = nchildren; i < BVH_N; ++i)
612 for (
int j = 0;
j < 3; ++
j)
617 for (
int j = 0;
j < 3; ++
j)
628 for (
int i = 0; i < nchildren; ++i)
630 const LocalData &child_data = child_data_array[i];
635 data_for_parent->myNijDiag += N*displacement;
636 T Nxy = child_data.myNxy + N.
x()*displacement.y();
637 T Nyx = child_data.myNyx + N.
y()*displacement.x();
638 T Nyz = child_data.myNyz + N.
y()*displacement.z();
639 T Nzy = child_data.myNzy + N.
z()*displacement.y();
640 T Nzx = child_data.myNzx + N.
z()*displacement.x();
641 T Nxz = child_data.myNxz + N.
x()*displacement.z();
643 data_for_parent->myNxy += Nxy;
644 data_for_parent->myNyx += Nyx;
645 data_for_parent->myNyz += Nyz;
646 data_for_parent->myNzy += Nzy;
647 data_for_parent->myNzx += Nzx;
648 data_for_parent->myNxz += Nxz;
650 #if TAYLOR_SERIES_ORDER >= 2
654 data_for_parent->myNijkDiag +=
T(2)*displacement*child_data.myNijDiag + displacement*displacement*child_data.myN;
655 data_for_parent->mySumPermuteNxyz +=
dot(displacement,
UT_Vector3T<T>(Nyz+Nzy, Nzx+Nxz, Nxy+Nyx));
656 data_for_parent->my2Nxxy_Nyxx +=
657 2*(displacement.y()*child_data.myNijDiag.x() + displacement.x()*child_data.myNxy + N.
x()*displacement.x()*displacement.y())
658 + 2*child_data.myNyx*displacement.x() + N.
y()*displacement.x()*displacement.x();
659 data_for_parent->my2Nxxz_Nzxx +=
660 2*(displacement.z()*child_data.myNijDiag.x() + displacement.x()*child_data.myNxz + N.
x()*displacement.x()*displacement.z())
661 + 2*child_data.myNzx*displacement.x() + N.
z()*displacement.x()*displacement.x();
662 data_for_parent->my2Nyyz_Nzyy +=
663 2*(displacement.z()*child_data.myNijDiag.y() + displacement.y()*child_data.myNyz + N.
y()*displacement.y()*displacement.z())
664 + 2*child_data.myNzy*displacement.y() + N.
z()*displacement.y()*displacement.y();
665 data_for_parent->my2Nyyx_Nxyy +=
666 2*(displacement.x()*child_data.myNijDiag.y() + displacement.y()*child_data.myNyx + N.
y()*displacement.y()*displacement.x())
667 + 2*child_data.myNxy*displacement.y() + N.
x()*displacement.y()*displacement.y();
668 data_for_parent->my2Nzzx_Nxzz +=
669 2*(displacement.x()*child_data.myNijDiag.z() + displacement.z()*child_data.myNzx + N.
z()*displacement.z()*displacement.x())
670 + 2*child_data.myNxz*displacement.z() + N.
x()*displacement.z()*displacement.z();
671 data_for_parent->my2Nzzy_Nyzz +=
672 2*(displacement.y()*child_data.myNijDiag.z() + displacement.z()*child_data.myNzy + N.
z()*displacement.z()*displacement.y())
673 + 2*child_data.myNyz*displacement.z() + N.
y()*displacement.z()*displacement.z();
679 #if SOLID_ANGLE_DEBUG
683 #if TAYLOR_SERIES_ORDER >= 1
686 #if TAYLOR_SERIES_ORDER >= 2
697 #if SOLID_ANGLE_TIME_PRECOMPUTE
700 const PrecomputeFunctors functors(box_data, triangle_boxes.
array(), triangle_points, positions,
order);
702 LocalData local_data;
703 myTree.template traverseParallel<LocalData>(4096, functors, &local_data);
705 #if SOLID_ANGLE_TIME_PRECOMPUTE
711 template<
typename T,
typename S>
719 myTrianglePoints =
nullptr;
721 myPositions =
nullptr;
724 template<
typename T,
typename S>
727 const T accuracy_scale2 = accuracy_scale*accuracy_scale;
729 struct SolidAngleFunctors
731 const BoxData *
const myBoxData;
733 const T myAccuracyScale2;
735 const int *
const myTrianglePoints;
741 const T accuracy_scale2,
744 const int *
const triangle_points)
745 : myBoxData(box_data)
746 , myQueryPoint(query_point)
747 , myAccuracyScale2(accuracy_scale2)
749 , myPositions(positions)
750 , myTrianglePoints(triangle_points)
752 uint pre(
const int nodei,
T *data_for_parent)
const
761 const typename BoxData::Type qlength2 = q[0]*q[0] + q[1]*q[1] + q[2]*q[2];
767 v4uu descend_mask = (qlength2 <= maxP2*myAccuracyScale2);
768 uint descend_bitmask = _mm_movemask_ps(
V4SF(descend_mask.
vector));
769 constexpr
uint allchildbits = ((
uint(1)<<BVH_N)-1);
770 if (descend_bitmask == allchildbits)
772 *data_for_parent = 0;
786 #if TAYLOR_SERIES_ORDER >= 1
791 const typename BoxData::Type qlength_m3 = qlength_m2*qlength_m1;
798 Omega_approx += Omega_1;
799 #if TAYLOR_SERIES_ORDER >= 2
803 const typename BoxData::Type qlength_m4 = qlength_m2*qlength_m2;
817 Omega_approx += Omega_2;
825 const v4uu mask = Omega_approx.isFinite() & ~descend_mask;
826 Omega_approx = Omega_approx &
mask;
827 descend_bitmask = (~_mm_movemask_ps(
V4SF(mask.vector))) & allchildbits;
829 T sum = Omega_approx[0];
830 for (
int i = 1; i < BVH_N; ++i)
831 sum += Omega_approx[i];
832 *data_for_parent = sum;
834 return descend_bitmask;
836 void item(
const int itemi,
const int parent_nodei,
T &data_for_parent)
const
839 const int *
const cur_triangle_points = myTrianglePoints + 3*itemi;
846 SYS_FORCE_INLINE void post(
const int nodei,
const int parent_nodei,
T *data_for_parent,
const int nchildren,
const T *child_data_array,
const uint descend_bits)
const
848 T sum = (descend_bits&1) ? child_data_array[0] : 0;
849 for (
int i = 1; i < nchildren; ++i)
850 sum += ((descend_bits>>i)&1) ? child_data_array[i] : 0;
852 *data_for_parent += sum;
855 const SolidAngleFunctors functors(myData.get(), query_point, accuracy_scale2,
myOrder, myPositions, myTrianglePoints);
858 myTree.traverseVector(functors, &sum);
862 template<
typename T,
typename S>
868 memset(
this,0,
sizeof(*
this));
897 template<
typename T,
typename S>
904 , mySegmentPoints(nullptr)
906 , myPositions(nullptr)
909 template<
typename T,
typename S>
917 template<
typename T,
typename S>
920 const int *
const segment_points,
925 #if SOLID_ANGLE_DEBUG
928 UTdebugFormat(
"Building BVH for {} segments on {} points:", nsegments, npoints);
931 myNSegments = nsegments;
932 mySegmentPoints = segment_points;
934 myPositions = positions;
936 #if SOLID_ANGLE_TIME_PRECOMPUTE
942 if (nsegments < 16*1024)
944 const int *cur_segment_points = segment_points;
945 for (
int i = 0; i < nsegments; ++i, cur_segment_points += 2)
948 box.
initBounds(positions[cur_segment_points[0]]);
956 const int *cur_segment_points = segment_points +
exint(r.begin())*2;
957 for (
int i = r.begin(),
end = r.end(); i <
end; ++i, cur_segment_points += 2)
960 box.
initBounds(positions[cur_segment_points[0]]);
965 #if SOLID_ANGLE_TIME_PRECOMPUTE
970 myTree.template init<UT::BVH_Heuristic::BOX_AREA,S,2>(segment_boxes.
array(), nsegments);
971 #if SOLID_ANGLE_TIME_PRECOMPUTE
973 UTdebugFormat(
"{} s to initialize UT_BVH structure. {} nodes", time, myTree.getNumNodes());
978 const int nnodes = myTree.getNumNodes();
982 myData.reset(box_data);
1007 struct PrecomputeFunctors
1011 const int *
const mySegmentPoints;
1018 const int *segment_points,
1021 : myBoxData(box_data)
1022 , mySegmentBoxes(segment_boxes)
1023 , mySegmentPoints(segment_points)
1024 , myPositions(positions)
1027 constexpr
SYS_FORCE_INLINE bool pre(
const int nodei, LocalData *data_for_parent)
const
1031 void item(
const int itemi,
const int parent_nodei, LocalData &data_for_parent)
const
1034 const int *
const cur_segment_points = mySegmentPoints + 2*itemi;
1039 const UT::Box<S,2> &segment_box = mySegmentBoxes[itemi];
1040 data_for_parent.myBox = segment_box;
1045 const T length = SYSsqrt(length2);
1047 data_for_parent.myAverageP = P;
1048 data_for_parent.myLengthP = P*
length;
1049 data_for_parent.myN =
N;
1050 #if SOLID_ANGLE_DEBUG
1052 UTdebugFormat(
"Triangle {}: P = {}; N = {}; length = {}", itemi, P,
N, length);
1056 data_for_parent.myLength =
length;
1063 data_for_parent.myNijDiag =
T(0);
1064 data_for_parent.myNxy = 0; data_for_parent.myNyx = 0;
1072 data_for_parent.myNijkDiag =
T(0);
1073 data_for_parent.my2Nxxy_Nyxx = 0;
1074 data_for_parent.my2Nyyx_Nxyy = 0;
1078 T integral_xx = ab.
x()*ab.
x()/
T(12);
1079 T integral_xy = ab.
x()*ab.
y()/
T(12);
1080 T integral_yy = ab.
y()*ab.
y()/
T(12);
1081 data_for_parent.myNijkDiag.assign(integral_xx*
N.x(),integral_yy*
N.y());
1082 T Nxxy =
N.x()*integral_xy;
1083 T Nyxx =
N.y()*integral_xx;
1084 T Nyyx =
N.y()*integral_xy;
1085 T Nxyy =
N.x()*integral_yy;
1086 data_for_parent.my2Nxxy_Nyxx = 2*Nxxy + Nyxx;
1087 data_for_parent.my2Nyyx_Nxyy = 2*Nyyx + Nxyy;
1088 #if SOLID_ANGLE_DEBUG
1089 UTdebugFormat(
" integral_xx = {}; yy = {}", integral_xx, integral_yy);
1094 void post(
const int nodei,
const int parent_nodei, LocalData *data_for_parent,
const int nchildren,
const LocalData *child_data_array)
const
1099 BoxData ¤t_box_data = myBoxData[nodei];
1102 ((
T*)¤t_box_data.
myN[0])[0] = N[0];
1103 ((
T*)¤t_box_data.
myN[1])[0] = N[1];
1105 T length = child_data_array[0].myLength;
1107 ((
T*)¤t_box_data.
myAverageP[0])[0] = local_P[0];
1108 ((
T*)¤t_box_data.
myAverageP[1])[0] = local_P[1];
1109 for (
int i = 1; i < nchildren; ++i)
1113 ((
T*)¤t_box_data.
myN[0])[i] = local_N[0];
1114 ((
T*)¤t_box_data.
myN[1])[i] = local_N[1];
1115 lengthP += child_data_array[i].myLengthP;
1116 length += child_data_array[i].myLength;
1118 ((
T*)¤t_box_data.
myAverageP[0])[i] = local_P[0];
1119 ((
T*)¤t_box_data.
myAverageP[1])[i] = local_P[1];
1121 for (
int i = nchildren; i < BVH_N; ++i)
1124 ((
T*)¤t_box_data.
myN[0])[i] = 0;
1125 ((
T*)¤t_box_data.
myN[1])[i] = 0;
1129 data_for_parent->myN =
N;
1130 data_for_parent->myLengthP = lengthP;
1131 data_for_parent->myLength =
length;
1134 for (
int i = 1; i < nchildren; ++i)
1135 box.
combine(child_data_array[i].myBox);
1142 averageP = lengthP/
length;
1144 averageP = vector2TFromFixed(
T(0.5)*(box.
getMin() + box.
getMax()) );
1145 data_for_parent->myAverageP = averageP;
1147 data_for_parent->myBox = box;
1149 for (
int i = 0; i < nchildren; ++i)
1151 const UT::Box<S,2> &local_box(child_data_array[i].myBox);
1154 local_P-vector2TFromFixed(local_box.
getMin()),
1155 vector2TFromFixed(local_box.
getMax())-local_P
1159 for (
int i = nchildren; i < BVH_N; ++i)
1163 ((
T*)¤t_box_data.
myMaxPDist2)[i] = std::numeric_limits<T>::infinity();
1170 data_for_parent->myNijDiag = child_data_array[0].myNijDiag;
1171 data_for_parent->myNxy = 0;
1172 data_for_parent->myNyx = 0;
1173 data_for_parent->myNijkDiag = child_data_array[0].myNijkDiag;
1174 data_for_parent->my2Nxxy_Nyxx = child_data_array[0].my2Nxxy_Nyxx;
1175 data_for_parent->my2Nyyx_Nxyy = child_data_array[0].my2Nyyx_Nxyy;
1177 for (
int i = 1; i < nchildren; ++i)
1179 data_for_parent->myNijDiag += child_data_array[i].myNijDiag;
1180 data_for_parent->myNijkDiag += child_data_array[i].myNijkDiag;
1181 data_for_parent->my2Nxxy_Nyxx += child_data_array[i].my2Nxxy_Nyxx;
1182 data_for_parent->my2Nyyx_Nxyy += child_data_array[i].my2Nyyx_Nxyy;
1184 for (
int j = 0;
j < 2; ++
j)
1185 ((
T*)¤t_box_data.
myNijDiag[
j])[0] = child_data_array[0].myNijDiag[
j];
1186 ((
T*)¤t_box_data.
myNxy_Nyx)[0] = child_data_array[0].myNxy + child_data_array[0].myNyx;
1187 for (
int j = 0;
j < 2; ++
j)
1188 ((
T*)¤t_box_data.
myNijkDiag[
j])[0] = child_data_array[0].myNijkDiag[
j];
1189 ((
T*)¤t_box_data.
my2Nxxy_Nyxx)[0] = child_data_array[0].my2Nxxy_Nyxx;
1190 ((
T*)¤t_box_data.
my2Nyyx_Nxyy)[0] = child_data_array[0].my2Nyyx_Nxyy;
1191 for (
int i = 1; i < nchildren; ++i)
1193 for (
int j = 0;
j < 2; ++
j)
1194 ((
T*)¤t_box_data.
myNijDiag[
j])[i] = child_data_array[i].myNijDiag[
j];
1195 ((
T*)¤t_box_data.
myNxy_Nyx)[i] = child_data_array[i].myNxy + child_data_array[i].myNyx;
1196 for (
int j = 0;
j < 2; ++
j)
1197 ((
T*)¤t_box_data.
myNijkDiag[
j])[i] = child_data_array[i].myNijkDiag[
j];
1198 ((
T*)¤t_box_data.
my2Nxxy_Nyxx)[i] = child_data_array[i].my2Nxxy_Nyxx;
1199 ((
T*)¤t_box_data.
my2Nyyx_Nxyy)[i] = child_data_array[i].my2Nyyx_Nxyy;
1201 for (
int i = nchildren; i < BVH_N; ++i)
1204 for (
int j = 0;
j < 2; ++
j)
1207 for (
int j = 0;
j < 2; ++
j)
1213 for (
int i = 0; i < nchildren; ++i)
1215 const LocalData &child_data = child_data_array[i];
1220 data_for_parent->myNijDiag += N*displacement;
1221 T Nxy = child_data.myNxy + N.
x()*displacement.y();
1222 T Nyx = child_data.myNyx + N.
y()*displacement.x();
1224 data_for_parent->myNxy += Nxy;
1225 data_for_parent->myNyx += Nyx;
1230 data_for_parent->myNijkDiag +=
T(2)*displacement*child_data.myNijDiag + displacement*displacement*child_data.myN;
1231 data_for_parent->my2Nxxy_Nyxx +=
1232 2*(displacement.y()*child_data.myNijDiag.x() + displacement.x()*child_data.myNxy + N.
x()*displacement.x()*displacement.y())
1233 + 2*child_data.myNyx*displacement.x() + N.
y()*displacement.x()*displacement.x();
1234 data_for_parent->my2Nyyx_Nxyy +=
1235 2*(displacement.x()*child_data.myNijDiag.y() + displacement.y()*child_data.myNyx + N.
y()*displacement.y()*displacement.x())
1236 + 2*child_data.myNxy*displacement.y() + N.
x()*displacement.y()*displacement.y();
1240 #if SOLID_ANGLE_DEBUG
1252 #if SOLID_ANGLE_TIME_PRECOMPUTE
1255 const PrecomputeFunctors functors(box_data, segment_boxes.
array(), segment_points, positions,
order);
1257 LocalData local_data;
1258 myTree.template traverseParallel<LocalData>(4096, functors, &local_data);
1260 #if SOLID_ANGLE_TIME_PRECOMPUTE
1261 time = timer.
stop();
1266 template<
typename T,
typename S>
1274 mySegmentPoints =
nullptr;
1276 myPositions =
nullptr;
1279 template<
typename T,
typename S>
1282 const T accuracy_scale2 = accuracy_scale*accuracy_scale;
1284 struct AngleFunctors
1286 const BoxData *
const myBoxData;
1288 const T myAccuracyScale2;
1290 const int *
const mySegmentPoints;
1294 const BoxData *
const box_data,
1296 const T accuracy_scale2,
1299 const int *
const segment_points)
1300 : myBoxData(box_data)
1301 , myQueryPoint(query_point)
1302 , myAccuracyScale2(accuracy_scale2)
1304 , myPositions(positions)
1305 , mySegmentPoints(segment_points)
1307 uint pre(
const int nodei,
T *data_for_parent)
const
1315 const typename BoxData::Type qlength2 = q[0]*q[0] + q[1]*q[1];
1321 v4uu descend_mask = (qlength2 <= maxP2*myAccuracyScale2);
1322 uint descend_bitmask = _mm_movemask_ps(
V4SF(descend_mask.
vector));
1323 constexpr
uint allchildbits = ((
uint(1)<<BVH_N)-1);
1324 if (descend_bitmask == allchildbits)
1326 *data_for_parent = 0;
1327 return allchildbits;
1348 Omega_approx += Omega_1;
1352 const typename BoxData::Type qlength_m3 = qlength_m2*qlength_m1;
1364 Omega_approx += Omega_2;
1370 const v4uu mask = Omega_approx.isFinite() & ~descend_mask;
1371 Omega_approx = Omega_approx &
mask;
1372 descend_bitmask = (~_mm_movemask_ps(
V4SF(mask.vector))) & allchildbits;
1374 T sum = Omega_approx[0];
1375 for (
int i = 1; i < BVH_N; ++i)
1376 sum += Omega_approx[i];
1377 *data_for_parent = sum;
1379 return descend_bitmask;
1381 void item(
const int itemi,
const int parent_nodei,
T &data_for_parent)
const
1384 const int *
const cur_segment_points = mySegmentPoints + 2*itemi;
1390 SYS_FORCE_INLINE void post(
const int nodei,
const int parent_nodei,
T *data_for_parent,
const int nchildren,
const T *child_data_array,
const uint descend_bits)
const
1392 T sum = (descend_bits&1) ? child_data_array[0] : 0;
1393 for (
int i = 1; i < nchildren; ++i)
1394 sum += ((descend_bits>>i)&1) ? child_data_array[i] : 0;
1396 *data_for_parent += sum;
1399 const AngleFunctors functors(myData.get(), query_point, accuracy_scale2,
myOrder, myPositions, mySegmentPoints);
1402 myTree.traverseVector(functors, &sum);
constexpr SYS_FORCE_INLINE T length2() const noexcept
SYS_FORCE_INLINE UT_FixedVector< T, NAXES > getMax() const noexcept
void UTparallelFor(const Range &range, const Body &body, const int subscribe_ratio=2, const int min_grain_size=1, const bool force_use_task_scope=true)
typename SYS_SelectType< UT_FixedVector< S, BVH_N >, v4uf, BVH_N==4 &&SYS_IsSame< S, float >::value >::type SType
Axis-aligned bounding box (AABB).
#define SYS_STATIC_ASSERT_MSG(expr, msg)
SYS_FORCE_INLINE void initBounds() noexcept
void swap(UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &a, UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &b)
GT_API const UT_StringHolder time
void setSizeNoInit(exint newsize)
UT_FixedVector< Type, 2 > myNijDiag
vfloat4 sqrt(const vfloat4 &a)
GLdouble GLdouble GLdouble z
SIM_API const UT_StringHolder local_P
constexpr SYS_FORCE_INLINE T & z() noexcept
UT_Vector3T< T > maxvec() const
GLboolean GLboolean GLboolean GLboolean a
GLuint GLsizei GLsizei * length
UT_FixedVector< Type, 3 > myNijkDiag
typename SYS_SelectType< UT_FixedVector< T, BVH_N >, v4uf, BVH_N==4 &&SYS_IsSame< T, float >::value >::type Type
constexpr SYS_FORCE_INLINE T length() const noexcept
#define UT_ASSERT_MSG_P(ZZ,...)
GLdouble GLdouble GLdouble q
~UT_SolidAngle()
This is outlined so that we don't need to include UT_BVHImpl.h.
constexpr UT_FixedVector< T, D > productComponentwise(const UT_FixedVector< T, D > &a, const UT_FixedVector< T, D > &b) noexcept
constexpr SYS_FORCE_INLINE T & x() noexcept
UT_SolidAngle()
This is outlined so that we don't need to include UT_BVHImpl.h.
typename SYS_SelectType< UT_FixedVector< S, BVH_N >, v4uf, BVH_N==4 &&SYS_IsSame< S, float >::value >::type SType
fpreal64 dot(const CE_VectorT< T > &a, const CE_VectorT< T > &b)
void clear()
Frees myTree and myData, and clears the rest.
UT_FixedVector< Type, 3 > myN
Unnormalized, area-weighted normal of the mesh in this box.
void init(const int nsegments, const int *const segment_points, const int npoints, const UT_Vector2T< S > *const positions, const int order=2)
T computeSolidAngle(const UT_Vector3T< T > &query_point, const T accuracy_scale=T(2.0)) const
SType myMaxPDist2
An upper bound on the squared distance from myAverageP to the farthest point in the box...
GLdouble GLdouble GLint GLint order
GLboolean GLboolean GLboolean b
void enlargeBounds(const UT_Vector3T< T > &min, const UT_Vector3T< T > &max)
UT_FixedVector< Type, 2 > myAverageP
Centre of mass of the mesh surface in this box.
void init(const int ntriangles, const int *const triangle_points, const int npoints, const UT_Vector3T< S > *const positions, const int order=2)
typename SYS_SelectType< UT_FixedVector< T, BVH_N >, v4uf, BVH_N==4 &&SYS_IsSame< T, float >::value >::type Type
T computeAngle(const UT_Vector2T< T > &query_point, const T accuracy_scale=T(2.0)) const
T UTsignedAngleSegment(const UT_Vector2T< T > &a, const UT_Vector2T< T > &b, const UT_Vector2T< T > &query)
UT_FixedVector< Type, 2 > myNijkDiag
constexpr SYS_FORCE_INLINE T length2() const noexcept
UT_SubtendedAngle()
This is outlined so that we don't need to include UT_BVHImpl.h.
SYS_FORCE_INLINE UT_FixedVector< T, NAXES > getMin() const noexcept
UT_FixedVector< Type, 3 > myAverageP
Centre of mass of the mesh surface in this box.
GLenum GLsizei GLsizei GLint * values
SYS_FORCE_INLINE void enlargeBounds(const TS &pt) noexcept
UT_Vector3T< T > minvec() const
GA_API const UT_StringHolder N
void clear()
Frees myTree and myData, and clears the rest.
UT_FixedVector< Type, 3 > myNijDiag
SType myMaxPDist2
An upper bound on the squared distance from myAverageP to the farthest point in the box...
~UT_SubtendedAngle()
This is outlined so that we don't need to include UT_BVHImpl.h.
constexpr SYS_FORCE_INLINE T & y() noexcept
SYS_FORCE_INLINE void combine(const Box< T, NAXES > &src) noexcept
T UTsignedSolidAngleTri(const UT_Vector3T< T > &a, const UT_Vector3T< T > &b, const UT_Vector3T< T > &c, const UT_Vector3T< T > &query)
SIM_DerVector3 cross(const SIM_DerVector3 &lhs, const SIM_DerVector3 &rhs)
constexpr SYS_FORCE_INLINE T & y() noexcept
UT_FixedVector< Type, 2 > myN
Unnormalized, area-weighted normal of the mesh in this box.
GA_API const UT_StringHolder area
#define UTdebugFormat(...)
constexpr SYS_FORCE_INLINE T & x() noexcept