3 #ifndef INCLUDE_NN_NLIB_SIMD_SIMDGEOMETRY_H_ 4 #define INCLUDE_NN_NLIB_SIMD_SIMDGEOMETRY_H_ 144 static f128 __vectorcall
152 static f128 __vectorcall
160 static f128 __vectorcall
195 static bool __vectorcall SphereRay(
float* distance,
SimdSphereArg sphere,
202 static bool __vectorcall TriangleRay(
float* distance,
SimdVectorArg triangle_point0,
211 static bool __vectorcall
223 static bool __vectorcall
225 static bool __vectorcall
228 static bool __vectorcall AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
233 static bool __vectorcall
235 static bool __vectorcall
237 static bool __vectorcall
239 static bool __vectorcall OrientedBoxTriangle(
const OrientedBox& box,
248 static bool __vectorcall
250 static bool __vectorcall
252 static bool __vectorcall
278 static bool __vectorcall
280 static bool __vectorcall
282 static bool __vectorcall
284 static bool __vectorcall
288 static bool __vectorcall
290 static bool __vectorcall AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
294 static bool __vectorcall
296 static bool __vectorcall
299 static bool __vectorcall
301 static bool __vectorcall
305 static bool __vectorcall
307 static bool __vectorcall OrientedBoxTriangle(
const OrientedBox& box,
311 static bool __vectorcall OrientedBoxOrientedBox(
const OrientedBox& box,
313 static bool __vectorcall
315 static bool __vectorcall
317 static bool __vectorcall
321 static bool __vectorcall
326 static bool __vectorcall
328 static bool __vectorcall
330 static bool __vectorcall
332 static bool __vectorcall
341 #define NLIB_M(tp) inline tp __vectorcall 342 #define NLIB_B inline bool __vectorcall 348 # pragma region Plane 352 return Vector4::Dot(plane, vec);
357 return Vector4::Dot(plane, F128::SetFloatToLane<3>(vec, 1.f));
362 return Vector3::Dot(plane, vec);
368 f128 dot = Vector3::Dot(point, normal);
369 dot = F128::Negate(dot);
370 return F128::Splat<false, false, false, true>(normal, dot);
378 SimdVector normal = Vector3::Normalize(Vector3::Cross(v10, v20));
379 return FromPointAndNormal(point0, normal);
385 return F128::Mult(Vector3::RecpLength(plane), plane);
390 return F128::Mult(Vector3::RecpLengthEst(plane), plane);
395 return Vector4::Transform(plane, m);
398 # pragma endregion Plane function implementation 405 # pragma region Sphere 410 SimdVector center = Vector3::Transform(sphere, m);
411 f128 dot_x = Vector3::Dot(m.
r[0], m.
r[0]);
412 f128 dot_y = Vector3::Dot(m.
r[1], m.
r[1]);
413 f128 dot_z = Vector3::Dot(m.
r[2], m.
r[2]);
414 f128 scale = F128::Max(dot_x, dot_y);
415 scale = F128::Max(scale, dot_z);
416 radius = F128::Mult(radius, scale);
418 return F128::Splat<false, false, false, true>(center, radius);
424 f128 min_x, min_y, min_z;
425 f128 max_x, max_y, max_z;
426 min_x = min_y = min_z = max_x = max_y = max_z = Vector3::LoadFloat3(points);
429 for (i = 1; i < count; ++i) {
431 f128 pt = Vector3::LoadFloat3(points + i);
434 cmp0 = F128::CmpLt(pt_x, F128::SetValue<0>(min_x,
each_select32));
435 min_x = F128::Select(cmp0, pt, min_x);
436 cmp1 = F128::CmpGt(pt_x, F128::SetValue<0>(max_x,
each_select32));
437 max_x = F128::Select(cmp1, pt, max_x);
440 cmp0 = F128::CmpLt(pt_y, F128::SetValue<0>(min_y,
each_select32));
441 min_y = F128::Select(cmp0, pt, min_y);
442 cmp1 = F128::CmpGt(pt_y, F128::SetValue<0>(max_y,
each_select32));
443 max_y = F128::Select(cmp1, pt, max_y);
446 cmp0 = F128::CmpLt(pt_z, F128::SetValue<0>(min_z,
each_select32));
447 min_z = F128::Select(cmp0, pt, min_z);
448 cmp1 = F128::CmpGt(pt_z, F128::SetValue<0>(max_z,
each_select32));
449 max_z = F128::Select(cmp1, pt, max_z);
456 f128 distsq_x = Vector3::LengthSq(F128::Sub(max_x, min_x));
457 f128 distsq_y = Vector3::LengthSq(F128::Sub(max_y, min_y));
458 f128 distsq_z = Vector3::LengthSq(F128::Sub(max_z, min_z));
459 if (Vector4::CmpGt(distsq_x, distsq_y)) {
460 if (Vector4::CmpGt(distsq_x, distsq_z)) {
461 center = F128::Lerp(min_x, max_x, c1_2);
462 radius = F128::Mult(F128::Sqrt(distsq_x), c1_2);
464 center = F128::Lerp(min_z, max_z, c1_2);
465 radius = F128::Mult(F128::Sqrt(distsq_z), c1_2);
468 if (Vector4::CmpGt(distsq_y, distsq_z)) {
469 center = F128::Lerp(min_y, max_y, c1_2);
470 radius = F128::Mult(F128::Sqrt(distsq_y), c1_2);
472 center = F128::Lerp(min_z, max_z, c1_2);
473 radius = F128::Mult(F128::Sqrt(distsq_z), c1_2);
478 f128 radsq = F128::Mult(radius, radius);
479 for (i = 0; i < count; ++i) {
480 f128 pt = Vector3::LoadFloat3(points + i);
481 f128 diff = F128::Sub(pt, center);
482 f128 distsq = Vector3::LengthSq(diff);
483 if (Vector3::CmpGt(distsq, radsq)) {
484 f128 dist = F128::Sqrt(distsq);
485 f128 t = F128::Div(radius, dist);
486 t = F128::MultSub(c1_2, t, c1_2);
487 radius = F128::Mult(c1_2, F128::Add(radius, dist));
488 radsq = F128::Mult(radius, radius);
489 center = F128::MultAdd(t, diff, center);
493 return F128::Splat<false, false, false, true>(center, radius);
498 SimdVector diff = F128::Sub(sphere1, sphere0);
499 f128 dist_sq = Vector3::LengthSq(diff);
501 f128 is_contained = F128::CmpLe(dist_sq, radius_diff_sq);
503 f128 dist = F128::Sqrt(dist_sq);
506 f128 new_radius = F128::Add(r0, r1);
507 new_radius = F128::Add(new_radius, dist);
508 new_radius = F128::Mult(0.5f, new_radius);
510 f128 t = F128::Div(diff, dist);
511 f128 use_new_center = F128::CmpGt(dist, F128::SetEpsilon());
514 ret = F128::MultAdd(t, F128::Sub(new_radius, r0), sphere0);
515 ret = F128::Select(use_new_center, ret, sphere0);
516 ret = F128::Splat<false, false, false, true>(ret, new_radius);
518 f128 s0_contained = F128::And(is_contained, F128::CmpLt(r0, r1));
519 f128 s1_contained = F128::And(is_contained, F128::CmpGe(r0, r1));
520 ret = F128::Select(s0_contained, sphere1, ret);
521 ret = F128::Select(s1_contained, sphere0, ret);
526 return F128::GetFloatFromLane<3>(sphere);
530 return F128::SetFloatToLane<3>(sphere, radius);
538 return F128::Permute<4, 5, 6, 3>(sphere, center);
541 # pragma endregion Sphere function implementation 548 # pragma region AxisAlignedBox 550 inline AxisAlignedBox::AxisAlignedBox(
const Float3& pmin,
const Float3& pmax) {
551 Vector3::LoadFloat3(&pmin);
552 Vector3::LoadFloat3(&pmax);
558 f128 p1 = F128::Splat<true, false, false, false>(point_min, point_max);
559 f128 p2 = F128::Splat<true, true, false, false>(point_min, point_max);
560 f128 p3 = F128::Splat<false, true, false, false>(point_min, point_max);
561 f128 p4 = F128::Splat<false, true, true, true>(point_min, point_max);
562 f128 p5 = F128::Splat<false, false, true, true>(point_min, point_max);
563 f128 p6 = F128::Splat<true, false, true, true>(point_min, point_max);
566 Vector3::StoreFloat3(corners + 0, p0);
567 Vector3::StoreFloat3(corners + 1, p1);
568 Vector3::StoreFloat3(corners + 2, p2);
569 Vector3::StoreFloat3(corners + 3, p3);
570 Vector3::StoreFloat3(corners + 4, p4);
571 Vector3::StoreFloat3(corners + 5, p5);
572 Vector3::StoreFloat3(corners + 6, p6);
573 Vector3::StoreFloat3(corners + 7, p7);
577 inline void __vectorcall
580 f128 p1 = F128::Splat<true, false, false, false>(point_min, point_max);
581 f128 p2 = F128::Splat<true, true, false, false>(point_min, point_max);
582 f128 p3 = F128::Splat<false, true, false, false>(point_min, point_max);
583 f128 p4 = F128::Splat<false, true, true, true>(point_min, point_max);
584 f128 p5 = F128::Splat<false, false, true, true>(point_min, point_max);
585 f128 p6 = F128::Splat<true, false, true, true>(point_min, point_max);
588 p0 = Vector3::Transform(p0, m);
589 p1 = Vector3::Transform(p1, m);
590 p2 = Vector3::Transform(p2, m);
591 p3 = Vector3::Transform(p3, m);
592 p4 = Vector3::Transform(p4, m);
593 p5 = Vector3::Transform(p5, m);
594 p6 = Vector3::Transform(p6, m);
595 p7 = Vector3::Transform(p7, m);
598 pmin = F128::Min(p0, p1);
599 pmax = F128::Max(p0, p1);
600 pmin = F128::Min(pmin, p2);
601 pmax = F128::Max(pmax, p2);
602 pmin = F128::Min(pmin, p3);
603 pmax = F128::Max(pmax, p3);
604 pmin = F128::Min(pmin, p4);
605 pmax = F128::Max(pmax, p4);
606 pmin = F128::Min(pmin, p5);
607 pmax = F128::Max(pmax, p5);
608 pmin = F128::Min(pmin, p6);
609 pmax = F128::Max(pmax, p6);
610 pmin = F128::Min(pmin, p7);
611 pmax = F128::Max(pmax, p7);
624 inline void __vectorcall
634 box->
point_min = F128::Min(point0, point1);
635 box->
point_max = F128::Max(point0, point1);
642 pmin = pmax = Vector3::LoadFloat3(points);
643 for (
size_t i = 1; i < count; ++i) {
644 f128 pt = Vector3::LoadFloat3(points + i);
645 pmin = F128::Min(pmin, pt);
646 pmax = F128::Max(pmax, pt);
652 # pragma endregion AxisAlignedBox function implementation 659 # pragma region OrientedBox 664 box->
center = Vector3::Transform(this->center, m);
665 f128 inv_dx = Vector3::RecpLength(m.
r[0]);
666 f128 inv_dy = Vector3::RecpLength(m.
r[1]);
667 f128 inv_dz = Vector3::RecpLength(m.
r[2]);
671 rot_matrix.
r[0] = F128::Mult(m.
r[0], inv_dx);
672 rot_matrix.
r[1] = F128::Mult(m.
r[1], inv_dy);
673 rot_matrix.
r[2] = F128::Mult(m.
r[2], inv_dz);
674 rot_matrix.
r[3] = F128::Set0001();
676 box->
rotation = Quaternion::Mult(this->rotation, rot);
680 scale = F128::Permute<0, 4, -1, -1>(inv_dx, inv_dy);
681 scale = F128::Permute<0, 1, 4, -1>(scale, inv_dz);
682 box->
extent = F128::Div(this->extent, scale);
687 f128 point_max = F128::Add(center, extent);
688 f128 point_min = F128::Sub(center, extent);
689 point_max = F128::SetZeroToLane<3>(point_max);
690 point_min = F128::SetZeroToLane<3>(point_min);
694 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
695 Vector3::StoreFloat3(corners + 0, pt);
697 pt = F128::Splat<true, false, false, false>(point_min, point_max);
698 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
699 Vector3::StoreFloat3(corners + 1, pt);
701 pt = F128::Splat<true, true, false, false>(point_min, point_max);
702 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
703 Vector3::StoreFloat3(corners + 2, pt);
705 pt = F128::Splat<false, true, false, false>(point_min, point_max);
706 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
707 Vector3::StoreFloat3(corners + 3, pt);
709 pt = F128::Splat<false, true, true, true>(point_min, point_max);
710 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
711 Vector3::StoreFloat3(corners + 4, pt);
713 pt = F128::Splat<false, false, true, true>(point_min, point_max);
714 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
715 Vector3::StoreFloat3(corners + 5, pt);
717 pt = F128::Splat<true, false, true, true>(point_min, point_max);
718 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
719 Vector3::StoreFloat3(corners + 6, pt);
722 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
723 Vector3::StoreFloat3(corners + 7, pt);
727 inline void OrientedBox::FromAxisAlignedBox(
OrientedBox* box,
733 box->
center = F128::MultAdd(c1_2, box_min, half);
734 box->
extent = F128::MultSub(c1_2, box_min, half);
738 # pragma endregion OrientedBox function implementation 745 # pragma region Capsule 748 f128 sphere_ = Vector3::LoadFloat3(&pt0);
749 point = Vector3::LoadFloat3(&pt1);
750 sphere = F128::SetFloatToLane<3>(sphere_, radius);
754 capsule->sphere = Sphere::Transform(sphere, m);
755 capsule->point = Vector3::Transform(point, m);
758 # pragma endregion Capsule function implementation 765 # pragma region Frustum 769 rotation_(rhs.rotation_),
770 near_plane_(rhs.near_plane_),
771 far_plane_(rhs.far_plane_),
772 top_plane_(rhs.top_plane_),
773 bottom_plane_(rhs.bottom_plane_),
774 left_plane_(rhs.left_plane_),
775 right_plane_(rhs.right_plane_) {
779 center_ = rhs.center_;
780 rotation_ = rhs.rotation_;
781 near_plane_ = rhs.near_plane_;
782 far_plane_ = rhs.far_plane_;
783 top_plane_ = rhs.top_plane_;
784 bottom_plane_ = rhs.bottom_plane_;
785 left_plane_ = rhs.left_plane_;
786 right_plane_ = rhs.right_plane_;
793 NLIB_ASSERT(n > 0.f);
795 rotation_ = rotation;
796 near_plane_ = Plane::Normalize(F128::SetValue(0.f, 0.f, 1.f, n));
797 far_plane_ = Plane::Normalize(F128::SetValue(0.f, 0.f, -1.f, -f));
798 top_plane_ = Plane::Normalize(F128::SetValue(0.f, 1.f, top / n, 0.f));
799 bottom_plane_ = Plane::Normalize(F128::SetValue(0.f, -1.f, -bottom / n, 0.f));
800 left_plane_ = Plane::Normalize(F128::SetValue(-1.f, 0.f, -left / n, 0.f));
801 right_plane_ = Plane::Normalize(F128::SetValue(1.f, 0.f, right / n, 0.f));
805 float bottom,
float left,
float right,
float n,
808 NLIB_ASSERT(n > 0.f);
810 rotation_ = rotation;
811 near_plane_ = Plane::Normalize(F128::SetValue(0.f, 0.f, 1.f, n));
812 far_plane_ = Plane::Normalize(F128::SetValue(0.f, 0.f, -1.f, -f));
813 top_plane_ = Plane::Normalize(F128::SetValue(0.f, 1.f, top / n, 0.f));
814 bottom_plane_ = Plane::Normalize(F128::SetValue(0.f, -1.f, -bottom / n, 0.f));
815 left_plane_ = Plane::Normalize(F128::SetValue(-1.f, 0.f, -left / n, 0.f));
816 right_plane_ = Plane::Normalize(F128::SetValue(1.f, 0.f, right / n, 0.f));
819 inline void __vectorcall Frustum::Transform(
Frustum* frustum,
float scale,
822 f128 s = F128::SetValue(1.f, 1.f, 1.f, scale);
823 frustum->rotation_ = Quaternion::Mult(rotation_, rotation);
824 SimdVector center = Vector3::Rotate(F128::Mult(scale, center_), rotation);
825 frustum->center_ = F128::Add(center, translation);
826 frustum->top_plane_ = top_plane_;
827 frustum->bottom_plane_ = bottom_plane_;
828 frustum->left_plane_ = left_plane_;
829 frustum->right_plane_ = right_plane_;
830 frustum->near_plane_ = F128::Mult(s, near_plane_);
831 frustum->far_plane_ = F128::Mult(s, far_plane_);
842 M.
r[0] = Vector3::Normalize(r0);
843 M.
r[1] = Vector3::Normalize(r1);
844 M.
r[2] = Vector3::Normalize(r2);
845 M.
r[3] = F128::Set0001();
847 frustum->rotation_ = Quaternion::Mult(rotation, rot);
848 frustum->center_ = Vector3::Transform(center, m);
853 f128 x_sq = Vector3::LengthSq(r0);
854 f128 y_sq = Vector3::LengthSq(r1);
855 f128 z_sq = Vector3::LengthSq(r2);
856 f128 sq = F128::Max(z_sq, F128::Max(x_sq, y_sq));
857 scale = F128::GetFloatFromLane<0>(F128::Sqrt(sq));
860 f128 s = F128::SetValue(1.f, 1.f, 1.f, scale);
861 frustum->top_plane_ = top_plane_;
862 frustum->bottom_plane_ = bottom_plane_;
863 frustum->left_plane_ = left_plane_;
864 frustum->right_plane_ = right_plane_;
865 frustum->near_plane_ = F128::Mult(s, near_plane_);
866 frustum->far_plane_ = F128::Mult(s, far_plane_);
870 float n = F128::GetFloatFromLane<3>(near_plane_) / F128::GetFloatFromLane<2>(near_plane_);
871 float f = F128::GetFloatFromLane<3>(far_plane_) / F128::GetFloatFromLane<2>(far_plane_);
872 float top = F128::GetFloatFromLane<2>(top_plane_) / F128::GetFloatFromLane<1>(top_plane_);
875 F128::GetFloatFromLane<2>(bottom_plane_) / F128::GetFloatFromLane<1>(bottom_plane_);
877 float left = F128::GetFloatFromLane<2>(left_plane_) / F128::GetFloatFromLane<0>(left_plane_);
880 F128::GetFloatFromLane<2>(right_plane_) / F128::GetFloatFromLane<0>(right_plane_);
888 pt = F128::SetValue(left, top, -n, 0.f);
889 pt = F128::Add(Vector3::Rotate(pt, rot), center);
890 Vector3::StoreFloat3(corners + 0, pt);
893 pt = F128::SetValue(right, top, -n, 0.f);
894 pt = F128::Add(Vector3::Rotate(pt, rot), center);
895 Vector3::StoreFloat3(corners + 1, pt);
898 pt = F128::SetValue(right, bottom, -n, 0.f);
899 pt = F128::Add(Vector3::Rotate(pt, rot), center);
900 Vector3::StoreFloat3(corners + 2, pt);
903 pt = F128::SetValue(left, bottom, -n, 0.f);
904 pt = F128::Add(Vector3::Rotate(pt, rot), center);
905 Vector3::StoreFloat3(corners + 3, pt);
910 pt = F128::SetValue(left * f_n, top * f_n, -f, 0.f);
911 pt = F128::Add(Vector3::Rotate(pt, rot), center);
912 Vector3::StoreFloat3(corners + 4, pt);
915 pt = F128::SetValue(right * f_n, top * f_n, -f, 0.f);
916 pt = F128::Add(Vector3::Rotate(pt, rot), center);
917 Vector3::StoreFloat3(corners + 5, pt);
920 pt = F128::SetValue(right * f_n, bottom * f_n, -f, 0.f);
921 pt = F128::Add(Vector3::Rotate(pt, rot), center);
922 Vector3::StoreFloat3(corners + 6, pt);
925 pt = F128::SetValue(left * f_n, bottom * f_n, -f, 0.f);
926 pt = F128::Add(Vector3::Rotate(pt, rot), center);
927 Vector3::StoreFloat3(corners + 7, pt);
931 # pragma endregion Frustum function implementation 938 # pragma region DistanceSq 942 SimdVector l0_pt = F128::Sub(point, line_point);
943 f128 dot = Vector3::Dot(l0_pt, line_dir_normalized);
944 SimdVector dist_vec = F128::Mult(line_dir_normalized, dot);
945 dist_vec = F128::Sub(l0_pt, dist_vec);
946 return Vector3::LengthSq(dist_vec);
951 SimdVector l0_pt = F128::Sub(point, ray_point);
952 f128 dot = Vector3::Dot(l0_pt, ray_dir_normalized);
953 SimdVector dist_vec = F128::Mult(ray_dir_normalized, dot);
954 dist_vec = F128::Sub(l0_pt, dist_vec);
956 f128 distsq0 = Vector3::LengthSq(dist_vec);
957 f128 distsq1 = Vector3::LengthSq(l0_pt);
958 f128 cmp = F128::CmpLt(dot, F128::SetZero());
959 return F128::Select(cmp, distsq1, distsq0);
964 SimdVector l0_pt = F128::Sub(point, segment_point0);
965 SimdVector l1_pt = F128::Sub(point, segment_point1);
966 SimdVector seg_dir_normalized = F128::Sub(segment_point1, segment_point0);
967 f128 seg_recplen = Vector3::RecpLength(seg_dir_normalized);
968 seg_dir_normalized = F128::Mult(seg_dir_normalized, seg_recplen);
970 f128 dot = Vector3::Dot(l0_pt, seg_dir_normalized);
971 SimdVector dist_vec = F128::Mult(seg_dir_normalized, dot);
972 dist_vec = F128::Sub(l0_pt, dist_vec);
974 f128 distsq0 = Vector3::LengthSq(dist_vec);
975 f128 distsq1 = Vector3::LengthSq(l0_pt);
976 f128 distsq2 = Vector3::LengthSq(l1_pt);
977 f128 cmp = F128::CmpLt(dot, F128::SetZero());
978 f128 ret = F128::Select(cmp, distsq1, distsq0);
979 cmp = F128::CmpLt(F128::Mult(dot, seg_recplen), F128::SetOne());
980 ret = F128::Select(cmp, ret, distsq2);
987 SimdVector pt = F128::SetZeroToLane<3>(point);
988 f128 dot = Vector4::Dot(pt, plane_normalized);
989 f128 ret = F128::Mult(dot, dot);
990 if (point_on_plane) {
991 *point_on_plane = F128::Sub(point, F128::Mult(dot, plane_normalized));
998 SimdVector c = F128::SetZeroToLane<3>(sphere);
1000 f128 dist = F128::Abs(Vector4::Dot(c, plane_normalized));
1001 f128 cmp = F128::CmpGt(dist, r);
1002 f128 ret = F128::Sub(dist, r);
1003 ret = F128::Mult(ret, ret);
1004 return F128::And(cmp, ret);
1011 f128 distsq = F128::Sub(vv, point);
1012 distsq = Vector3::LengthSq(distsq);
1013 if (point_on_box) *point_on_box = vv;
1023 u = F128::Sub(line0_point, line1_point);
1024 f128 b = Vector3::Dot(line0_dir_normalized, line1_dir_normalized);
1025 f128 d = Vector3::Dot(line0_dir_normalized, u);
1026 f128 e = Vector3::Dot(line1_dir_normalized, u);
1027 f128 det = F128::MultSub(b, b, F128::SetOne());
1029 f128 recp_det = F128::Recp(det);
1030 f128 s = F128::MultAdd(b, e, F128::Negate(d));
1031 f128 t = F128::MultSub(b, d, e);
1032 s = F128::Mult(s, recp_det);
1033 t = F128::Mult(t, recp_det);
1035 SimdVector tmp = F128::Mult(s, line0_dir_normalized);
1036 tmp = F128::MultSub(t, line1_dir_normalized, tmp);
1038 ret = Vector3::LengthSq(ret);
1040 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1041 tmp = Vector3::LengthSq(F128::MultSub(e, line1_dir_normalized, u));
1042 ret = F128::Select(parallel, tmp, ret);
1044 if (point_on_line0) {
1045 s = F128::AndNot(parallel, s);
1046 *point_on_line0 = F128::MultAdd(s, line0_dir_normalized, line0_point);
1048 if (point_on_line1) {
1049 t = F128::Select(parallel, e, t);
1050 *point_on_line1 = F128::MultAdd(t, line1_dir_normalized, line1_point);
1057 NLIB_M(
f128) DistanceSq::SegmentSegment(
SimdVector* point_on_segment0,
1063 SimdVector u = F128::Sub(segment0_point1, segment0_point0);
1064 SimdVector v = F128::Sub(segment1_point1, segment1_point0);
1065 SimdVector w = F128::Sub(segment0_point0, segment1_point0);
1066 f128 a = Vector3::LengthSq(u);
1067 f128 b = Vector3::Dot(u, v);
1068 f128 c = Vector3::LengthSq(v);
1069 f128 d = Vector3::Dot(u, w);
1070 f128 e = Vector3::Dot(v, w);
1071 f128 D = F128::MultSub(b, b, F128::Mult(a, c));
1073 f128 epsilon = F128::SetEpsilon();
1076 f128 sN = F128::MultSub(c, d, F128::Mult(b, e));
1077 f128 tN = F128::MultSub(b, d, F128::Mult(a, e));
1080 f128 parallel = F128::CmpLt(D, epsilon);
1081 f128 sN_under = F128::CmpLtZero(sN);
1082 f128 sN_out = F128::Or(sN_under, F128::CmpGt(sN, D));
1083 f128 cmp = F128::Or(parallel, sN_out);
1084 f128 under_or_parallel = F128::Or(parallel, sN_under);
1091 sN = F128::Select(cmp, F128::AndNot(under_or_parallel, D), sN);
1098 tN = F128::Select(cmp, F128::Select(under_or_parallel, e, F128::Add(e, b)), tN);
1105 tD = F128::Select(cmp, c, D);
1109 sD = F128::Select(parallel, F128::SetOne(), D);
1113 f128 tN_under = F128::CmpLtZero(tN);
1114 f128 tN_out = F128::Or(tN_under, F128::CmpGt(tN, tD));
1120 tN = F128::Clamp(tN, F128::SetZero(), tD);
1122 f128 val = F128::Select(tN_under, F128::Negate(d), F128::Sub(b, d));
1128 f128 val_in = F128::And(F128::CmpGeZero(val), F128::CmpLe(val, a));
1129 sD = F128::Select(F128::And(tN_out, val_in), a, sD);
1137 f128 sntmp = F128::AndNot(F128::CmpLtZero(val), val);
1138 sntmp = F128::Select(F128::CmpGt(val, a), sD, sntmp);
1139 sN = F128::Select(tN_out, sntmp, sN);
1142 f128 sc = F128::AndNot(F128::InBound(sN, epsilon), F128::Div(sN, sD));
1143 f128 tc = F128::AndNot(F128::InBound(tN, epsilon), F128::Div(tN, tD));
1146 f128 pt_s0 = F128::MultAdd(sc, u, segment0_point0);
1147 f128 pt_s1 = F128::MultAdd(tc, v, segment1_point0);
1148 f128 ret = F128::Sub(pt_s0, pt_s1);
1149 ret = Vector3::LengthSq(ret);
1151 if (point_on_segment0) *point_on_segment0 = pt_s0;
1152 if (point_on_segment1) *point_on_segment1 = pt_s1;
1161 SimdVector u = F128::Sub(line_point, ray_point);
1162 f128 b = Vector3::Dot(line_dir_normalized, ray_dir_normalized);
1163 f128 d = Vector3::Dot(line_dir_normalized, u);
1164 f128 e = Vector3::Dot(ray_dir_normalized, u);
1165 f128 one = F128::SetOne();
1166 f128 det = F128::MultSub(b, b, one);
1167 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1172 f128 tNum = F128::MultSub(b, d, e);
1173 tNum = F128::Select(parallel, e, tNum);
1174 f128 tNum_negative = F128::CmpLtZero(tNum);
1179 f128 minus_d = F128::Negate(d);
1180 f128 sNum = F128::MultAdd(b, e, minus_d);
1181 sNum = F128::AndNot(parallel, sNum);
1186 f128 tDenom = F128::Select(parallel, one, det);
1191 f128 sDenom = F128::Select(F128::Or(tNum_negative, parallel), one, det);
1196 sNum = F128::Select(tNum_negative, minus_d, sNum);
1201 tNum = F128::AndNot(tNum_negative, tNum);
1203 f128 s = F128::Div(sNum, sDenom);
1204 f128 t = F128::Div(tNum, tDenom);
1206 f128 pt_l = F128::MultAdd(s, line_dir_normalized, line_point);
1207 f128 pt_r = F128::MultAdd(t, ray_dir_normalized, ray_point);
1209 ret = Vector3::LengthSq(ret);
1211 if (point_on_line) *point_on_line = pt_l;
1212 if (point_on_ray) *point_on_ray = pt_r;
1221 SimdVector seg_dir = F128::Sub(segment_point1, segment_point0);
1222 SimdVector u = F128::Sub(line_point, segment_point0);
1223 f128 b = Vector3::Dot(line_dir_normalized, seg_dir);
1224 f128 c = Vector3::LengthSq(seg_dir);
1225 f128 d = Vector3::Dot(line_dir_normalized, u);
1226 f128 e = Vector3::Dot(seg_dir, u);
1227 f128 det = F128::MultSub(b, b, c);
1228 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1233 f128 tNum = F128::Select(parallel, e, F128::MultSub(b, d, e));
1238 f128 tDenom = F128::Select(parallel, c, det);
1243 f128 tmp = F128::Mult(b, e);
1244 tmp = F128::MultSub(c, d, tmp);
1245 f128 sNum = F128::AndNot(parallel, tmp);
1251 f128 tNum_under = F128::CmpLtZero(tNum);
1252 f128 tNum_out = F128::Or(tNum_under, F128::CmpGt(tNum, tDenom));
1253 tmp = F128::Select(tNum_under, F128::Negate(d), F128::Sub(b, d));
1254 sNum = F128::Select(tNum_out, tmp, sNum);
1259 f128 sDenom = F128::Select(F128::Or(tNum_out, parallel), F128::SetOne(), det);
1264 tNum = F128::Clamp(tNum, F128::SetZero(), tDenom);
1266 f128 s = F128::Div(sNum, sDenom);
1267 f128 t = F128::Div(tNum, tDenom);
1269 f128 pt_l = F128::MultAdd(s, line_dir_normalized, line_point);
1270 f128 pt_s = F128::MultAdd(t, seg_dir, segment_point0);
1272 ret = Vector3::LengthSq(ret);
1274 if (point_on_line) *point_on_line = pt_l;
1275 if (point_on_segment) *point_on_segment = pt_s;
1284 SimdVector u = F128::Sub(ray0_point, ray1_point);
1285 f128 b = Vector3::Dot(ray0_dir_normalized, ray1_dir_normalized);
1286 f128 d = Vector3::Dot(ray0_dir_normalized, u);
1287 f128 e = Vector3::Dot(ray1_dir_normalized, u);
1288 f128 one = F128::SetOne();
1289 f128 det = F128::MultSub(b, b, one);
1290 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1295 f128 minus_d = F128::Negate(d);
1296 f128 sNum = F128::AndNot(parallel, F128::MultAdd(b, e, minus_d));
1297 f128 sNum_negative = F128::CmpLtZero(sNum);
1298 f128 parallel_or_sNum_negative = F128::Or(parallel, sNum_negative);
1303 f128 tNum = F128::Select(parallel_or_sNum_negative, e, F128::MultSub(b, d, e));
1308 f128 tDenom = F128::Select(parallel_or_sNum_negative, one, det);
1313 sNum = F128::AndNot(sNum_negative, sNum);
1319 f128 tNum_negative = F128::CmpLtZero(tNum);
1320 f128 d_negative = F128::CmpLeZero(d);
1321 f128 tmp = F128::And(d_negative, minus_d);
1322 sNum = F128::Select(tNum_negative, tmp, sNum);
1327 tmp = F128::Or(parallel, F128::And(tNum_negative, d_negative));
1328 f128 sDenom = F128::Select(tmp, one, det);
1333 tNum = F128::AndNot(tNum_negative, tNum);
1335 f128 s = F128::Div(sNum, sDenom);
1336 f128 t = F128::Div(tNum, tDenom);
1338 f128 pt_r0 = F128::MultAdd(s, ray0_dir_normalized, ray0_point);
1339 f128 pt_r1 = F128::MultAdd(t, ray1_dir_normalized, ray1_point);
1341 ret = Vector3::LengthSq(ret);
1343 if (point_on_ray0) *point_on_ray0 = pt_r0;
1344 if (point_on_ray1) *point_on_ray1 = pt_r1;
1353 SimdVector seg_dir = F128::Sub(segment_point1, segment_point0);
1354 SimdVector u = F128::Sub(ray_point, segment_point0);
1355 f128 b = Vector3::Dot(ray_dir_normalized, seg_dir);
1356 f128 c = Vector3::LengthSq(seg_dir);
1357 f128 d = Vector3::Dot(ray_dir_normalized, u);
1358 f128 e = Vector3::Dot(seg_dir, u);
1359 f128 det = F128::MultSub(b, b, c);
1360 f128 one = F128::SetOne();
1361 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1367 tmp0 = F128::Mult(b, e);
1368 tmp0 = F128::MultSub(c, d, tmp0);
1369 f128 sNum = F128::AndNot(parallel, tmp0);
1374 f128 sNum_negative = F128::CmpLtZero(sNum);
1375 f128 parallel_or_sNum_negative = F128::Or(parallel, sNum_negative);
1376 tmp1 = F128::MultSub(b, d, e);
1377 f128 tNum = F128::Select(parallel_or_sNum_negative, e, tmp1);
1382 f128 tDenom = F128::Select(parallel_or_sNum_negative, c, det);
1387 sNum = F128::AndNot(sNum_negative, sNum);
1395 f128 minus_d = F128::Negate(d);
1396 f128 b_minus_d = F128::Sub(b, d);
1397 f128 tNum_negative = F128::CmpLtZero(tNum);
1398 f128 tNum_out = F128::Or(tNum_negative, F128::CmpGt(tNum, tDenom));
1399 tmp0 = F128::Select(tNum_negative, minus_d, b_minus_d);
1400 f128 cmp = F128::CmpGeZero(tmp0);
1401 tmp1 = F128::And(cmp, tmp0);
1402 sNum = F128::Select(tNum_out, tmp1, sNum);
1409 tmp0 = F128::Or(parallel, F128::And(tNum_out, cmp));
1410 f128 sDenom = F128::Select(tmp0, one, det);
1416 tNum = F128::Clamp(tNum, F128::SetZero(), tDenom);
1418 f128 s = F128::Div(sNum, sDenom);
1419 f128 t = F128::Div(tNum, tDenom);
1421 f128 pt_r = F128::MultAdd(s, ray_dir_normalized, ray_point);
1422 f128 pt_s = F128::MultAdd(t, seg_dir, segment_point0);
1424 ret = Vector3::LengthSq(ret);
1426 if (point_on_ray) *point_on_ray = pt_r;
1427 if (point_on_segment) *point_on_segment = pt_s;
1432 # pragma endregion DistanceSq function implementation 1439 # pragma region Intersection 1446 f128 dot = Plane::DotNormal(plane, line_dir_normalized);
1447 SimdVector t = Plane::DotCoord(plane, line_point);
1448 t = F128::Div(t, dot);
1449 SimdVector ret = F128::MultSub(t, line_dir_normalized, line_point);
1451 f128 eps = F128::SetEpsilon();
1452 f128 dotzero = F128::CmpNearEqZero(dot, eps);
1453 f128 nan = F128::SetNaN();
1455 return F128::Select(dotzero, nan, ret);
1461 f128 dot = Plane::DotNormal(plane, ray_dir_normalized);
1462 SimdVector t = Plane::DotCoord(plane, ray_point);
1463 t = F128::Div(t, dot);
1464 SimdVector ret = F128::MultSub(t, ray_dir_normalized, ray_point);
1466 f128 eps = F128::SetEpsilon();
1467 f128 dotzero = F128::CmpNearEqZero(dot, eps);
1468 f128 t_gt_0 = F128::CmpGtZero(t);
1469 f128 nan = F128::SetNaN();
1471 return F128::Select(F128::Or(t_gt_0, dotzero), nan, ret);
1477 SimdVector dir = F128::Sub(segment_point1, segment_point0);
1478 f128 recp_len = Vector3::RecpLength(dir);
1479 dir = F128::Mult(dir, recp_len);
1481 f128 dot = Plane::DotNormal(plane, dir);
1482 SimdVector t = Plane::DotCoord(plane, segment_point1);
1483 t = F128::Div(t, dot);
1484 SimdVector ret = F128::MultSub(t, dir, segment_point1);
1486 f128 t_gt_len = F128::CmpGt(F128::Mult(t, recp_len), F128::SetOne());
1487 f128 t_lt_0 = F128::CmpLtZero(t);
1488 f128 nan = F128::SetNaN();
1490 return F128::Select(F128::Or(t_gt_len, t_lt_0), nan, ret);
1496 SimdVector pt_c = F128::Sub(sphere, ray_point);
1498 f128 len_on_ray = Vector3::Dot(pt_c, ray_dir_normalized);
1499 f128 lensq_pt_c = Vector3::LengthSq(pt_c);
1501 r_sq = F128::Mult(r_sq, r_sq);
1502 f128 distsq = F128::MultSub(len_on_ray, len_on_ray, lensq_pt_c);
1504 f128 origin_inside = F128::CmpLe(lensq_pt_c, r_sq);
1505 f128 intersection_none;
1506 intersection_none = F128::CmpLt(len_on_ray, F128::SetZero());
1507 intersection_none = F128::AndNot(origin_inside, intersection_none);
1508 intersection_none = F128::Or(intersection_none, F128::CmpGt(distsq, r_sq));
1510 if (F128::IsAllMaskFalse(intersection_none)) {
1514 f128 q = F128::Sqrt(F128::Sub(r_sq, distsq));
1515 f128 t0 = F128::Sub(len_on_ray, q);
1516 f128 t1 = F128::Add(len_on_ray, q);
1517 f128 t = F128::Select(origin_inside, t1, t0);
1518 *distance = F128::GetFloatFromLane<0>(t);
1527 NLIB_B Intersection::TriangleRay(
float* distance,
SimdVectorArg triangle_point0,
1533 SimdVector E1 = F128::Sub(triangle_point1, triangle_point0);
1534 SimdVector E2 = F128::Sub(triangle_point2, triangle_point0);
1535 SimdVector P = Vector3::Cross(ray_dir_normalized, E2);
1537 f128 det = Vector3::Dot(E1, P);
1538 f128 inv_det = F128::Recp(det);
1541 f128 intersection_none = F128::InBound(det, F128::SetEpsilon());
1544 SimdVector T = F128::Sub(ray_point, triangle_point0);
1548 f128 u = Vector3::Dot(T, P);
1550 f128 v = Vector3::Dot(ray_dir_normalized, Q);
1551 f128 uv = F128::Mult(F128::Permute<0, 1, 4, 5>(u, v), inv_det);
1553 f128 t = F128::Mult(Vector3::Dot(E2, Q), inv_det);
1556 intersection_none = F128::Or(intersection_none, F128::CmpLt(uv, F128::SetZero()));
1557 intersection_none = F128::Or(intersection_none, F128::CmpGt(uv, F128::SetOne()));
1558 intersection_none = F128::Or(intersection_none, F128::CmpLt(t, F128::SetZero()));
1560 if (F128::IsAllMaskFalse(intersection_none)) {
1562 *distance = F128::GetFloatFromLane<0>(t);
1575 SimdVector tp0 = F128::SetFloatToLane<3>(triangle_point0, 1.f);
1576 SimdVector tp1 = F128::SetFloatToLane<3>(triangle_point1, 1.f);
1577 SimdVector tp2 = F128::SetFloatToLane<3>(triangle_point2, 1.f);
1580 f128 dist0 = Vector4::Dot(plane_normalized, tp0);
1581 f128 dist1 = Vector4::Dot(plane_normalized, tp1);
1582 f128 dist2 = Vector4::Dot(plane_normalized, tp2);
1584 f128 dist012 = Vector4::Dot3(plane_normalized, tp0, tp1, tp2);
1589 f128 min_dist = F128::Min(dist0, dist1);
1590 f128 max_dist = F128::Max(dist0, dist1);
1591 min_dist = F128::Min(min_dist, dist2);
1592 max_dist = F128::Max(max_dist, dist2);
1594 f128 outside = F128::CmpGtZero(min_dist);
1595 f128 inside = F128::CmpLtZero(max_dist);
1597 if (F128::IsAllMaskTrue(outside))
return PLANE_FRONT;
1598 if (F128::IsAllMaskTrue(inside))
return PLANE_BACK;
1599 return PLANE_INTERSECT;
1605 f128 c = F128::SetFloatToLane<3>(sphere, 1.f);
1607 f128 dist = Vector4::Dot(plane_normalized, c);
1608 f128 outside = F128::CmpGt(dist, r);
1609 f128 inside = F128::CmpLt(dist, F128::Negate(r));
1611 if (F128::IsAllMaskTrue(outside))
return PLANE_FRONT;
1612 if (F128::IsAllMaskTrue(inside))
return PLANE_BACK;
1613 return PLANE_INTERSECT;
1618 f128 distsq = Vector3::LengthSq(F128::Sub(sphere0, sphere1));
1620 radsq = F128::Mult(radsq, radsq);
1621 return F128::IsAllMaskFalse(F128::CmpGt(distsq, radsq));
1628 SimdVector lineVec = Vector3::Cross(plane1, plane0);
1629 f128 lineVecLenSq = Vector3::LengthSq(lineVec);
1633 SimdVector p1_line = Vector3::Cross(plane1, lineVec);
1638 SimdVector line_p0 = Vector3::Cross(lineVec, plane0);
1639 point = F128::MultAdd<3>(plane1, line_p0, point,
each_select32);
1641 SimdVector point0 = F128::Div(point, lineVecLenSq);
1642 SimdVector point1 = F128::Add(point0, lineVec);
1643 f128 eps = F128::SetEpsilon();
1644 f128 nan = F128::SetNaN();
1645 f128 parallel = F128::CmpNearEq(F128::SetZero(), lineVecLenSq, eps);
1647 ret.val[0] = F128::Select(parallel, nan, point0);
1648 ret.val[1] = F128::Select(parallel, nan, point1);
1656 SimdPlane plane = Plane::FromPoint(triangle_point0, triangle_point1, triangle_point2);
1660 f128 distsq = DistanceSq::PointPlane(&q, sphere, plane);
1662 r_sq = F128::Mult(r_sq, r_sq);
1663 f128 cmp = F128::CmpLe(distsq, r_sq);
1664 if (F128::IsAllMaskFalse(cmp))
return false;
1669 Vector3::Cross(F128::Sub(q, triangle_point0), F128::Sub(triangle_point1, triangle_point0));
1671 Vector3::Cross(F128::Sub(q, triangle_point1), F128::Sub(triangle_point2, triangle_point1));
1673 Vector3::Cross(F128::Sub(q, triangle_point2), F128::Sub(triangle_point0, triangle_point2));
1674 plane = F128::SetZeroToLane<3>(plane);
1675 f128 three_dots = Vector4::Dot3(plane, c0, c1, c2);
1676 three_dots = F128::Swizzle<0, 1, 2, 2>(three_dots);
1677 cmp = F128::CmpGeZero(three_dots);
1678 if (F128::IsAllMaskFalse(cmp) || F128::IsAllMaskTrue(cmp))
return true;
1682 f128 seg_dist01 = DistanceSq::PointSegment(sphere, triangle_point0, triangle_point1);
1683 f128 seg_dist02 = DistanceSq::PointSegment(sphere, triangle_point0, triangle_point2);
1684 f128 seg_dist = F128::Min(seg_dist01, seg_dist02);
1685 f128 seg_dist12 = DistanceSq::PointSegment(sphere, triangle_point1, triangle_point2);
1686 seg_dist = F128::Min(seg_dist, seg_dist12);
1687 cmp = F128::CmpLe(seg_dist, r_sq);
1688 if (F128::IsAllMaskFalse(cmp))
return false;
1698 SimdVector center = F128::Add(aabb_max, aabb_min);
1699 center = F128::Mult(0.5f, center);
1700 SimdVector extents = F128::Sub(aabb_max, center);
1701 center = F128::SetFloatToLane<3>(center, 1.f);
1703 f128 dist = Vector4::Dot(center, plane_normalized);
1704 f128 radius = Vector3::Dot(extents, F128::Abs(plane_normalized));
1705 if (F128::IsAllMaskFalse(F128::CmpLe(dist, radius))) {
1708 if (F128::IsAllMaskFalse(F128::CmpGe(dist, F128::Negate(radius)))) {
1711 return PLANE_INTERSECT;
1719 f128 inv_dir = F128::Recp(ray_dir_normalized);
1720 f128 selector = F128::CmpGeZero(ray_dir_normalized);
1723 f128 tmin = F128::Select(selector, aabb_min, aabb_max);
1724 f128 tmax = F128::Select(selector, aabb_max, aabb_min);
1725 tmin = F128::Sub(tmin, ray_point);
1726 tmax = F128::Sub(tmax, ray_point);
1727 tmin = F128::Mult(tmin, inv_dir);
1728 tmax = F128::Mult(tmax, inv_dir);
1733 tmin = F128::Swizzle<0, 1, 2, 0>(tmin);
1734 tmax = F128::Swizzle<2, 0, 0, 1>(tmax);
1735 f128 result = F128::CmpGeZero(tmax);
1736 if (!F128::IsAllMaskFalse(F128::CmpGt(tmin, tmax)))
return false;
1739 return F128::IsAllMaskTrue(result);
1743 NLIB_B Intersection::AxisAlignedBoxSphere(
const AxisAlignedBox& aabb,
1747 f128 max_center = F128::Sub(sphere, aabb_max);
1748 f128 min_center = F128::Sub(sphere, aabb_min);
1749 f128 max_mask = F128::CmpGt(sphere, aabb_max);
1750 f128 min_mask = F128::CmpLt(sphere, aabb_min);
1751 f128 dist_sq = F128::SetZero();
1752 dist_sq = F128::Select(max_mask, max_center, dist_sq);
1753 dist_sq = F128::Select(min_mask, min_center, dist_sq);
1754 dist_sq = Vector3::LengthSq(dist_sq);
1756 r_sq = F128::Mult(r_sq, r_sq);
1757 return F128::IsAllMaskTrue(F128::CmpLe(dist_sq, r_sq));
1761 NLIB_B Intersection::AxisAlignedBoxAxisAlignedBox(
const AxisAlignedBox& aabb0,
1765 return F128::IsAllMaskFalse(F128::Or(cond0, cond1));
1769 NLIB_B Intersection::AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
1783 F128::Min(F128::Min(tri0, tri1), tri2);
1785 F128::Max(F128::Max(tri0, tri1), tri2);
1786 f128 cond0 = F128::CmpGt(tri_min, box_max);
1787 f128 cond1 = F128::CmpGt(box_min, tri_max);
1788 if (!F128::IsAllMaskFalse(F128::Or(cond0, cond1))) {
1795 point_in = F128::And(F128::CmpGe(tri0, box_min),
1796 F128::CmpLe(tri0, box_max));
1797 if (F128::IsAllMaskTrue(point_in))
return true;
1798 point_in = F128::And(F128::CmpGe(tri1, box_min),
1799 F128::CmpLe(tri1, box_max));
1800 if (F128::IsAllMaskTrue(point_in))
return true;
1801 point_in = F128::And(F128::CmpGe(tri2, box_min),
1802 F128::CmpLe(tri2, box_max));
1803 if (F128::IsAllMaskTrue(point_in))
return true;
1813 N = F128::SetZeroToLane<3>(N);
1814 f128 D = Vector3::Dot(N, tri0);
1815 f128 normal_gt_0 = F128::CmpGt(N, F128::SetZero());
1816 SimdVector v_near = F128::Select(normal_gt_0, box_min, box_max);
1817 SimdVector v_far = F128::Select(normal_gt_0, box_max, box_min);
1818 f128 min_near = Vector4::Dot(N, v_near);
1819 f128 max_far = Vector4::Dot(N, v_far);
1820 min_near = F128::CmpGt(min_near, D);
1821 max_far = F128::CmpLt(max_far, D);
1822 if (!F128::IsAllMaskFalse(F128::Or(min_near, max_far))) {
1827 SimdVector box_center = F128::Add(box_max, box_min);
1828 box_center = F128::Mult(0.5f, box_center);
1829 SimdVector extents = F128::Sub(box_center, box_min);
1830 SimdVector tp0 = F128::Sub(tri0, box_center);
1831 SimdVector tp1 = F128::Sub(tri1, box_center);
1832 SimdVector tp2 = F128::Sub(tri2, box_center);
1833 tp0 = F128::SetZeroToLane<3>(tp0);
1834 tp1 = F128::SetZeroToLane<3>(tp1);
1835 tp2 = F128::SetZeroToLane<3>(tp2);
1838 f0 = F128::SetZeroToLane<3>(f0);
1839 f1 = F128::SetZeroToLane<3>(f1);
1840 f2 = F128::SetZeroToLane<3>(f2);
1844 f128 tp0dot_A00A01A02A10;
1845 f128 tp0dot_A11A12A20A21;
1847 f128 tp1dot_A11A12A21A22;
1848 f128 tp2dot_A00A10A20A22;
1849 f128 neg_f0 = F128::Negate(f0);
1850 f128 neg_f1 = F128::Negate(f1);
1851 f128 neg_f2 = F128::Negate(f2);
1854 SimdVector A00 = F128::Permute<7, 6, 1, 3>(f0, neg_f0);
1856 SimdVector A01 = F128::Permute<7, 6, 1, 3>(f1, neg_f1);
1858 SimdVector A02 = F128::Permute<7, 6, 1, 3>(f2, neg_f2);
1861 SimdVector A10 = F128::Permute<2, 3, 4, 3>(f0, neg_f0);
1863 SimdVector A11 = F128::Permute<2, 3, 4, 3>(f1, neg_f1);
1865 SimdVector A12 = F128::Permute<2, 3, 4, 3>(f2, neg_f2);
1868 SimdVector A20 = F128::Permute<5, 0, 3, 3>(f0, neg_f0);
1870 SimdVector A21 = F128::Permute<5, 0, 3, 3>(f1, neg_f1);
1872 SimdVector A22 = F128::Permute<5, 0, 3, 3>(f2, neg_f2);
1874 tp0dot_A00A01A02A10 = Vector4::Dot4(tp0, A00, A01, A02, A10);
1875 tp0dot_A11A12A20A21 = Vector4::Dot4(tp0, A11, A12, A10, A11);
1876 tp1dot_A01A02 = Vector4::Dot2(tp1, A01, A02);
1877 tp1dot_A11A12A21A22 = Vector4::Dot4(tp1, A11, A12, A21, A22);
1878 tp2dot_A00A10A20A22 = Vector4::Dot4(tp2, A00, A10, A20, A22);
1880 A00 = F128::Abs(A00);
1881 A01 = F128::Abs(A01);
1882 A02 = F128::Abs(A02);
1883 A10 = F128::Abs(A10);
1884 A11 = F128::Abs(A11);
1885 A12 = F128::Abs(A12);
1886 A20 = F128::Abs(A20);
1887 A21 = F128::Abs(A21);
1888 A22 = F128::Abs(A22);
1892 radius = Vector4::Dot4(extents, A00, A01, A02, A10);
1893 tp12dot = F128::Permute<4, 0, 1, 5>(tp1dot_A01A02, tp2dot_A00A10A20A22);
1894 pmax = F128::Max(tp0dot_A00A01A02A10, tp12dot);
1895 pmin = F128::Min(tp0dot_A00A01A02A10, tp12dot);
1896 f128 intersection_none = F128::CmpGt(pmin, radius);
1897 intersection_none = F128::Or(intersection_none, F128::CmpLt(pmax, F128::Negate(radius)));
1900 radius = Vector4::Dot4(extents, A11, A12, A20, A21);
1901 tp12dot = F128::Permute<0, 1, 6, 2>(tp1dot_A11A12A21A22, tp2dot_A00A10A20A22);
1902 pmax = F128::Max(tp0dot_A11A12A20A21, tp12dot);
1903 pmin = F128::Min(tp0dot_A11A12A20A21, tp12dot);
1904 intersection_none = F128::Or(intersection_none, F128::CmpGt(pmin, radius));
1905 intersection_none = F128::Or(intersection_none, F128::CmpLt(pmax, F128::Negate(radius)));
1908 radius = Vector4::Dot(extents, A22);
1909 pmax = F128::Max(tp1dot_A11A12A21A22, tp2dot_A00A10A20A22);
1910 pmin = F128::Min(tp1dot_A11A12A21A22, tp2dot_A00A10A20A22);
1913 intersection_none = F128::Or(intersection_none, F128::CmpGt(pmin, radius));
1914 intersection_none = F128::Or(intersection_none, F128::CmpLt(pmax, F128::Negate(radius)));
1916 return F128::IsAllMaskFalse(intersection_none);
1921 Intersection::OrientedBoxAxisAlignedBox(
const OrientedBox& box,
1927 aabb_center = F128::Mult(0.5f, F128::Add(aabb_max, aabb_min));
1928 aabb_extent = F128::Sub(aabb_max, aabb_center);
1929 aabb_extent = F128::SetZeroToLane<3>(aabb_extent);
1932 box_center = F128::SetZeroToLane<3>(box_center);
1940 abs_M0x = F128::Abs(rot.
r[0]);
1941 abs_M1x = F128::Abs(rot.
r[1]);
1942 abs_M2x = F128::Abs(rot.
r[2]);
1947 neg_Mx0 = F128::Negate(Mx0);
1948 neg_Mx1 = F128::Negate(Mx1);
1949 neg_Mx2 = F128::Negate(Mx2);
1978 f128 d, d_aabb, d_box;
1980 f128 intersection_none = F128::SetZero();
1985 d = F128::Abs(box_center);
1986 d_aabb = aabb_extent;
1987 d_box = Vector4::Dot3(box_extent, F128::Abs(Mx0), F128::Abs(Mx1), F128::Abs(Mx2));
1988 d_aabb_box = F128::Add(d_aabb, d_box);
1989 intersection_none = F128::CmpGt(d, d_aabb_box);
1992 d = F128::Abs(Vector4::Dot3(box_center, Mx0, Mx1, Mx2));
1993 d_aabb = Vector4::Dot3(aabb_extent, F128::Abs(Mx0), F128::Abs(Mx1), F128::Abs(Mx2));
1995 d_aabb_box = F128::Add(d_aabb, d_box);
1996 cmp = F128::CmpGt(d, d_aabb_box);
1997 intersection_none = F128::Or(intersection_none, cmp);
2004 t0 = F128::Permute<3, 6, 1, 3>(Mx0, neg_Mx0);
2005 t1 = F128::Permute<3, 6, 1, 3>(Mx1, neg_Mx1);
2006 t2 = F128::Permute<3, 6, 1, 3>(Mx2, neg_Mx2);
2007 d = F128::Abs(Vector4::Dot3(box_center, t0, t1, t2));
2008 d_aabb = Vector4::Dot3(aabb_extent, F128::Abs(t0), F128::Abs(t1), F128::Abs(t2));
2010 t0 = F128::Swizzle<3, 2, 1, 3>(abs_M0x);
2011 t1 = F128::Swizzle<2, 3, 0, 3>(abs_M0x);
2012 t2 = F128::Swizzle<1, 0, 3, 3>(abs_M0x);
2013 d_box = Vector4::Dot3(box_extent, t0, t1, t2);
2014 d_aabb_box = F128::Add(d_aabb, d_box);
2015 cmp = F128::CmpGt(d, d_aabb_box);
2016 intersection_none = F128::Or(intersection_none, cmp);
2021 t0 = F128::Permute<2, 3, 4, 3>(Mx0, neg_Mx0);
2022 t1 = F128::Permute<2, 3, 4, 3>(Mx1, neg_Mx1);
2023 t2 = F128::Permute<2, 3, 4, 3>(Mx2, neg_Mx2);
2024 d = F128::Abs(Vector4::Dot3(box_center, t0, t1, t2));
2025 d_aabb = Vector4::Dot3(aabb_extent, F128::Abs(t0), F128::Abs(t1), F128::Abs(t2));
2027 t0 = F128::Swizzle<3, 2, 1, 3>(abs_M1x);
2028 t1 = F128::Swizzle<2, 3, 0, 3>(abs_M1x);
2029 t2 = F128::Swizzle<1, 0, 3, 3>(abs_M1x);
2030 d_box = Vector4::Dot3(box_extent, t0, t1, t2);
2031 d_aabb_box = F128::Add(d_aabb, d_box);
2032 cmp = F128::CmpGt(d, d_aabb_box);
2033 intersection_none = F128::Or(intersection_none, cmp);
2038 t0 = F128::Permute<5, 0, 3, 3>(Mx0, neg_Mx0);
2039 t1 = F128::Permute<5, 0, 3, 3>(Mx1, neg_Mx1);
2040 t2 = F128::Permute<5, 0, 3, 3>(Mx2, neg_Mx2);
2041 d = F128::Abs(Vector4::Dot3(box_center, t0, t1, t2));
2042 d_aabb = Vector4::Dot3(aabb_extent, F128::Abs(t0), F128::Abs(t1), F128::Abs(t2));
2044 t0 = F128::Swizzle<3, 2, 1, 3>(abs_M2x);
2045 t1 = F128::Swizzle<2, 3, 0, 3>(abs_M2x);
2046 t2 = F128::Swizzle<1, 0, 3, 3>(abs_M2x);
2047 d_box = Vector4::Dot3(box_extent, t0, t1, t2);
2048 d_aabb_box = F128::Add(d_aabb, d_box);
2049 cmp = F128::CmpGt(d, d_aabb_box);
2050 intersection_none = F128::Or(intersection_none, cmp);
2052 intersection_none = F128::SetZeroToLane<3>(intersection_none);
2053 return F128::IsAllMaskFalse(intersection_none);
2057 NLIB_B Intersection::OrientedBoxOrientedBox(
const OrientedBox& box0,
2062 obox.
rotation = Quaternion::Mult(box0_rot, Quaternion::Conjugate(box1_rot));
2070 return Intersection::OrientedBoxAxisAlignedBox(obox, aabb);
2080 SimdVector sphere_center = F128::Sub(sphere, box_center);
2081 sphere_center = Vector3::InvRotate(sphere_center, box_rotation);
2084 f128 lt_min = F128::CmpLt(sphere_center, F128::Negate(box_extent));
2085 f128 gt_max = F128::CmpGt(sphere_center, box_extent);
2086 SimdVector diff_min = F128::Add(sphere_center, box_extent);
2087 SimdVector diff_max = F128::Sub(sphere_center, box_extent);
2089 f128 dist_sq = F128::SetZero();
2090 dist_sq = F128::Select(lt_min, diff_min, dist_sq);
2091 dist_sq = F128::Select(gt_max, diff_max, dist_sq);
2092 dist_sq = Vector3::Dot(dist_sq, dist_sq);
2094 f128 rad_sq = F128::Mult(sphere, sphere);
2097 return Vector4::CmpLe(dist_sq, rad_sq);
2107 SimdVector tp0 = F128::Sub(triangle_point0, box_center);
2108 SimdVector tp1 = F128::Sub(triangle_point1, box_center);
2109 SimdVector tp2 = F128::Sub(triangle_point2, box_center);
2110 tp0 = Vector3::InvRotate(tp0, box_rotation);
2111 tp1 = Vector3::InvRotate(tp1, box_rotation);
2112 tp2 = Vector3::InvRotate(tp2, box_rotation);
2118 return Intersection::AxisAlignedBoxTriangle(aabb, tp0, tp1, tp2);
2123 Intersection::OrientedBoxPlane(
const OrientedBox& box,
2127 f128 new_d = F128::Sub(plane_normalized, Vector3::Dot(plane_normalized, box.
center));
2128 new_plane = F128::Permute<0, 1, 2, 7>(new_plane, new_d);
2132 aabb.point_min = F128::Negate(aabb.point_max);
2134 return Intersection::AxisAlignedBoxPlane(aabb, new_plane);
2142 P = Vector3::InvRotate(P, box_rotation);
2143 SimdVector D = Vector3::InvRotate(ray_dir_normalized, box_rotation);
2149 return Intersection::AxisAlignedBoxRay(aabb, P, D);
2153 SimdPlane near_plane = frustum.near_plane_;
2154 SimdPlane far_plane = frustum.far_plane_;
2155 SimdPlane left_plane = frustum.left_plane_;
2156 SimdPlane right_plane = frustum.right_plane_;
2157 SimdPlane top_plane = frustum.top_plane_;
2158 SimdPlane bottom_plane = frustum.bottom_plane_;
2165 center = Vector3::InvRotate(F128::Sub(center, frustum_center), frustum_rot);
2166 center = F128::SetFloatToLane<3>(center, 1.f);
2170 dist0 = Vector4::Dot4(center, near_plane, far_plane, left_plane, right_plane);
2171 dist1 = Vector4::Dot2(center, top_plane, bottom_plane);
2172 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2175 f128 outside = F128::CmpGt(dist0, radius);
2176 outside = F128::Or(F128::CmpGt(dist1, radius), outside);
2177 if (!F128::IsAllMaskFalse(outside))
return false;
2180 f128 center_inside = F128::CmpLeZero(dist0);
2181 center_inside = F128::And(F128::CmpLeZero(dist0), center_inside);
2182 if (F128::IsAllMaskTrue(center_inside))
return true;
2191 dist_plane = Vector4::Dot4(center, near_plane, far_plane, left_plane, right_plane);
2194 pt_plane = F128::MultSub(near_plane, F128::SetValue<0>(dist0,
each_select32), center);
2195 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2196 inside = Vector4::Dot4(pt_plane, left_plane, right_plane, top_plane, bottom_plane);
2197 inside = F128::CmpLeZero(inside);
2198 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<0>(dist_plane,
each_select32)));
2199 if (F128::IsAllMaskTrue(inside))
return true;
2202 pt_plane = F128::MultSub(far_plane, F128::SetValue<1>(dist0,
each_select32), center);
2203 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2204 inside = Vector4::Dot4(pt_plane, left_plane, right_plane, top_plane, bottom_plane);
2205 inside = F128::CmpLeZero(inside);
2206 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<1>(dist_plane,
each_select32)));
2207 if (F128::IsAllMaskTrue(inside))
return true;
2210 pt_plane = F128::MultSub(left_plane, F128::SetValue<2>(dist0,
each_select32), center);
2211 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2212 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, top_plane, bottom_plane);
2213 inside = F128::CmpLeZero(inside);
2214 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<2>(dist_plane,
each_select32)));
2215 if (F128::IsAllMaskTrue(inside))
return true;
2218 pt_plane = F128::MultSub(right_plane, F128::SetValue<3>(dist0,
each_select32), center);
2219 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2220 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, top_plane, bottom_plane);
2221 inside = F128::CmpLeZero(inside);
2222 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<3>(dist_plane,
each_select32)));
2223 if (F128::IsAllMaskTrue(inside))
return true;
2225 dist_plane = Vector4::Dot2(center, top_plane, bottom_plane);
2228 pt_plane = F128::MultSub(top_plane, F128::SetValue<0>(dist1,
each_select32), center);
2229 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2230 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, left_plane, right_plane);
2231 inside = F128::CmpLeZero(inside);
2232 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<0>(dist_plane,
each_select32)));
2233 if (F128::IsAllMaskTrue(inside))
return true;
2236 pt_plane = F128::MultSub(bottom_plane, F128::SetValue<1>(dist1,
each_select32), center);
2237 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2238 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, left_plane, right_plane);
2239 inside = F128::CmpLeZero(inside);
2240 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<1>(dist_plane,
each_select32)));
2241 if (F128::IsAllMaskTrue(inside))
return true;
2245 f128 radius_sq = F128::Mult(radius, radius);
2252 SimdVector left_top = Vector3::LoadFloat3(&corners[0]);
2253 SimdVector right_top = Vector3::LoadFloat3(&corners[1]);
2254 SimdVector right_bottom = Vector3::LoadFloat3(&corners[2]);
2255 SimdVector left_bottom = Vector3::LoadFloat3(&corners[3]);
2256 SimdVector left_top_far = Vector3::LoadFloat3(&corners[4]);
2257 SimdVector right_top_far = Vector3::LoadFloat3(&corners[5]);
2258 SimdVector right_bottom_far = Vector3::LoadFloat3(&corners[6]);
2259 SimdVector left_bottom_far = Vector3::LoadFloat3(&corners[7]);
2262 dist_sq = DistanceSq::PointSegment(center, left_top, right_top);
2263 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_top, right_bottom));
2264 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_bottom, left_bottom));
2265 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_bottom, left_top));
2267 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_top_far, right_top_far));
2268 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_top_far, right_bottom_far));
2270 F128::Min(dist_sq, DistanceSq::PointSegment(center, right_bottom_far, left_bottom_far));
2271 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_bottom_far, left_top_far));
2273 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_top_far, left_top));
2274 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_top_far, right_top));
2275 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_bottom_far, right_bottom));
2276 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_bottom_far, left_bottom));
2278 return F128::IsAllMaskTrue(F128::CmpLe(dist_sq, radius_sq));
2282 SimdVector pt = F128::Sub(point, frustum.center_);
2283 pt = Vector3::InvRotate(pt, frustum.rotation_);
2284 pt = F128::SetFloatToLane<3>(pt, 1.f);
2286 f128 dot1 = Vector4::Dot4(pt, frustum.near_plane_, frustum.far_plane_, frustum.top_plane_,
2287 frustum.bottom_plane_);
2288 f128 dot2 = Vector4::Dot2(pt, frustum.left_plane_, frustum.right_plane_);
2289 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
2290 dot1 = F128::Max(dot1, dot2);
2291 f128 outside = F128::CmpGt(dot1, F128::SetZero());
2292 return F128::IsAllMaskFalse(outside);
2295 NLIB_B Intersection::FrustumAxisAlignedBox(
const Frustum& frustum,
2301 if (Containment::FrustumPoint(frustum, C))
return true;
2308 frustum.
Transform(&fstm, 1.f, F128::Set0001(), F128::Negate(C));
2314 for (
size_t i = 0; i < 8; ++i) {
2315 corners[i] = Vector3::LoadFloat3(&corners_[i]);
2316 corners[i] = F128::SetFloatToLane<3>(corners[i], 1.f);
2321 pt_min = pt_max = corners[0];
2322 for (
size_t i = 1; i < 8; ++i) {
2324 pt_min = F128::Min(vec, pt_min);
2325 pt_max = F128::Max(vec, pt_max);
2327 f128 disjoint = F128::Or(F128::CmpGt(pt_min, extent),
2328 F128::CmpLt(pt_max, F128::Negate(extent)));
2329 disjoint = F128::SetZeroToLane<3>(disjoint);
2330 if (!F128::IsAllMaskFalse(disjoint))
return false;
2338 f128 dist0_frustum, dist1_frustum;
2339 f128 dist_aabb_max, dist_aabb_min;
2343 plane = fstm.near_plane_;
2344 N = Vector3::Rotate(plane, frustum_rot);
2345 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2346 plane = F128::Permute<0, 1, 2, 7>(N, D);
2348 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2349 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2350 N = Vector3::Dot(F128::Abs(N), extent);
2351 dist_aabb_max = F128::Add(D, N);
2352 dist_aabb_min = F128::Sub(D, N);
2353 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2354 F128::CmpGe(dist1_frustum, dist_aabb_min));
2355 if (F128::IsAllMaskFalse(intersect))
return false;
2356 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2357 F128::CmpLe(dist1_frustum, dist_aabb_max));
2358 if (F128::IsAllMaskFalse(intersect))
return false;
2361 plane = fstm.left_plane_;
2362 N = Vector3::Rotate(plane, frustum_rot);
2363 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2364 plane = F128::Permute<0, 1, 2, 7>(N, D);
2366 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2367 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2368 N = Vector3::Dot(F128::Abs(N), extent);
2369 dist_aabb_max = F128::Add(D, N);
2370 dist_aabb_min = F128::Sub(D, N);
2371 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2372 F128::CmpGe(dist1_frustum, dist_aabb_min));
2373 if (F128::IsAllMaskFalse(intersect))
return false;
2374 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2375 F128::CmpLe(dist1_frustum, dist_aabb_max));
2376 if (F128::IsAllMaskFalse(intersect))
return false;
2379 plane = fstm.right_plane_;
2380 N = Vector3::Rotate(plane, frustum_rot);
2381 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2382 plane = F128::Permute<0, 1, 2, 7>(N, D);
2384 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2385 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2386 N = Vector3::Dot(F128::Abs(N), extent);
2387 dist_aabb_max = F128::Add(D, N);
2388 dist_aabb_min = F128::Sub(D, N);
2389 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2390 F128::CmpGe(dist1_frustum, dist_aabb_min));
2391 if (F128::IsAllMaskFalse(intersect))
return false;
2392 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2393 F128::CmpLe(dist1_frustum, dist_aabb_max));
2394 if (F128::IsAllMaskFalse(intersect))
return false;
2397 plane = fstm.top_plane_;
2398 N = Vector3::Rotate(plane, frustum_rot);
2399 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2400 plane = F128::Permute<0, 1, 2, 7>(N, D);
2402 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2403 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2404 N = Vector3::Dot(F128::Abs(N), extent);
2405 dist_aabb_max = F128::Add(D, N);
2406 dist_aabb_min = F128::Sub(D, N);
2407 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2408 F128::CmpGe(dist1_frustum, dist_aabb_min));
2409 if (F128::IsAllMaskFalse(intersect))
return false;
2410 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2411 F128::CmpLe(dist1_frustum, dist_aabb_max));
2412 if (F128::IsAllMaskFalse(intersect))
return false;
2415 plane = fstm.bottom_plane_;
2416 N = Vector3::Rotate(plane, frustum_rot);
2417 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2418 plane = F128::Permute<0, 1, 2, 7>(N, D);
2420 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2421 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2422 N = Vector3::Dot(F128::Abs(N), extent);
2423 dist_aabb_max = F128::Add(D, N);
2424 dist_aabb_min = F128::Sub(D, N);
2425 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2426 F128::CmpGe(dist1_frustum, dist_aabb_min));
2427 if (F128::IsAllMaskFalse(intersect))
return false;
2428 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2429 F128::CmpLe(dist1_frustum, dist_aabb_max));
2430 if (F128::IsAllMaskFalse(intersect))
return false;
2434 E0[0] = F128::Set1000();
2435 E0[1] = F128::Set0100();
2436 E0[2] = F128::Set0010();
2438 E1[0] = F128::Sub(corners[0], corners[4]);
2439 E1[1] = F128::Sub(corners[1], corners[5]);
2440 E1[2] = F128::Sub(corners[2], corners[6]);
2441 E1[3] = F128::Sub(corners[3], corners[7]);
2442 E1[4] = F128::Sub(corners[1], corners[0]);
2443 E1[5] = F128::Sub(corners[1], corners[2]);
2446 for (
size_t i = 0; i < 3; ++i) {
2447 for (
size_t j = 0; j < 6; ++j) {
2448 SimdVector axis = Vector3::Cross(E0[i], E1[j]);
2449 axis = F128::SetZeroToLane<3>(axis);
2450 N = Vector3::Dot(F128::Abs(axis), extent);
2452 f128 aabb_min = F128::Sub(D, N);
2453 f128 aabb_max = F128::Add(D, N);
2454 dot0 = Vector4::Dot4(axis, corners[0], corners[1], corners[2], corners[3]);
2455 dot1 = Vector4::Dot4(axis, corners[4], corners[5], corners[6], corners[7]);
2457 intersect = F128::CmpGe(F128::Max(dot0, dot1), aabb_min);
2458 if (F128::IsAllMaskFalse(intersect))
return false;
2459 intersect = F128::CmpLe(F128::Min(dot0, dot1), aabb_max);
2460 if (F128::IsAllMaskFalse(intersect))
return false;
2466 NLIB_B Intersection::FrustumOrientedBox(
const Frustum& frustum,
2469 frustum.
Transform(&frstm, 1.f, F128::Set0001(), F128::Negate(obb.
center));
2470 frstm.
Transform(&frstm, 1.f, Quaternion::Conjugate(obb.
rotation), F128::SetZero());
2475 return Intersection::FrustumAxisAlignedBox(frstm, aabb);
2484 SimdVector pt0 = Vector3::InvRotate(F128::Sub(triangle_point0, frustum_center), frustum_rot);
2485 SimdVector pt1 = Vector3::InvRotate(F128::Sub(triangle_point1, frustum_center), frustum_rot);
2486 SimdVector pt2 = Vector3::InvRotate(F128::Sub(triangle_point2, frustum_center), frustum_rot);
2487 pt0 = F128::SetFloatToLane<3>(pt0, 1.f);
2488 pt1 = F128::SetFloatToLane<3>(pt1, 1.f);
2489 pt2 = F128::SetFloatToLane<3>(pt2, 1.f);
2491 SimdPlane near_plane = frustum.near_plane_;
2492 SimdPlane far_plane = frustum.far_plane_;
2493 SimdPlane left_plane = frustum.left_plane_;
2494 SimdPlane right_plane = frustum.right_plane_;
2495 SimdPlane top_plane = frustum.top_plane_;
2496 SimdPlane bottom_plane = frustum.bottom_plane_;
2498 f128 dist0, dist1, dist_max;
2499 f128 dist0_min, dist1_min;
2503 dist0 = Vector4::Dot4(pt0, near_plane, far_plane, left_plane, right_plane);
2505 dist1 = Vector4::Dot2(pt0, top_plane, bottom_plane);
2506 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2508 dist_max = F128::Max(dist0, dist1);
2509 outside = F128::CmpGtZero(dist_max);
2510 if (F128::IsAllMaskFalse(outside))
return true;
2513 dist0 = Vector4::Dot4(pt1, near_plane, far_plane, left_plane, right_plane);
2514 dist0_min = F128::Min(dist0, dist0_min);
2515 dist1 = Vector4::Dot2(pt1, top_plane, bottom_plane);
2516 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2517 dist1_min = F128::Min(dist1, dist1_min);
2518 dist_max = F128::Max(dist0, dist1);
2519 outside = F128::CmpGtZero(dist_max);
2520 if (F128::IsAllMaskFalse(outside))
return true;
2523 dist0 = Vector4::Dot4(pt2, near_plane, far_plane, left_plane, right_plane);
2524 dist0_min = F128::Min(dist0, dist0_min);
2525 dist1 = Vector4::Dot2(pt2, top_plane, bottom_plane);
2526 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2527 dist1_min = F128::Min(dist1, dist1_min);
2528 dist_max = F128::Max(dist0, dist1);
2529 outside = F128::CmpGtZero(dist_max);
2530 if (F128::IsAllMaskFalse(outside))
return true;
2533 if (!F128::IsAllMaskFalse(F128::Or(
2534 F128::CmpGtZero(dist0_min), F128::CmpGtZero(dist1_min))))
return false;
2539 pt0 = triangle_point0;
2540 pt1 = triangle_point1;
2541 pt2 = triangle_point2;
2544 SimdPlane triangle = Plane::FromPoint(pt0, pt1, pt2);
2548 for (
size_t i = 0; i < 8; ++i) {
2549 corners[i] = Vector3::LoadFloat3(&corners_[i]);
2550 corners[i] = F128::SetFloatToLane<3>(corners[i], 1.f);
2552 f128 dot0 = Vector4::Dot4(triangle, corners[0], corners[1], corners[2], corners[3]);
2553 f128 dot1 = Vector4::Dot4(triangle, corners[4], corners[5], corners[6], corners[7]);
2555 if (F128::IsAllMaskFalse(F128::CmpGeZero(F128::Max(dot0, dot1))))
return false;
2557 if (F128::IsAllMaskFalse(F128::CmpLeZero(F128::Min(dot0, dot1))))
return false;
2561 E0[0] = F128::Sub(pt1, pt0);
2562 E0[1] = F128::Sub(pt2, pt1);
2563 E0[2] = F128::Sub(pt0, pt2);
2565 E1[0] = F128::Sub(corners[0], corners[4]);
2566 E1[1] = F128::Sub(corners[1], corners[5]);
2567 E1[2] = F128::Sub(corners[2], corners[6]);
2568 E1[3] = F128::Sub(corners[3], corners[7]);
2569 E1[4] = F128::Sub(corners[1], corners[0]);
2570 E1[5] = F128::Sub(corners[1], corners[2]);
2572 for (
size_t i = 0; i < 3; ++i) {
2573 for (
size_t j = 0; j < 6; ++j) {
2574 SimdVector axis = Vector3::Cross(E0[i], E1[j]);
2575 axis = F128::SetZeroToLane<3>(axis);
2576 f128 tri_min, tri_max;
2578 f128 tmp0 = Vector3::Dot(axis, pt0);
2579 f128 tmp1 = Vector3::Dot(axis, pt1);
2580 f128 tmp2 = Vector3::Dot(axis, pt2);
2581 tri_min = F128::Min(tmp0, tmp1);
2582 tri_max = F128::Max(tmp0, tmp1);
2583 tri_min = F128::Min(tri_min, tmp2);
2584 tri_max = F128::Max(tri_max, tmp2);
2586 dot0 = Vector4::Dot4(axis, corners[0], corners[1], corners[2], corners[3]);
2587 dot1 = Vector4::Dot4(axis, corners[4], corners[5], corners[6], corners[7]);
2589 if (F128::IsAllMaskFalse(F128::CmpGe(F128::Max(dot0, dot1), tri_min)))
return false;
2591 if (F128::IsAllMaskFalse(F128::CmpLe(F128::Min(dot0, dot1), tri_max)))
return false;
2602 for (
size_t i = 0; i < 8; ++i) {
2603 corners[i] = Vector3::LoadFloat3(&corners_[i]);
2604 corners[i] = F128::SetFloatToLane<3>(corners[i], 1.f);
2606 f128 dot0 = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2607 f128 dot1 = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2610 f128 outside = F128::CmpLeZero(F128::Min(dot0, dot1));
2611 if (F128::IsAllMaskFalse(outside))
return Intersection::PLANE_FRONT;
2614 f128 inside = F128::CmpGeZero(F128::Max(dot0, dot1));
2615 if (F128::IsAllMaskFalse(inside))
return Intersection::PLANE_BACK;
2617 return Intersection::PLANE_INTERSECT;
2623 if (Containment::FrustumPoint(frustum, ray_point))
return true;
2626 SimdVector rp = F128::Sub(ray_point, frustum.center_);
2627 rp = Vector3::InvRotate(rp, frustum.rotation_);
2628 rp = F128::SetFloatToLane<3>(rp, 1.f);
2629 SimdVector rd = Vector3::InvRotate(ray_dir_normalized, frustum.rotation_);
2630 rd = F128::SetZeroToLane<3>(rd);
2632 f128 dot_rp0, dot_rp1;
2633 dot_rp0 = Vector4::Dot4(rp, frustum.near_plane_, frustum.far_plane_,
2634 frustum.left_plane_, frustum.right_plane_);
2635 dot_rp1 = Vector4::Dot2(rp, frustum.top_plane_, frustum.bottom_plane_);
2636 dot_rp1 = F128::Swizzle<0, 1, 0, 1>(dot_rp1);
2638 f128 dot_rd0, dot_rd1;
2639 dot_rd0 = Vector4::Dot4(rd, frustum.near_plane_, frustum.far_plane_,
2640 frustum.left_plane_, frustum.right_plane_);
2641 dot_rd1 = Vector4::Dot2(rd, frustum.top_plane_, frustum.bottom_plane_);
2642 dot_rd1 = F128::Swizzle<0, 1, 0, 1>(dot_rd1);
2645 f128 eps = F128::SetEpsilon();
2646 f128 parallel0 = F128::CmpLe(F128::Abs(dot_rd0), eps);
2647 f128 parallel1 = F128::CmpLe(F128::Abs(dot_rd1), eps);
2648 f128 mask0 = F128::And(parallel0, F128::CmpGtZero(dot_rp0));
2649 f128 mask1 = F128::And(parallel1, F128::CmpGtZero(dot_rp1));
2650 if (!F128::IsAllMaskFalse(F128::Or(mask0, mask1)))
return false;
2652 f128 t0 = F128::Negate(F128::Div(dot_rp0, dot_rd0));
2653 f128 t1 = F128::Negate(F128::Div(dot_rp1, dot_rd1));
2654 f128 inf = F128::SetInfinity();
2657 mask0 = F128::AndNot(parallel0, F128::CmpGtZero(dot_rd0));
2658 mask1 = F128::AndNot(parallel1, F128::CmpGtZero(dot_rd1));
2659 f128 to = F128::Min(F128::Select(mask0, t0, inf), F128::Select(mask1, t1, inf));
2660 to = F128::PairwiseMin(to, to);
2661 to = F128::PairwiseMin(to, to);
2664 inf = F128::Negate(inf);
2665 mask0 = F128::AndNot(parallel0, F128::CmpLtZero(dot_rd0));
2666 mask1 = F128::AndNot(parallel1, F128::CmpLtZero(dot_rd1));
2667 f128 from = F128::Max(F128::Select(mask0, t0, inf), F128::Select(mask1, t1, inf));
2668 from = F128::PairwiseMax(from, from);
2669 from = F128::PairwiseMax(from, from);
2671 float n = F128::GetFloatFromLane<0>(from);
2672 float f = F128::GetFloatFromLane<0>(to);
2673 return n <= f && (n >= 0.f || f >= 0.f);
2677 # pragma endregion Intersection function implementation 2684 # pragma region Containment 2690 f128 dist_sq = Vector3::LengthSq(F128::Sub(sphere, point));
2692 return F128::IsAllMaskFalse(F128::CmpGt(dist_sq, rsq));
2701 SimdVector tp0_c = F128::Sub(triangle_point0, sphere);
2702 SimdVector tp1_c = F128::Sub(triangle_point1, sphere);
2703 SimdVector tp2_c = F128::Sub(triangle_point2, sphere);
2704 r_sq = F128::Mult(r_sq, r_sq);
2705 tp0_c = Vector3::LengthSq(tp0_c);
2706 tp1_c = Vector3::LengthSq(tp1_c);
2707 tp2_c = Vector3::LengthSq(tp2_c);
2708 f128 dist_sq = F128::Max(F128::Max(tp0_c, tp1_c), tp2_c);
2709 return F128::IsAllMaskFalse(F128::CmpGt(dist_sq, r_sq));
2714 NLIB_B Containment::SphereAxisAlignedBox(
SimdSphereArg sphere,
2719 r_sq = F128::Mult(r_sq, r_sq);
2720 aabb_max = F128::Abs(aabb_max);
2721 aabb_min = F128::Abs(aabb_min);
2722 f128 dist_sq = Vector3::LengthSq(F128::Max(aabb_max, aabb_min));
2723 return F128::IsAllMaskFalse(F128::CmpGt(dist_sq, r_sq));
2730 new_sphere = Vector3::InvRotate(new_sphere, obb.
rotation);
2731 new_sphere = F128::Permute<0, 1, 2, 7>(new_sphere, sphere);
2735 aabb.
point_min = F128::Negate(box_extent);
2736 return Containment::SphereAxisAlignedBox(new_sphere, aabb);
2742 float dist = F128::GetFloatFromLane<0>(Vector3::Length(F128::Sub(sphere, contained)));
2743 float r0 = F128::GetFloatFromLane<3>(sphere);
2744 float r1 = F128::GetFloatFromLane<3>(contained);
2745 return (r0 - r1) >= dist;
2759 pt = Vector3::LoadFloat3(&corners[0]);
2760 d_sq = Vector3::LengthSq(F128::Sub(pt, sp));
2761 inside = F128::CmpLe(d_sq, rad_sq);
2762 for (
size_t i = 1; i < 8; ++i) {
2763 pt = Vector3::LoadFloat3(&corners[i]);
2764 d_sq = Vector3::LengthSq(F128::Sub(pt, sp));
2765 inside = F128::And(inside, F128::CmpLe(d_sq, rad_sq));
2767 return F128::IsAllMaskTrue(inside);
2772 NLIB_B Containment::AxisAlignedBoxPoint(
const AxisAlignedBox& aabb,
2776 out = F128::SetZeroToLane<3>(out);
2777 return F128::IsAllMaskFalse(out);
2782 NLIB_B Containment::AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
2787 pt_max = F128::Max(triangle_point0, triangle_point1);
2788 pt_min = F128::Min(triangle_point0, triangle_point1);
2789 pt_max = F128::Max(pt_max, triangle_point2);
2790 pt_min = F128::Min(pt_min, triangle_point2);
2793 out = F128::SetZeroToLane<3>(out);
2794 return F128::IsAllMaskFalse(out);
2799 NLIB_B Containment::AxisAlignedBoxOrientedBox(
const AxisAlignedBox& aabb,
2801 f128 zero = F128::SetZero();
2803 SimdVector P = F128::Splat<false, true, true, true>(box_extent, zero);
2804 SimdVector Q = F128::Splat<true, false, true, true>(box_extent, zero);
2805 SimdVector R = F128::Splat<true, true, false, true>(box_extent, zero);
2807 P = Vector3::Rotate(P, box_rotation);
2808 Q = Vector3::Rotate(Q, box_rotation);
2809 R = Vector3::Rotate(R, box_rotation);
2815 v = F128::Add(F128::Add(P, Q), R);
2816 v_neg = F128::Negate(v);
2817 pt_min = F128::Min(v, v_neg);
2818 pt_max = F128::Max(v, v_neg);
2821 v = F128::Sub(F128::Add(P, Q), R);
2822 v_neg = F128::Negate(v);
2823 pt_min = F128::Min(pt_min, v);
2824 pt_max = F128::Max(pt_max, v);
2825 pt_min = F128::Min(pt_min, v_neg);
2826 pt_max = F128::Max(pt_max, v_neg);
2829 v = F128::Sub(F128::Add(P, R), Q);
2830 v_neg = F128::Negate(v);
2831 pt_min = F128::Min(pt_min, v);
2832 pt_max = F128::Max(pt_max, v);
2833 pt_min = F128::Min(pt_min, v_neg);
2834 pt_max = F128::Max(pt_max, v_neg);
2839 f128 out = F128::Or(F128::CmpGt(pt_max, aabb_max),
2840 F128::CmpLt(pt_min, aabb_min));
2841 out = F128::SetZeroToLane<3>(out);
2842 return F128::IsAllMaskFalse(out);
2847 NLIB_B Containment::AxisAlignedBoxAxisAlignedBox(
2851 out = F128::SetZeroToLane<3>(out);
2852 return F128::IsAllMaskFalse(out);
2857 NLIB_B Containment::AxisAlignedBoxSphere(
const AxisAlignedBox& aabb,
2860 SimdVector pt_min = F128::Sub(sphere, radius);
2861 SimdVector pt_max = F128::Add(sphere, radius);
2864 out = F128::SetZeroToLane<3>(out);
2865 return F128::IsAllMaskFalse(out);
2870 NLIB_B Containment::AxisAlignedBoxFrustum(
const AxisAlignedBox& aabb,
2874 SimdVector frustum_max = Vector3::LoadFloat3(&corners[0]);
2876 for (
size_t i = 1; i < 8; ++i) {
2877 SimdVector tmp = Vector3::LoadFloat3(&corners[i]);
2878 frustum_max = F128::Max(tmp, frustum_max);
2879 frustum_min = F128::Min(tmp, frustum_min);
2884 return Containment::AxisAlignedBoxAxisAlignedBox(aabb, contained);
2891 pt = Vector3::InvRotate(pt, box.
rotation);
2892 return Vector3::InBound(pt, box.
extent);
2901 SimdVector pt0 = F128::Sub(triangle_point0, center);
2902 SimdVector pt1 = F128::Sub(triangle_point1, center);
2903 SimdVector pt2 = F128::Sub(triangle_point2, center);
2905 pt0 = Vector3::InvRotate(pt0, rot);
2906 pt1 = Vector3::InvRotate(pt1, rot);
2907 pt2 = Vector3::InvRotate(pt2, rot);
2908 pt0 = F128::Abs(pt0);
2909 pt1 = F128::Abs(pt1);
2910 pt2 = F128::Abs(pt2);
2912 pt_absmax = F128::Max(pt_absmax, pt2);
2913 return Vector3::CmpLe(pt_absmax, box.
extent);
2918 NLIB_B Containment::OrientedBoxAxisAlignedBox(
const OrientedBox& box,
2923 SimdVector aabb_center = F128::Add(aabb_min, aabb_max);
2924 aabb_center = F128::Mult(0.5f, aabb_center);
2925 new_aabb.
extent = F128::Sub(aabb_max, aabb_center);
2926 aabb_center = F128::Sub(aabb_center, box.
center);
2927 new_aabb.
center = aabb_center;
2934 return Containment::AxisAlignedBoxOrientedBox(new_box, new_aabb);
2939 NLIB_B Containment::OrientedBoxOrientedBox(
const OrientedBox& box,
2945 contained_obb.
center = Vector3::Rotate(F128::Sub(contained.
center, box.
center), inv_rot);
2952 return Containment::AxisAlignedBoxOrientedBox(aabb, contained_obb);
2961 aabb.
point_min = F128::Negate(box_extent);
2964 new_sphere = F128::Permute<0, 1, 2, 7>(new_sphere, sphere);
2966 return Containment::AxisAlignedBoxSphere(aabb, new_sphere);
2969 NLIB_B Containment::OrientedBoxFrustum(
const OrientedBox& box,
2972 frustum.
Transform(&frstm, 1.f, F128::Set0001(), F128::Negate(box.
center));
2973 frstm.
Transform(&frstm, 1.f, Quaternion::Conjugate(box.
rotation), F128::SetZero());
2977 return Containment::AxisAlignedBoxFrustum(aabb, frstm);
2984 f128 dot, dot1, dot2;
2985 SimdPlane near_plane = frustum.near_plane_;
2986 SimdPlane far_plane = frustum.far_plane_;
2987 SimdPlane top_plane = frustum.top_plane_;
2988 SimdPlane bottom_plane = frustum.bottom_plane_;
2989 SimdPlane left_plane = frustum.left_plane_;
2990 SimdPlane right_plane = frustum.right_plane_;
2994 pt = F128::Sub(triangle_point0, center);
2995 pt = Vector3::InvRotate(pt, rot);
2996 pt = F128::SetFloatToLane<3>(pt, 1.f);
2997 dot1 = Vector4::Dot4(pt, near_plane, far_plane, top_plane, bottom_plane);
2998 dot2 = Vector4::Dot2(pt, left_plane, right_plane);
2999 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3000 dot = F128::Max(dot1, dot2);
3002 pt = F128::Sub(triangle_point1, center);
3003 pt = Vector3::InvRotate(pt, rot);
3004 pt = F128::SetFloatToLane<3>(pt, 1.f);
3005 dot1 = Vector4::Dot4(pt, near_plane, far_plane, top_plane, bottom_plane);
3006 dot2 = Vector4::Dot2(pt, left_plane, right_plane);
3007 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3008 dot = F128::Max(dot, F128::Max(dot1, dot2));
3010 pt = F128::Sub(triangle_point2, 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(dot, F128::Max(dot1, dot2));
3018 f128 outside = F128::CmpGt(dot, F128::SetZero());
3019 return F128::IsAllMaskFalse(outside);
3024 dot = F128::Negate(dot);
3026 SimdVector pt = F128::Sub(sphere, frustum.center_);
3027 pt = Vector3::InvRotate(pt, frustum.rotation_);
3028 pt = F128::SetFloatToLane<3>(pt, 1.f);
3030 f128 dot1 = Vector4::Dot4(pt, frustum.near_plane_, frustum.far_plane_, frustum.top_plane_,
3031 frustum.bottom_plane_);
3032 f128 dot2 = Vector4::Dot2(pt, frustum.left_plane_, frustum.right_plane_);
3033 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3034 dot1 = F128::Max(dot1, dot2);
3035 f128 outside = F128::CmpGt(dot1, dot);
3036 return F128::IsAllMaskFalse(outside);
3039 NLIB_B Containment::FrustumAxisAlignedBox(
const Frustum& frustum,
3043 SimdVector center = F128::Mult(0.5f, F128::Add(pt_min, pt_max));
3044 center = F128::SetFloatToLane<3>(center, 1.f);
3045 SimdVector extent_neg = F128::Sub(center, pt_max);
3046 extent_neg = F128::SetZeroToLane<3>(extent_neg);
3056 tmp = frustum.near_plane_;
3057 N = Vector3::Rotate(tmp, rot);
3058 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3059 SimdPlane near_plane = F128::Permute<0, 1, 2, 7>(N, D);
3061 tmp = frustum.far_plane_;
3062 N = Vector3::Rotate(tmp, rot);
3063 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3064 SimdPlane far_plane = F128::Permute<0, 1, 2, 7>(N, D);
3066 tmp = frustum.right_plane_;
3067 N = Vector3::Rotate(tmp, rot);
3068 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3069 SimdPlane right_plane = F128::Permute<0, 1, 2, 7>(N, D);
3071 tmp = frustum.left_plane_;
3072 N = Vector3::Rotate(tmp, rot);
3073 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3074 SimdPlane left_plane = F128::Permute<0, 1, 2, 7>(N, D);
3076 tmp = frustum.top_plane_;
3077 N = Vector3::Rotate(tmp, rot);
3078 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3079 SimdPlane top_plane = F128::Permute<0, 1, 2, 7>(N, D);
3081 tmp = frustum.bottom_plane_;
3082 N = Vector3::Rotate(tmp, rot);
3083 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3084 SimdPlane bottom_plane = F128::Permute<0, 1, 2, 7>(N, D);
3088 f128 all_points_inside;
3091 dist = Vector4::Dot4(center, near_plane, far_plane, right_plane, left_plane);
3093 radius_neg = Vector4::Dot4(extent_neg, F128::Abs(near_plane), F128::Abs(far_plane),
3094 F128::Abs(right_plane), F128::Abs(left_plane));
3096 all_points_inside = F128::CmpLe(dist, radius_neg);
3098 dist = Vector4::Dot2(center, top_plane, bottom_plane);
3099 radius_neg = Vector4::Dot2(extent_neg, F128::Abs(top_plane), F128::Abs(bottom_plane));
3101 F128::And(all_points_inside, F128::Swizzle<0, 1, 0, 1>(F128::CmpLe(dist, radius_neg)));
3103 return F128::IsAllMaskTrue(all_points_inside);
3106 NLIB_B Containment::FrustumOrientedBox(
const Frustum& frustum,
3110 frustum.
Transform(&frstm, 1.f, F128::Set0001(), F128::Negate(box.
center));
3112 frstm.
Transform(&frstm, 1.f, Quaternion::Conjugate(box.
rotation), F128::SetZero());
3117 return Containment::FrustumAxisAlignedBox(frstm, aabb);
3123 for (
size_t i = 0; i < 8; ++i) {
3124 SimdVector pt = Vector3::LoadFloat3(&corners[i]);
3125 if (!Containment::FrustumPoint(frustum, pt))
return false;
3131 # pragma endregion Containment function implementation 3137 #endif // NLIB_DOXYGEN 3142 #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...