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
208 static bool __vectorcall SphereRay(
float* distance,
SimdSphereArg sphere,
215 static bool __vectorcall TriangleRay(
float* distance,
SimdVectorArg triangle_point0,
224 static bool __vectorcall
236 static bool __vectorcall
238 static bool __vectorcall
241 static bool __vectorcall AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
246 static bool __vectorcall
248 static bool __vectorcall
250 static bool __vectorcall
252 static bool __vectorcall OrientedBoxTriangle(
const OrientedBox& box,
261 static bool __vectorcall
263 static bool __vectorcall
265 static bool __vectorcall
291 static bool __vectorcall
293 static bool __vectorcall
295 static bool __vectorcall
297 static bool __vectorcall
301 static bool __vectorcall
303 static bool __vectorcall AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
307 static bool __vectorcall
309 static bool __vectorcall
312 static bool __vectorcall
314 static bool __vectorcall
318 static bool __vectorcall
320 static bool __vectorcall OrientedBoxTriangle(
const OrientedBox& box,
324 static bool __vectorcall OrientedBoxOrientedBox(
const OrientedBox& box,
326 static bool __vectorcall
328 static bool __vectorcall
330 static bool __vectorcall
334 static bool __vectorcall
339 static bool __vectorcall
341 static bool __vectorcall
343 static bool __vectorcall
345 static bool __vectorcall
354 #define NLIB_M(tp) inline tp __vectorcall 355 #define NLIB_B inline bool __vectorcall 361 # pragma region Plane 365 return Vector4::Dot(plane, vec);
370 return Vector4::Dot(plane, F128::SetFloatToLane<3>(vec, 1.f));
375 return Vector3::Dot(plane, vec);
381 f128 dot = Vector3::Dot(point, normal);
382 dot = F128::Negate(dot);
383 return F128::Splat<false, false, false, true>(normal, dot);
391 SimdVector normal = Vector3::Normalize(Vector3::Cross(v10, v20));
392 return FromPointAndNormal(point0, normal);
398 return F128::Mult(Vector3::RecpLength(plane), plane);
403 return F128::Mult(Vector3::RecpLengthEst(plane), plane);
408 return Vector4::Transform(plane, m);
411 # pragma endregion Plane function implementation 418 # pragma region Sphere 423 SimdVector center = Vector3::Transform(sphere, m);
424 f128 dot_x = Vector3::Dot(m.
r[0], m.
r[0]);
425 f128 dot_y = Vector3::Dot(m.
r[1], m.
r[1]);
426 f128 dot_z = Vector3::Dot(m.
r[2], m.
r[2]);
427 f128 scale = F128::Max(dot_x, dot_y);
428 scale = F128::Max(scale, dot_z);
429 radius = F128::Mult(radius, scale);
431 return F128::Splat<false, false, false, true>(center, radius);
437 f128 min_x, min_y, min_z;
438 f128 max_x, max_y, max_z;
439 min_x = min_y = min_z = max_x = max_y = max_z = Vector3::LoadFloat3(points);
442 for (i = 1; i < count; ++i) {
444 f128 pt = Vector3::LoadFloat3(points + i);
447 cmp0 = F128::CmpLt(pt_x, F128::SetValue<0>(min_x,
each_select32));
448 min_x = F128::Select(cmp0, pt, min_x);
449 cmp1 = F128::CmpGt(pt_x, F128::SetValue<0>(max_x,
each_select32));
450 max_x = F128::Select(cmp1, pt, max_x);
453 cmp0 = F128::CmpLt(pt_y, F128::SetValue<0>(min_y,
each_select32));
454 min_y = F128::Select(cmp0, pt, min_y);
455 cmp1 = F128::CmpGt(pt_y, F128::SetValue<0>(max_y,
each_select32));
456 max_y = F128::Select(cmp1, pt, max_y);
459 cmp0 = F128::CmpLt(pt_z, F128::SetValue<0>(min_z,
each_select32));
460 min_z = F128::Select(cmp0, pt, min_z);
461 cmp1 = F128::CmpGt(pt_z, F128::SetValue<0>(max_z,
each_select32));
462 max_z = F128::Select(cmp1, pt, max_z);
469 f128 distsq_x = Vector3::LengthSq(F128::Sub(max_x, min_x));
470 f128 distsq_y = Vector3::LengthSq(F128::Sub(max_y, min_y));
471 f128 distsq_z = Vector3::LengthSq(F128::Sub(max_z, min_z));
472 if (Vector4::CmpGt(distsq_x, distsq_y)) {
473 if (Vector4::CmpGt(distsq_x, distsq_z)) {
474 center = F128::Lerp(min_x, max_x, c1_2);
475 radius = F128::Mult(F128::Sqrt(distsq_x), c1_2);
477 center = F128::Lerp(min_z, max_z, c1_2);
478 radius = F128::Mult(F128::Sqrt(distsq_z), c1_2);
481 if (Vector4::CmpGt(distsq_y, distsq_z)) {
482 center = F128::Lerp(min_y, max_y, c1_2);
483 radius = F128::Mult(F128::Sqrt(distsq_y), c1_2);
485 center = F128::Lerp(min_z, max_z, c1_2);
486 radius = F128::Mult(F128::Sqrt(distsq_z), c1_2);
491 f128 radsq = F128::Mult(radius, radius);
492 for (i = 0; i < count; ++i) {
493 f128 pt = Vector3::LoadFloat3(points + i);
494 f128 diff = F128::Sub(pt, center);
495 f128 distsq = Vector3::LengthSq(diff);
496 if (Vector3::CmpGt(distsq, radsq)) {
497 f128 dist = F128::Sqrt(distsq);
498 f128 t = F128::Div(radius, dist);
499 t = F128::MultSub(c1_2, t, c1_2);
500 radius = F128::Mult(c1_2, F128::Add(radius, dist));
501 radsq = F128::Mult(radius, radius);
502 center = F128::MultAdd(t, diff, center);
506 return F128::Splat<false, false, false, true>(center, radius);
511 SimdVector diff = F128::Sub(sphere1, sphere0);
512 f128 dist_sq = Vector3::LengthSq(diff);
514 f128 is_contained = F128::CmpLe(dist_sq, radius_diff_sq);
516 f128 dist = F128::Sqrt(dist_sq);
519 f128 new_radius = F128::Add(r0, r1);
520 new_radius = F128::Add(new_radius, dist);
521 new_radius = F128::Mult(0.5f, new_radius);
523 f128 t = F128::Div(diff, dist);
524 f128 use_new_center = F128::CmpGt(dist, F128::SetEpsilon());
527 ret = F128::MultAdd(t, F128::Sub(new_radius, r0), sphere0);
528 ret = F128::Select(use_new_center, ret, sphere0);
529 ret = F128::Splat<false, false, false, true>(ret, new_radius);
531 f128 s0_contained = F128::And(is_contained, F128::CmpLt(r0, r1));
532 f128 s1_contained = F128::And(is_contained, F128::CmpGe(r0, r1));
533 ret = F128::Select(s0_contained, sphere1, ret);
534 ret = F128::Select(s1_contained, sphere0, ret);
539 return F128::GetFloatFromLane<3>(sphere);
543 return F128::SetFloatToLane<3>(sphere, radius);
551 return F128::Permute<4, 5, 6, 3>(sphere, center);
554 # pragma endregion Sphere function implementation 561 # pragma region AxisAlignedBox 563 inline AxisAlignedBox::AxisAlignedBox(
const Float3& pmin,
const Float3& pmax) {
564 Vector3::LoadFloat3(&pmin);
565 Vector3::LoadFloat3(&pmax);
571 f128 p1 = F128::Splat<true, false, false, false>(point_min, point_max);
572 f128 p2 = F128::Splat<true, true, false, false>(point_min, point_max);
573 f128 p3 = F128::Splat<false, true, false, false>(point_min, point_max);
574 f128 p4 = F128::Splat<false, true, true, true>(point_min, point_max);
575 f128 p5 = F128::Splat<false, false, true, true>(point_min, point_max);
576 f128 p6 = F128::Splat<true, false, true, true>(point_min, point_max);
579 Vector3::StoreFloat3(corners + 0, p0);
580 Vector3::StoreFloat3(corners + 1, p1);
581 Vector3::StoreFloat3(corners + 2, p2);
582 Vector3::StoreFloat3(corners + 3, p3);
583 Vector3::StoreFloat3(corners + 4, p4);
584 Vector3::StoreFloat3(corners + 5, p5);
585 Vector3::StoreFloat3(corners + 6, p6);
586 Vector3::StoreFloat3(corners + 7, p7);
590 inline void __vectorcall
593 f128 p1 = F128::Splat<true, false, false, false>(point_min, point_max);
594 f128 p2 = F128::Splat<true, true, false, false>(point_min, point_max);
595 f128 p3 = F128::Splat<false, true, false, false>(point_min, point_max);
596 f128 p4 = F128::Splat<false, true, true, true>(point_min, point_max);
597 f128 p5 = F128::Splat<false, false, true, true>(point_min, point_max);
598 f128 p6 = F128::Splat<true, false, true, true>(point_min, point_max);
601 p0 = Vector3::Transform(p0, m);
602 p1 = Vector3::Transform(p1, m);
603 p2 = Vector3::Transform(p2, m);
604 p3 = Vector3::Transform(p3, m);
605 p4 = Vector3::Transform(p4, m);
606 p5 = Vector3::Transform(p5, m);
607 p6 = Vector3::Transform(p6, m);
608 p7 = Vector3::Transform(p7, m);
611 pmin = F128::Min(p0, p1);
612 pmax = F128::Max(p0, p1);
613 pmin = F128::Min(pmin, p2);
614 pmax = F128::Max(pmax, p2);
615 pmin = F128::Min(pmin, p3);
616 pmax = F128::Max(pmax, p3);
617 pmin = F128::Min(pmin, p4);
618 pmax = F128::Max(pmax, p4);
619 pmin = F128::Min(pmin, p5);
620 pmax = F128::Max(pmax, p5);
621 pmin = F128::Min(pmin, p6);
622 pmax = F128::Max(pmax, p6);
623 pmin = F128::Min(pmin, p7);
624 pmax = F128::Max(pmax, p7);
637 inline void __vectorcall
647 box->
point_min = F128::Min(point0, point1);
648 box->
point_max = F128::Max(point0, point1);
655 pmin = pmax = Vector3::LoadFloat3(points);
656 for (
size_t i = 1; i < count; ++i) {
657 f128 pt = Vector3::LoadFloat3(points + i);
658 pmin = F128::Min(pmin, pt);
659 pmax = F128::Max(pmax, pt);
665 # pragma endregion AxisAlignedBox function implementation 672 # pragma region OrientedBox 677 box->
center = Vector3::Transform(this->center, m);
678 f128 inv_dx = Vector3::RecpLength(m.
r[0]);
679 f128 inv_dy = Vector3::RecpLength(m.
r[1]);
680 f128 inv_dz = Vector3::RecpLength(m.
r[2]);
684 rot_matrix.
r[0] = F128::Mult(m.
r[0], inv_dx);
685 rot_matrix.
r[1] = F128::Mult(m.
r[1], inv_dy);
686 rot_matrix.
r[2] = F128::Mult(m.
r[2], inv_dz);
687 rot_matrix.
r[3] = F128::Set0001();
689 box->
rotation = Quaternion::Mult(this->rotation, rot);
693 scale = F128::Permute<0, 4, -1, -1>(inv_dx, inv_dy);
694 scale = F128::Permute<0, 1, 4, -1>(scale, inv_dz);
695 box->
extent = F128::Div(this->extent, scale);
700 f128 point_max = F128::Add(center, extent);
701 f128 point_min = F128::Sub(center, extent);
702 point_max = F128::SetZeroToLane<3>(point_max);
703 point_min = F128::SetZeroToLane<3>(point_min);
707 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
708 Vector3::StoreFloat3(corners + 0, pt);
710 pt = F128::Splat<true, false, false, false>(point_min, point_max);
711 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
712 Vector3::StoreFloat3(corners + 1, pt);
714 pt = F128::Splat<true, true, false, false>(point_min, point_max);
715 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
716 Vector3::StoreFloat3(corners + 2, pt);
718 pt = F128::Splat<false, true, false, false>(point_min, point_max);
719 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
720 Vector3::StoreFloat3(corners + 3, pt);
722 pt = F128::Splat<false, true, true, true>(point_min, point_max);
723 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
724 Vector3::StoreFloat3(corners + 4, pt);
726 pt = F128::Splat<false, false, true, true>(point_min, point_max);
727 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
728 Vector3::StoreFloat3(corners + 5, pt);
730 pt = F128::Splat<true, false, true, true>(point_min, point_max);
731 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
732 Vector3::StoreFloat3(corners + 6, pt);
735 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
736 Vector3::StoreFloat3(corners + 7, pt);
740 inline void OrientedBox::FromAxisAlignedBox(
OrientedBox* box,
746 box->
center = F128::MultAdd(c1_2, box_min, half);
747 box->
extent = F128::MultSub(c1_2, box_min, half);
751 # pragma endregion OrientedBox function implementation 758 # pragma region Capsule 761 f128 sphere_ = Vector3::LoadFloat3(&pt0);
762 point = Vector3::LoadFloat3(&pt1);
763 sphere = F128::SetFloatToLane<3>(sphere_, radius);
767 capsule->sphere = Sphere::Transform(sphere, m);
768 capsule->point = Vector3::Transform(point, m);
771 # pragma endregion Capsule function implementation 778 # pragma region Frustum 782 rotation_(rhs.rotation_),
783 near_plane_(rhs.near_plane_),
784 far_plane_(rhs.far_plane_),
785 top_plane_(rhs.top_plane_),
786 bottom_plane_(rhs.bottom_plane_),
787 left_plane_(rhs.left_plane_),
788 right_plane_(rhs.right_plane_) {
792 center_ = rhs.center_;
793 rotation_ = rhs.rotation_;
794 near_plane_ = rhs.near_plane_;
795 far_plane_ = rhs.far_plane_;
796 top_plane_ = rhs.top_plane_;
797 bottom_plane_ = rhs.bottom_plane_;
798 left_plane_ = rhs.left_plane_;
799 right_plane_ = rhs.right_plane_;
806 NLIB_ASSERT(n > 0.f);
808 rotation_ = rotation;
809 near_plane_ = Plane::Normalize(F128::SetValue(0.f, 0.f, 1.f, n));
810 far_plane_ = Plane::Normalize(F128::SetValue(0.f, 0.f, -1.f, -f));
811 top_plane_ = Plane::Normalize(F128::SetValue(0.f, 1.f, top / n, 0.f));
812 bottom_plane_ = Plane::Normalize(F128::SetValue(0.f, -1.f, -bottom / n, 0.f));
813 left_plane_ = Plane::Normalize(F128::SetValue(-1.f, 0.f, -left / n, 0.f));
814 right_plane_ = Plane::Normalize(F128::SetValue(1.f, 0.f, right / n, 0.f));
818 float bottom,
float left,
float right,
float n,
821 NLIB_ASSERT(n > 0.f);
823 rotation_ = rotation;
824 near_plane_ = Plane::Normalize(F128::SetValue(0.f, 0.f, 1.f, n));
825 far_plane_ = Plane::Normalize(F128::SetValue(0.f, 0.f, -1.f, -f));
826 top_plane_ = Plane::Normalize(F128::SetValue(0.f, 1.f, top / n, 0.f));
827 bottom_plane_ = Plane::Normalize(F128::SetValue(0.f, -1.f, -bottom / n, 0.f));
828 left_plane_ = Plane::Normalize(F128::SetValue(-1.f, 0.f, -left / n, 0.f));
829 right_plane_ = Plane::Normalize(F128::SetValue(1.f, 0.f, right / n, 0.f));
832 inline void __vectorcall Frustum::Transform(
Frustum* frustum,
float scale,
835 f128 s = F128::SetValue(1.f, 1.f, 1.f, scale);
836 frustum->rotation_ = Quaternion::Mult(rotation_, rotation);
837 SimdVector center = Vector3::Rotate(F128::Mult(scale, center_), rotation);
838 frustum->center_ = F128::Add(center, translation);
839 frustum->top_plane_ = top_plane_;
840 frustum->bottom_plane_ = bottom_plane_;
841 frustum->left_plane_ = left_plane_;
842 frustum->right_plane_ = right_plane_;
843 frustum->near_plane_ = F128::Mult(s, near_plane_);
844 frustum->far_plane_ = F128::Mult(s, far_plane_);
855 M.
r[0] = Vector3::Normalize(r0);
856 M.
r[1] = Vector3::Normalize(r1);
857 M.
r[2] = Vector3::Normalize(r2);
858 M.
r[3] = F128::Set0001();
860 frustum->rotation_ = Quaternion::Mult(rotation, rot);
861 frustum->center_ = Vector3::Transform(center, m);
866 f128 x_sq = Vector3::LengthSq(r0);
867 f128 y_sq = Vector3::LengthSq(r1);
868 f128 z_sq = Vector3::LengthSq(r2);
869 f128 sq = F128::Max(z_sq, F128::Max(x_sq, y_sq));
870 scale = F128::GetFloatFromLane<0>(F128::Sqrt(sq));
873 f128 s = F128::SetValue(1.f, 1.f, 1.f, scale);
874 frustum->top_plane_ = top_plane_;
875 frustum->bottom_plane_ = bottom_plane_;
876 frustum->left_plane_ = left_plane_;
877 frustum->right_plane_ = right_plane_;
878 frustum->near_plane_ = F128::Mult(s, near_plane_);
879 frustum->far_plane_ = F128::Mult(s, far_plane_);
883 float n = F128::GetFloatFromLane<3>(near_plane_) / F128::GetFloatFromLane<2>(near_plane_);
884 float f = F128::GetFloatFromLane<3>(far_plane_) / F128::GetFloatFromLane<2>(far_plane_);
885 float top = F128::GetFloatFromLane<2>(top_plane_) / F128::GetFloatFromLane<1>(top_plane_);
888 F128::GetFloatFromLane<2>(bottom_plane_) / F128::GetFloatFromLane<1>(bottom_plane_);
890 float left = F128::GetFloatFromLane<2>(left_plane_) / F128::GetFloatFromLane<0>(left_plane_);
893 F128::GetFloatFromLane<2>(right_plane_) / F128::GetFloatFromLane<0>(right_plane_);
901 pt = F128::SetValue(left, top, -n, 0.f);
902 pt = F128::Add(Vector3::Rotate(pt, rot), center);
903 Vector3::StoreFloat3(corners + 0, pt);
906 pt = F128::SetValue(right, top, -n, 0.f);
907 pt = F128::Add(Vector3::Rotate(pt, rot), center);
908 Vector3::StoreFloat3(corners + 1, pt);
911 pt = F128::SetValue(right, bottom, -n, 0.f);
912 pt = F128::Add(Vector3::Rotate(pt, rot), center);
913 Vector3::StoreFloat3(corners + 2, pt);
916 pt = F128::SetValue(left, bottom, -n, 0.f);
917 pt = F128::Add(Vector3::Rotate(pt, rot), center);
918 Vector3::StoreFloat3(corners + 3, pt);
923 pt = F128::SetValue(left * f_n, top * f_n, -f, 0.f);
924 pt = F128::Add(Vector3::Rotate(pt, rot), center);
925 Vector3::StoreFloat3(corners + 4, pt);
928 pt = F128::SetValue(right * f_n, top * f_n, -f, 0.f);
929 pt = F128::Add(Vector3::Rotate(pt, rot), center);
930 Vector3::StoreFloat3(corners + 5, pt);
933 pt = F128::SetValue(right * f_n, bottom * f_n, -f, 0.f);
934 pt = F128::Add(Vector3::Rotate(pt, rot), center);
935 Vector3::StoreFloat3(corners + 6, pt);
938 pt = F128::SetValue(left * f_n, bottom * f_n, -f, 0.f);
939 pt = F128::Add(Vector3::Rotate(pt, rot), center);
940 Vector3::StoreFloat3(corners + 7, pt);
944 # pragma endregion Frustum function implementation 951 # pragma region DistanceSq 955 SimdVector l0_pt = F128::Sub(point, line_point);
956 f128 dot = Vector3::Dot(l0_pt, line_dir_normalized);
957 SimdVector dist_vec = F128::Mult(line_dir_normalized, dot);
958 dist_vec = F128::Sub(l0_pt, dist_vec);
959 return Vector3::LengthSq(dist_vec);
964 SimdVector l0_pt = F128::Sub(point, ray_point);
965 f128 dot = Vector3::Dot(l0_pt, ray_dir_normalized);
966 SimdVector dist_vec = F128::Mult(ray_dir_normalized, dot);
967 dist_vec = F128::Sub(l0_pt, dist_vec);
969 f128 distsq0 = Vector3::LengthSq(dist_vec);
970 f128 distsq1 = Vector3::LengthSq(l0_pt);
971 f128 cmp = F128::CmpLt(dot, F128::SetZero());
972 return F128::Select(cmp, distsq1, distsq0);
977 SimdVector l0_pt = F128::Sub(point, segment_point0);
978 SimdVector l1_pt = F128::Sub(point, segment_point1);
979 SimdVector seg_dir_normalized = F128::Sub(segment_point1, segment_point0);
980 f128 seg_recplen = Vector3::RecpLength(seg_dir_normalized);
981 seg_dir_normalized = F128::Mult(seg_dir_normalized, seg_recplen);
983 f128 dot = Vector3::Dot(l0_pt, seg_dir_normalized);
984 SimdVector dist_vec = F128::Mult(seg_dir_normalized, dot);
985 dist_vec = F128::Sub(l0_pt, dist_vec);
987 f128 distsq0 = Vector3::LengthSq(dist_vec);
988 f128 distsq1 = Vector3::LengthSq(l0_pt);
989 f128 distsq2 = Vector3::LengthSq(l1_pt);
990 f128 cmp = F128::CmpLt(dot, F128::SetZero());
991 f128 ret = F128::Select(cmp, distsq1, distsq0);
992 cmp = F128::CmpLt(F128::Mult(dot, seg_recplen), F128::SetOne());
993 ret = F128::Select(cmp, ret, distsq2);
1000 SimdVector pt = F128::SetZeroToLane<3>(point);
1001 f128 dot = Vector4::Dot(pt, plane_normalized);
1002 f128 ret = F128::Mult(dot, dot);
1003 if (point_on_plane) {
1004 *point_on_plane = F128::Sub(point, F128::Mult(dot, plane_normalized));
1011 SimdVector c = F128::SetZeroToLane<3>(sphere);
1013 f128 dist = F128::Abs(Vector4::Dot(c, plane_normalized));
1014 f128 cmp = F128::CmpGt(dist, r);
1015 f128 ret = F128::Sub(dist, r);
1016 ret = F128::Mult(ret, ret);
1017 return F128::And(cmp, ret);
1024 f128 distsq = F128::Sub(vv, point);
1025 distsq = Vector3::LengthSq(distsq);
1026 if (point_on_box) *point_on_box = vv;
1036 u = F128::Sub(line0_point, line1_point);
1037 f128 b = Vector3::Dot(line0_dir_normalized, line1_dir_normalized);
1038 f128 d = Vector3::Dot(line0_dir_normalized, u);
1039 f128 e = Vector3::Dot(line1_dir_normalized, u);
1040 f128 det = F128::MultSub(b, b, F128::SetOne());
1042 f128 recp_det = F128::Recp(det);
1043 f128 s = F128::MultAdd(b, e, F128::Negate(d));
1044 f128 t = F128::MultSub(b, d, e);
1045 s = F128::Mult(s, recp_det);
1046 t = F128::Mult(t, recp_det);
1048 SimdVector tmp = F128::Mult(s, line0_dir_normalized);
1049 tmp = F128::MultSub(t, line1_dir_normalized, tmp);
1051 ret = Vector3::LengthSq(ret);
1053 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1054 tmp = Vector3::LengthSq(F128::MultSub(e, line1_dir_normalized, u));
1055 ret = F128::Select(parallel, tmp, ret);
1057 if (point_on_line0) {
1058 s = F128::AndNot(parallel, s);
1059 *point_on_line0 = F128::MultAdd(s, line0_dir_normalized, line0_point);
1061 if (point_on_line1) {
1062 t = F128::Select(parallel, e, t);
1063 *point_on_line1 = F128::MultAdd(t, line1_dir_normalized, line1_point);
1070 NLIB_M(
f128) DistanceSq::SegmentSegment(
SimdVector* point_on_segment0,
1076 SimdVector u = F128::Sub(segment0_point1, segment0_point0);
1077 SimdVector v = F128::Sub(segment1_point1, segment1_point0);
1078 SimdVector w = F128::Sub(segment0_point0, segment1_point0);
1079 f128 a = Vector3::LengthSq(u);
1080 f128 b = Vector3::Dot(u, v);
1081 f128 c = Vector3::LengthSq(v);
1082 f128 d = Vector3::Dot(u, w);
1083 f128 e = Vector3::Dot(v, w);
1084 f128 D = F128::MultSub(b, b, F128::Mult(a, c));
1086 f128 epsilon = F128::SetEpsilon();
1089 f128 sN = F128::MultSub(c, d, F128::Mult(b, e));
1090 f128 tN = F128::MultSub(b, d, F128::Mult(a, e));
1093 f128 parallel = F128::CmpLt(D, epsilon);
1094 f128 sN_under = F128::CmpLtZero(sN);
1095 f128 sN_out = F128::Or(sN_under, F128::CmpGt(sN, D));
1096 f128 cmp = F128::Or(parallel, sN_out);
1097 f128 under_or_parallel = F128::Or(parallel, sN_under);
1104 sN = F128::Select(cmp, F128::AndNot(under_or_parallel, D), sN);
1111 tN = F128::Select(cmp, F128::Select(under_or_parallel, e, F128::Add(e, b)), tN);
1118 tD = F128::Select(cmp, c, D);
1122 sD = F128::Select(parallel, F128::SetOne(), D);
1126 f128 tN_under = F128::CmpLtZero(tN);
1127 f128 tN_out = F128::Or(tN_under, F128::CmpGt(tN, tD));
1133 tN = F128::Clamp(tN, F128::SetZero(), tD);
1135 f128 val = F128::Select(tN_under, F128::Negate(d), F128::Sub(b, d));
1141 f128 val_in = F128::And(F128::CmpGeZero(val), F128::CmpLe(val, a));
1142 sD = F128::Select(F128::And(tN_out, val_in), a, sD);
1150 f128 sntmp = F128::AndNot(F128::CmpLtZero(val), val);
1151 sntmp = F128::Select(F128::CmpGt(val, a), sD, sntmp);
1152 sN = F128::Select(tN_out, sntmp, sN);
1155 f128 sc = F128::AndNot(F128::InBound(sN, epsilon), F128::Div(sN, sD));
1156 f128 tc = F128::AndNot(F128::InBound(tN, epsilon), F128::Div(tN, tD));
1159 f128 pt_s0 = F128::MultAdd(sc, u, segment0_point0);
1160 f128 pt_s1 = F128::MultAdd(tc, v, segment1_point0);
1161 f128 ret = F128::Sub(pt_s0, pt_s1);
1162 ret = Vector3::LengthSq(ret);
1164 if (point_on_segment0) *point_on_segment0 = pt_s0;
1165 if (point_on_segment1) *point_on_segment1 = pt_s1;
1174 SimdVector u = F128::Sub(line_point, ray_point);
1175 f128 b = Vector3::Dot(line_dir_normalized, ray_dir_normalized);
1176 f128 d = Vector3::Dot(line_dir_normalized, u);
1177 f128 e = Vector3::Dot(ray_dir_normalized, u);
1178 f128 one = F128::SetOne();
1179 f128 det = F128::MultSub(b, b, one);
1180 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1185 f128 tNum = F128::MultSub(b, d, e);
1186 tNum = F128::Select(parallel, e, tNum);
1187 f128 tNum_negative = F128::CmpLtZero(tNum);
1192 f128 minus_d = F128::Negate(d);
1193 f128 sNum = F128::MultAdd(b, e, minus_d);
1194 sNum = F128::AndNot(parallel, sNum);
1199 f128 tDenom = F128::Select(parallel, one, det);
1204 f128 sDenom = F128::Select(F128::Or(tNum_negative, parallel), one, det);
1209 sNum = F128::Select(tNum_negative, minus_d, sNum);
1214 tNum = F128::AndNot(tNum_negative, tNum);
1216 f128 s = F128::Div(sNum, sDenom);
1217 f128 t = F128::Div(tNum, tDenom);
1219 f128 pt_l = F128::MultAdd(s, line_dir_normalized, line_point);
1220 f128 pt_r = F128::MultAdd(t, ray_dir_normalized, ray_point);
1222 ret = Vector3::LengthSq(ret);
1224 if (point_on_line) *point_on_line = pt_l;
1225 if (point_on_ray) *point_on_ray = pt_r;
1234 SimdVector seg_dir = F128::Sub(segment_point1, segment_point0);
1235 SimdVector u = F128::Sub(line_point, segment_point0);
1236 f128 b = Vector3::Dot(line_dir_normalized, seg_dir);
1237 f128 c = Vector3::LengthSq(seg_dir);
1238 f128 d = Vector3::Dot(line_dir_normalized, u);
1239 f128 e = Vector3::Dot(seg_dir, u);
1240 f128 det = F128::MultSub(b, b, c);
1241 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1246 f128 tNum = F128::Select(parallel, e, F128::MultSub(b, d, e));
1251 f128 tDenom = F128::Select(parallel, c, det);
1256 f128 tmp = F128::Mult(b, e);
1257 tmp = F128::MultSub(c, d, tmp);
1258 f128 sNum = F128::AndNot(parallel, tmp);
1264 f128 tNum_under = F128::CmpLtZero(tNum);
1265 f128 tNum_out = F128::Or(tNum_under, F128::CmpGt(tNum, tDenom));
1266 tmp = F128::Select(tNum_under, F128::Negate(d), F128::Sub(b, d));
1267 sNum = F128::Select(tNum_out, tmp, sNum);
1272 f128 sDenom = F128::Select(F128::Or(tNum_out, parallel), F128::SetOne(), det);
1277 tNum = F128::Clamp(tNum, F128::SetZero(), tDenom);
1279 f128 s = F128::Div(sNum, sDenom);
1280 f128 t = F128::Div(tNum, tDenom);
1282 f128 pt_l = F128::MultAdd(s, line_dir_normalized, line_point);
1283 f128 pt_s = F128::MultAdd(t, seg_dir, segment_point0);
1285 ret = Vector3::LengthSq(ret);
1287 if (point_on_line) *point_on_line = pt_l;
1288 if (point_on_segment) *point_on_segment = pt_s;
1297 SimdVector u = F128::Sub(ray0_point, ray1_point);
1298 f128 b = Vector3::Dot(ray0_dir_normalized, ray1_dir_normalized);
1299 f128 d = Vector3::Dot(ray0_dir_normalized, u);
1300 f128 e = Vector3::Dot(ray1_dir_normalized, u);
1301 f128 one = F128::SetOne();
1302 f128 det = F128::MultSub(b, b, one);
1303 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1308 f128 minus_d = F128::Negate(d);
1309 f128 sNum = F128::AndNot(parallel, F128::MultAdd(b, e, minus_d));
1310 f128 sNum_negative = F128::CmpLtZero(sNum);
1311 f128 parallel_or_sNum_negative = F128::Or(parallel, sNum_negative);
1316 f128 tNum = F128::Select(parallel_or_sNum_negative, e, F128::MultSub(b, d, e));
1321 f128 tDenom = F128::Select(parallel_or_sNum_negative, one, det);
1326 sNum = F128::AndNot(sNum_negative, sNum);
1332 f128 tNum_negative = F128::CmpLtZero(tNum);
1333 f128 d_negative = F128::CmpLeZero(d);
1334 f128 tmp = F128::And(d_negative, minus_d);
1335 sNum = F128::Select(tNum_negative, tmp, sNum);
1340 tmp = F128::Or(parallel, F128::And(tNum_negative, d_negative));
1341 f128 sDenom = F128::Select(tmp, one, det);
1346 tNum = F128::AndNot(tNum_negative, tNum);
1348 f128 s = F128::Div(sNum, sDenom);
1349 f128 t = F128::Div(tNum, tDenom);
1351 f128 pt_r0 = F128::MultAdd(s, ray0_dir_normalized, ray0_point);
1352 f128 pt_r1 = F128::MultAdd(t, ray1_dir_normalized, ray1_point);
1354 ret = Vector3::LengthSq(ret);
1356 if (point_on_ray0) *point_on_ray0 = pt_r0;
1357 if (point_on_ray1) *point_on_ray1 = pt_r1;
1366 SimdVector seg_dir = F128::Sub(segment_point1, segment_point0);
1367 SimdVector u = F128::Sub(ray_point, segment_point0);
1368 f128 b = Vector3::Dot(ray_dir_normalized, seg_dir);
1369 f128 c = Vector3::LengthSq(seg_dir);
1370 f128 d = Vector3::Dot(ray_dir_normalized, u);
1371 f128 e = Vector3::Dot(seg_dir, u);
1372 f128 det = F128::MultSub(b, b, c);
1373 f128 one = F128::SetOne();
1374 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1380 tmp0 = F128::Mult(b, e);
1381 tmp0 = F128::MultSub(c, d, tmp0);
1382 f128 sNum = F128::AndNot(parallel, tmp0);
1387 f128 sNum_negative = F128::CmpLtZero(sNum);
1388 f128 parallel_or_sNum_negative = F128::Or(parallel, sNum_negative);
1389 tmp1 = F128::MultSub(b, d, e);
1390 f128 tNum = F128::Select(parallel_or_sNum_negative, e, tmp1);
1395 f128 tDenom = F128::Select(parallel_or_sNum_negative, c, det);
1400 sNum = F128::AndNot(sNum_negative, sNum);
1408 f128 minus_d = F128::Negate(d);
1409 f128 b_minus_d = F128::Sub(b, d);
1410 f128 tNum_negative = F128::CmpLtZero(tNum);
1411 f128 tNum_out = F128::Or(tNum_negative, F128::CmpGt(tNum, tDenom));
1412 tmp0 = F128::Select(tNum_negative, minus_d, b_minus_d);
1413 f128 cmp = F128::CmpGeZero(tmp0);
1414 tmp1 = F128::And(cmp, tmp0);
1415 sNum = F128::Select(tNum_out, tmp1, sNum);
1422 tmp0 = F128::Or(parallel, F128::And(tNum_out, cmp));
1423 f128 sDenom = F128::Select(tmp0, one, det);
1429 tNum = F128::Clamp(tNum, F128::SetZero(), tDenom);
1431 f128 s = F128::Div(sNum, sDenom);
1432 f128 t = F128::Div(tNum, tDenom);
1434 f128 pt_r = F128::MultAdd(s, ray_dir_normalized, ray_point);
1435 f128 pt_s = F128::MultAdd(t, seg_dir, segment_point0);
1437 ret = Vector3::LengthSq(ret);
1439 if (point_on_ray) *point_on_ray = pt_r;
1440 if (point_on_segment) *point_on_segment = pt_s;
1445 # pragma endregion DistanceSq function implementation 1452 # pragma region Intersection 1459 f128 dot = Plane::DotNormal(plane, line_dir_normalized);
1460 SimdVector t = Plane::DotCoord(plane, line_point);
1461 t = F128::Div(t, dot);
1462 SimdVector ret = F128::MultSub(t, line_dir_normalized, line_point);
1464 f128 eps = F128::SetEpsilon();
1465 f128 dotzero = F128::CmpNearEqZero(dot, eps);
1466 f128 nan = F128::SetNaN();
1468 return F128::Select(dotzero, nan, ret);
1474 f128 dot = Plane::DotNormal(plane, ray_dir_normalized);
1475 SimdVector t = Plane::DotCoord(plane, ray_point);
1476 t = F128::Div(t, dot);
1477 SimdVector ret = F128::MultSub(t, ray_dir_normalized, ray_point);
1479 f128 eps = F128::SetEpsilon();
1480 f128 dotzero = F128::CmpNearEqZero(dot, eps);
1481 f128 t_gt_0 = F128::CmpGtZero(t);
1482 f128 nan = F128::SetNaN();
1484 return F128::Select(F128::Or(t_gt_0, dotzero), nan, ret);
1490 SimdVector dir = F128::Sub(segment_point1, segment_point0);
1491 f128 recp_len = Vector3::RecpLength(dir);
1492 dir = F128::Mult(dir, recp_len);
1494 f128 dot = Plane::DotNormal(plane, dir);
1495 SimdVector t = Plane::DotCoord(plane, segment_point1);
1496 t = F128::Div(t, dot);
1497 SimdVector ret = F128::MultSub(t, dir, segment_point1);
1499 f128 t_gt_len = F128::CmpGt(F128::Mult(t, recp_len), F128::SetOne());
1500 f128 t_lt_0 = F128::CmpLtZero(t);
1501 f128 nan = F128::SetNaN();
1503 return F128::Select(F128::Or(t_gt_len, t_lt_0), nan, ret);
1509 SimdVector pt_c = F128::Sub(sphere, ray_point);
1511 f128 len_on_ray = Vector3::Dot(pt_c, ray_dir_normalized);
1512 f128 lensq_pt_c = Vector3::LengthSq(pt_c);
1514 r_sq = F128::Mult(r_sq, r_sq);
1515 f128 distsq = F128::MultSub(len_on_ray, len_on_ray, lensq_pt_c);
1517 f128 origin_inside = F128::CmpLe(lensq_pt_c, r_sq);
1518 f128 intersection_none;
1519 intersection_none = F128::CmpLt(len_on_ray, F128::SetZero());
1520 intersection_none = F128::AndNot(origin_inside, intersection_none);
1521 intersection_none = F128::Or(intersection_none, F128::CmpGt(distsq, r_sq));
1523 if (F128::IsAllMaskFalse(intersection_none)) {
1527 f128 q = F128::Sqrt(F128::Sub(r_sq, distsq));
1528 f128 t0 = F128::Sub(len_on_ray, q);
1529 f128 t1 = F128::Add(len_on_ray, q);
1530 f128 t = F128::Select(origin_inside, t1, t0);
1531 *distance = F128::GetFloatFromLane<0>(t);
1540 NLIB_B Intersection::TriangleRay(
float* distance,
SimdVectorArg triangle_point0,
1546 SimdVector E1 = F128::Sub(triangle_point1, triangle_point0);
1547 SimdVector E2 = F128::Sub(triangle_point2, triangle_point0);
1548 SimdVector P = Vector3::Cross(ray_dir_normalized, E2);
1550 f128 det = Vector3::Dot(E1, P);
1551 f128 inv_det = F128::Recp(det);
1554 f128 intersection_none = F128::InBound(det, F128::SetEpsilon());
1557 SimdVector T = F128::Sub(ray_point, triangle_point0);
1561 f128 u = Vector3::Dot(T, P);
1563 f128 v = Vector3::Dot(ray_dir_normalized, Q);
1564 f128 uv = F128::Mult(F128::Permute<0, 1, 4, 5>(u, v), inv_det);
1566 f128 t = F128::Mult(Vector3::Dot(E2, Q), inv_det);
1569 intersection_none = F128::Or(intersection_none, F128::CmpLt(uv, F128::SetZero()));
1570 intersection_none = F128::Or(intersection_none, F128::CmpGt(uv, F128::SetOne()));
1571 intersection_none = F128::Or(intersection_none, F128::CmpLt(t, F128::SetZero()));
1573 if (F128::IsAllMaskFalse(intersection_none)) {
1575 *distance = F128::GetFloatFromLane<0>(t);
1588 SimdVector tp0 = F128::SetFloatToLane<3>(triangle_point0, 1.f);
1589 SimdVector tp1 = F128::SetFloatToLane<3>(triangle_point1, 1.f);
1590 SimdVector tp2 = F128::SetFloatToLane<3>(triangle_point2, 1.f);
1593 f128 dist0 = Vector4::Dot(plane_normalized, tp0);
1594 f128 dist1 = Vector4::Dot(plane_normalized, tp1);
1595 f128 dist2 = Vector4::Dot(plane_normalized, tp2);
1597 f128 dist012 = Vector4::Dot3(plane_normalized, tp0, tp1, tp2);
1602 f128 min_dist = F128::Min(dist0, dist1);
1603 f128 max_dist = F128::Max(dist0, dist1);
1604 min_dist = F128::Min(min_dist, dist2);
1605 max_dist = F128::Max(max_dist, dist2);
1607 f128 outside = F128::CmpGtZero(min_dist);
1608 f128 inside = F128::CmpLtZero(max_dist);
1610 if (F128::IsAllMaskTrue(outside))
return PLANE_FRONT;
1611 if (F128::IsAllMaskTrue(inside))
return PLANE_BACK;
1612 return PLANE_INTERSECT;
1618 f128 c = F128::SetFloatToLane<3>(sphere, 1.f);
1620 f128 dist = Vector4::Dot(plane_normalized, c);
1621 f128 outside = F128::CmpGt(dist, r);
1622 f128 inside = F128::CmpLt(dist, F128::Negate(r));
1624 if (F128::IsAllMaskTrue(outside))
return PLANE_FRONT;
1625 if (F128::IsAllMaskTrue(inside))
return PLANE_BACK;
1626 return PLANE_INTERSECT;
1631 f128 distsq = Vector3::LengthSq(F128::Sub(sphere0, sphere1));
1633 radsq = F128::Mult(radsq, radsq);
1634 return F128::IsAllMaskFalse(F128::CmpGt(distsq, radsq));
1641 SimdVector lineVec = Vector3::Cross(plane1, plane0);
1642 f128 lineVecLenSq = Vector3::LengthSq(lineVec);
1646 SimdVector p1_line = Vector3::Cross(plane1, lineVec);
1651 SimdVector line_p0 = Vector3::Cross(lineVec, plane0);
1652 point = F128::MultAdd<3>(plane1, line_p0, point,
each_select32);
1654 SimdVector point0 = F128::Div(point, lineVecLenSq);
1655 SimdVector point1 = F128::Add(point0, lineVec);
1656 f128 eps = F128::SetEpsilon();
1657 f128 nan = F128::SetNaN();
1658 f128 parallel = F128::CmpNearEq(F128::SetZero(), lineVecLenSq, eps);
1660 ret.val[0] = F128::Select(parallel, nan, point0);
1661 ret.val[1] = F128::Select(parallel, nan, point1);
1669 SimdPlane plane = Plane::FromPoint(triangle_point0, triangle_point1, triangle_point2);
1673 f128 distsq = DistanceSq::PointPlane(&q, sphere, plane);
1675 r_sq = F128::Mult(r_sq, r_sq);
1676 f128 cmp = F128::CmpLe(distsq, r_sq);
1677 if (F128::IsAllMaskFalse(cmp))
return false;
1682 Vector3::Cross(F128::Sub(q, triangle_point0), F128::Sub(triangle_point1, triangle_point0));
1684 Vector3::Cross(F128::Sub(q, triangle_point1), F128::Sub(triangle_point2, triangle_point1));
1686 Vector3::Cross(F128::Sub(q, triangle_point2), F128::Sub(triangle_point0, triangle_point2));
1687 plane = F128::SetZeroToLane<3>(plane);
1688 f128 three_dots = Vector4::Dot3(plane, c0, c1, c2);
1689 three_dots = F128::Swizzle<0, 1, 2, 2>(three_dots);
1690 cmp = F128::CmpGeZero(three_dots);
1691 if (F128::IsAllMaskFalse(cmp) || F128::IsAllMaskTrue(cmp))
return true;
1695 f128 seg_dist01 = DistanceSq::PointSegment(sphere, triangle_point0, triangle_point1);
1696 f128 seg_dist02 = DistanceSq::PointSegment(sphere, triangle_point0, triangle_point2);
1697 f128 seg_dist = F128::Min(seg_dist01, seg_dist02);
1698 f128 seg_dist12 = DistanceSq::PointSegment(sphere, triangle_point1, triangle_point2);
1699 seg_dist = F128::Min(seg_dist, seg_dist12);
1700 cmp = F128::CmpLe(seg_dist, r_sq);
1701 if (F128::IsAllMaskFalse(cmp))
return false;
1711 SimdVector center = F128::Add(aabb_max, aabb_min);
1712 center = F128::Mult(0.5f, center);
1713 SimdVector extents = F128::Sub(aabb_max, center);
1714 center = F128::SetFloatToLane<3>(center, 1.f);
1716 f128 dist = Vector4::Dot(center, plane_normalized);
1717 f128 radius = Vector3::Dot(extents, F128::Abs(plane_normalized));
1718 if (F128::IsAllMaskFalse(F128::CmpLe(dist, radius))) {
1721 if (F128::IsAllMaskFalse(F128::CmpGe(dist, F128::Negate(radius)))) {
1724 return PLANE_INTERSECT;
1732 f128 inv_dir = F128::Recp(ray_dir_normalized);
1733 f128 selector = F128::CmpGeZero(ray_dir_normalized);
1736 f128 tmin = F128::Select(selector, aabb_min, aabb_max);
1737 f128 tmax = F128::Select(selector, aabb_max, aabb_min);
1738 tmin = F128::Sub(tmin, ray_point);
1739 tmax = F128::Sub(tmax, ray_point);
1740 tmin = F128::Mult(tmin, inv_dir);
1741 tmax = F128::Mult(tmax, inv_dir);
1746 tmin = F128::Swizzle<0, 1, 2, 0>(tmin);
1747 tmax = F128::Swizzle<2, 0, 0, 1>(tmax);
1748 f128 result = F128::CmpGeZero(tmax);
1749 if (!F128::IsAllMaskFalse(F128::CmpGt(tmin, tmax)))
return false;
1752 return F128::IsAllMaskTrue(result);
1756 NLIB_B Intersection::AxisAlignedBoxSphere(
const AxisAlignedBox& aabb,
1760 f128 max_center = F128::Sub(sphere, aabb_max);
1761 f128 min_center = F128::Sub(sphere, aabb_min);
1762 f128 max_mask = F128::CmpGt(sphere, aabb_max);
1763 f128 min_mask = F128::CmpLt(sphere, aabb_min);
1764 f128 dist_sq = F128::SetZero();
1765 dist_sq = F128::Select(max_mask, max_center, dist_sq);
1766 dist_sq = F128::Select(min_mask, min_center, dist_sq);
1767 dist_sq = Vector3::LengthSq(dist_sq);
1769 r_sq = F128::Mult(r_sq, r_sq);
1770 return F128::IsAllMaskTrue(F128::CmpLe(dist_sq, r_sq));
1774 NLIB_B Intersection::AxisAlignedBoxAxisAlignedBox(
const AxisAlignedBox& aabb0,
1778 return F128::IsAllMaskFalse(F128::Or(cond0, cond1));
1782 NLIB_B Intersection::AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
1796 F128::Min(F128::Min(tri0, tri1), tri2);
1798 F128::Max(F128::Max(tri0, tri1), tri2);
1799 f128 cond0 = F128::CmpGt(tri_min, box_max);
1800 f128 cond1 = F128::CmpGt(box_min, tri_max);
1801 if (!F128::IsAllMaskFalse(F128::Or(cond0, cond1))) {
1808 point_in = F128::And(F128::CmpGe(tri0, box_min),
1809 F128::CmpLe(tri0, box_max));
1810 if (F128::IsAllMaskTrue(point_in))
return true;
1811 point_in = F128::And(F128::CmpGe(tri1, box_min),
1812 F128::CmpLe(tri1, box_max));
1813 if (F128::IsAllMaskTrue(point_in))
return true;
1814 point_in = F128::And(F128::CmpGe(tri2, box_min),
1815 F128::CmpLe(tri2, box_max));
1816 if (F128::IsAllMaskTrue(point_in))
return true;
1826 N = F128::SetZeroToLane<3>(N);
1827 f128 D = Vector3::Dot(N, tri0);
1828 f128 normal_gt_0 = F128::CmpGt(N, F128::SetZero());
1829 SimdVector v_near = F128::Select(normal_gt_0, box_min, box_max);
1830 SimdVector v_far = F128::Select(normal_gt_0, box_max, box_min);
1831 f128 min_near = Vector4::Dot(N, v_near);
1832 f128 max_far = Vector4::Dot(N, v_far);
1833 min_near = F128::CmpGt(min_near, D);
1834 max_far = F128::CmpLt(max_far, D);
1835 if (!F128::IsAllMaskFalse(F128::Or(min_near, max_far))) {
1840 SimdVector box_center = F128::Add(box_max, box_min);
1841 box_center = F128::Mult(0.5f, box_center);
1842 SimdVector extents = F128::Sub(box_center, box_min);
1843 SimdVector tp0 = F128::Sub(tri0, box_center);
1844 SimdVector tp1 = F128::Sub(tri1, box_center);
1845 SimdVector tp2 = F128::Sub(tri2, box_center);
1846 tp0 = F128::SetZeroToLane<3>(tp0);
1847 tp1 = F128::SetZeroToLane<3>(tp1);
1848 tp2 = F128::SetZeroToLane<3>(tp2);
1851 f0 = F128::SetZeroToLane<3>(f0);
1852 f1 = F128::SetZeroToLane<3>(f1);
1853 f2 = F128::SetZeroToLane<3>(f2);
1857 f128 tp0dot_A00A01A02A10;
1858 f128 tp0dot_A11A12A20A21;
1860 f128 tp1dot_A11A12A21A22;
1861 f128 tp2dot_A00A10A20A22;
1862 f128 neg_f0 = F128::Negate(f0);
1863 f128 neg_f1 = F128::Negate(f1);
1864 f128 neg_f2 = F128::Negate(f2);
1867 SimdVector A00 = F128::Permute<7, 6, 1, 3>(f0, neg_f0);
1869 SimdVector A01 = F128::Permute<7, 6, 1, 3>(f1, neg_f1);
1871 SimdVector A02 = F128::Permute<7, 6, 1, 3>(f2, neg_f2);
1874 SimdVector A10 = F128::Permute<2, 3, 4, 3>(f0, neg_f0);
1876 SimdVector A11 = F128::Permute<2, 3, 4, 3>(f1, neg_f1);
1878 SimdVector A12 = F128::Permute<2, 3, 4, 3>(f2, neg_f2);
1881 SimdVector A20 = F128::Permute<5, 0, 3, 3>(f0, neg_f0);
1883 SimdVector A21 = F128::Permute<5, 0, 3, 3>(f1, neg_f1);
1885 SimdVector A22 = F128::Permute<5, 0, 3, 3>(f2, neg_f2);
1887 tp0dot_A00A01A02A10 = Vector4::Dot4(tp0, A00, A01, A02, A10);
1888 tp0dot_A11A12A20A21 = Vector4::Dot4(tp0, A11, A12, A10, A11);
1889 tp1dot_A01A02 = Vector4::Dot2(tp1, A01, A02);
1890 tp1dot_A11A12A21A22 = Vector4::Dot4(tp1, A11, A12, A21, A22);
1891 tp2dot_A00A10A20A22 = Vector4::Dot4(tp2, A00, A10, A20, A22);
1893 A00 = F128::Abs(A00);
1894 A01 = F128::Abs(A01);
1895 A02 = F128::Abs(A02);
1896 A10 = F128::Abs(A10);
1897 A11 = F128::Abs(A11);
1898 A12 = F128::Abs(A12);
1899 A20 = F128::Abs(A20);
1900 A21 = F128::Abs(A21);
1901 A22 = F128::Abs(A22);
1905 radius = Vector4::Dot4(extents, A00, A01, A02, A10);
1906 tp12dot = F128::Permute<4, 0, 1, 5>(tp1dot_A01A02, tp2dot_A00A10A20A22);
1907 pmax = F128::Max(tp0dot_A00A01A02A10, tp12dot);
1908 pmin = F128::Min(tp0dot_A00A01A02A10, tp12dot);
1909 f128 intersection_none = F128::CmpGt(pmin, radius);
1910 intersection_none = F128::Or(intersection_none, F128::CmpLt(pmax, F128::Negate(radius)));
1913 radius = Vector4::Dot4(extents, A11, A12, A20, A21);
1914 tp12dot = F128::Permute<0, 1, 6, 2>(tp1dot_A11A12A21A22, tp2dot_A00A10A20A22);
1915 pmax = F128::Max(tp0dot_A11A12A20A21, tp12dot);
1916 pmin = F128::Min(tp0dot_A11A12A20A21, tp12dot);
1917 intersection_none = F128::Or(intersection_none, F128::CmpGt(pmin, radius));
1918 intersection_none = F128::Or(intersection_none, F128::CmpLt(pmax, F128::Negate(radius)));
1921 radius = Vector4::Dot(extents, A22);
1922 pmax = F128::Max(tp1dot_A11A12A21A22, tp2dot_A00A10A20A22);
1923 pmin = F128::Min(tp1dot_A11A12A21A22, tp2dot_A00A10A20A22);
1926 intersection_none = F128::Or(intersection_none, F128::CmpGt(pmin, radius));
1927 intersection_none = F128::Or(intersection_none, F128::CmpLt(pmax, F128::Negate(radius)));
1929 return F128::IsAllMaskFalse(intersection_none);
1934 Intersection::OrientedBoxAxisAlignedBox(
const OrientedBox& box,
1940 aabb_center = F128::Mult(0.5f, F128::Add(aabb_max, aabb_min));
1941 aabb_extent = F128::Sub(aabb_max, aabb_center);
1942 aabb_extent = F128::SetZeroToLane<3>(aabb_extent);
1945 box_center = F128::SetZeroToLane<3>(box_center);
1953 abs_M0x = F128::Abs(rot.
r[0]);
1954 abs_M1x = F128::Abs(rot.
r[1]);
1955 abs_M2x = F128::Abs(rot.
r[2]);
1960 neg_Mx0 = F128::Negate(Mx0);
1961 neg_Mx1 = F128::Negate(Mx1);
1962 neg_Mx2 = F128::Negate(Mx2);
1991 f128 d, d_aabb, d_box;
1993 f128 intersection_none = F128::SetZero();
1998 d = F128::Abs(box_center);
1999 d_aabb = aabb_extent;
2000 d_box = Vector4::Dot3(box_extent, F128::Abs(Mx0), F128::Abs(Mx1), F128::Abs(Mx2));
2001 d_aabb_box = F128::Add(d_aabb, d_box);
2002 intersection_none = F128::CmpGt(d, d_aabb_box);
2005 d = F128::Abs(Vector4::Dot3(box_center, Mx0, Mx1, Mx2));
2006 d_aabb = Vector4::Dot3(aabb_extent, F128::Abs(Mx0), F128::Abs(Mx1), F128::Abs(Mx2));
2008 d_aabb_box = F128::Add(d_aabb, d_box);
2009 cmp = F128::CmpGt(d, d_aabb_box);
2010 intersection_none = F128::Or(intersection_none, cmp);
2017 t0 = F128::Permute<3, 6, 1, 3>(Mx0, neg_Mx0);
2018 t1 = F128::Permute<3, 6, 1, 3>(Mx1, neg_Mx1);
2019 t2 = F128::Permute<3, 6, 1, 3>(Mx2, neg_Mx2);
2020 d = F128::Abs(Vector4::Dot3(box_center, t0, t1, t2));
2021 d_aabb = Vector4::Dot3(aabb_extent, F128::Abs(t0), F128::Abs(t1), F128::Abs(t2));
2023 t0 = F128::Swizzle<3, 2, 1, 3>(abs_M0x);
2024 t1 = F128::Swizzle<2, 3, 0, 3>(abs_M0x);
2025 t2 = F128::Swizzle<1, 0, 3, 3>(abs_M0x);
2026 d_box = Vector4::Dot3(box_extent, t0, t1, t2);
2027 d_aabb_box = F128::Add(d_aabb, d_box);
2028 cmp = F128::CmpGt(d, d_aabb_box);
2029 intersection_none = F128::Or(intersection_none, cmp);
2034 t0 = F128::Permute<2, 3, 4, 3>(Mx0, neg_Mx0);
2035 t1 = F128::Permute<2, 3, 4, 3>(Mx1, neg_Mx1);
2036 t2 = F128::Permute<2, 3, 4, 3>(Mx2, neg_Mx2);
2037 d = F128::Abs(Vector4::Dot3(box_center, t0, t1, t2));
2038 d_aabb = Vector4::Dot3(aabb_extent, F128::Abs(t0), F128::Abs(t1), F128::Abs(t2));
2040 t0 = F128::Swizzle<3, 2, 1, 3>(abs_M1x);
2041 t1 = F128::Swizzle<2, 3, 0, 3>(abs_M1x);
2042 t2 = F128::Swizzle<1, 0, 3, 3>(abs_M1x);
2043 d_box = Vector4::Dot3(box_extent, t0, t1, t2);
2044 d_aabb_box = F128::Add(d_aabb, d_box);
2045 cmp = F128::CmpGt(d, d_aabb_box);
2046 intersection_none = F128::Or(intersection_none, cmp);
2051 t0 = F128::Permute<5, 0, 3, 3>(Mx0, neg_Mx0);
2052 t1 = F128::Permute<5, 0, 3, 3>(Mx1, neg_Mx1);
2053 t2 = F128::Permute<5, 0, 3, 3>(Mx2, neg_Mx2);
2054 d = F128::Abs(Vector4::Dot3(box_center, t0, t1, t2));
2055 d_aabb = Vector4::Dot3(aabb_extent, F128::Abs(t0), F128::Abs(t1), F128::Abs(t2));
2057 t0 = F128::Swizzle<3, 2, 1, 3>(abs_M2x);
2058 t1 = F128::Swizzle<2, 3, 0, 3>(abs_M2x);
2059 t2 = F128::Swizzle<1, 0, 3, 3>(abs_M2x);
2060 d_box = Vector4::Dot3(box_extent, t0, t1, t2);
2061 d_aabb_box = F128::Add(d_aabb, d_box);
2062 cmp = F128::CmpGt(d, d_aabb_box);
2063 intersection_none = F128::Or(intersection_none, cmp);
2065 intersection_none = F128::SetZeroToLane<3>(intersection_none);
2066 return F128::IsAllMaskFalse(intersection_none);
2070 NLIB_B Intersection::OrientedBoxOrientedBox(
const OrientedBox& box0,
2075 obox.
rotation = Quaternion::Mult(box0_rot, Quaternion::Conjugate(box1_rot));
2083 return Intersection::OrientedBoxAxisAlignedBox(obox, aabb);
2093 SimdVector sphere_center = F128::Sub(sphere, box_center);
2094 sphere_center = Vector3::InvRotate(sphere_center, box_rotation);
2097 f128 lt_min = F128::CmpLt(sphere_center, F128::Negate(box_extent));
2098 f128 gt_max = F128::CmpGt(sphere_center, box_extent);
2099 SimdVector diff_min = F128::Add(sphere_center, box_extent);
2100 SimdVector diff_max = F128::Sub(sphere_center, box_extent);
2102 f128 dist_sq = F128::SetZero();
2103 dist_sq = F128::Select(lt_min, diff_min, dist_sq);
2104 dist_sq = F128::Select(gt_max, diff_max, dist_sq);
2105 dist_sq = Vector3::Dot(dist_sq, dist_sq);
2107 f128 rad_sq = F128::Mult(sphere, sphere);
2110 return Vector4::CmpLe(dist_sq, rad_sq);
2120 SimdVector tp0 = F128::Sub(triangle_point0, box_center);
2121 SimdVector tp1 = F128::Sub(triangle_point1, box_center);
2122 SimdVector tp2 = F128::Sub(triangle_point2, box_center);
2123 tp0 = Vector3::InvRotate(tp0, box_rotation);
2124 tp1 = Vector3::InvRotate(tp1, box_rotation);
2125 tp2 = Vector3::InvRotate(tp2, box_rotation);
2131 return Intersection::AxisAlignedBoxTriangle(aabb, tp0, tp1, tp2);
2136 Intersection::OrientedBoxPlane(
const OrientedBox& box,
2140 f128 new_d = F128::Sub(plane_normalized, Vector3::Dot(plane_normalized, box.
center));
2141 new_plane = F128::Permute<0, 1, 2, 7>(new_plane, new_d);
2145 aabb.point_min = F128::Negate(aabb.point_max);
2147 return Intersection::AxisAlignedBoxPlane(aabb, new_plane);
2155 P = Vector3::InvRotate(P, box_rotation);
2156 SimdVector D = Vector3::InvRotate(ray_dir_normalized, box_rotation);
2162 return Intersection::AxisAlignedBoxRay(aabb, P, D);
2166 SimdPlane near_plane = frustum.near_plane_;
2167 SimdPlane far_plane = frustum.far_plane_;
2168 SimdPlane left_plane = frustum.left_plane_;
2169 SimdPlane right_plane = frustum.right_plane_;
2170 SimdPlane top_plane = frustum.top_plane_;
2171 SimdPlane bottom_plane = frustum.bottom_plane_;
2178 center = Vector3::InvRotate(F128::Sub(center, frustum_center), frustum_rot);
2179 center = F128::SetFloatToLane<3>(center, 1.f);
2183 dist0 = Vector4::Dot4(center, near_plane, far_plane, left_plane, right_plane);
2184 dist1 = Vector4::Dot2(center, top_plane, bottom_plane);
2185 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2188 f128 outside = F128::CmpGt(dist0, radius);
2189 outside = F128::Or(F128::CmpGt(dist1, radius), outside);
2190 if (!F128::IsAllMaskFalse(outside))
return false;
2193 f128 center_inside = F128::CmpLeZero(dist0);
2194 center_inside = F128::And(F128::CmpLeZero(dist0), center_inside);
2195 if (F128::IsAllMaskTrue(center_inside))
return true;
2204 dist_plane = Vector4::Dot4(center, near_plane, far_plane, left_plane, right_plane);
2207 pt_plane = F128::MultSub(near_plane, F128::SetValue<0>(dist0,
each_select32), center);
2208 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2209 inside = Vector4::Dot4(pt_plane, left_plane, right_plane, top_plane, bottom_plane);
2210 inside = F128::CmpLeZero(inside);
2211 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<0>(dist_plane,
each_select32)));
2212 if (F128::IsAllMaskTrue(inside))
return true;
2215 pt_plane = F128::MultSub(far_plane, F128::SetValue<1>(dist0,
each_select32), center);
2216 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2217 inside = Vector4::Dot4(pt_plane, left_plane, right_plane, top_plane, bottom_plane);
2218 inside = F128::CmpLeZero(inside);
2219 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<1>(dist_plane,
each_select32)));
2220 if (F128::IsAllMaskTrue(inside))
return true;
2223 pt_plane = F128::MultSub(left_plane, F128::SetValue<2>(dist0,
each_select32), center);
2224 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2225 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, top_plane, bottom_plane);
2226 inside = F128::CmpLeZero(inside);
2227 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<2>(dist_plane,
each_select32)));
2228 if (F128::IsAllMaskTrue(inside))
return true;
2231 pt_plane = F128::MultSub(right_plane, F128::SetValue<3>(dist0,
each_select32), center);
2232 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2233 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, top_plane, bottom_plane);
2234 inside = F128::CmpLeZero(inside);
2235 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<3>(dist_plane,
each_select32)));
2236 if (F128::IsAllMaskTrue(inside))
return true;
2238 dist_plane = Vector4::Dot2(center, top_plane, bottom_plane);
2241 pt_plane = F128::MultSub(top_plane, F128::SetValue<0>(dist1,
each_select32), center);
2242 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2243 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, left_plane, right_plane);
2244 inside = F128::CmpLeZero(inside);
2245 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<0>(dist_plane,
each_select32)));
2246 if (F128::IsAllMaskTrue(inside))
return true;
2249 pt_plane = F128::MultSub(bottom_plane, F128::SetValue<1>(dist1,
each_select32), center);
2250 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2251 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, left_plane, right_plane);
2252 inside = F128::CmpLeZero(inside);
2253 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<1>(dist_plane,
each_select32)));
2254 if (F128::IsAllMaskTrue(inside))
return true;
2258 f128 radius_sq = F128::Mult(radius, radius);
2265 SimdVector left_top = Vector3::LoadFloat3(&corners[0]);
2266 SimdVector right_top = Vector3::LoadFloat3(&corners[1]);
2267 SimdVector right_bottom = Vector3::LoadFloat3(&corners[2]);
2268 SimdVector left_bottom = Vector3::LoadFloat3(&corners[3]);
2269 SimdVector left_top_far = Vector3::LoadFloat3(&corners[4]);
2270 SimdVector right_top_far = Vector3::LoadFloat3(&corners[5]);
2271 SimdVector right_bottom_far = Vector3::LoadFloat3(&corners[6]);
2272 SimdVector left_bottom_far = Vector3::LoadFloat3(&corners[7]);
2275 dist_sq = DistanceSq::PointSegment(center, left_top, right_top);
2276 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_top, right_bottom));
2277 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_bottom, left_bottom));
2278 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_bottom, left_top));
2280 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_top_far, right_top_far));
2281 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_top_far, right_bottom_far));
2283 F128::Min(dist_sq, DistanceSq::PointSegment(center, right_bottom_far, left_bottom_far));
2284 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_bottom_far, left_top_far));
2286 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_top_far, left_top));
2287 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_top_far, right_top));
2288 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_bottom_far, right_bottom));
2289 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_bottom_far, left_bottom));
2291 return F128::IsAllMaskTrue(F128::CmpLe(dist_sq, radius_sq));
2295 SimdVector pt = F128::Sub(point, frustum.center_);
2296 pt = Vector3::InvRotate(pt, frustum.rotation_);
2297 pt = F128::SetFloatToLane<3>(pt, 1.f);
2299 f128 dot1 = Vector4::Dot4(pt, frustum.near_plane_, frustum.far_plane_, frustum.top_plane_,
2300 frustum.bottom_plane_);
2301 f128 dot2 = Vector4::Dot2(pt, frustum.left_plane_, frustum.right_plane_);
2302 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
2303 dot1 = F128::Max(dot1, dot2);
2304 f128 outside = F128::CmpGt(dot1, F128::SetZero());
2305 return F128::IsAllMaskFalse(outside);
2308 NLIB_B Intersection::FrustumAxisAlignedBox(
const Frustum& frustum,
2314 if (Containment::FrustumPoint(frustum, C))
return true;
2321 frustum.
Transform(&fstm, 1.f, F128::Set0001(), F128::Negate(C));
2327 for (
size_t i = 0; i < 8; ++i) {
2328 corners[i] = Vector3::LoadFloat3(&corners_[i]);
2329 corners[i] = F128::SetFloatToLane<3>(corners[i], 1.f);
2334 pt_min = pt_max = corners[0];
2335 for (
size_t i = 1; i < 8; ++i) {
2337 pt_min = F128::Min(vec, pt_min);
2338 pt_max = F128::Max(vec, pt_max);
2340 f128 disjoint = F128::Or(F128::CmpGt(pt_min, extent),
2341 F128::CmpLt(pt_max, F128::Negate(extent)));
2342 disjoint = F128::SetZeroToLane<3>(disjoint);
2343 if (!F128::IsAllMaskFalse(disjoint))
return false;
2351 f128 dist0_frustum, dist1_frustum;
2352 f128 dist_aabb_max, dist_aabb_min;
2356 plane = fstm.near_plane_;
2357 N = Vector3::Rotate(plane, frustum_rot);
2358 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2359 plane = F128::Permute<0, 1, 2, 7>(N, D);
2361 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2362 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2363 N = Vector3::Dot(F128::Abs(N), extent);
2364 dist_aabb_max = F128::Add(D, N);
2365 dist_aabb_min = F128::Sub(D, N);
2366 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2367 F128::CmpGe(dist1_frustum, dist_aabb_min));
2368 if (F128::IsAllMaskFalse(intersect))
return false;
2369 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2370 F128::CmpLe(dist1_frustum, dist_aabb_max));
2371 if (F128::IsAllMaskFalse(intersect))
return false;
2374 plane = fstm.left_plane_;
2375 N = Vector3::Rotate(plane, frustum_rot);
2376 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2377 plane = F128::Permute<0, 1, 2, 7>(N, D);
2379 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2380 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2381 N = Vector3::Dot(F128::Abs(N), extent);
2382 dist_aabb_max = F128::Add(D, N);
2383 dist_aabb_min = F128::Sub(D, N);
2384 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2385 F128::CmpGe(dist1_frustum, dist_aabb_min));
2386 if (F128::IsAllMaskFalse(intersect))
return false;
2387 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2388 F128::CmpLe(dist1_frustum, dist_aabb_max));
2389 if (F128::IsAllMaskFalse(intersect))
return false;
2392 plane = fstm.right_plane_;
2393 N = Vector3::Rotate(plane, frustum_rot);
2394 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2395 plane = F128::Permute<0, 1, 2, 7>(N, D);
2397 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2398 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2399 N = Vector3::Dot(F128::Abs(N), extent);
2400 dist_aabb_max = F128::Add(D, N);
2401 dist_aabb_min = F128::Sub(D, N);
2402 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2403 F128::CmpGe(dist1_frustum, dist_aabb_min));
2404 if (F128::IsAllMaskFalse(intersect))
return false;
2405 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2406 F128::CmpLe(dist1_frustum, dist_aabb_max));
2407 if (F128::IsAllMaskFalse(intersect))
return false;
2410 plane = fstm.top_plane_;
2411 N = Vector3::Rotate(plane, frustum_rot);
2412 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2413 plane = F128::Permute<0, 1, 2, 7>(N, D);
2415 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2416 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2417 N = Vector3::Dot(F128::Abs(N), extent);
2418 dist_aabb_max = F128::Add(D, N);
2419 dist_aabb_min = F128::Sub(D, N);
2420 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2421 F128::CmpGe(dist1_frustum, dist_aabb_min));
2422 if (F128::IsAllMaskFalse(intersect))
return false;
2423 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2424 F128::CmpLe(dist1_frustum, dist_aabb_max));
2425 if (F128::IsAllMaskFalse(intersect))
return false;
2428 plane = fstm.bottom_plane_;
2429 N = Vector3::Rotate(plane, frustum_rot);
2430 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2431 plane = F128::Permute<0, 1, 2, 7>(N, D);
2433 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2434 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2435 N = Vector3::Dot(F128::Abs(N), extent);
2436 dist_aabb_max = F128::Add(D, N);
2437 dist_aabb_min = F128::Sub(D, N);
2438 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2439 F128::CmpGe(dist1_frustum, dist_aabb_min));
2440 if (F128::IsAllMaskFalse(intersect))
return false;
2441 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2442 F128::CmpLe(dist1_frustum, dist_aabb_max));
2443 if (F128::IsAllMaskFalse(intersect))
return false;
2447 E0[0] = F128::Set1000();
2448 E0[1] = F128::Set0100();
2449 E0[2] = F128::Set0010();
2451 E1[0] = F128::Sub(corners[0], corners[4]);
2452 E1[1] = F128::Sub(corners[1], corners[5]);
2453 E1[2] = F128::Sub(corners[2], corners[6]);
2454 E1[3] = F128::Sub(corners[3], corners[7]);
2455 E1[4] = F128::Sub(corners[1], corners[0]);
2456 E1[5] = F128::Sub(corners[1], corners[2]);
2459 for (
size_t i = 0; i < 3; ++i) {
2460 for (
size_t j = 0; j < 6; ++j) {
2461 SimdVector axis = Vector3::Cross(E0[i], E1[j]);
2462 axis = F128::SetZeroToLane<3>(axis);
2463 N = Vector3::Dot(F128::Abs(axis), extent);
2465 f128 aabb_min = F128::Sub(D, N);
2466 f128 aabb_max = F128::Add(D, N);
2467 dot0 = Vector4::Dot4(axis, corners[0], corners[1], corners[2], corners[3]);
2468 dot1 = Vector4::Dot4(axis, corners[4], corners[5], corners[6], corners[7]);
2470 intersect = F128::CmpGe(F128::Max(dot0, dot1), aabb_min);
2471 if (F128::IsAllMaskFalse(intersect))
return false;
2472 intersect = F128::CmpLe(F128::Min(dot0, dot1), aabb_max);
2473 if (F128::IsAllMaskFalse(intersect))
return false;
2479 NLIB_B Intersection::FrustumOrientedBox(
const Frustum& frustum,
2482 frustum.
Transform(&frstm, 1.f, F128::Set0001(), F128::Negate(obb.
center));
2483 frstm.
Transform(&frstm, 1.f, Quaternion::Conjugate(obb.
rotation), F128::SetZero());
2488 return Intersection::FrustumAxisAlignedBox(frstm, aabb);
2497 SimdVector pt0 = Vector3::InvRotate(F128::Sub(triangle_point0, frustum_center), frustum_rot);
2498 SimdVector pt1 = Vector3::InvRotate(F128::Sub(triangle_point1, frustum_center), frustum_rot);
2499 SimdVector pt2 = Vector3::InvRotate(F128::Sub(triangle_point2, frustum_center), frustum_rot);
2500 pt0 = F128::SetFloatToLane<3>(pt0, 1.f);
2501 pt1 = F128::SetFloatToLane<3>(pt1, 1.f);
2502 pt2 = F128::SetFloatToLane<3>(pt2, 1.f);
2504 SimdPlane near_plane = frustum.near_plane_;
2505 SimdPlane far_plane = frustum.far_plane_;
2506 SimdPlane left_plane = frustum.left_plane_;
2507 SimdPlane right_plane = frustum.right_plane_;
2508 SimdPlane top_plane = frustum.top_plane_;
2509 SimdPlane bottom_plane = frustum.bottom_plane_;
2511 f128 dist0, dist1, dist_max;
2512 f128 dist0_min, dist1_min;
2516 dist0 = Vector4::Dot4(pt0, near_plane, far_plane, left_plane, right_plane);
2518 dist1 = Vector4::Dot2(pt0, top_plane, bottom_plane);
2519 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2521 dist_max = F128::Max(dist0, dist1);
2522 outside = F128::CmpGtZero(dist_max);
2523 if (F128::IsAllMaskFalse(outside))
return true;
2526 dist0 = Vector4::Dot4(pt1, near_plane, far_plane, left_plane, right_plane);
2527 dist0_min = F128::Min(dist0, dist0_min);
2528 dist1 = Vector4::Dot2(pt1, top_plane, bottom_plane);
2529 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2530 dist1_min = F128::Min(dist1, dist1_min);
2531 dist_max = F128::Max(dist0, dist1);
2532 outside = F128::CmpGtZero(dist_max);
2533 if (F128::IsAllMaskFalse(outside))
return true;
2536 dist0 = Vector4::Dot4(pt2, near_plane, far_plane, left_plane, right_plane);
2537 dist0_min = F128::Min(dist0, dist0_min);
2538 dist1 = Vector4::Dot2(pt2, top_plane, bottom_plane);
2539 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2540 dist1_min = F128::Min(dist1, dist1_min);
2541 dist_max = F128::Max(dist0, dist1);
2542 outside = F128::CmpGtZero(dist_max);
2543 if (F128::IsAllMaskFalse(outside))
return true;
2546 if (!F128::IsAllMaskFalse(F128::Or(
2547 F128::CmpGtZero(dist0_min), F128::CmpGtZero(dist1_min))))
return false;
2552 pt0 = triangle_point0;
2553 pt1 = triangle_point1;
2554 pt2 = triangle_point2;
2557 SimdPlane triangle = Plane::FromPoint(pt0, pt1, pt2);
2561 for (
size_t i = 0; i < 8; ++i) {
2562 corners[i] = Vector3::LoadFloat3(&corners_[i]);
2563 corners[i] = F128::SetFloatToLane<3>(corners[i], 1.f);
2565 f128 dot0 = Vector4::Dot4(triangle, corners[0], corners[1], corners[2], corners[3]);
2566 f128 dot1 = Vector4::Dot4(triangle, corners[4], corners[5], corners[6], corners[7]);
2568 if (F128::IsAllMaskFalse(F128::CmpGeZero(F128::Max(dot0, dot1))))
return false;
2570 if (F128::IsAllMaskFalse(F128::CmpLeZero(F128::Min(dot0, dot1))))
return false;
2574 E0[0] = F128::Sub(pt1, pt0);
2575 E0[1] = F128::Sub(pt2, pt1);
2576 E0[2] = F128::Sub(pt0, pt2);
2578 E1[0] = F128::Sub(corners[0], corners[4]);
2579 E1[1] = F128::Sub(corners[1], corners[5]);
2580 E1[2] = F128::Sub(corners[2], corners[6]);
2581 E1[3] = F128::Sub(corners[3], corners[7]);
2582 E1[4] = F128::Sub(corners[1], corners[0]);
2583 E1[5] = F128::Sub(corners[1], corners[2]);
2585 for (
size_t i = 0; i < 3; ++i) {
2586 for (
size_t j = 0; j < 6; ++j) {
2587 SimdVector axis = Vector3::Cross(E0[i], E1[j]);
2588 axis = F128::SetZeroToLane<3>(axis);
2589 f128 tri_min, tri_max;
2591 f128 tmp0 = Vector3::Dot(axis, pt0);
2592 f128 tmp1 = Vector3::Dot(axis, pt1);
2593 f128 tmp2 = Vector3::Dot(axis, pt2);
2594 tri_min = F128::Min(tmp0, tmp1);
2595 tri_max = F128::Max(tmp0, tmp1);
2596 tri_min = F128::Min(tri_min, tmp2);
2597 tri_max = F128::Max(tri_max, tmp2);
2599 dot0 = Vector4::Dot4(axis, corners[0], corners[1], corners[2], corners[3]);
2600 dot1 = Vector4::Dot4(axis, corners[4], corners[5], corners[6], corners[7]);
2602 if (F128::IsAllMaskFalse(F128::CmpGe(F128::Max(dot0, dot1), tri_min)))
return false;
2604 if (F128::IsAllMaskFalse(F128::CmpLe(F128::Min(dot0, dot1), tri_max)))
return false;
2615 for (
size_t i = 0; i < 8; ++i) {
2616 corners[i] = Vector3::LoadFloat3(&corners_[i]);
2617 corners[i] = F128::SetFloatToLane<3>(corners[i], 1.f);
2619 f128 dot0 = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2620 f128 dot1 = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2623 f128 outside = F128::CmpLeZero(F128::Min(dot0, dot1));
2624 if (F128::IsAllMaskFalse(outside))
return Intersection::PLANE_FRONT;
2627 f128 inside = F128::CmpGeZero(F128::Max(dot0, dot1));
2628 if (F128::IsAllMaskFalse(inside))
return Intersection::PLANE_BACK;
2630 return Intersection::PLANE_INTERSECT;
2636 if (Containment::FrustumPoint(frustum, ray_point))
return true;
2639 SimdVector rp = F128::Sub(ray_point, frustum.center_);
2640 rp = Vector3::InvRotate(rp, frustum.rotation_);
2641 rp = F128::SetFloatToLane<3>(rp, 1.f);
2642 SimdVector rd = Vector3::InvRotate(ray_dir_normalized, frustum.rotation_);
2643 rd = F128::SetZeroToLane<3>(rd);
2645 f128 dot_rp0, dot_rp1;
2646 dot_rp0 = Vector4::Dot4(rp, frustum.near_plane_, frustum.far_plane_,
2647 frustum.left_plane_, frustum.right_plane_);
2648 dot_rp1 = Vector4::Dot2(rp, frustum.top_plane_, frustum.bottom_plane_);
2649 dot_rp1 = F128::Swizzle<0, 1, 0, 1>(dot_rp1);
2651 f128 dot_rd0, dot_rd1;
2652 dot_rd0 = Vector4::Dot4(rd, frustum.near_plane_, frustum.far_plane_,
2653 frustum.left_plane_, frustum.right_plane_);
2654 dot_rd1 = Vector4::Dot2(rd, frustum.top_plane_, frustum.bottom_plane_);
2655 dot_rd1 = F128::Swizzle<0, 1, 0, 1>(dot_rd1);
2658 f128 eps = F128::SetEpsilon();
2659 f128 parallel0 = F128::CmpLe(F128::Abs(dot_rd0), eps);
2660 f128 parallel1 = F128::CmpLe(F128::Abs(dot_rd1), eps);
2661 f128 mask0 = F128::And(parallel0, F128::CmpGtZero(dot_rp0));
2662 f128 mask1 = F128::And(parallel1, F128::CmpGtZero(dot_rp1));
2663 if (!F128::IsAllMaskFalse(F128::Or(mask0, mask1)))
return false;
2665 f128 t0 = F128::Negate(F128::Div(dot_rp0, dot_rd0));
2666 f128 t1 = F128::Negate(F128::Div(dot_rp1, dot_rd1));
2667 f128 inf = F128::SetInfinity();
2670 mask0 = F128::AndNot(parallel0, F128::CmpGtZero(dot_rd0));
2671 mask1 = F128::AndNot(parallel1, F128::CmpGtZero(dot_rd1));
2672 f128 to = F128::Min(F128::Select(mask0, t0, inf), F128::Select(mask1, t1, inf));
2673 to = F128::PairwiseMin(to, to);
2674 to = F128::PairwiseMin(to, to);
2677 inf = F128::Negate(inf);
2678 mask0 = F128::AndNot(parallel0, F128::CmpLtZero(dot_rd0));
2679 mask1 = F128::AndNot(parallel1, F128::CmpLtZero(dot_rd1));
2680 f128 from = F128::Max(F128::Select(mask0, t0, inf), F128::Select(mask1, t1, inf));
2681 from = F128::PairwiseMax(from, from);
2682 from = F128::PairwiseMax(from, from);
2684 float n = F128::GetFloatFromLane<0>(from);
2685 float f = F128::GetFloatFromLane<0>(to);
2686 return n <= f && (n >= 0.f || f >= 0.f);
2690 # pragma endregion Intersection function implementation 2697 # pragma region Containment 2703 f128 dist_sq = Vector3::LengthSq(F128::Sub(sphere, point));
2705 return F128::IsAllMaskFalse(F128::CmpGt(dist_sq, rsq));
2714 SimdVector tp0_c = F128::Sub(triangle_point0, sphere);
2715 SimdVector tp1_c = F128::Sub(triangle_point1, sphere);
2716 SimdVector tp2_c = F128::Sub(triangle_point2, sphere);
2717 r_sq = F128::Mult(r_sq, r_sq);
2718 tp0_c = Vector3::LengthSq(tp0_c);
2719 tp1_c = Vector3::LengthSq(tp1_c);
2720 tp2_c = Vector3::LengthSq(tp2_c);
2721 f128 dist_sq = F128::Max(F128::Max(tp0_c, tp1_c), tp2_c);
2722 return F128::IsAllMaskFalse(F128::CmpGt(dist_sq, r_sq));
2727 NLIB_B Containment::SphereAxisAlignedBox(
SimdSphereArg sphere,
2732 r_sq = F128::Mult(r_sq, r_sq);
2733 aabb_max = F128::Abs(aabb_max);
2734 aabb_min = F128::Abs(aabb_min);
2735 f128 dist_sq = Vector3::LengthSq(F128::Max(aabb_max, aabb_min));
2736 return F128::IsAllMaskFalse(F128::CmpGt(dist_sq, r_sq));
2743 new_sphere = Vector3::InvRotate(new_sphere, obb.
rotation);
2744 new_sphere = F128::Permute<0, 1, 2, 7>(new_sphere, sphere);
2748 aabb.
point_min = F128::Negate(box_extent);
2749 return Containment::SphereAxisAlignedBox(new_sphere, aabb);
2755 float dist = F128::GetFloatFromLane<0>(Vector3::Length(F128::Sub(sphere, contained)));
2756 float r0 = F128::GetFloatFromLane<3>(sphere);
2757 float r1 = F128::GetFloatFromLane<3>(contained);
2758 return (r0 - r1) >= dist;
2772 pt = Vector3::LoadFloat3(&corners[0]);
2773 d_sq = Vector3::LengthSq(F128::Sub(pt, sp));
2774 inside = F128::CmpLe(d_sq, rad_sq);
2775 for (
size_t i = 1; i < 8; ++i) {
2776 pt = Vector3::LoadFloat3(&corners[i]);
2777 d_sq = Vector3::LengthSq(F128::Sub(pt, sp));
2778 inside = F128::And(inside, F128::CmpLe(d_sq, rad_sq));
2780 return F128::IsAllMaskTrue(inside);
2785 NLIB_B Containment::AxisAlignedBoxPoint(
const AxisAlignedBox& aabb,
2789 out = F128::SetZeroToLane<3>(out);
2790 return F128::IsAllMaskFalse(out);
2795 NLIB_B Containment::AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
2800 pt_max = F128::Max(triangle_point0, triangle_point1);
2801 pt_min = F128::Min(triangle_point0, triangle_point1);
2802 pt_max = F128::Max(pt_max, triangle_point2);
2803 pt_min = F128::Min(pt_min, triangle_point2);
2806 out = F128::SetZeroToLane<3>(out);
2807 return F128::IsAllMaskFalse(out);
2812 NLIB_B Containment::AxisAlignedBoxOrientedBox(
const AxisAlignedBox& aabb,
2814 f128 zero = F128::SetZero();
2816 SimdVector P = F128::Splat<false, true, true, true>(box_extent, zero);
2817 SimdVector Q = F128::Splat<true, false, true, true>(box_extent, zero);
2818 SimdVector R = F128::Splat<true, true, false, true>(box_extent, zero);
2820 P = Vector3::Rotate(P, box_rotation);
2821 Q = Vector3::Rotate(Q, box_rotation);
2822 R = Vector3::Rotate(R, box_rotation);
2828 v = F128::Add(F128::Add(P, Q), R);
2829 v_neg = F128::Negate(v);
2830 pt_min = F128::Min(v, v_neg);
2831 pt_max = F128::Max(v, v_neg);
2834 v = F128::Sub(F128::Add(P, Q), R);
2835 v_neg = F128::Negate(v);
2836 pt_min = F128::Min(pt_min, v);
2837 pt_max = F128::Max(pt_max, v);
2838 pt_min = F128::Min(pt_min, v_neg);
2839 pt_max = F128::Max(pt_max, v_neg);
2842 v = F128::Sub(F128::Add(P, R), Q);
2843 v_neg = F128::Negate(v);
2844 pt_min = F128::Min(pt_min, v);
2845 pt_max = F128::Max(pt_max, v);
2846 pt_min = F128::Min(pt_min, v_neg);
2847 pt_max = F128::Max(pt_max, v_neg);
2852 f128 out = F128::Or(F128::CmpGt(pt_max, aabb_max),
2853 F128::CmpLt(pt_min, aabb_min));
2854 out = F128::SetZeroToLane<3>(out);
2855 return F128::IsAllMaskFalse(out);
2860 NLIB_B Containment::AxisAlignedBoxAxisAlignedBox(
2864 out = F128::SetZeroToLane<3>(out);
2865 return F128::IsAllMaskFalse(out);
2870 NLIB_B Containment::AxisAlignedBoxSphere(
const AxisAlignedBox& aabb,
2873 SimdVector pt_min = F128::Sub(sphere, radius);
2874 SimdVector pt_max = F128::Add(sphere, radius);
2877 out = F128::SetZeroToLane<3>(out);
2878 return F128::IsAllMaskFalse(out);
2883 NLIB_B Containment::AxisAlignedBoxFrustum(
const AxisAlignedBox& aabb,
2887 SimdVector frustum_max = Vector3::LoadFloat3(&corners[0]);
2889 for (
size_t i = 1; i < 8; ++i) {
2890 SimdVector tmp = Vector3::LoadFloat3(&corners[i]);
2891 frustum_max = F128::Max(tmp, frustum_max);
2892 frustum_min = F128::Min(tmp, frustum_min);
2897 return Containment::AxisAlignedBoxAxisAlignedBox(aabb, contained);
2904 pt = Vector3::InvRotate(pt, box.
rotation);
2905 return Vector3::InBound(pt, box.
extent);
2914 SimdVector pt0 = F128::Sub(triangle_point0, center);
2915 SimdVector pt1 = F128::Sub(triangle_point1, center);
2916 SimdVector pt2 = F128::Sub(triangle_point2, center);
2918 pt0 = Vector3::InvRotate(pt0, rot);
2919 pt1 = Vector3::InvRotate(pt1, rot);
2920 pt2 = Vector3::InvRotate(pt2, rot);
2921 pt0 = F128::Abs(pt0);
2922 pt1 = F128::Abs(pt1);
2923 pt2 = F128::Abs(pt2);
2925 pt_absmax = F128::Max(pt_absmax, pt2);
2926 return Vector3::CmpLe(pt_absmax, box.
extent);
2931 NLIB_B Containment::OrientedBoxAxisAlignedBox(
const OrientedBox& box,
2936 SimdVector aabb_center = F128::Add(aabb_min, aabb_max);
2937 aabb_center = F128::Mult(0.5f, aabb_center);
2938 new_aabb.
extent = F128::Sub(aabb_max, aabb_center);
2939 aabb_center = F128::Sub(aabb_center, box.
center);
2940 new_aabb.
center = aabb_center;
2947 return Containment::AxisAlignedBoxOrientedBox(new_box, new_aabb);
2952 NLIB_B Containment::OrientedBoxOrientedBox(
const OrientedBox& box,
2958 contained_obb.
center = Vector3::Rotate(F128::Sub(contained.
center, box.
center), inv_rot);
2965 return Containment::AxisAlignedBoxOrientedBox(aabb, contained_obb);
2974 aabb.
point_min = F128::Negate(box_extent);
2977 new_sphere = F128::Permute<0, 1, 2, 7>(new_sphere, sphere);
2979 return Containment::AxisAlignedBoxSphere(aabb, new_sphere);
2982 NLIB_B Containment::OrientedBoxFrustum(
const OrientedBox& box,
2985 frustum.
Transform(&frstm, 1.f, F128::Set0001(), F128::Negate(box.
center));
2986 frstm.
Transform(&frstm, 1.f, Quaternion::Conjugate(box.
rotation), F128::SetZero());
2990 return Containment::AxisAlignedBoxFrustum(aabb, frstm);
2997 f128 dot, dot1, dot2;
2998 SimdPlane near_plane = frustum.near_plane_;
2999 SimdPlane far_plane = frustum.far_plane_;
3000 SimdPlane top_plane = frustum.top_plane_;
3001 SimdPlane bottom_plane = frustum.bottom_plane_;
3002 SimdPlane left_plane = frustum.left_plane_;
3003 SimdPlane right_plane = frustum.right_plane_;
3007 pt = F128::Sub(triangle_point0, center);
3008 pt = Vector3::InvRotate(pt, rot);
3009 pt = F128::SetFloatToLane<3>(pt, 1.f);
3010 dot1 = Vector4::Dot4(pt, near_plane, far_plane, top_plane, bottom_plane);
3011 dot2 = Vector4::Dot2(pt, left_plane, right_plane);
3012 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3013 dot = F128::Max(dot1, dot2);
3015 pt = F128::Sub(triangle_point1, center);
3016 pt = Vector3::InvRotate(pt, rot);
3017 pt = F128::SetFloatToLane<3>(pt, 1.f);
3018 dot1 = Vector4::Dot4(pt, near_plane, far_plane, top_plane, bottom_plane);
3019 dot2 = Vector4::Dot2(pt, left_plane, right_plane);
3020 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3021 dot = F128::Max(dot, F128::Max(dot1, dot2));
3023 pt = F128::Sub(triangle_point2, center);
3024 pt = Vector3::InvRotate(pt, rot);
3025 pt = F128::SetFloatToLane<3>(pt, 1.f);
3026 dot1 = Vector4::Dot4(pt, near_plane, far_plane, top_plane, bottom_plane);
3027 dot2 = Vector4::Dot2(pt, left_plane, right_plane);
3028 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3029 dot = F128::Max(dot, F128::Max(dot1, dot2));
3031 f128 outside = F128::CmpGt(dot, F128::SetZero());
3032 return F128::IsAllMaskFalse(outside);
3037 dot = F128::Negate(dot);
3039 SimdVector pt = F128::Sub(sphere, frustum.center_);
3040 pt = Vector3::InvRotate(pt, frustum.rotation_);
3041 pt = F128::SetFloatToLane<3>(pt, 1.f);
3043 f128 dot1 = Vector4::Dot4(pt, frustum.near_plane_, frustum.far_plane_, frustum.top_plane_,
3044 frustum.bottom_plane_);
3045 f128 dot2 = Vector4::Dot2(pt, frustum.left_plane_, frustum.right_plane_);
3046 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3047 dot1 = F128::Max(dot1, dot2);
3048 f128 outside = F128::CmpGt(dot1, dot);
3049 return F128::IsAllMaskFalse(outside);
3052 NLIB_B Containment::FrustumAxisAlignedBox(
const Frustum& frustum,
3056 SimdVector center = F128::Mult(0.5f, F128::Add(pt_min, pt_max));
3057 center = F128::SetFloatToLane<3>(center, 1.f);
3058 SimdVector extent_neg = F128::Sub(center, pt_max);
3059 extent_neg = F128::SetZeroToLane<3>(extent_neg);
3069 tmp = frustum.near_plane_;
3070 N = Vector3::Rotate(tmp, rot);
3071 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3072 SimdPlane near_plane = F128::Permute<0, 1, 2, 7>(N, D);
3074 tmp = frustum.far_plane_;
3075 N = Vector3::Rotate(tmp, rot);
3076 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3077 SimdPlane far_plane = F128::Permute<0, 1, 2, 7>(N, D);
3079 tmp = frustum.right_plane_;
3080 N = Vector3::Rotate(tmp, rot);
3081 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3082 SimdPlane right_plane = F128::Permute<0, 1, 2, 7>(N, D);
3084 tmp = frustum.left_plane_;
3085 N = Vector3::Rotate(tmp, rot);
3086 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3087 SimdPlane left_plane = F128::Permute<0, 1, 2, 7>(N, D);
3089 tmp = frustum.top_plane_;
3090 N = Vector3::Rotate(tmp, rot);
3091 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3092 SimdPlane top_plane = F128::Permute<0, 1, 2, 7>(N, D);
3094 tmp = frustum.bottom_plane_;
3095 N = Vector3::Rotate(tmp, rot);
3096 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3097 SimdPlane bottom_plane = F128::Permute<0, 1, 2, 7>(N, D);
3101 f128 all_points_inside;
3104 dist = Vector4::Dot4(center, near_plane, far_plane, right_plane, left_plane);
3106 radius_neg = Vector4::Dot4(extent_neg, F128::Abs(near_plane), F128::Abs(far_plane),
3107 F128::Abs(right_plane), F128::Abs(left_plane));
3109 all_points_inside = F128::CmpLe(dist, radius_neg);
3111 dist = Vector4::Dot2(center, top_plane, bottom_plane);
3112 radius_neg = Vector4::Dot2(extent_neg, F128::Abs(top_plane), F128::Abs(bottom_plane));
3114 F128::And(all_points_inside, F128::Swizzle<0, 1, 0, 1>(F128::CmpLe(dist, radius_neg)));
3116 return F128::IsAllMaskTrue(all_points_inside);
3119 NLIB_B Containment::FrustumOrientedBox(
const Frustum& frustum,
3123 frustum.
Transform(&frstm, 1.f, F128::Set0001(), F128::Negate(box.
center));
3125 frstm.
Transform(&frstm, 1.f, Quaternion::Conjugate(box.
rotation), F128::SetZero());
3130 return Containment::FrustumAxisAlignedBox(frstm, aabb);
3136 for (
size_t i = 0; i < 8; ++i) {
3137 SimdVector pt = Vector3::LoadFloat3(&corners[i]);
3138 if (!Containment::FrustumPoint(frustum, pt))
return false;
3144 # pragma endregion Containment function implementation 3150 #endif // NLIB_DOXYGEN 3155 #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...