16 #ifndef INCLUDE_NN_NLIB_SIMD_SIMDGEOMETRY_H_ 17 #define INCLUDE_NN_NLIB_SIMD_SIMDGEOMETRY_H_ 157 static f128 __vectorcall
165 static f128 __vectorcall
173 static f128 __vectorcall
198 PLANE_FRONT = kPlaneFront,
199 PLANE_INTERSECT = kPlaneInterect,
200 PLANE_BACK = kPlaneBack
211 static bool __vectorcall SphereRay(
float* distance,
SimdSphereArg sphere,
218 static bool __vectorcall TriangleRay(
float* distance,
SimdVectorArg triangle_point0,
227 static bool __vectorcall
239 static bool __vectorcall
241 static bool __vectorcall
244 static bool __vectorcall AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
249 static bool __vectorcall
251 static bool __vectorcall
253 static bool __vectorcall
255 static bool __vectorcall OrientedBoxTriangle(
const OrientedBox& box,
264 static bool __vectorcall
266 static bool __vectorcall
268 static bool __vectorcall
294 static bool __vectorcall
296 static bool __vectorcall
298 static bool __vectorcall
300 static bool __vectorcall
304 static bool __vectorcall
306 static bool __vectorcall AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
310 static bool __vectorcall
312 static bool __vectorcall
315 static bool __vectorcall
317 static bool __vectorcall
321 static bool __vectorcall
323 static bool __vectorcall OrientedBoxTriangle(
const OrientedBox& box,
327 static bool __vectorcall OrientedBoxOrientedBox(
const OrientedBox& box,
329 static bool __vectorcall
331 static bool __vectorcall
333 static bool __vectorcall
337 static bool __vectorcall
342 static bool __vectorcall
344 static bool __vectorcall
346 static bool __vectorcall
348 static bool __vectorcall
357 #define NLIB_M(tp) inline tp __vectorcall 358 #define NLIB_B inline bool __vectorcall 364 # pragma region Plane 368 return Vector4::Dot(plane, vec);
373 return Vector4::Dot(plane, F128::SetFloatToLane<3>(vec, 1.f));
378 return Vector3::Dot(plane, vec);
384 f128 dot = Vector3::Dot(point, normal);
385 dot = F128::Negate(dot);
386 return F128::Splat<false, false, false, true>(normal, dot);
394 SimdVector normal = Vector3::Normalize(Vector3::Cross(v10, v20));
395 return FromPointAndNormal(point0, normal);
401 return F128::Mult(Vector3::RecpLength(plane), plane);
406 return F128::Mult(Vector3::RecpLengthEst(plane), plane);
411 return Vector4::Transform(plane, m);
414 # pragma endregion Plane function implementation 421 # pragma region Sphere 426 SimdVector center = Vector3::Transform(sphere, m);
427 f128 dot_x = Vector3::Dot(m.
r[0], m.
r[0]);
428 f128 dot_y = Vector3::Dot(m.
r[1], m.
r[1]);
429 f128 dot_z = Vector3::Dot(m.
r[2], m.
r[2]);
430 f128 scale = F128::Max(dot_x, dot_y);
431 scale = F128::Max(scale, dot_z);
432 radius = F128::Mult(radius, scale);
434 return F128::Splat<false, false, false, true>(center, radius);
440 f128 min_x, min_y, min_z;
441 f128 max_x, max_y, max_z;
442 min_x = min_y = min_z = max_x = max_y = max_z = Vector3::LoadFloat3(points);
445 for (i = 1; i < count; ++i) {
447 f128 pt = Vector3::LoadFloat3(points + i);
450 cmp0 = F128::CmpLt(pt_x, F128::SetValue<0>(min_x,
each_select32));
451 min_x = F128::Select(cmp0, pt, min_x);
452 cmp1 = F128::CmpGt(pt_x, F128::SetValue<0>(max_x,
each_select32));
453 max_x = F128::Select(cmp1, pt, max_x);
456 cmp0 = F128::CmpLt(pt_y, F128::SetValue<0>(min_y,
each_select32));
457 min_y = F128::Select(cmp0, pt, min_y);
458 cmp1 = F128::CmpGt(pt_y, F128::SetValue<0>(max_y,
each_select32));
459 max_y = F128::Select(cmp1, pt, max_y);
462 cmp0 = F128::CmpLt(pt_z, F128::SetValue<0>(min_z,
each_select32));
463 min_z = F128::Select(cmp0, pt, min_z);
464 cmp1 = F128::CmpGt(pt_z, F128::SetValue<0>(max_z,
each_select32));
465 max_z = F128::Select(cmp1, pt, max_z);
472 f128 distsq_x = Vector3::LengthSq(F128::Sub(max_x, min_x));
473 f128 distsq_y = Vector3::LengthSq(F128::Sub(max_y, min_y));
474 f128 distsq_z = Vector3::LengthSq(F128::Sub(max_z, min_z));
475 if (Vector4::CmpGt(distsq_x, distsq_y)) {
476 if (Vector4::CmpGt(distsq_x, distsq_z)) {
477 center = F128::Lerp(min_x, max_x, c1_2);
478 radius = F128::Mult(F128::Sqrt(distsq_x), c1_2);
480 center = F128::Lerp(min_z, max_z, c1_2);
481 radius = F128::Mult(F128::Sqrt(distsq_z), c1_2);
484 if (Vector4::CmpGt(distsq_y, distsq_z)) {
485 center = F128::Lerp(min_y, max_y, c1_2);
486 radius = F128::Mult(F128::Sqrt(distsq_y), c1_2);
488 center = F128::Lerp(min_z, max_z, c1_2);
489 radius = F128::Mult(F128::Sqrt(distsq_z), c1_2);
494 f128 radsq = F128::Mult(radius, radius);
495 for (i = 0; i < count; ++i) {
496 f128 pt = Vector3::LoadFloat3(points + i);
497 f128 diff = F128::Sub(pt, center);
498 f128 distsq = Vector3::LengthSq(diff);
499 if (Vector3::CmpGt(distsq, radsq)) {
500 f128 dist = F128::Sqrt(distsq);
501 f128 t = F128::Div(radius, dist);
502 t = F128::MultSub(c1_2, t, c1_2);
503 radius = F128::Mult(c1_2, F128::Add(radius, dist));
504 radsq = F128::Mult(radius, radius);
505 center = F128::MultAdd(t, diff, center);
509 return F128::Splat<false, false, false, true>(center, radius);
514 SimdVector diff = F128::Sub(sphere1, sphere0);
515 f128 dist_sq = Vector3::LengthSq(diff);
517 f128 is_contained = F128::CmpLe(dist_sq, radius_diff_sq);
519 f128 dist = F128::Sqrt(dist_sq);
522 f128 new_radius = F128::Add(r0, r1);
523 new_radius = F128::Add(new_radius, dist);
524 new_radius = F128::Mult(0.5f, new_radius);
526 f128 t = F128::Div(diff, dist);
527 f128 use_new_center = F128::CmpGt(dist, F128::SetEpsilon());
530 ret = F128::MultAdd(t, F128::Sub(new_radius, r0), sphere0);
531 ret = F128::Select(use_new_center, ret, sphere0);
532 ret = F128::Splat<false, false, false, true>(ret, new_radius);
534 f128 s0_contained = F128::And(is_contained, F128::CmpLt(r0, r1));
535 f128 s1_contained = F128::And(is_contained, F128::CmpGe(r0, r1));
536 ret = F128::Select(s0_contained, sphere1, ret);
537 ret = F128::Select(s1_contained, sphere0, ret);
542 return F128::GetFloatFromLane<3>(sphere);
546 return F128::SetFloatToLane<3>(sphere, radius);
554 return F128::Permute<4, 5, 6, 3>(sphere, center);
557 # pragma endregion Sphere function implementation 564 # pragma region AxisAlignedBox 566 inline AxisAlignedBox::AxisAlignedBox(
const Float3& pmin,
const Float3& pmax) {
567 Vector3::LoadFloat3(&pmin);
568 Vector3::LoadFloat3(&pmax);
574 f128 p1 = F128::Splat<true, false, false, false>(point_min, point_max);
575 f128 p2 = F128::Splat<true, true, false, false>(point_min, point_max);
576 f128 p3 = F128::Splat<false, true, false, false>(point_min, point_max);
577 f128 p4 = F128::Splat<false, true, true, true>(point_min, point_max);
578 f128 p5 = F128::Splat<false, false, true, true>(point_min, point_max);
579 f128 p6 = F128::Splat<true, false, true, true>(point_min, point_max);
582 Vector3::StoreFloat3(corners + 0, p0);
583 Vector3::StoreFloat3(corners + 1, p1);
584 Vector3::StoreFloat3(corners + 2, p2);
585 Vector3::StoreFloat3(corners + 3, p3);
586 Vector3::StoreFloat3(corners + 4, p4);
587 Vector3::StoreFloat3(corners + 5, p5);
588 Vector3::StoreFloat3(corners + 6, p6);
589 Vector3::StoreFloat3(corners + 7, p7);
593 inline void __vectorcall
596 f128 p1 = F128::Splat<true, false, false, false>(point_min, point_max);
597 f128 p2 = F128::Splat<true, true, false, false>(point_min, point_max);
598 f128 p3 = F128::Splat<false, true, false, false>(point_min, point_max);
599 f128 p4 = F128::Splat<false, true, true, true>(point_min, point_max);
600 f128 p5 = F128::Splat<false, false, true, true>(point_min, point_max);
601 f128 p6 = F128::Splat<true, false, true, true>(point_min, point_max);
604 p0 = Vector3::Transform(p0, m);
605 p1 = Vector3::Transform(p1, m);
606 p2 = Vector3::Transform(p2, m);
607 p3 = Vector3::Transform(p3, m);
608 p4 = Vector3::Transform(p4, m);
609 p5 = Vector3::Transform(p5, m);
610 p6 = Vector3::Transform(p6, m);
611 p7 = Vector3::Transform(p7, m);
614 pmin = F128::Min(p0, p1);
615 pmax = F128::Max(p0, p1);
616 pmin = F128::Min(pmin, p2);
617 pmax = F128::Max(pmax, p2);
618 pmin = F128::Min(pmin, p3);
619 pmax = F128::Max(pmax, p3);
620 pmin = F128::Min(pmin, p4);
621 pmax = F128::Max(pmax, p4);
622 pmin = F128::Min(pmin, p5);
623 pmax = F128::Max(pmax, p5);
624 pmin = F128::Min(pmin, p6);
625 pmax = F128::Max(pmax, p6);
626 pmin = F128::Min(pmin, p7);
627 pmax = F128::Max(pmax, p7);
640 inline void __vectorcall
650 box->
point_min = F128::Min(point0, point1);
651 box->
point_max = F128::Max(point0, point1);
658 pmin = pmax = Vector3::LoadFloat3(points);
659 for (
size_t i = 1; i < count; ++i) {
660 f128 pt = Vector3::LoadFloat3(points + i);
661 pmin = F128::Min(pmin, pt);
662 pmax = F128::Max(pmax, pt);
668 # pragma endregion AxisAlignedBox function implementation 675 # pragma region OrientedBox 680 box->
center = Vector3::Transform(this->center, m);
681 f128 inv_dx = Vector3::RecpLength(m.
r[0]);
682 f128 inv_dy = Vector3::RecpLength(m.
r[1]);
683 f128 inv_dz = Vector3::RecpLength(m.
r[2]);
687 rot_matrix.
r[0] = F128::Mult(m.
r[0], inv_dx);
688 rot_matrix.
r[1] = F128::Mult(m.
r[1], inv_dy);
689 rot_matrix.
r[2] = F128::Mult(m.
r[2], inv_dz);
690 rot_matrix.
r[3] = F128::Set0001();
692 box->
rotation = Quaternion::Mult(this->rotation, rot);
696 scale = F128::Permute<0, 4, -1, -1>(inv_dx, inv_dy);
697 scale = F128::Permute<0, 1, 4, -1>(scale, inv_dz);
698 box->
extent = F128::Div(this->extent, scale);
703 f128 point_max = F128::Add(center, extent);
704 f128 point_min = F128::Sub(center, extent);
705 point_max = F128::SetZeroToLane<3>(point_max);
706 point_min = F128::SetZeroToLane<3>(point_min);
710 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
711 Vector3::StoreFloat3(corners + 0, pt);
713 pt = F128::Splat<true, false, false, false>(point_min, point_max);
714 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
715 Vector3::StoreFloat3(corners + 1, pt);
717 pt = F128::Splat<true, true, false, false>(point_min, point_max);
718 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
719 Vector3::StoreFloat3(corners + 2, pt);
721 pt = F128::Splat<false, true, false, false>(point_min, point_max);
722 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
723 Vector3::StoreFloat3(corners + 3, pt);
725 pt = F128::Splat<false, true, true, true>(point_min, point_max);
726 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
727 Vector3::StoreFloat3(corners + 4, pt);
729 pt = F128::Splat<false, false, true, true>(point_min, point_max);
730 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
731 Vector3::StoreFloat3(corners + 5, pt);
733 pt = F128::Splat<true, false, true, true>(point_min, point_max);
734 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
735 Vector3::StoreFloat3(corners + 6, pt);
738 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
739 Vector3::StoreFloat3(corners + 7, pt);
743 inline void OrientedBox::FromAxisAlignedBox(
OrientedBox* box,
749 box->
center = F128::MultAdd(c1_2, box_min, half);
750 box->
extent = F128::MultSub(c1_2, box_min, half);
754 # pragma endregion OrientedBox function implementation 761 # pragma region Capsule 764 f128 sphere_ = Vector3::LoadFloat3(&pt0);
765 point = Vector3::LoadFloat3(&pt1);
766 sphere = F128::SetFloatToLane<3>(sphere_, radius);
770 capsule->sphere = Sphere::Transform(sphere, m);
771 capsule->point = Vector3::Transform(point, m);
774 # pragma endregion Capsule function implementation 781 # pragma region Frustum 785 rotation_(rhs.rotation_),
786 near_plane_(rhs.near_plane_),
787 far_plane_(rhs.far_plane_),
788 top_plane_(rhs.top_plane_),
789 bottom_plane_(rhs.bottom_plane_),
790 left_plane_(rhs.left_plane_),
791 right_plane_(rhs.right_plane_) {
795 center_ = rhs.center_;
796 rotation_ = rhs.rotation_;
797 near_plane_ = rhs.near_plane_;
798 far_plane_ = rhs.far_plane_;
799 top_plane_ = rhs.top_plane_;
800 bottom_plane_ = rhs.bottom_plane_;
801 left_plane_ = rhs.left_plane_;
802 right_plane_ = rhs.right_plane_;
809 NLIB_ASSERT(n > 0.f);
811 rotation_ = rotation;
812 near_plane_ = Plane::Normalize(F128::SetValue(0.f, 0.f, 1.f, n));
813 far_plane_ = Plane::Normalize(F128::SetValue(0.f, 0.f, -1.f, -f));
814 top_plane_ = Plane::Normalize(F128::SetValue(0.f, 1.f, top / n, 0.f));
815 bottom_plane_ = Plane::Normalize(F128::SetValue(0.f, -1.f, -bottom / n, 0.f));
816 left_plane_ = Plane::Normalize(F128::SetValue(-1.f, 0.f, -left / n, 0.f));
817 right_plane_ = Plane::Normalize(F128::SetValue(1.f, 0.f, right / n, 0.f));
821 float bottom,
float left,
float right,
float n,
824 NLIB_ASSERT(n > 0.f);
826 rotation_ = rotation;
827 near_plane_ = Plane::Normalize(F128::SetValue(0.f, 0.f, 1.f, n));
828 far_plane_ = Plane::Normalize(F128::SetValue(0.f, 0.f, -1.f, -f));
829 top_plane_ = Plane::Normalize(F128::SetValue(0.f, 1.f, top / n, 0.f));
830 bottom_plane_ = Plane::Normalize(F128::SetValue(0.f, -1.f, -bottom / n, 0.f));
831 left_plane_ = Plane::Normalize(F128::SetValue(-1.f, 0.f, -left / n, 0.f));
832 right_plane_ = Plane::Normalize(F128::SetValue(1.f, 0.f, right / n, 0.f));
835 inline void __vectorcall Frustum::Transform(
Frustum* frustum,
float scale,
838 f128 s = F128::SetValue(1.f, 1.f, 1.f, scale);
839 frustum->rotation_ = Quaternion::Mult(rotation_, rotation);
840 SimdVector center = Vector3::Rotate(F128::Mult(scale, center_), rotation);
841 frustum->center_ = F128::Add(center, translation);
842 frustum->top_plane_ = top_plane_;
843 frustum->bottom_plane_ = bottom_plane_;
844 frustum->left_plane_ = left_plane_;
845 frustum->right_plane_ = right_plane_;
846 frustum->near_plane_ = F128::Mult(s, near_plane_);
847 frustum->far_plane_ = F128::Mult(s, far_plane_);
858 M.
r[0] = Vector3::Normalize(r0);
859 M.
r[1] = Vector3::Normalize(r1);
860 M.
r[2] = Vector3::Normalize(r2);
861 M.
r[3] = F128::Set0001();
863 frustum->rotation_ = Quaternion::Mult(rotation, rot);
864 frustum->center_ = Vector3::Transform(center, m);
869 f128 x_sq = Vector3::LengthSq(r0);
870 f128 y_sq = Vector3::LengthSq(r1);
871 f128 z_sq = Vector3::LengthSq(r2);
872 f128 sq = F128::Max(z_sq, F128::Max(x_sq, y_sq));
873 scale = F128::GetFloatFromLane<0>(F128::Sqrt(sq));
876 f128 s = F128::SetValue(1.f, 1.f, 1.f, scale);
877 frustum->top_plane_ = top_plane_;
878 frustum->bottom_plane_ = bottom_plane_;
879 frustum->left_plane_ = left_plane_;
880 frustum->right_plane_ = right_plane_;
881 frustum->near_plane_ = F128::Mult(s, near_plane_);
882 frustum->far_plane_ = F128::Mult(s, far_plane_);
886 float n = F128::GetFloatFromLane<3>(near_plane_) / F128::GetFloatFromLane<2>(near_plane_);
887 float f = F128::GetFloatFromLane<3>(far_plane_) / F128::GetFloatFromLane<2>(far_plane_);
888 float top = F128::GetFloatFromLane<2>(top_plane_) / F128::GetFloatFromLane<1>(top_plane_);
891 F128::GetFloatFromLane<2>(bottom_plane_) / F128::GetFloatFromLane<1>(bottom_plane_);
893 float left = F128::GetFloatFromLane<2>(left_plane_) / F128::GetFloatFromLane<0>(left_plane_);
896 F128::GetFloatFromLane<2>(right_plane_) / F128::GetFloatFromLane<0>(right_plane_);
904 pt = F128::SetValue(left, top, -n, 0.f);
905 pt = F128::Add(Vector3::Rotate(pt, rot), center);
906 Vector3::StoreFloat3(corners + 0, pt);
909 pt = F128::SetValue(right, top, -n, 0.f);
910 pt = F128::Add(Vector3::Rotate(pt, rot), center);
911 Vector3::StoreFloat3(corners + 1, pt);
914 pt = F128::SetValue(right, bottom, -n, 0.f);
915 pt = F128::Add(Vector3::Rotate(pt, rot), center);
916 Vector3::StoreFloat3(corners + 2, pt);
919 pt = F128::SetValue(left, bottom, -n, 0.f);
920 pt = F128::Add(Vector3::Rotate(pt, rot), center);
921 Vector3::StoreFloat3(corners + 3, pt);
926 pt = F128::SetValue(left * f_n, top * f_n, -f, 0.f);
927 pt = F128::Add(Vector3::Rotate(pt, rot), center);
928 Vector3::StoreFloat3(corners + 4, pt);
931 pt = F128::SetValue(right * f_n, top * f_n, -f, 0.f);
932 pt = F128::Add(Vector3::Rotate(pt, rot), center);
933 Vector3::StoreFloat3(corners + 5, pt);
936 pt = F128::SetValue(right * f_n, bottom * f_n, -f, 0.f);
937 pt = F128::Add(Vector3::Rotate(pt, rot), center);
938 Vector3::StoreFloat3(corners + 6, pt);
941 pt = F128::SetValue(left * f_n, bottom * f_n, -f, 0.f);
942 pt = F128::Add(Vector3::Rotate(pt, rot), center);
943 Vector3::StoreFloat3(corners + 7, pt);
947 # pragma endregion Frustum function implementation 954 # pragma region DistanceSq 958 SimdVector l0_pt = F128::Sub(point, line_point);
959 f128 dot = Vector3::Dot(l0_pt, line_dir_normalized);
960 SimdVector dist_vec = F128::Mult(line_dir_normalized, dot);
961 dist_vec = F128::Sub(l0_pt, dist_vec);
962 return Vector3::LengthSq(dist_vec);
967 SimdVector l0_pt = F128::Sub(point, ray_point);
968 f128 dot = Vector3::Dot(l0_pt, ray_dir_normalized);
969 SimdVector dist_vec = F128::Mult(ray_dir_normalized, dot);
970 dist_vec = F128::Sub(l0_pt, dist_vec);
972 f128 distsq0 = Vector3::LengthSq(dist_vec);
973 f128 distsq1 = Vector3::LengthSq(l0_pt);
974 f128 cmp = F128::CmpLt(dot, F128::SetZero());
975 return F128::Select(cmp, distsq1, distsq0);
980 SimdVector l0_pt = F128::Sub(point, segment_point0);
981 SimdVector l1_pt = F128::Sub(point, segment_point1);
982 SimdVector seg_dir_normalized = F128::Sub(segment_point1, segment_point0);
983 f128 seg_recplen = Vector3::RecpLength(seg_dir_normalized);
984 seg_dir_normalized = F128::Mult(seg_dir_normalized, seg_recplen);
986 f128 dot = Vector3::Dot(l0_pt, seg_dir_normalized);
987 SimdVector dist_vec = F128::Mult(seg_dir_normalized, dot);
988 dist_vec = F128::Sub(l0_pt, dist_vec);
990 f128 distsq0 = Vector3::LengthSq(dist_vec);
991 f128 distsq1 = Vector3::LengthSq(l0_pt);
992 f128 distsq2 = Vector3::LengthSq(l1_pt);
993 f128 cmp = F128::CmpLt(dot, F128::SetZero());
994 f128 ret = F128::Select(cmp, distsq1, distsq0);
995 cmp = F128::CmpLt(F128::Mult(dot, seg_recplen), F128::SetOne());
996 ret = F128::Select(cmp, ret, distsq2);
1003 SimdVector pt = F128::SetZeroToLane<3>(point);
1004 f128 dot = Vector4::Dot(pt, plane_normalized);
1005 f128 ret = F128::Mult(dot, dot);
1006 if (point_on_plane) {
1007 *point_on_plane = F128::Sub(point, F128::Mult(dot, plane_normalized));
1014 SimdVector c = F128::SetZeroToLane<3>(sphere);
1016 f128 dist = F128::Abs(Vector4::Dot(c, plane_normalized));
1017 f128 cmp = F128::CmpGt(dist, r);
1018 f128 ret = F128::Sub(dist, r);
1019 ret = F128::Mult(ret, ret);
1020 return F128::And(cmp, ret);
1027 f128 distsq = F128::Sub(vv, point);
1028 distsq = Vector3::LengthSq(distsq);
1029 if (point_on_box) *point_on_box = vv;
1039 u = F128::Sub(line0_point, line1_point);
1040 f128 b = Vector3::Dot(line0_dir_normalized, line1_dir_normalized);
1041 f128 d = Vector3::Dot(line0_dir_normalized, u);
1042 f128 e = Vector3::Dot(line1_dir_normalized, u);
1043 f128 det = F128::MultSub(b, b, F128::SetOne());
1045 f128 recp_det = F128::Recp(det);
1046 f128 s = F128::MultAdd(b, e, F128::Negate(d));
1047 f128 t = F128::MultSub(b, d, e);
1048 s = F128::Mult(s, recp_det);
1049 t = F128::Mult(t, recp_det);
1051 SimdVector tmp = F128::Mult(s, line0_dir_normalized);
1052 tmp = F128::MultSub(t, line1_dir_normalized, tmp);
1054 ret = Vector3::LengthSq(ret);
1056 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1057 tmp = Vector3::LengthSq(F128::MultSub(e, line1_dir_normalized, u));
1058 ret = F128::Select(parallel, tmp, ret);
1060 if (point_on_line0) {
1061 s = F128::AndNot(parallel, s);
1062 *point_on_line0 = F128::MultAdd(s, line0_dir_normalized, line0_point);
1064 if (point_on_line1) {
1065 t = F128::Select(parallel, e, t);
1066 *point_on_line1 = F128::MultAdd(t, line1_dir_normalized, line1_point);
1073 NLIB_M(
f128) DistanceSq::SegmentSegment(
SimdVector* point_on_segment0,
1079 SimdVector u = F128::Sub(segment0_point1, segment0_point0);
1080 SimdVector v = F128::Sub(segment1_point1, segment1_point0);
1081 SimdVector w = F128::Sub(segment0_point0, segment1_point0);
1082 f128 a = Vector3::LengthSq(u);
1083 f128 b = Vector3::Dot(u, v);
1084 f128 c = Vector3::LengthSq(v);
1085 f128 d = Vector3::Dot(u, w);
1086 f128 e = Vector3::Dot(v, w);
1087 f128 D = F128::MultSub(b, b, F128::Mult(a, c));
1089 f128 epsilon = F128::SetEpsilon();
1092 f128 sN = F128::MultSub(c, d, F128::Mult(b, e));
1093 f128 tN = F128::MultSub(b, d, F128::Mult(a, e));
1096 f128 parallel = F128::CmpLt(D, epsilon);
1097 f128 sN_under = F128::CmpLtZero(sN);
1098 f128 sN_out = F128::Or(sN_under, F128::CmpGt(sN, D));
1099 f128 cmp = F128::Or(parallel, sN_out);
1100 f128 under_or_parallel = F128::Or(parallel, sN_under);
1107 sN = F128::Select(cmp, F128::AndNot(under_or_parallel, D), sN);
1114 tN = F128::Select(cmp, F128::Select(under_or_parallel, e, F128::Add(e, b)), tN);
1121 tD = F128::Select(cmp, c, D);
1125 sD = F128::Select(parallel, F128::SetOne(), D);
1129 f128 tN_under = F128::CmpLtZero(tN);
1130 f128 tN_out = F128::Or(tN_under, F128::CmpGt(tN, tD));
1136 tN = F128::Clamp(tN, F128::SetZero(), tD);
1138 f128 val = F128::Select(tN_under, F128::Negate(d), F128::Sub(b, d));
1144 f128 val_in = F128::And(F128::CmpGeZero(val), F128::CmpLe(val, a));
1145 sD = F128::Select(F128::And(tN_out, val_in), a, sD);
1153 f128 sntmp = F128::AndNot(F128::CmpLtZero(val), val);
1154 sntmp = F128::Select(F128::CmpGt(val, a), sD, sntmp);
1155 sN = F128::Select(tN_out, sntmp, sN);
1158 f128 sc = F128::AndNot(F128::InBound(sN, epsilon), F128::Div(sN, sD));
1159 f128 tc = F128::AndNot(F128::InBound(tN, epsilon), F128::Div(tN, tD));
1162 f128 pt_s0 = F128::MultAdd(sc, u, segment0_point0);
1163 f128 pt_s1 = F128::MultAdd(tc, v, segment1_point0);
1164 f128 ret = F128::Sub(pt_s0, pt_s1);
1165 ret = Vector3::LengthSq(ret);
1167 if (point_on_segment0) *point_on_segment0 = pt_s0;
1168 if (point_on_segment1) *point_on_segment1 = pt_s1;
1177 SimdVector u = F128::Sub(line_point, ray_point);
1178 f128 b = Vector3::Dot(line_dir_normalized, ray_dir_normalized);
1179 f128 d = Vector3::Dot(line_dir_normalized, u);
1180 f128 e = Vector3::Dot(ray_dir_normalized, u);
1181 f128 one = F128::SetOne();
1182 f128 det = F128::MultSub(b, b, one);
1183 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1188 f128 t_num = F128::MultSub(b, d, e);
1189 t_num = F128::Select(parallel, e, t_num);
1190 f128 t_num_negative = F128::CmpLtZero(t_num);
1195 f128 minus_d = F128::Negate(d);
1196 f128 s_num = F128::MultAdd(b, e, minus_d);
1197 s_num = F128::AndNot(parallel, s_num);
1202 f128 t_denom = F128::Select(parallel, one, det);
1207 f128 s_denom = F128::Select(F128::Or(t_num_negative, parallel), one, det);
1212 s_num = F128::Select(t_num_negative, minus_d, s_num);
1217 t_num = F128::AndNot(t_num_negative, t_num);
1219 f128 s = F128::Div(s_num, s_denom);
1220 f128 t = F128::Div(t_num, t_denom);
1222 f128 pt_l = F128::MultAdd(s, line_dir_normalized, line_point);
1223 f128 pt_r = F128::MultAdd(t, ray_dir_normalized, ray_point);
1225 ret = Vector3::LengthSq(ret);
1227 if (point_on_line) *point_on_line = pt_l;
1228 if (point_on_ray) *point_on_ray = pt_r;
1237 SimdVector seg_dir = F128::Sub(segment_point1, segment_point0);
1238 SimdVector u = F128::Sub(line_point, segment_point0);
1239 f128 b = Vector3::Dot(line_dir_normalized, seg_dir);
1240 f128 c = Vector3::LengthSq(seg_dir);
1241 f128 d = Vector3::Dot(line_dir_normalized, u);
1242 f128 e = Vector3::Dot(seg_dir, u);
1243 f128 det = F128::MultSub(b, b, c);
1244 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1249 f128 t_num = F128::Select(parallel, e, F128::MultSub(b, d, e));
1254 f128 t_denom = F128::Select(parallel, c, det);
1259 f128 tmp = F128::Mult(b, e);
1260 tmp = F128::MultSub(c, d, tmp);
1261 f128 s_num = F128::AndNot(parallel, tmp);
1267 f128 tNum_under = F128::CmpLtZero(t_num);
1268 f128 tNum_out = F128::Or(tNum_under, F128::CmpGt(t_num, t_denom));
1269 tmp = F128::Select(tNum_under, F128::Negate(d), F128::Sub(b, d));
1270 s_num = F128::Select(tNum_out, tmp, s_num);
1275 f128 s_denom = F128::Select(F128::Or(tNum_out, parallel), F128::SetOne(), det);
1280 t_num = F128::Clamp(t_num, F128::SetZero(), t_denom);
1282 f128 s = F128::Div(s_num, s_denom);
1283 f128 t = F128::Div(t_num, t_denom);
1285 f128 pt_l = F128::MultAdd(s, line_dir_normalized, line_point);
1286 f128 pt_s = F128::MultAdd(t, seg_dir, segment_point0);
1288 ret = Vector3::LengthSq(ret);
1290 if (point_on_line) *point_on_line = pt_l;
1291 if (point_on_segment) *point_on_segment = pt_s;
1300 SimdVector u = F128::Sub(ray0_point, ray1_point);
1301 f128 b = Vector3::Dot(ray0_dir_normalized, ray1_dir_normalized);
1302 f128 d = Vector3::Dot(ray0_dir_normalized, u);
1303 f128 e = Vector3::Dot(ray1_dir_normalized, u);
1304 f128 one = F128::SetOne();
1305 f128 det = F128::MultSub(b, b, one);
1306 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1311 f128 minus_d = F128::Negate(d);
1312 f128 s_num = F128::AndNot(parallel, F128::MultAdd(b, e, minus_d));
1313 f128 s_num_negative = F128::CmpLtZero(s_num);
1314 f128 parallel_or_sNum_negative = F128::Or(parallel, s_num_negative);
1319 f128 t_num = F128::Select(parallel_or_sNum_negative, e, F128::MultSub(b, d, e));
1324 f128 t_denom = F128::Select(parallel_or_sNum_negative, one, det);
1329 s_num = F128::AndNot(s_num_negative, s_num);
1335 f128 t_num_negative = F128::CmpLtZero(t_num);
1336 f128 d_negative = F128::CmpLeZero(d);
1337 f128 tmp = F128::And(d_negative, minus_d);
1338 s_num = F128::Select(t_num_negative, tmp, s_num);
1343 tmp = F128::Or(parallel, F128::And(t_num_negative, d_negative));
1344 f128 s_denom = F128::Select(tmp, one, det);
1349 t_num = F128::AndNot(t_num_negative, t_num);
1351 f128 s = F128::Div(s_num, s_denom);
1352 f128 t = F128::Div(t_num, t_denom);
1354 f128 pt_r0 = F128::MultAdd(s, ray0_dir_normalized, ray0_point);
1355 f128 pt_r1 = F128::MultAdd(t, ray1_dir_normalized, ray1_point);
1357 ret = Vector3::LengthSq(ret);
1359 if (point_on_ray0) *point_on_ray0 = pt_r0;
1360 if (point_on_ray1) *point_on_ray1 = pt_r1;
1369 SimdVector seg_dir = F128::Sub(segment_point1, segment_point0);
1370 SimdVector u = F128::Sub(ray_point, segment_point0);
1371 f128 b = Vector3::Dot(ray_dir_normalized, seg_dir);
1372 f128 c = Vector3::LengthSq(seg_dir);
1373 f128 d = Vector3::Dot(ray_dir_normalized, u);
1374 f128 e = Vector3::Dot(seg_dir, u);
1375 f128 det = F128::MultSub(b, b, c);
1376 f128 one = F128::SetOne();
1377 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1383 tmp0 = F128::Mult(b, e);
1384 tmp0 = F128::MultSub(c, d, tmp0);
1385 f128 s_num = F128::AndNot(parallel, tmp0);
1390 f128 sNum_negative = F128::CmpLtZero(s_num);
1391 f128 parallel_or_sNum_negative = F128::Or(parallel, sNum_negative);
1392 tmp1 = F128::MultSub(b, d, e);
1393 f128 t_num = F128::Select(parallel_or_sNum_negative, e, tmp1);
1398 f128 t_denom = F128::Select(parallel_or_sNum_negative, c, det);
1403 s_num = F128::AndNot(sNum_negative, s_num);
1411 f128 minus_d = F128::Negate(d);
1412 f128 b_minus_d = F128::Sub(b, d);
1413 f128 tNum_negative = F128::CmpLtZero(t_num);
1414 f128 tNum_out = F128::Or(tNum_negative, F128::CmpGt(t_num, t_denom));
1415 tmp0 = F128::Select(tNum_negative, minus_d, b_minus_d);
1416 f128 cmp = F128::CmpGeZero(tmp0);
1417 tmp1 = F128::And(cmp, tmp0);
1418 s_num = F128::Select(tNum_out, tmp1, s_num);
1425 tmp0 = F128::Or(parallel, F128::And(tNum_out, cmp));
1426 f128 s_denom = F128::Select(tmp0, one, det);
1432 t_num = F128::Clamp(t_num, F128::SetZero(), t_denom);
1434 f128 s = F128::Div(s_num, s_denom);
1435 f128 t = F128::Div(t_num, t_denom);
1437 f128 pt_r = F128::MultAdd(s, ray_dir_normalized, ray_point);
1438 f128 pt_s = F128::MultAdd(t, seg_dir, segment_point0);
1440 ret = Vector3::LengthSq(ret);
1442 if (point_on_ray) *point_on_ray = pt_r;
1443 if (point_on_segment) *point_on_segment = pt_s;
1448 # pragma endregion DistanceSq function implementation 1455 # pragma region Intersection 1462 f128 dot = Plane::DotNormal(plane, line_dir_normalized);
1463 SimdVector t = Plane::DotCoord(plane, line_point);
1464 t = F128::Div(t, dot);
1465 SimdVector ret = F128::MultSub(t, line_dir_normalized, line_point);
1467 f128 eps = F128::SetEpsilon();
1468 f128 dotzero = F128::CmpNearEqZero(dot, eps);
1469 f128 nan = F128::SetNaN();
1471 return F128::Select(dotzero, nan, ret);
1477 f128 dot = Plane::DotNormal(plane, ray_dir_normalized);
1478 SimdVector t = Plane::DotCoord(plane, ray_point);
1479 t = F128::Div(t, dot);
1480 SimdVector ret = F128::MultSub(t, ray_dir_normalized, ray_point);
1482 f128 eps = F128::SetEpsilon();
1483 f128 dotzero = F128::CmpNearEqZero(dot, eps);
1484 f128 t_gt_0 = F128::CmpGtZero(t);
1485 f128 nan = F128::SetNaN();
1487 return F128::Select(F128::Or(t_gt_0, dotzero), nan, ret);
1493 SimdVector dir = F128::Sub(segment_point1, segment_point0);
1494 f128 recp_len = Vector3::RecpLength(dir);
1495 dir = F128::Mult(dir, recp_len);
1497 f128 dot = Plane::DotNormal(plane, dir);
1498 SimdVector t = Plane::DotCoord(plane, segment_point1);
1499 t = F128::Div(t, dot);
1500 SimdVector ret = F128::MultSub(t, dir, segment_point1);
1502 f128 t_gt_len = F128::CmpGt(F128::Mult(t, recp_len), F128::SetOne());
1503 f128 t_lt_0 = F128::CmpLtZero(t);
1504 f128 nan = F128::SetNaN();
1506 return F128::Select(F128::Or(t_gt_len, t_lt_0), nan, ret);
1512 SimdVector pt_c = F128::Sub(sphere, ray_point);
1514 f128 len_on_ray = Vector3::Dot(pt_c, ray_dir_normalized);
1515 f128 lensq_pt_c = Vector3::LengthSq(pt_c);
1517 r_sq = F128::Mult(r_sq, r_sq);
1518 f128 distsq = F128::MultSub(len_on_ray, len_on_ray, lensq_pt_c);
1520 f128 origin_inside = F128::CmpLe(lensq_pt_c, r_sq);
1521 f128 intersection_none;
1522 intersection_none = F128::CmpLt(len_on_ray, F128::SetZero());
1523 intersection_none = F128::AndNot(origin_inside, intersection_none);
1524 intersection_none = F128::Or(intersection_none, F128::CmpGt(distsq, r_sq));
1526 if (F128::IsAllMaskFalse(intersection_none)) {
1530 f128 q = F128::Sqrt(F128::Sub(r_sq, distsq));
1531 f128 t0 = F128::Sub(len_on_ray, q);
1532 f128 t1 = F128::Add(len_on_ray, q);
1533 f128 t = F128::Select(origin_inside, t1, t0);
1534 *distance = F128::GetFloatFromLane<0>(t);
1543 NLIB_B Intersection::TriangleRay(
float* distance,
SimdVectorArg triangle_point0,
1549 SimdVector E1 = F128::Sub(triangle_point1, triangle_point0);
1550 SimdVector E2 = F128::Sub(triangle_point2, triangle_point0);
1551 SimdVector P = Vector3::Cross(ray_dir_normalized, E2);
1553 f128 det = Vector3::Dot(E1, P);
1554 f128 inv_det = F128::Recp(det);
1557 f128 intersection_none = F128::InBound(det, F128::SetEpsilon());
1560 SimdVector T = F128::Sub(ray_point, triangle_point0);
1564 f128 u = Vector3::Dot(T, P);
1566 f128 v = Vector3::Dot(ray_dir_normalized, Q);
1567 f128 uv = F128::Mult(F128::Permute<0, 1, 4, 5>(u, v), inv_det);
1569 f128 t = F128::Mult(Vector3::Dot(E2, Q), inv_det);
1572 intersection_none = F128::Or(intersection_none, F128::CmpLt(uv, F128::SetZero()));
1573 intersection_none = F128::Or(intersection_none, F128::CmpGt(uv, F128::SetOne()));
1574 intersection_none = F128::Or(intersection_none, F128::CmpLt(t, F128::SetZero()));
1576 if (F128::IsAllMaskFalse(intersection_none)) {
1578 *distance = F128::GetFloatFromLane<0>(t);
1591 SimdVector tp0 = F128::SetFloatToLane<3>(triangle_point0, 1.f);
1592 SimdVector tp1 = F128::SetFloatToLane<3>(triangle_point1, 1.f);
1593 SimdVector tp2 = F128::SetFloatToLane<3>(triangle_point2, 1.f);
1596 f128 dist0 = Vector4::Dot(plane_normalized, tp0);
1597 f128 dist1 = Vector4::Dot(plane_normalized, tp1);
1598 f128 dist2 = Vector4::Dot(plane_normalized, tp2);
1600 f128 dist012 = Vector4::Dot3(plane_normalized, tp0, tp1, tp2);
1605 f128 min_dist = F128::Min(dist0, dist1);
1606 f128 max_dist = F128::Max(dist0, dist1);
1607 min_dist = F128::Min(min_dist, dist2);
1608 max_dist = F128::Max(max_dist, dist2);
1610 f128 outside = F128::CmpGtZero(min_dist);
1611 f128 inside = F128::CmpLtZero(max_dist);
1613 if (F128::IsAllMaskTrue(outside))
return kPlaneFront;
1614 if (F128::IsAllMaskTrue(inside))
return kPlaneBack;
1615 return kPlaneInterect;
1621 f128 c = F128::SetFloatToLane<3>(sphere, 1.f);
1623 f128 dist = Vector4::Dot(plane_normalized, c);
1624 f128 outside = F128::CmpGt(dist, r);
1625 f128 inside = F128::CmpLt(dist, F128::Negate(r));
1627 if (F128::IsAllMaskTrue(outside))
return kPlaneFront;
1628 if (F128::IsAllMaskTrue(inside))
return kPlaneBack;
1629 return kPlaneInterect;
1634 f128 distsq = Vector3::LengthSq(F128::Sub(sphere0, sphere1));
1636 radsq = F128::Mult(radsq, radsq);
1637 return F128::IsAllMaskFalse(F128::CmpGt(distsq, radsq));
1644 SimdVector linevec = Vector3::Cross(plane1, plane0);
1645 f128 linevec_lensq = Vector3::LengthSq(linevec);
1649 SimdVector p1_line = Vector3::Cross(plane1, linevec);
1654 SimdVector line_p0 = Vector3::Cross(linevec, plane0);
1655 point = F128::MultAdd<3>(plane1, line_p0, point,
each_select32);
1657 SimdVector point0 = F128::Div(point, linevec_lensq);
1658 SimdVector point1 = F128::Add(point0, linevec);
1659 f128 eps = F128::SetEpsilon();
1660 f128 nan = F128::SetNaN();
1661 f128 parallel = F128::CmpNearEq(F128::SetZero(), linevec_lensq, eps);
1663 ret.val[0] = F128::Select(parallel, nan, point0);
1664 ret.val[1] = F128::Select(parallel, nan, point1);
1672 SimdPlane plane = Plane::FromPoint(triangle_point0, triangle_point1, triangle_point2);
1676 f128 distsq = DistanceSq::PointPlane(&q, sphere, plane);
1678 r_sq = F128::Mult(r_sq, r_sq);
1679 f128 cmp = F128::CmpLe(distsq, r_sq);
1680 if (F128::IsAllMaskFalse(cmp))
return false;
1685 Vector3::Cross(F128::Sub(q, triangle_point0), F128::Sub(triangle_point1, triangle_point0));
1687 Vector3::Cross(F128::Sub(q, triangle_point1), F128::Sub(triangle_point2, triangle_point1));
1689 Vector3::Cross(F128::Sub(q, triangle_point2), F128::Sub(triangle_point0, triangle_point2));
1690 plane = F128::SetZeroToLane<3>(plane);
1691 f128 three_dots = Vector4::Dot3(plane, c0, c1, c2);
1692 three_dots = F128::Swizzle<0, 1, 2, 2>(three_dots);
1693 cmp = F128::CmpGeZero(three_dots);
1694 if (F128::IsAllMaskFalse(cmp) || F128::IsAllMaskTrue(cmp))
return true;
1698 f128 seg_dist01 = DistanceSq::PointSegment(sphere, triangle_point0, triangle_point1);
1699 f128 seg_dist02 = DistanceSq::PointSegment(sphere, triangle_point0, triangle_point2);
1700 f128 seg_dist = F128::Min(seg_dist01, seg_dist02);
1701 f128 seg_dist12 = DistanceSq::PointSegment(sphere, triangle_point1, triangle_point2);
1702 seg_dist = F128::Min(seg_dist, seg_dist12);
1703 cmp = F128::CmpLe(seg_dist, r_sq);
1704 if (F128::IsAllMaskFalse(cmp))
return false;
1714 SimdVector center = F128::Add(aabb_max, aabb_min);
1715 center = F128::Mult(0.5f, center);
1716 SimdVector extents = F128::Sub(aabb_max, center);
1717 center = F128::SetFloatToLane<3>(center, 1.f);
1719 f128 dist = Vector4::Dot(center, plane_normalized);
1720 f128 radius = Vector3::Dot(extents, F128::Abs(plane_normalized));
1721 if (F128::IsAllMaskFalse(F128::CmpLe(dist, radius))) {
1724 if (F128::IsAllMaskFalse(F128::CmpGe(dist, F128::Negate(radius)))) {
1727 return kPlaneInterect;
1735 f128 inv_dir = F128::Recp(ray_dir_normalized);
1736 f128 selector = F128::CmpGeZero(ray_dir_normalized);
1739 f128 tmin = F128::Select(selector, aabb_min, aabb_max);
1740 f128 tmax = F128::Select(selector, aabb_max, aabb_min);
1741 tmin = F128::Sub(tmin, ray_point);
1742 tmax = F128::Sub(tmax, ray_point);
1743 tmin = F128::Mult(tmin, inv_dir);
1744 tmax = F128::Mult(tmax, inv_dir);
1749 tmin = F128::Swizzle<0, 1, 2, 0>(tmin);
1750 tmax = F128::Swizzle<2, 0, 0, 1>(tmax);
1751 f128 result = F128::CmpGeZero(tmax);
1752 if (!F128::IsAllMaskFalse(F128::CmpGt(tmin, tmax)))
return false;
1755 return F128::IsAllMaskTrue(result);
1759 NLIB_B Intersection::AxisAlignedBoxSphere(
const AxisAlignedBox& aabb,
1763 f128 max_center = F128::Sub(sphere, aabb_max);
1764 f128 min_center = F128::Sub(sphere, aabb_min);
1765 f128 max_mask = F128::CmpGt(sphere, aabb_max);
1766 f128 min_mask = F128::CmpLt(sphere, aabb_min);
1767 f128 dist_sq = F128::SetZero();
1768 dist_sq = F128::Select(max_mask, max_center, dist_sq);
1769 dist_sq = F128::Select(min_mask, min_center, dist_sq);
1770 dist_sq = Vector3::LengthSq(dist_sq);
1772 r_sq = F128::Mult(r_sq, r_sq);
1773 return F128::IsAllMaskTrue(F128::CmpLe(dist_sq, r_sq));
1777 NLIB_B Intersection::AxisAlignedBoxAxisAlignedBox(
const AxisAlignedBox& aabb0,
1781 return F128::IsAllMaskFalse(F128::Or(cond0, cond1));
1785 NLIB_B Intersection::AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
1799 F128::Min(F128::Min(tri0, tri1), tri2);
1801 F128::Max(F128::Max(tri0, tri1), tri2);
1802 f128 cond0 = F128::CmpGt(tri_min, box_max);
1803 f128 cond1 = F128::CmpGt(box_min, tri_max);
1804 if (!F128::IsAllMaskFalse(F128::Or(cond0, cond1))) {
1811 point_in = F128::And(F128::CmpGe(tri0, box_min),
1812 F128::CmpLe(tri0, box_max));
1813 if (F128::IsAllMaskTrue(point_in))
return true;
1814 point_in = F128::And(F128::CmpGe(tri1, box_min),
1815 F128::CmpLe(tri1, box_max));
1816 if (F128::IsAllMaskTrue(point_in))
return true;
1817 point_in = F128::And(F128::CmpGe(tri2, box_min),
1818 F128::CmpLe(tri2, box_max));
1819 if (F128::IsAllMaskTrue(point_in))
return true;
1829 N = F128::SetZeroToLane<3>(N);
1830 f128 D = Vector3::Dot(N, tri0);
1831 f128 normal_gt_0 = F128::CmpGt(N, F128::SetZero());
1832 SimdVector v_near = F128::Select(normal_gt_0, box_min, box_max);
1833 SimdVector v_far = F128::Select(normal_gt_0, box_max, box_min);
1834 f128 min_near = Vector4::Dot(N, v_near);
1835 f128 max_far = Vector4::Dot(N, v_far);
1836 min_near = F128::CmpGt(min_near, D);
1837 max_far = F128::CmpLt(max_far, D);
1838 if (!F128::IsAllMaskFalse(F128::Or(min_near, max_far))) {
1843 SimdVector box_center = F128::Add(box_max, box_min);
1844 box_center = F128::Mult(0.5f, box_center);
1845 SimdVector extents = F128::Sub(box_center, box_min);
1846 SimdVector tp0 = F128::Sub(tri0, box_center);
1847 SimdVector tp1 = F128::Sub(tri1, box_center);
1848 SimdVector tp2 = F128::Sub(tri2, box_center);
1849 tp0 = F128::SetZeroToLane<3>(tp0);
1850 tp1 = F128::SetZeroToLane<3>(tp1);
1851 tp2 = F128::SetZeroToLane<3>(tp2);
1854 f0 = F128::SetZeroToLane<3>(f0);
1855 f1 = F128::SetZeroToLane<3>(f1);
1856 f2 = F128::SetZeroToLane<3>(f2);
1860 f128 tp0dot_A00A01A02A10;
1861 f128 tp0dot_A11A12A20A21;
1863 f128 tp1dot_A11A12A21A22;
1864 f128 tp2dot_A00A10A20A22;
1865 f128 neg_f0 = F128::Negate(f0);
1866 f128 neg_f1 = F128::Negate(f1);
1867 f128 neg_f2 = F128::Negate(f2);
1870 SimdVector A00 = F128::Permute<7, 6, 1, 3>(f0, neg_f0);
1872 SimdVector A01 = F128::Permute<7, 6, 1, 3>(f1, neg_f1);
1874 SimdVector A02 = F128::Permute<7, 6, 1, 3>(f2, neg_f2);
1877 SimdVector A10 = F128::Permute<2, 3, 4, 3>(f0, neg_f0);
1879 SimdVector A11 = F128::Permute<2, 3, 4, 3>(f1, neg_f1);
1881 SimdVector A12 = F128::Permute<2, 3, 4, 3>(f2, neg_f2);
1884 SimdVector A20 = F128::Permute<5, 0, 3, 3>(f0, neg_f0);
1886 SimdVector A21 = F128::Permute<5, 0, 3, 3>(f1, neg_f1);
1888 SimdVector A22 = F128::Permute<5, 0, 3, 3>(f2, neg_f2);
1890 tp0dot_A00A01A02A10 = Vector4::Dot4(tp0, A00, A01, A02, A10);
1891 tp0dot_A11A12A20A21 = Vector4::Dot4(tp0, A11, A12, A10, A11);
1892 tp1dot_A01A02 = Vector4::Dot2(tp1, A01, A02);
1893 tp1dot_A11A12A21A22 = Vector4::Dot4(tp1, A11, A12, A21, A22);
1894 tp2dot_A00A10A20A22 = Vector4::Dot4(tp2, A00, A10, A20, A22);
1896 A00 = F128::Abs(A00);
1897 A01 = F128::Abs(A01);
1898 A02 = F128::Abs(A02);
1899 A10 = F128::Abs(A10);
1900 A11 = F128::Abs(A11);
1901 A12 = F128::Abs(A12);
1902 A20 = F128::Abs(A20);
1903 A21 = F128::Abs(A21);
1904 A22 = F128::Abs(A22);
1908 radius = Vector4::Dot4(extents, A00, A01, A02, A10);
1909 tp12dot = F128::Permute<4, 0, 1, 5>(tp1dot_A01A02, tp2dot_A00A10A20A22);
1910 pmax = F128::Max(tp0dot_A00A01A02A10, tp12dot);
1911 pmin = F128::Min(tp0dot_A00A01A02A10, tp12dot);
1912 f128 intersection_none = F128::CmpGt(pmin, radius);
1913 intersection_none = F128::Or(intersection_none, F128::CmpLt(pmax, F128::Negate(radius)));
1916 radius = Vector4::Dot4(extents, A11, A12, A20, A21);
1917 tp12dot = F128::Permute<0, 1, 6, 2>(tp1dot_A11A12A21A22, tp2dot_A00A10A20A22);
1918 pmax = F128::Max(tp0dot_A11A12A20A21, tp12dot);
1919 pmin = F128::Min(tp0dot_A11A12A20A21, tp12dot);
1920 intersection_none = F128::Or(intersection_none, F128::CmpGt(pmin, radius));
1921 intersection_none = F128::Or(intersection_none, F128::CmpLt(pmax, F128::Negate(radius)));
1924 radius = Vector4::Dot(extents, A22);
1925 pmax = F128::Max(tp1dot_A11A12A21A22, tp2dot_A00A10A20A22);
1926 pmin = F128::Min(tp1dot_A11A12A21A22, tp2dot_A00A10A20A22);
1929 intersection_none = F128::Or(intersection_none, F128::CmpGt(pmin, radius));
1930 intersection_none = F128::Or(intersection_none, F128::CmpLt(pmax, F128::Negate(radius)));
1932 return F128::IsAllMaskFalse(intersection_none);
1937 Intersection::OrientedBoxAxisAlignedBox(
const OrientedBox& box,
1943 aabb_center = F128::Mult(0.5f, F128::Add(aabb_max, aabb_min));
1944 aabb_extent = F128::Sub(aabb_max, aabb_center);
1945 aabb_extent = F128::SetZeroToLane<3>(aabb_extent);
1948 box_center = F128::SetZeroToLane<3>(box_center);
1956 abs_M0x = F128::Abs(rot.
r[0]);
1957 abs_M1x = F128::Abs(rot.
r[1]);
1958 abs_M2x = F128::Abs(rot.
r[2]);
1963 neg_Mx0 = F128::Negate(Mx0);
1964 neg_Mx1 = F128::Negate(Mx1);
1965 neg_Mx2 = F128::Negate(Mx2);
1994 f128 d, d_aabb, d_box;
1996 f128 intersection_none = F128::SetZero();
2001 d = F128::Abs(box_center);
2002 d_aabb = aabb_extent;
2003 d_box = Vector4::Dot3(box_extent, F128::Abs(Mx0), F128::Abs(Mx1), F128::Abs(Mx2));
2004 d_aabb_box = F128::Add(d_aabb, d_box);
2005 intersection_none = F128::CmpGt(d, d_aabb_box);
2008 d = F128::Abs(Vector4::Dot3(box_center, Mx0, Mx1, Mx2));
2009 d_aabb = Vector4::Dot3(aabb_extent, F128::Abs(Mx0), F128::Abs(Mx1), F128::Abs(Mx2));
2011 d_aabb_box = F128::Add(d_aabb, d_box);
2012 cmp = F128::CmpGt(d, d_aabb_box);
2013 intersection_none = F128::Or(intersection_none, cmp);
2020 t0 = F128::Permute<3, 6, 1, 3>(Mx0, neg_Mx0);
2021 t1 = F128::Permute<3, 6, 1, 3>(Mx1, neg_Mx1);
2022 t2 = F128::Permute<3, 6, 1, 3>(Mx2, neg_Mx2);
2023 d = F128::Abs(Vector4::Dot3(box_center, t0, t1, t2));
2024 d_aabb = Vector4::Dot3(aabb_extent, F128::Abs(t0), F128::Abs(t1), F128::Abs(t2));
2026 t0 = F128::Swizzle<3, 2, 1, 3>(abs_M0x);
2027 t1 = F128::Swizzle<2, 3, 0, 3>(abs_M0x);
2028 t2 = F128::Swizzle<1, 0, 3, 3>(abs_M0x);
2029 d_box = Vector4::Dot3(box_extent, t0, t1, t2);
2030 d_aabb_box = F128::Add(d_aabb, d_box);
2031 cmp = F128::CmpGt(d, d_aabb_box);
2032 intersection_none = F128::Or(intersection_none, cmp);
2037 t0 = F128::Permute<2, 3, 4, 3>(Mx0, neg_Mx0);
2038 t1 = F128::Permute<2, 3, 4, 3>(Mx1, neg_Mx1);
2039 t2 = F128::Permute<2, 3, 4, 3>(Mx2, neg_Mx2);
2040 d = F128::Abs(Vector4::Dot3(box_center, t0, t1, t2));
2041 d_aabb = Vector4::Dot3(aabb_extent, F128::Abs(t0), F128::Abs(t1), F128::Abs(t2));
2043 t0 = F128::Swizzle<3, 2, 1, 3>(abs_M1x);
2044 t1 = F128::Swizzle<2, 3, 0, 3>(abs_M1x);
2045 t2 = F128::Swizzle<1, 0, 3, 3>(abs_M1x);
2046 d_box = Vector4::Dot3(box_extent, t0, t1, t2);
2047 d_aabb_box = F128::Add(d_aabb, d_box);
2048 cmp = F128::CmpGt(d, d_aabb_box);
2049 intersection_none = F128::Or(intersection_none, cmp);
2054 t0 = F128::Permute<5, 0, 3, 3>(Mx0, neg_Mx0);
2055 t1 = F128::Permute<5, 0, 3, 3>(Mx1, neg_Mx1);
2056 t2 = F128::Permute<5, 0, 3, 3>(Mx2, neg_Mx2);
2057 d = F128::Abs(Vector4::Dot3(box_center, t0, t1, t2));
2058 d_aabb = Vector4::Dot3(aabb_extent, F128::Abs(t0), F128::Abs(t1), F128::Abs(t2));
2060 t0 = F128::Swizzle<3, 2, 1, 3>(abs_M2x);
2061 t1 = F128::Swizzle<2, 3, 0, 3>(abs_M2x);
2062 t2 = F128::Swizzle<1, 0, 3, 3>(abs_M2x);
2063 d_box = Vector4::Dot3(box_extent, t0, t1, t2);
2064 d_aabb_box = F128::Add(d_aabb, d_box);
2065 cmp = F128::CmpGt(d, d_aabb_box);
2066 intersection_none = F128::Or(intersection_none, cmp);
2068 intersection_none = F128::SetZeroToLane<3>(intersection_none);
2069 return F128::IsAllMaskFalse(intersection_none);
2073 NLIB_B Intersection::OrientedBoxOrientedBox(
const OrientedBox& box0,
2078 obox.
rotation = Quaternion::Mult(box0_rot, Quaternion::Conjugate(box1_rot));
2086 return Intersection::OrientedBoxAxisAlignedBox(obox, aabb);
2096 SimdVector sphere_center = F128::Sub(sphere, box_center);
2097 sphere_center = Vector3::InvRotate(sphere_center, box_rotation);
2100 f128 lt_min = F128::CmpLt(sphere_center, F128::Negate(box_extent));
2101 f128 gt_max = F128::CmpGt(sphere_center, box_extent);
2102 SimdVector diff_min = F128::Add(sphere_center, box_extent);
2103 SimdVector diff_max = F128::Sub(sphere_center, box_extent);
2105 f128 dist_sq = F128::SetZero();
2106 dist_sq = F128::Select(lt_min, diff_min, dist_sq);
2107 dist_sq = F128::Select(gt_max, diff_max, dist_sq);
2108 dist_sq = Vector3::Dot(dist_sq, dist_sq);
2110 f128 rad_sq = F128::Mult(sphere, sphere);
2113 return Vector4::CmpLe(dist_sq, rad_sq);
2123 SimdVector tp0 = F128::Sub(triangle_point0, box_center);
2124 SimdVector tp1 = F128::Sub(triangle_point1, box_center);
2125 SimdVector tp2 = F128::Sub(triangle_point2, box_center);
2126 tp0 = Vector3::InvRotate(tp0, box_rotation);
2127 tp1 = Vector3::InvRotate(tp1, box_rotation);
2128 tp2 = Vector3::InvRotate(tp2, box_rotation);
2134 return Intersection::AxisAlignedBoxTriangle(aabb, tp0, tp1, tp2);
2139 Intersection::OrientedBoxPlane(
const OrientedBox& box,
2143 f128 new_d = F128::Sub(plane_normalized, Vector3::Dot(plane_normalized, box.
center));
2144 new_plane = F128::Permute<0, 1, 2, 7>(new_plane, new_d);
2148 aabb.point_min = F128::Negate(aabb.point_max);
2150 return Intersection::AxisAlignedBoxPlane(aabb, new_plane);
2158 P = Vector3::InvRotate(P, box_rotation);
2159 SimdVector D = Vector3::InvRotate(ray_dir_normalized, box_rotation);
2165 return Intersection::AxisAlignedBoxRay(aabb, P, D);
2169 SimdPlane near_plane = frustum.near_plane_;
2170 SimdPlane far_plane = frustum.far_plane_;
2171 SimdPlane left_plane = frustum.left_plane_;
2172 SimdPlane right_plane = frustum.right_plane_;
2173 SimdPlane top_plane = frustum.top_plane_;
2174 SimdPlane bottom_plane = frustum.bottom_plane_;
2181 center = Vector3::InvRotate(F128::Sub(center, frustum_center), frustum_rot);
2182 center = F128::SetFloatToLane<3>(center, 1.f);
2186 dist0 = Vector4::Dot4(center, near_plane, far_plane, left_plane, right_plane);
2187 dist1 = Vector4::Dot2(center, top_plane, bottom_plane);
2188 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2191 f128 outside = F128::CmpGt(dist0, radius);
2192 outside = F128::Or(F128::CmpGt(dist1, radius), outside);
2193 if (!F128::IsAllMaskFalse(outside))
return false;
2196 f128 center_inside = F128::CmpLeZero(dist0);
2197 center_inside = F128::And(F128::CmpLeZero(dist0), center_inside);
2198 if (F128::IsAllMaskTrue(center_inside))
return true;
2207 dist_plane = Vector4::Dot4(center, near_plane, far_plane, left_plane, right_plane);
2210 pt_plane = F128::MultSub(near_plane, F128::SetValue<0>(dist0,
each_select32), center);
2211 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2212 inside = Vector4::Dot4(pt_plane, left_plane, right_plane, top_plane, bottom_plane);
2213 inside = F128::CmpLeZero(inside);
2214 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<0>(dist_plane,
each_select32)));
2215 if (F128::IsAllMaskTrue(inside))
return true;
2218 pt_plane = F128::MultSub(far_plane, F128::SetValue<1>(dist0,
each_select32), center);
2219 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2220 inside = Vector4::Dot4(pt_plane, left_plane, right_plane, top_plane, bottom_plane);
2221 inside = F128::CmpLeZero(inside);
2222 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<1>(dist_plane,
each_select32)));
2223 if (F128::IsAllMaskTrue(inside))
return true;
2226 pt_plane = F128::MultSub(left_plane, F128::SetValue<2>(dist0,
each_select32), center);
2227 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2228 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, top_plane, bottom_plane);
2229 inside = F128::CmpLeZero(inside);
2230 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<2>(dist_plane,
each_select32)));
2231 if (F128::IsAllMaskTrue(inside))
return true;
2234 pt_plane = F128::MultSub(right_plane, F128::SetValue<3>(dist0,
each_select32), center);
2235 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2236 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, top_plane, bottom_plane);
2237 inside = F128::CmpLeZero(inside);
2238 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<3>(dist_plane,
each_select32)));
2239 if (F128::IsAllMaskTrue(inside))
return true;
2241 dist_plane = Vector4::Dot2(center, top_plane, bottom_plane);
2244 pt_plane = F128::MultSub(top_plane, F128::SetValue<0>(dist1,
each_select32), center);
2245 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2246 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, left_plane, right_plane);
2247 inside = F128::CmpLeZero(inside);
2248 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<0>(dist_plane,
each_select32)));
2249 if (F128::IsAllMaskTrue(inside))
return true;
2252 pt_plane = F128::MultSub(bottom_plane, F128::SetValue<1>(dist1,
each_select32), center);
2253 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2254 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, left_plane, right_plane);
2255 inside = F128::CmpLeZero(inside);
2256 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<1>(dist_plane,
each_select32)));
2257 if (F128::IsAllMaskTrue(inside))
return true;
2261 f128 radius_sq = F128::Mult(radius, radius);
2268 SimdVector left_top = Vector3::LoadFloat3(&corners[0]);
2269 SimdVector right_top = Vector3::LoadFloat3(&corners[1]);
2270 SimdVector right_bottom = Vector3::LoadFloat3(&corners[2]);
2271 SimdVector left_bottom = Vector3::LoadFloat3(&corners[3]);
2272 SimdVector left_top_far = Vector3::LoadFloat3(&corners[4]);
2273 SimdVector right_top_far = Vector3::LoadFloat3(&corners[5]);
2274 SimdVector right_bottom_far = Vector3::LoadFloat3(&corners[6]);
2275 SimdVector left_bottom_far = Vector3::LoadFloat3(&corners[7]);
2278 dist_sq = DistanceSq::PointSegment(center, left_top, right_top);
2279 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_top, right_bottom));
2280 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_bottom, left_bottom));
2281 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_bottom, left_top));
2283 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_top_far, right_top_far));
2284 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_top_far, right_bottom_far));
2286 F128::Min(dist_sq, DistanceSq::PointSegment(center, right_bottom_far, left_bottom_far));
2287 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_bottom_far, left_top_far));
2289 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_top_far, left_top));
2290 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_top_far, right_top));
2291 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_bottom_far, right_bottom));
2292 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_bottom_far, left_bottom));
2294 return F128::IsAllMaskTrue(F128::CmpLe(dist_sq, radius_sq));
2298 SimdVector pt = F128::Sub(point, frustum.center_);
2299 pt = Vector3::InvRotate(pt, frustum.rotation_);
2300 pt = F128::SetFloatToLane<3>(pt, 1.f);
2302 f128 dot1 = Vector4::Dot4(pt, frustum.near_plane_, frustum.far_plane_, frustum.top_plane_,
2303 frustum.bottom_plane_);
2304 f128 dot2 = Vector4::Dot2(pt, frustum.left_plane_, frustum.right_plane_);
2305 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
2306 dot1 = F128::Max(dot1, dot2);
2307 f128 outside = F128::CmpGt(dot1, F128::SetZero());
2308 return F128::IsAllMaskFalse(outside);
2311 NLIB_B Intersection::FrustumAxisAlignedBox(
const Frustum& frustum,
2317 if (Containment::FrustumPoint(frustum, C))
return true;
2324 frustum.
Transform(&fstm, 1.f, F128::Set0001(), F128::Negate(C));
2330 for (
size_t i = 0; i < 8; ++i) {
2331 corners[i] = Vector3::LoadFloat3(&corners_[i]);
2332 corners[i] = F128::SetFloatToLane<3>(corners[i], 1.f);
2337 pt_min = pt_max = corners[0];
2338 for (
size_t i = 1; i < 8; ++i) {
2340 pt_min = F128::Min(vec, pt_min);
2341 pt_max = F128::Max(vec, pt_max);
2343 f128 disjoint = F128::Or(F128::CmpGt(pt_min, extent),
2344 F128::CmpLt(pt_max, F128::Negate(extent)));
2345 disjoint = F128::SetZeroToLane<3>(disjoint);
2346 if (!F128::IsAllMaskFalse(disjoint))
return false;
2354 f128 dist0_frustum, dist1_frustum;
2355 f128 dist_aabb_max, dist_aabb_min;
2359 plane = fstm.near_plane_;
2360 N = Vector3::Rotate(plane, frustum_rot);
2361 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2362 plane = F128::Permute<0, 1, 2, 7>(N, D);
2364 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2365 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2366 N = Vector3::Dot(F128::Abs(N), extent);
2367 dist_aabb_max = F128::Add(D, N);
2368 dist_aabb_min = F128::Sub(D, N);
2369 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2370 F128::CmpGe(dist1_frustum, dist_aabb_min));
2371 if (F128::IsAllMaskFalse(intersect))
return false;
2372 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2373 F128::CmpLe(dist1_frustum, dist_aabb_max));
2374 if (F128::IsAllMaskFalse(intersect))
return false;
2377 plane = fstm.left_plane_;
2378 N = Vector3::Rotate(plane, frustum_rot);
2379 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2380 plane = F128::Permute<0, 1, 2, 7>(N, D);
2382 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2383 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2384 N = Vector3::Dot(F128::Abs(N), extent);
2385 dist_aabb_max = F128::Add(D, N);
2386 dist_aabb_min = F128::Sub(D, N);
2387 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2388 F128::CmpGe(dist1_frustum, dist_aabb_min));
2389 if (F128::IsAllMaskFalse(intersect))
return false;
2390 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2391 F128::CmpLe(dist1_frustum, dist_aabb_max));
2392 if (F128::IsAllMaskFalse(intersect))
return false;
2395 plane = fstm.right_plane_;
2396 N = Vector3::Rotate(plane, frustum_rot);
2397 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2398 plane = F128::Permute<0, 1, 2, 7>(N, D);
2400 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2401 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2402 N = Vector3::Dot(F128::Abs(N), extent);
2403 dist_aabb_max = F128::Add(D, N);
2404 dist_aabb_min = F128::Sub(D, N);
2405 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2406 F128::CmpGe(dist1_frustum, dist_aabb_min));
2407 if (F128::IsAllMaskFalse(intersect))
return false;
2408 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2409 F128::CmpLe(dist1_frustum, dist_aabb_max));
2410 if (F128::IsAllMaskFalse(intersect))
return false;
2413 plane = fstm.top_plane_;
2414 N = Vector3::Rotate(plane, frustum_rot);
2415 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2416 plane = F128::Permute<0, 1, 2, 7>(N, D);
2418 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2419 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2420 N = Vector3::Dot(F128::Abs(N), extent);
2421 dist_aabb_max = F128::Add(D, N);
2422 dist_aabb_min = F128::Sub(D, N);
2423 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2424 F128::CmpGe(dist1_frustum, dist_aabb_min));
2425 if (F128::IsAllMaskFalse(intersect))
return false;
2426 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2427 F128::CmpLe(dist1_frustum, dist_aabb_max));
2428 if (F128::IsAllMaskFalse(intersect))
return false;
2431 plane = fstm.bottom_plane_;
2432 N = Vector3::Rotate(plane, frustum_rot);
2433 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2434 plane = F128::Permute<0, 1, 2, 7>(N, D);
2436 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2437 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2438 N = Vector3::Dot(F128::Abs(N), extent);
2439 dist_aabb_max = F128::Add(D, N);
2440 dist_aabb_min = F128::Sub(D, N);
2441 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2442 F128::CmpGe(dist1_frustum, dist_aabb_min));
2443 if (F128::IsAllMaskFalse(intersect))
return false;
2444 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2445 F128::CmpLe(dist1_frustum, dist_aabb_max));
2446 if (F128::IsAllMaskFalse(intersect))
return false;
2450 E0[0] = F128::Set1000();
2451 E0[1] = F128::Set0100();
2452 E0[2] = F128::Set0010();
2454 E1[0] = F128::Sub(corners[0], corners[4]);
2455 E1[1] = F128::Sub(corners[1], corners[5]);
2456 E1[2] = F128::Sub(corners[2], corners[6]);
2457 E1[3] = F128::Sub(corners[3], corners[7]);
2458 E1[4] = F128::Sub(corners[1], corners[0]);
2459 E1[5] = F128::Sub(corners[1], corners[2]);
2462 for (
size_t i = 0; i < 3; ++i) {
2463 for (
size_t j = 0; j < 6; ++j) {
2464 SimdVector axis = Vector3::Cross(E0[i], E1[j]);
2465 axis = F128::SetZeroToLane<3>(axis);
2466 N = Vector3::Dot(F128::Abs(axis), extent);
2468 f128 aabb_min = F128::Sub(D, N);
2469 f128 aabb_max = F128::Add(D, N);
2470 dot0 = Vector4::Dot4(axis, corners[0], corners[1], corners[2], corners[3]);
2471 dot1 = Vector4::Dot4(axis, corners[4], corners[5], corners[6], corners[7]);
2473 intersect = F128::CmpGe(F128::Max(dot0, dot1), aabb_min);
2474 if (F128::IsAllMaskFalse(intersect))
return false;
2475 intersect = F128::CmpLe(F128::Min(dot0, dot1), aabb_max);
2476 if (F128::IsAllMaskFalse(intersect))
return false;
2482 NLIB_B Intersection::FrustumOrientedBox(
const Frustum& frustum,
2485 frustum.
Transform(&frstm, 1.f, F128::Set0001(), F128::Negate(obb.
center));
2486 frstm.
Transform(&frstm, 1.f, Quaternion::Conjugate(obb.
rotation), F128::SetZero());
2491 return Intersection::FrustumAxisAlignedBox(frstm, aabb);
2500 SimdVector pt0 = Vector3::InvRotate(F128::Sub(triangle_point0, frustum_center), frustum_rot);
2501 SimdVector pt1 = Vector3::InvRotate(F128::Sub(triangle_point1, frustum_center), frustum_rot);
2502 SimdVector pt2 = Vector3::InvRotate(F128::Sub(triangle_point2, frustum_center), frustum_rot);
2503 pt0 = F128::SetFloatToLane<3>(pt0, 1.f);
2504 pt1 = F128::SetFloatToLane<3>(pt1, 1.f);
2505 pt2 = F128::SetFloatToLane<3>(pt2, 1.f);
2507 SimdPlane near_plane = frustum.near_plane_;
2508 SimdPlane far_plane = frustum.far_plane_;
2509 SimdPlane left_plane = frustum.left_plane_;
2510 SimdPlane right_plane = frustum.right_plane_;
2511 SimdPlane top_plane = frustum.top_plane_;
2512 SimdPlane bottom_plane = frustum.bottom_plane_;
2514 f128 dist0, dist1, dist_max;
2515 f128 dist0_min, dist1_min;
2519 dist0 = Vector4::Dot4(pt0, near_plane, far_plane, left_plane, right_plane);
2521 dist1 = Vector4::Dot2(pt0, top_plane, bottom_plane);
2522 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2524 dist_max = F128::Max(dist0, dist1);
2525 outside = F128::CmpGtZero(dist_max);
2526 if (F128::IsAllMaskFalse(outside))
return true;
2529 dist0 = Vector4::Dot4(pt1, near_plane, far_plane, left_plane, right_plane);
2530 dist0_min = F128::Min(dist0, dist0_min);
2531 dist1 = Vector4::Dot2(pt1, top_plane, bottom_plane);
2532 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2533 dist1_min = F128::Min(dist1, dist1_min);
2534 dist_max = F128::Max(dist0, dist1);
2535 outside = F128::CmpGtZero(dist_max);
2536 if (F128::IsAllMaskFalse(outside))
return true;
2539 dist0 = Vector4::Dot4(pt2, near_plane, far_plane, left_plane, right_plane);
2540 dist0_min = F128::Min(dist0, dist0_min);
2541 dist1 = Vector4::Dot2(pt2, top_plane, bottom_plane);
2542 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2543 dist1_min = F128::Min(dist1, dist1_min);
2544 dist_max = F128::Max(dist0, dist1);
2545 outside = F128::CmpGtZero(dist_max);
2546 if (F128::IsAllMaskFalse(outside))
return true;
2549 if (!F128::IsAllMaskFalse(F128::Or(
2550 F128::CmpGtZero(dist0_min), F128::CmpGtZero(dist1_min))))
return false;
2555 pt0 = triangle_point0;
2556 pt1 = triangle_point1;
2557 pt2 = triangle_point2;
2560 SimdPlane triangle = Plane::FromPoint(pt0, pt1, pt2);
2564 for (
size_t i = 0; i < 8; ++i) {
2565 corners[i] = Vector3::LoadFloat3(&corners_[i]);
2566 corners[i] = F128::SetFloatToLane<3>(corners[i], 1.f);
2568 f128 dot0 = Vector4::Dot4(triangle, corners[0], corners[1], corners[2], corners[3]);
2569 f128 dot1 = Vector4::Dot4(triangle, corners[4], corners[5], corners[6], corners[7]);
2571 if (F128::IsAllMaskFalse(F128::CmpGeZero(F128::Max(dot0, dot1))))
return false;
2573 if (F128::IsAllMaskFalse(F128::CmpLeZero(F128::Min(dot0, dot1))))
return false;
2577 E0[0] = F128::Sub(pt1, pt0);
2578 E0[1] = F128::Sub(pt2, pt1);
2579 E0[2] = F128::Sub(pt0, pt2);
2581 E1[0] = F128::Sub(corners[0], corners[4]);
2582 E1[1] = F128::Sub(corners[1], corners[5]);
2583 E1[2] = F128::Sub(corners[2], corners[6]);
2584 E1[3] = F128::Sub(corners[3], corners[7]);
2585 E1[4] = F128::Sub(corners[1], corners[0]);
2586 E1[5] = F128::Sub(corners[1], corners[2]);
2588 for (
size_t i = 0; i < 3; ++i) {
2589 for (
size_t j = 0; j < 6; ++j) {
2590 SimdVector axis = Vector3::Cross(E0[i], E1[j]);
2591 axis = F128::SetZeroToLane<3>(axis);
2592 f128 tri_min, tri_max;
2594 f128 tmp0 = Vector3::Dot(axis, pt0);
2595 f128 tmp1 = Vector3::Dot(axis, pt1);
2596 f128 tmp2 = Vector3::Dot(axis, pt2);
2597 tri_min = F128::Min(tmp0, tmp1);
2598 tri_max = F128::Max(tmp0, tmp1);
2599 tri_min = F128::Min(tri_min, tmp2);
2600 tri_max = F128::Max(tri_max, tmp2);
2602 dot0 = Vector4::Dot4(axis, corners[0], corners[1], corners[2], corners[3]);
2603 dot1 = Vector4::Dot4(axis, corners[4], corners[5], corners[6], corners[7]);
2605 if (F128::IsAllMaskFalse(F128::CmpGe(F128::Max(dot0, dot1), tri_min)))
return false;
2607 if (F128::IsAllMaskFalse(F128::CmpLe(F128::Min(dot0, dot1), tri_max)))
return false;
2618 for (
size_t i = 0; i < 8; ++i) {
2619 corners[i] = Vector3::LoadFloat3(&corners_[i]);
2620 corners[i] = F128::SetFloatToLane<3>(corners[i], 1.f);
2622 f128 dot0 = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2623 f128 dot1 = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2626 f128 outside = F128::CmpLeZero(F128::Min(dot0, dot1));
2627 if (F128::IsAllMaskFalse(outside))
return Intersection::kPlaneFront;
2630 f128 inside = F128::CmpGeZero(F128::Max(dot0, dot1));
2631 if (F128::IsAllMaskFalse(inside))
return Intersection::kPlaneBack;
2633 return Intersection::kPlaneInterect;
2639 if (Containment::FrustumPoint(frustum, ray_point))
return true;
2642 SimdVector rp = F128::Sub(ray_point, frustum.center_);
2643 rp = Vector3::InvRotate(rp, frustum.rotation_);
2644 rp = F128::SetFloatToLane<3>(rp, 1.f);
2645 SimdVector rd = Vector3::InvRotate(ray_dir_normalized, frustum.rotation_);
2646 rd = F128::SetZeroToLane<3>(rd);
2648 f128 dot_rp0, dot_rp1;
2649 dot_rp0 = Vector4::Dot4(rp, frustum.near_plane_, frustum.far_plane_,
2650 frustum.left_plane_, frustum.right_plane_);
2651 dot_rp1 = Vector4::Dot2(rp, frustum.top_plane_, frustum.bottom_plane_);
2652 dot_rp1 = F128::Swizzle<0, 1, 0, 1>(dot_rp1);
2654 f128 dot_rd0, dot_rd1;
2655 dot_rd0 = Vector4::Dot4(rd, frustum.near_plane_, frustum.far_plane_,
2656 frustum.left_plane_, frustum.right_plane_);
2657 dot_rd1 = Vector4::Dot2(rd, frustum.top_plane_, frustum.bottom_plane_);
2658 dot_rd1 = F128::Swizzle<0, 1, 0, 1>(dot_rd1);
2661 f128 eps = F128::SetEpsilon();
2662 f128 parallel0 = F128::CmpLe(F128::Abs(dot_rd0), eps);
2663 f128 parallel1 = F128::CmpLe(F128::Abs(dot_rd1), eps);
2664 f128 mask0 = F128::And(parallel0, F128::CmpGtZero(dot_rp0));
2665 f128 mask1 = F128::And(parallel1, F128::CmpGtZero(dot_rp1));
2666 if (!F128::IsAllMaskFalse(F128::Or(mask0, mask1)))
return false;
2668 f128 t0 = F128::Negate(F128::Div(dot_rp0, dot_rd0));
2669 f128 t1 = F128::Negate(F128::Div(dot_rp1, dot_rd1));
2670 f128 inf = F128::SetInfinity();
2673 mask0 = F128::AndNot(parallel0, F128::CmpGtZero(dot_rd0));
2674 mask1 = F128::AndNot(parallel1, F128::CmpGtZero(dot_rd1));
2675 f128 to = F128::Min(F128::Select(mask0, t0, inf), F128::Select(mask1, t1, inf));
2676 to = F128::PairwiseMin(to, to);
2677 to = F128::PairwiseMin(to, to);
2680 inf = F128::Negate(inf);
2681 mask0 = F128::AndNot(parallel0, F128::CmpLtZero(dot_rd0));
2682 mask1 = F128::AndNot(parallel1, F128::CmpLtZero(dot_rd1));
2683 f128 from = F128::Max(F128::Select(mask0, t0, inf), F128::Select(mask1, t1, inf));
2684 from = F128::PairwiseMax(from, from);
2685 from = F128::PairwiseMax(from, from);
2687 float n = F128::GetFloatFromLane<0>(from);
2688 float f = F128::GetFloatFromLane<0>(to);
2689 return n <= f && (n >= 0.f || f >= 0.f);
2693 # pragma endregion Intersection function implementation 2700 # pragma region Containment 2706 f128 dist_sq = Vector3::LengthSq(F128::Sub(sphere, point));
2708 return F128::IsAllMaskFalse(F128::CmpGt(dist_sq, rsq));
2717 SimdVector tp0_c = F128::Sub(triangle_point0, sphere);
2718 SimdVector tp1_c = F128::Sub(triangle_point1, sphere);
2719 SimdVector tp2_c = F128::Sub(triangle_point2, sphere);
2720 r_sq = F128::Mult(r_sq, r_sq);
2721 tp0_c = Vector3::LengthSq(tp0_c);
2722 tp1_c = Vector3::LengthSq(tp1_c);
2723 tp2_c = Vector3::LengthSq(tp2_c);
2724 f128 dist_sq = F128::Max(F128::Max(tp0_c, tp1_c), tp2_c);
2725 return F128::IsAllMaskFalse(F128::CmpGt(dist_sq, r_sq));
2730 NLIB_B Containment::SphereAxisAlignedBox(
SimdSphereArg sphere,
2735 r_sq = F128::Mult(r_sq, r_sq);
2736 aabb_max = F128::Abs(aabb_max);
2737 aabb_min = F128::Abs(aabb_min);
2738 f128 dist_sq = Vector3::LengthSq(F128::Max(aabb_max, aabb_min));
2739 return F128::IsAllMaskFalse(F128::CmpGt(dist_sq, r_sq));
2746 new_sphere = Vector3::InvRotate(new_sphere, obb.
rotation);
2747 new_sphere = F128::Permute<0, 1, 2, 7>(new_sphere, sphere);
2751 aabb.
point_min = F128::Negate(box_extent);
2752 return Containment::SphereAxisAlignedBox(new_sphere, aabb);
2758 float dist = F128::GetFloatFromLane<0>(Vector3::Length(F128::Sub(sphere, contained)));
2759 float r0 = F128::GetFloatFromLane<3>(sphere);
2760 float r1 = F128::GetFloatFromLane<3>(contained);
2761 return (r0 - r1) >= dist;
2775 pt = Vector3::LoadFloat3(&corners[0]);
2776 d_sq = Vector3::LengthSq(F128::Sub(pt, sp));
2777 inside = F128::CmpLe(d_sq, rad_sq);
2778 for (
size_t i = 1; i < 8; ++i) {
2779 pt = Vector3::LoadFloat3(&corners[i]);
2780 d_sq = Vector3::LengthSq(F128::Sub(pt, sp));
2781 inside = F128::And(inside, F128::CmpLe(d_sq, rad_sq));
2783 return F128::IsAllMaskTrue(inside);
2788 NLIB_B Containment::AxisAlignedBoxPoint(
const AxisAlignedBox& aabb,
2792 out = F128::SetZeroToLane<3>(out);
2793 return F128::IsAllMaskFalse(out);
2798 NLIB_B Containment::AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
2803 pt_max = F128::Max(triangle_point0, triangle_point1);
2804 pt_min = F128::Min(triangle_point0, triangle_point1);
2805 pt_max = F128::Max(pt_max, triangle_point2);
2806 pt_min = F128::Min(pt_min, triangle_point2);
2809 out = F128::SetZeroToLane<3>(out);
2810 return F128::IsAllMaskFalse(out);
2815 NLIB_B Containment::AxisAlignedBoxOrientedBox(
const AxisAlignedBox& aabb,
2817 f128 zero = F128::SetZero();
2819 SimdVector P = F128::Splat<false, true, true, true>(box_extent, zero);
2820 SimdVector Q = F128::Splat<true, false, true, true>(box_extent, zero);
2821 SimdVector R = F128::Splat<true, true, false, true>(box_extent, zero);
2823 P = Vector3::Rotate(P, box_rotation);
2824 Q = Vector3::Rotate(Q, box_rotation);
2825 R = Vector3::Rotate(R, box_rotation);
2831 v = F128::Add(F128::Add(P, Q), R);
2832 v_neg = F128::Negate(v);
2833 pt_min = F128::Min(v, v_neg);
2834 pt_max = F128::Max(v, v_neg);
2837 v = F128::Sub(F128::Add(P, Q), R);
2838 v_neg = F128::Negate(v);
2839 pt_min = F128::Min(pt_min, v);
2840 pt_max = F128::Max(pt_max, v);
2841 pt_min = F128::Min(pt_min, v_neg);
2842 pt_max = F128::Max(pt_max, v_neg);
2845 v = F128::Sub(F128::Add(P, R), Q);
2846 v_neg = F128::Negate(v);
2847 pt_min = F128::Min(pt_min, v);
2848 pt_max = F128::Max(pt_max, v);
2849 pt_min = F128::Min(pt_min, v_neg);
2850 pt_max = F128::Max(pt_max, v_neg);
2855 f128 out = F128::Or(F128::CmpGt(pt_max, aabb_max),
2856 F128::CmpLt(pt_min, aabb_min));
2857 out = F128::SetZeroToLane<3>(out);
2858 return F128::IsAllMaskFalse(out);
2863 NLIB_B Containment::AxisAlignedBoxAxisAlignedBox(
2867 out = F128::SetZeroToLane<3>(out);
2868 return F128::IsAllMaskFalse(out);
2873 NLIB_B Containment::AxisAlignedBoxSphere(
const AxisAlignedBox& aabb,
2876 SimdVector pt_min = F128::Sub(sphere, radius);
2877 SimdVector pt_max = F128::Add(sphere, radius);
2880 out = F128::SetZeroToLane<3>(out);
2881 return F128::IsAllMaskFalse(out);
2886 NLIB_B Containment::AxisAlignedBoxFrustum(
const AxisAlignedBox& aabb,
2890 SimdVector frustum_max = Vector3::LoadFloat3(&corners[0]);
2892 for (
size_t i = 1; i < 8; ++i) {
2893 SimdVector tmp = Vector3::LoadFloat3(&corners[i]);
2894 frustum_max = F128::Max(tmp, frustum_max);
2895 frustum_min = F128::Min(tmp, frustum_min);
2900 return Containment::AxisAlignedBoxAxisAlignedBox(aabb, contained);
2907 pt = Vector3::InvRotate(pt, box.
rotation);
2908 return Vector3::InBound(pt, box.
extent);
2917 SimdVector pt0 = F128::Sub(triangle_point0, center);
2918 SimdVector pt1 = F128::Sub(triangle_point1, center);
2919 SimdVector pt2 = F128::Sub(triangle_point2, center);
2921 pt0 = Vector3::InvRotate(pt0, rot);
2922 pt1 = Vector3::InvRotate(pt1, rot);
2923 pt2 = Vector3::InvRotate(pt2, rot);
2924 pt0 = F128::Abs(pt0);
2925 pt1 = F128::Abs(pt1);
2926 pt2 = F128::Abs(pt2);
2928 pt_absmax = F128::Max(pt_absmax, pt2);
2929 return Vector3::CmpLe(pt_absmax, box.
extent);
2934 NLIB_B Containment::OrientedBoxAxisAlignedBox(
const OrientedBox& box,
2939 SimdVector aabb_center = F128::Add(aabb_min, aabb_max);
2940 aabb_center = F128::Mult(0.5f, aabb_center);
2941 new_aabb.
extent = F128::Sub(aabb_max, aabb_center);
2942 aabb_center = F128::Sub(aabb_center, box.
center);
2943 new_aabb.
center = aabb_center;
2950 return Containment::AxisAlignedBoxOrientedBox(new_box, new_aabb);
2955 NLIB_B Containment::OrientedBoxOrientedBox(
const OrientedBox& box,
2961 contained_obb.
center = Vector3::Rotate(F128::Sub(contained.
center, box.
center), inv_rot);
2968 return Containment::AxisAlignedBoxOrientedBox(aabb, contained_obb);
2977 aabb.
point_min = F128::Negate(box_extent);
2980 new_sphere = F128::Permute<0, 1, 2, 7>(new_sphere, sphere);
2982 return Containment::AxisAlignedBoxSphere(aabb, new_sphere);
2985 NLIB_B Containment::OrientedBoxFrustum(
const OrientedBox& box,
2988 frustum.
Transform(&frstm, 1.f, F128::Set0001(), F128::Negate(box.
center));
2989 frstm.
Transform(&frstm, 1.f, Quaternion::Conjugate(box.
rotation), F128::SetZero());
2993 return Containment::AxisAlignedBoxFrustum(aabb, frstm);
3000 f128 dot, dot1, dot2;
3001 SimdPlane near_plane = frustum.near_plane_;
3002 SimdPlane far_plane = frustum.far_plane_;
3003 SimdPlane top_plane = frustum.top_plane_;
3004 SimdPlane bottom_plane = frustum.bottom_plane_;
3005 SimdPlane left_plane = frustum.left_plane_;
3006 SimdPlane right_plane = frustum.right_plane_;
3010 pt = F128::Sub(triangle_point0, center);
3011 pt = Vector3::InvRotate(pt, rot);
3012 pt = F128::SetFloatToLane<3>(pt, 1.f);
3013 dot1 = Vector4::Dot4(pt, near_plane, far_plane, top_plane, bottom_plane);
3014 dot2 = Vector4::Dot2(pt, left_plane, right_plane);
3015 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3016 dot = F128::Max(dot1, dot2);
3018 pt = F128::Sub(triangle_point1, center);
3019 pt = Vector3::InvRotate(pt, rot);
3020 pt = F128::SetFloatToLane<3>(pt, 1.f);
3021 dot1 = Vector4::Dot4(pt, near_plane, far_plane, top_plane, bottom_plane);
3022 dot2 = Vector4::Dot2(pt, left_plane, right_plane);
3023 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3024 dot = F128::Max(dot, F128::Max(dot1, dot2));
3026 pt = F128::Sub(triangle_point2, center);
3027 pt = Vector3::InvRotate(pt, rot);
3028 pt = F128::SetFloatToLane<3>(pt, 1.f);
3029 dot1 = Vector4::Dot4(pt, near_plane, far_plane, top_plane, bottom_plane);
3030 dot2 = Vector4::Dot2(pt, left_plane, right_plane);
3031 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3032 dot = F128::Max(dot, F128::Max(dot1, dot2));
3034 f128 outside = F128::CmpGt(dot, F128::SetZero());
3035 return F128::IsAllMaskFalse(outside);
3040 dot = F128::Negate(dot);
3042 SimdVector pt = F128::Sub(sphere, frustum.center_);
3043 pt = Vector3::InvRotate(pt, frustum.rotation_);
3044 pt = F128::SetFloatToLane<3>(pt, 1.f);
3046 f128 dot1 = Vector4::Dot4(pt, frustum.near_plane_, frustum.far_plane_, frustum.top_plane_,
3047 frustum.bottom_plane_);
3048 f128 dot2 = Vector4::Dot2(pt, frustum.left_plane_, frustum.right_plane_);
3049 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3050 dot1 = F128::Max(dot1, dot2);
3051 f128 outside = F128::CmpGt(dot1, dot);
3052 return F128::IsAllMaskFalse(outside);
3055 NLIB_B Containment::FrustumAxisAlignedBox(
const Frustum& frustum,
3059 SimdVector center = F128::Mult(0.5f, F128::Add(pt_min, pt_max));
3060 center = F128::SetFloatToLane<3>(center, 1.f);
3061 SimdVector extent_neg = F128::Sub(center, pt_max);
3062 extent_neg = F128::SetZeroToLane<3>(extent_neg);
3072 tmp = frustum.near_plane_;
3073 N = Vector3::Rotate(tmp, rot);
3074 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3075 SimdPlane near_plane = F128::Permute<0, 1, 2, 7>(N, D);
3077 tmp = frustum.far_plane_;
3078 N = Vector3::Rotate(tmp, rot);
3079 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3080 SimdPlane far_plane = F128::Permute<0, 1, 2, 7>(N, D);
3082 tmp = frustum.right_plane_;
3083 N = Vector3::Rotate(tmp, rot);
3084 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3085 SimdPlane right_plane = F128::Permute<0, 1, 2, 7>(N, D);
3087 tmp = frustum.left_plane_;
3088 N = Vector3::Rotate(tmp, rot);
3089 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3090 SimdPlane left_plane = F128::Permute<0, 1, 2, 7>(N, D);
3092 tmp = frustum.top_plane_;
3093 N = Vector3::Rotate(tmp, rot);
3094 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3095 SimdPlane top_plane = F128::Permute<0, 1, 2, 7>(N, D);
3097 tmp = frustum.bottom_plane_;
3098 N = Vector3::Rotate(tmp, rot);
3099 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3100 SimdPlane bottom_plane = F128::Permute<0, 1, 2, 7>(N, D);
3104 f128 all_points_inside;
3107 dist = Vector4::Dot4(center, near_plane, far_plane, right_plane, left_plane);
3109 radius_neg = Vector4::Dot4(extent_neg, F128::Abs(near_plane), F128::Abs(far_plane),
3110 F128::Abs(right_plane), F128::Abs(left_plane));
3112 all_points_inside = F128::CmpLe(dist, radius_neg);
3114 dist = Vector4::Dot2(center, top_plane, bottom_plane);
3115 radius_neg = Vector4::Dot2(extent_neg, F128::Abs(top_plane), F128::Abs(bottom_plane));
3117 F128::And(all_points_inside, F128::Swizzle<0, 1, 0, 1>(F128::CmpLe(dist, radius_neg)));
3119 return F128::IsAllMaskTrue(all_points_inside);
3122 NLIB_B Containment::FrustumOrientedBox(
const Frustum& frustum,
3126 frustum.
Transform(&frstm, 1.f, F128::Set0001(), F128::Negate(box.
center));
3128 frstm.
Transform(&frstm, 1.f, Quaternion::Conjugate(box.
rotation), F128::SetZero());
3133 return Containment::FrustumAxisAlignedBox(frstm, aabb);
3139 for (
size_t i = 0; i < 8; ++i) {
3140 SimdVector pt = Vector3::LoadFloat3(&corners[i]);
3141 if (!Containment::FrustumPoint(frustum, pt))
return false;
3147 # pragma endregion Containment function implementation 3153 #endif // NLIB_DOXYGEN 3158 #endif // INCLUDE_NN_NLIB_SIMD_SIMDGEOMETRY_H_ SimdQuaternion rotation
A quaternion representing the orientation of the OBB.
SimdVector point_min
The minimum coordinates of the AABB. Lane 3 is ignored.
Class representing the view frustum.
Frustum() noexcept
Instantiates the object with default parameters (default constructor). Does not configure the default...
f128arg SimdVectorArg
f128arg is defined using typedef.
The type for two SIMD registers for 128-bit, single-precision, floating-point numbers.
SimdVector extent
The size of the x-coordinate, y-coordinate, and z-coordinate of the OBB. All of the elements must hav...
AxisAlignedBox() noexcept
Instantiates the object with default parameters (default constructor). Does not configure the default...
f128arg SimdSphereArg
f128arg is defined using typedef.
Class for representing oriented bounding boxes (OBB). This class has data members to hold the center ...
SimdVector point_max
The maximum coordinates of the AABB. Lane 3 is ignored.
The class with the collection of functions that determine containment relations.
The class with the collection of static member functions that handle spheres in three-dimensional spa...
#define NLIB_F128_TRANSPOSE(row0, row1, row2, row3)
A macro for in-place matrix transposition.
constexpr const each_float_tag each_float
The tag for representing a single-precision floating-point number with an each_float_tag-type constan...
f128arg SimdQuaternionArg
f128arg is defined using typedef.
The class with the collection of functions that handle planes in three-dimensional space...
f128arg SimdPlaneArg
f128arg is defined using typedef.
The class with the collection of functions that perform square-of-distance calculations.
f128 r[4]
Keeps each row of a 4x4 matrix.
The structure for keeping a 4x4 matrix.
PlaneResult
The return value types when determining intersection with a plane. The front of the plane is on the s...
f128 SimdSphere
f128 is defined using typedef. Used when handling spheres.
SimdVector center
The center coordinates of the OBB. A 3D vector.
void GetCorners(Float3 *corners) const noexcept
Gets the vertices of the frustum in world coordinates.
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
OrientedBox() noexcept
Instantiates the object with default parameters (default constructor). Does not configure the default...
Defines the class and functions for SIMD computations on single-precision floating-point numbers...
The type for reading and writing three-dimensional vectors in memory. Keeps float-type x...
constexpr const each_select32_tag each_select32
The tag for representing the selection of a 32-bit lane with an each_select32_tag-type constant objec...
Defines a three-dimensional vector.
nlib_f128_t f128
nlib_f128_t is defined using typedef.
Class for representing axis-aligned bounding boxes (AABB). The class has data members to hold the min...
Defines a four-dimensional vector.
The class with the collection of functions that determine intersections.
f128 SimdQuaternion
f128 is defined using typedef. Used when handling quaternions.
void Transform(Frustum *frustum, float scale, SimdQuaternionArg rotation, SimdVectorArg translation) const noexcept
Performs a 3D transform on an existing frustum and stores the transformed frustum in frustum...
f128 SimdPlane
f128 is defined using typedef. Used when handling planes.
f128 SimdVector
f128 is defined using typedef. Used when handling three-dimensional or four-dimensional vectors...