16 #ifndef INCLUDE_NN_NLIB_SIMD_SIMDGEOMETRY_H_ 17 #define INCLUDE_NN_NLIB_SIMD_SIMDGEOMETRY_H_ 109 Capsule(
const Float3& pt0,
const Float3& pt1,
float radius)
NLIB_NOEXCEPT;
110 void __vectorcall Transform(Capsule* capsule, SimdMatrixArg m)
NLIB_NOEXCEPT;
164 static f128 __vectorcall SegmentSegment(
SimdVector* point_on_segment0,
211 static bool __vectorcall SphereRay(
float* distance,
SimdSphereArg sphere,
218 static bool __vectorcall TriangleRay(
float* distance,
SimdVectorArg triangle_point0,
222 static PlaneResult __vectorcall TrianglePlane(
SimdVectorArg triangle_point0,
226 static PlaneResult __vectorcall SpherePlane(
SimdSphereArg sphere,
235 static PlaneResult __vectorcall AxisAlignedBoxPlane(
239 static bool __vectorcall AxisAlignedBoxSphere(
const AxisAlignedBox& aabb,
241 static bool __vectorcall AxisAlignedBoxAxisAlignedBox(
243 static bool __vectorcall AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
248 static bool __vectorcall OrientedBoxSphere(
const OrientedBox& box,
250 static bool __vectorcall OrientedBoxAxisAlignedBox(
const OrientedBox& box,
252 static bool __vectorcall OrientedBoxOrientedBox(
const OrientedBox& box0,
254 static bool __vectorcall OrientedBoxTriangle(
const OrientedBox& box,
258 static PlaneResult __vectorcall OrientedBoxPlane(
const OrientedBox& box,
263 static bool __vectorcall FrustumSphere(
const Frustum& frustum,
265 static bool __vectorcall FrustumAxisAlignedBox(
const Frustum& frustum,
267 static bool __vectorcall FrustumOrientedBox(
const Frustum& frustum,
272 static PlaneResult __vectorcall FrustumPlane(
const Frustum& frustum,
293 static bool __vectorcall SphereOrientedBox(
SimdSphereArg sphere,
295 static bool __vectorcall SphereAxisAlignedBox(
SimdSphereArg sphere,
303 static bool __vectorcall AxisAlignedBoxPoint(
const AxisAlignedBox& aabb,
305 static bool __vectorcall AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
309 static bool __vectorcall AxisAlignedBoxOrientedBox(
const AxisAlignedBox& aabb,
311 static bool __vectorcall AxisAlignedBoxAxisAlignedBox(
313 static bool __vectorcall AxisAlignedBoxSphere(
const AxisAlignedBox& aabb,
315 static bool __vectorcall AxisAlignedBoxFrustum(
const AxisAlignedBox& aabb,
319 static bool __vectorcall OrientedBoxPoint(
const OrientedBox& box,
321 static bool __vectorcall OrientedBoxTriangle(
const OrientedBox& box,
325 static bool __vectorcall OrientedBoxOrientedBox(
const OrientedBox& box,
327 static bool __vectorcall OrientedBoxAxisAlignedBox(
const OrientedBox& box,
329 static bool __vectorcall OrientedBoxSphere(
const OrientedBox& box,
331 static bool __vectorcall OrientedBoxFrustum(
const OrientedBox& box,
335 static bool __vectorcall FrustumPoint(
const Frustum& frustum,
340 static bool __vectorcall FrustumSphere(
const Frustum& frustum,
342 static bool __vectorcall FrustumAxisAlignedBox(
const Frustum& frustum,
344 static bool __vectorcall FrustumOrientedBox(
const Frustum& frustum,
346 static bool __vectorcall FrustumFrustum(
const Frustum& frustum,
355 #define NLIB_M(tp) inline tp __vectorcall 356 #define NLIB_B inline bool __vectorcall 366 return Vector4::Dot(plane, vec);
371 return Vector4::Dot(plane, F128::SetFloatToLane<3>(vec, 1.f));
376 return Vector3::Dot(plane, vec);
382 f128 dot = Vector3::Dot(point, normal);
383 dot = F128::Negate(dot);
384 return F128::Splat<false, false, false, true>(normal, dot);
392 SimdVector normal = Vector3::Normalize(Vector3::Cross(v10, v20));
393 return FromPointAndNormal(point0, normal);
399 return F128::Mult(Vector3::RecpLength(plane), plane);
404 return F128::Mult(Vector3::RecpLengthEst(plane), plane);
409 return Vector4::Transform(plane, m);
412 #pragma endregion Plane function implementation 419 #pragma region Sphere 424 SimdVector center = Vector3::Transform(sphere, m);
425 f128 dot_x = Vector3::Dot(m.r[0], m.r[0]);
426 f128 dot_y = Vector3::Dot(m.r[1], m.r[1]);
427 f128 dot_z = Vector3::Dot(m.r[2], m.r[2]);
428 f128 scale = F128::Max(dot_x, dot_y);
429 scale = F128::Max(scale, dot_z);
430 radius = F128::Mult(radius, scale);
432 return F128::Splat<false, false, false, true>(center, radius);
438 f128 min_x, min_y, min_z;
439 f128 max_x, max_y, max_z;
440 min_x = min_y = min_z = max_x = max_y = max_z = Vector3::LoadFloat3(points);
443 for (i = 1; i < count; ++i) {
445 f128 pt = Vector3::LoadFloat3(points + i);
448 cmp0 = F128::CmpLt(pt_x, F128::SetValue<0>(min_x,
each_select32));
449 min_x = F128::Select(cmp0, pt, min_x);
450 cmp1 = F128::CmpGt(pt_x, F128::SetValue<0>(max_x,
each_select32));
451 max_x = F128::Select(cmp1, pt, max_x);
454 cmp0 = F128::CmpLt(pt_y, F128::SetValue<0>(min_y,
each_select32));
455 min_y = F128::Select(cmp0, pt, min_y);
456 cmp1 = F128::CmpGt(pt_y, F128::SetValue<0>(max_y,
each_select32));
457 max_y = F128::Select(cmp1, pt, max_y);
460 cmp0 = F128::CmpLt(pt_z, F128::SetValue<0>(min_z,
each_select32));
461 min_z = F128::Select(cmp0, pt, min_z);
462 cmp1 = F128::CmpGt(pt_z, F128::SetValue<0>(max_z,
each_select32));
463 max_z = F128::Select(cmp1, pt, max_z);
470 f128 distsq_x = Vector3::LengthSq(F128::Sub(max_x, min_x));
471 f128 distsq_y = Vector3::LengthSq(F128::Sub(max_y, min_y));
472 f128 distsq_z = Vector3::LengthSq(F128::Sub(max_z, min_z));
473 if (Vector4::CmpGt(distsq_x, distsq_y)) {
474 if (Vector4::CmpGt(distsq_x, distsq_z)) {
475 center = F128::Lerp(min_x, max_x, c1_2);
476 radius = F128::Mult(F128::Sqrt(distsq_x), c1_2);
478 center = F128::Lerp(min_z, max_z, c1_2);
479 radius = F128::Mult(F128::Sqrt(distsq_z), c1_2);
482 if (Vector4::CmpGt(distsq_y, distsq_z)) {
483 center = F128::Lerp(min_y, max_y, c1_2);
484 radius = F128::Mult(F128::Sqrt(distsq_y), c1_2);
486 center = F128::Lerp(min_z, max_z, c1_2);
487 radius = F128::Mult(F128::Sqrt(distsq_z), c1_2);
492 f128 radsq = F128::Mult(radius, radius);
493 for (i = 0; i < count; ++i) {
494 f128 pt = Vector3::LoadFloat3(points + i);
495 f128 diff = F128::Sub(pt, center);
496 f128 distsq = Vector3::LengthSq(diff);
497 if (Vector3::CmpGt(distsq, radsq)) {
498 f128 dist = F128::Sqrt(distsq);
499 f128 t = F128::Div(radius, dist);
500 t = F128::MultSub(c1_2, t, c1_2);
501 radius = F128::Mult(c1_2, F128::Add(radius, dist));
502 radsq = F128::Mult(radius, radius);
503 center = F128::MultAdd(t, diff, center);
507 return F128::Splat<false, false, false, true>(center, radius);
512 SimdVector diff = F128::Sub(sphere1, sphere0);
513 f128 dist_sq = Vector3::LengthSq(diff);
515 f128 is_contained = F128::CmpLe(dist_sq, radius_diff_sq);
517 f128 dist = F128::Sqrt(dist_sq);
520 f128 new_radius = F128::Add(r0, r1);
521 new_radius = F128::Add(new_radius, dist);
522 new_radius = F128::Mult(0.5f, new_radius);
524 f128 t = F128::Div(diff, dist);
525 f128 use_new_center = F128::CmpGt(dist, F128::SetEpsilon());
528 ret = F128::MultAdd(t, F128::Sub(new_radius, r0), sphere0);
529 ret = F128::Select(use_new_center, ret, sphere0);
530 ret = F128::Splat<false, false, false, true>(ret, new_radius);
532 f128 s0_contained = F128::And(is_contained, F128::CmpLt(r0, r1));
533 f128 s1_contained = F128::And(is_contained, F128::CmpGe(r0, r1));
534 ret = F128::Select(s0_contained, sphere1, ret);
535 ret = F128::Select(s1_contained, sphere0, ret);
540 return F128::GetFloatFromLane<3>(sphere);
544 return F128::SetFloatToLane<3>(sphere, radius);
552 return F128::Permute<4, 5, 6, 3>(sphere, center);
555 #pragma endregion Sphere function implementation 562 #pragma region AxisAlignedBox 564 inline AxisAlignedBox::AxisAlignedBox(
const Float3& pmin,
const Float3& pmax) {
565 Vector3::LoadFloat3(&pmin);
566 Vector3::LoadFloat3(&pmax);
570 inline void AxisAlignedBox::GetCorners(Float3* corners)
const NLIB_NOEXCEPT {
572 f128 p1 = F128::Splat<true, false, false, false>(point_min, point_max);
573 f128 p2 = F128::Splat<true, true, false, false>(point_min, point_max);
574 f128 p3 = F128::Splat<false, true, false, false>(point_min, point_max);
575 f128 p4 = F128::Splat<false, true, true, true>(point_min, point_max);
576 f128 p5 = F128::Splat<false, false, true, true>(point_min, point_max);
577 f128 p6 = F128::Splat<true, false, true, true>(point_min, point_max);
580 Vector3::StoreFloat3(corners + 0, p0);
581 Vector3::StoreFloat3(corners + 1, p1);
582 Vector3::StoreFloat3(corners + 2, p2);
583 Vector3::StoreFloat3(corners + 3, p3);
584 Vector3::StoreFloat3(corners + 4, p4);
585 Vector3::StoreFloat3(corners + 5, p5);
586 Vector3::StoreFloat3(corners + 6, p6);
587 Vector3::StoreFloat3(corners + 7, p7);
591 inline void __vectorcall AxisAlignedBox::Transform(AxisAlignedBox* box,
594 f128 p1 = F128::Splat<true, false, false, false>(point_min, point_max);
595 f128 p2 = F128::Splat<true, true, false, false>(point_min, point_max);
596 f128 p3 = F128::Splat<false, true, false, false>(point_min, point_max);
597 f128 p4 = F128::Splat<false, true, true, true>(point_min, point_max);
598 f128 p5 = F128::Splat<false, false, true, true>(point_min, point_max);
599 f128 p6 = F128::Splat<true, false, true, true>(point_min, point_max);
602 p0 = Vector3::Transform(p0, m);
603 p1 = Vector3::Transform(p1, m);
604 p2 = Vector3::Transform(p2, m);
605 p3 = Vector3::Transform(p3, m);
606 p4 = Vector3::Transform(p4, m);
607 p5 = Vector3::Transform(p5, m);
608 p6 = Vector3::Transform(p6, m);
609 p7 = Vector3::Transform(p7, m);
612 pmin = F128::Min(p0, p1);
613 pmax = F128::Max(p0, p1);
614 pmin = F128::Min(pmin, p2);
615 pmax = F128::Max(pmax, p2);
616 pmin = F128::Min(pmin, p3);
617 pmax = F128::Max(pmax, p3);
618 pmin = F128::Min(pmin, p4);
619 pmax = F128::Max(pmax, p4);
620 pmin = F128::Min(pmin, p5);
621 pmax = F128::Max(pmax, p5);
622 pmin = F128::Min(pmin, p6);
623 pmax = F128::Max(pmax, p6);
624 pmin = F128::Min(pmin, p7);
625 pmax = F128::Max(pmax, p7);
626 box->point_min = pmin;
627 box->point_max = pmax;
631 inline void AxisAlignedBox::Merge(AxisAlignedBox* box,
const AxisAlignedBox& box0,
633 box->point_min = F128::Min(box0.point_min, box1.point_min);
634 box->point_max = F128::Max(box0.point_max, box1.point_max);
638 inline void __vectorcall AxisAlignedBox::FromSphere(AxisAlignedBox* box,
641 box->point_min = F128::Sub(sphere, r);
642 box->point_max = F128::Add(sphere, r);
646 inline void __vectorcall AxisAlignedBox::FromPoints(AxisAlignedBox* box,
SimdVectorArg point0,
648 box->point_min = F128::Min(point0, point1);
649 box->point_max = F128::Max(point0, point1);
654 AxisAlignedBox::FromPoints(AxisAlignedBox* box,
const Float3* points,
size_t count)
NLIB_NOEXCEPT {
656 pmin = pmax = Vector3::LoadFloat3(points);
657 for (
size_t i = 1; i < count; ++i) {
658 f128 pt = Vector3::LoadFloat3(points + i);
659 pmin = F128::Min(pmin, pt);
660 pmax = F128::Max(pmax, pt);
662 box->point_min = pmin;
663 box->point_max = pmax;
666 #pragma endregion AxisAlignedBox function implementation 673 #pragma region OrientedBox 677 inline void __vectorcall OrientedBox::Transform(OrientedBox* box, SimdMatrixArg m)
NLIB_NOEXCEPT {
678 box->center = Vector3::Transform(this->center, m);
679 f128 inv_dx = Vector3::RecpLength(m.r[0]);
680 f128 inv_dy = Vector3::RecpLength(m.r[1]);
681 f128 inv_dz = Vector3::RecpLength(m.r[2]);
684 SimdMatrix rot_matrix;
685 rot_matrix.r[0] = F128::Mult(m.r[0], inv_dx);
686 rot_matrix.r[1] = F128::Mult(m.r[1], inv_dy);
687 rot_matrix.r[2] = F128::Mult(m.r[2], inv_dz);
688 rot_matrix.r[3] = F128::Set0001();
690 box->rotation = Quaternion::Mult(this->rotation, rot);
694 scale = F128::Permute<0, 4, -1, -1>(inv_dx, inv_dy);
695 scale = F128::Permute<0, 1, 4, -1>(scale, inv_dz);
696 box->extent = F128::Div(this->extent, scale);
700 inline void OrientedBox::GetCorners(Float3* corners)
const NLIB_NOEXCEPT {
701 f128 point_max = F128::Add(center, extent);
702 f128 point_min = F128::Sub(center, extent);
703 point_max = F128::SetZeroToLane<3>(point_max);
704 point_min = F128::SetZeroToLane<3>(point_min);
708 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
709 Vector3::StoreFloat3(corners + 0, pt);
711 pt = F128::Splat<true, false, false, false>(point_min, point_max);
712 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
713 Vector3::StoreFloat3(corners + 1, pt);
715 pt = F128::Splat<true, true, false, false>(point_min, point_max);
716 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
717 Vector3::StoreFloat3(corners + 2, pt);
719 pt = F128::Splat<false, true, false, false>(point_min, point_max);
720 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
721 Vector3::StoreFloat3(corners + 3, pt);
723 pt = F128::Splat<false, true, true, true>(point_min, point_max);
724 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
725 Vector3::StoreFloat3(corners + 4, pt);
727 pt = F128::Splat<false, false, true, true>(point_min, point_max);
728 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
729 Vector3::StoreFloat3(corners + 5, pt);
731 pt = F128::Splat<true, false, true, true>(point_min, point_max);
732 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
733 Vector3::StoreFloat3(corners + 6, pt);
736 pt = F128::Add(center, Vector3::Rotate(pt, rotation));
737 Vector3::StoreFloat3(corners + 7, pt);
742 OrientedBox::FromAxisAlignedBox(OrientedBox* box,
const AxisAlignedBox& aabb)
NLIB_NOEXCEPT {
744 f128 half = F128::Mult(c1_2, aabb.point_max);
745 box->rotation = F128::Set0001();
747 box->center = F128::MultAdd(c1_2, box_min, half);
748 box->extent = F128::MultSub(c1_2, box_min, half);
752 #pragma endregion OrientedBox function implementation 759 #pragma region Capsule 761 inline Capsule::Capsule(
const Float3& pt0,
const Float3& pt1,
float radius)
NLIB_NOEXCEPT {
762 f128 sphere_ = Vector3::LoadFloat3(&pt0);
763 point = Vector3::LoadFloat3(&pt1);
764 sphere = F128::SetFloatToLane<3>(sphere_, radius);
767 inline void __vectorcall Capsule::Transform(Capsule* capsule, SimdMatrixArg m)
NLIB_NOEXCEPT {
768 capsule->sphere = Sphere::Transform(sphere, m);
769 capsule->point = Vector3::Transform(point, m);
772 #pragma endregion Capsule function implementation 779 #pragma region Frustum 782 inline Frustum::Frustum(
const Frustum& rhs)
NLIB_NOEXCEPT : center_(rhs.center_),
783 rotation_(rhs.rotation_),
784 near_plane_(rhs.near_plane_),
785 far_plane_(rhs.far_plane_),
786 top_plane_(rhs.top_plane_),
787 bottom_plane_(rhs.bottom_plane_),
788 left_plane_(rhs.left_plane_),
789 right_plane_(rhs.right_plane_) {}
791 inline Frustum& Frustum::operator=(
const Frustum& rhs)
NLIB_NOEXCEPT {
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_);
847 inline void __vectorcall Frustum::Transform(Frustum* frustum, SimdMatrixArg m)
const NLIB_NOEXCEPT {
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_);
882 inline void Frustum::GetCorners(Float3* corners)
const NLIB_NOEXCEPT {
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_);
892 float right = F128::GetFloatFromLane<2>(right_plane_) / F128::GetFloatFromLane<0>(right_plane_);
900 pt = F128::SetValue(left, top, -n, 0.f);
901 pt = F128::Add(Vector3::Rotate(pt, rot), center);
902 Vector3::StoreFloat3(corners + 0, pt);
905 pt = F128::SetValue(right, top, -n, 0.f);
906 pt = F128::Add(Vector3::Rotate(pt, rot), center);
907 Vector3::StoreFloat3(corners + 1, pt);
910 pt = F128::SetValue(right, bottom, -n, 0.f);
911 pt = F128::Add(Vector3::Rotate(pt, rot), center);
912 Vector3::StoreFloat3(corners + 2, pt);
915 pt = F128::SetValue(left, bottom, -n, 0.f);
916 pt = F128::Add(Vector3::Rotate(pt, rot), center);
917 Vector3::StoreFloat3(corners + 3, pt);
922 pt = F128::SetValue(left * f_n, top * f_n, -f, 0.f);
923 pt = F128::Add(Vector3::Rotate(pt, rot), center);
924 Vector3::StoreFloat3(corners + 4, pt);
927 pt = F128::SetValue(right * f_n, top * f_n, -f, 0.f);
928 pt = F128::Add(Vector3::Rotate(pt, rot), center);
929 Vector3::StoreFloat3(corners + 5, pt);
932 pt = F128::SetValue(right * f_n, bottom * f_n, -f, 0.f);
933 pt = F128::Add(Vector3::Rotate(pt, rot), center);
934 Vector3::StoreFloat3(corners + 6, pt);
937 pt = F128::SetValue(left * f_n, bottom * f_n, -f, 0.f);
938 pt = F128::Add(Vector3::Rotate(pt, rot), center);
939 Vector3::StoreFloat3(corners + 7, pt);
943 #pragma endregion Frustum function implementation 950 #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);
965 SimdVector l0_pt = F128::Sub(point, ray_point);
966 f128 dot = Vector3::Dot(l0_pt, ray_dir_normalized);
967 SimdVector dist_vec = F128::Mult(ray_dir_normalized, dot);
968 dist_vec = F128::Sub(l0_pt, dist_vec);
970 f128 distsq0 = Vector3::LengthSq(dist_vec);
971 f128 distsq1 = Vector3::LengthSq(l0_pt);
972 f128 cmp = F128::CmpLt(dot, F128::SetZero());
973 return F128::Select(cmp, distsq1, distsq0);
979 SimdVector l0_pt = F128::Sub(point, segment_point0);
980 SimdVector l1_pt = F128::Sub(point, segment_point1);
981 SimdVector seg_dir_normalized = F128::Sub(segment_point1, segment_point0);
982 f128 seg_recplen = Vector3::RecpLength(seg_dir_normalized);
983 seg_dir_normalized = F128::Mult(seg_dir_normalized, seg_recplen);
985 f128 dot = Vector3::Dot(l0_pt, seg_dir_normalized);
986 SimdVector dist_vec = F128::Mult(seg_dir_normalized, dot);
987 dist_vec = F128::Sub(l0_pt, dist_vec);
989 f128 distsq0 = Vector3::LengthSq(dist_vec);
990 f128 distsq1 = Vector3::LengthSq(l0_pt);
991 f128 distsq2 = Vector3::LengthSq(l1_pt);
992 f128 cmp = F128::CmpLt(dot, F128::SetZero());
993 f128 ret = F128::Select(cmp, distsq1, distsq0);
994 cmp = F128::CmpLt(F128::Mult(dot, seg_recplen), F128::SetOne());
995 ret = F128::Select(cmp, ret, distsq2);
1003 SimdVector pt = F128::SetZeroToLane<3>(point);
1004 f128 dot = Vector4::Dot(pt, plane_normalized);
1005 f128 ret = F128::Mult(dot, dot);
1006 if (point_on_plane) {
1007 *point_on_plane = F128::Sub(point, F128::Mult(dot, plane_normalized));
1014 SimdVector c = F128::SetZeroToLane<3>(sphere);
1016 f128 dist = F128::Abs(Vector4::Dot(c, plane_normalized));
1017 f128 cmp = F128::CmpGt(dist, r);
1018 f128 ret = F128::Sub(dist, r);
1019 ret = F128::Mult(ret, ret);
1020 return F128::And(cmp, ret);
1027 f128 vv = F128::Clamp(point, aabb.point_min, aabb.point_max);
1028 f128 distsq = F128::Sub(vv, point);
1029 distsq = Vector3::LengthSq(distsq);
1030 if (point_on_box) *point_on_box = vv;
1040 u = F128::Sub(line0_point, line1_point);
1041 f128 b = Vector3::Dot(line0_dir_normalized, line1_dir_normalized);
1042 f128 d = Vector3::Dot(line0_dir_normalized, u);
1043 f128 e = Vector3::Dot(line1_dir_normalized, u);
1044 f128 det = F128::MultSub(b, b, F128::SetOne());
1046 f128 recp_det = F128::Recp(det);
1047 f128 s = F128::MultAdd(b, e, F128::Negate(d));
1048 f128 t = F128::MultSub(b, d, e);
1049 s = F128::Mult(s, recp_det);
1050 t = F128::Mult(t, recp_det);
1052 SimdVector tmp = F128::Mult(s, line0_dir_normalized);
1053 tmp = F128::MultSub(t, line1_dir_normalized, tmp);
1055 ret = Vector3::LengthSq(ret);
1057 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1058 tmp = Vector3::LengthSq(F128::MultSub(e, line1_dir_normalized, u));
1059 ret = F128::Select(parallel, tmp, ret);
1061 if (point_on_line0) {
1062 s = F128::AndNot(parallel, s);
1063 *point_on_line0 = F128::MultAdd(s, line0_dir_normalized, line0_point);
1065 if (point_on_line1) {
1066 t = F128::Select(parallel, e, t);
1067 *point_on_line1 = F128::MultAdd(t, line1_dir_normalized, line1_point);
1079 SimdVector u = F128::Sub(segment0_point1, segment0_point0);
1080 SimdVector v = F128::Sub(segment1_point1, segment1_point0);
1081 SimdVector w = F128::Sub(segment0_point0, segment1_point0);
1082 f128 a = Vector3::LengthSq(u);
1083 f128 b = Vector3::Dot(u, v);
1084 f128 c = Vector3::LengthSq(v);
1085 f128 d = Vector3::Dot(u, w);
1086 f128 e = Vector3::Dot(v, w);
1087 f128 D = F128::MultSub(b, b, F128::Mult(a, c));
1089 f128 epsilon = F128::SetEpsilon();
1092 f128 sN = F128::MultSub(c, d, F128::Mult(b, e));
1093 f128 tN = F128::MultSub(b, d, F128::Mult(a, e));
1096 f128 parallel = F128::CmpLt(D, epsilon);
1097 f128 sN_under = F128::CmpLtZero(sN);
1098 f128 sN_out = F128::Or(sN_under, F128::CmpGt(sN, D));
1099 f128 cmp = F128::Or(parallel, sN_out);
1100 f128 under_or_parallel = F128::Or(parallel, sN_under);
1107 sN = F128::Select(cmp, F128::AndNot(under_or_parallel, D), sN);
1114 tN = F128::Select(cmp, F128::Select(under_or_parallel, e, F128::Add(e, b)), tN);
1121 tD = F128::Select(cmp, c, D);
1125 sD = F128::Select(parallel, F128::SetOne(), D);
1129 f128 tN_under = F128::CmpLtZero(tN);
1130 f128 tN_out = F128::Or(tN_under, F128::CmpGt(tN, tD));
1136 tN = F128::Clamp(tN, F128::SetZero(), tD);
1138 f128 val = F128::Select(tN_under, F128::Negate(d), F128::Sub(b, d));
1144 f128 val_in = F128::And(F128::CmpGeZero(val), F128::CmpLe(val, a));
1145 sD = F128::Select(F128::And(tN_out, val_in), a, sD);
1153 f128 sntmp = F128::AndNot(F128::CmpLtZero(val), val);
1154 sntmp = F128::Select(F128::CmpGt(val, a), sD, sntmp);
1155 sN = F128::Select(tN_out, sntmp, sN);
1158 f128 sc = F128::AndNot(F128::InBound(sN, epsilon), F128::Div(sN, sD));
1159 f128 tc = F128::AndNot(F128::InBound(tN, epsilon), F128::Div(tN, tD));
1162 f128 pt_s0 = F128::MultAdd(sc, u, segment0_point0);
1163 f128 pt_s1 = F128::MultAdd(tc, v, segment1_point0);
1164 f128 ret = F128::Sub(pt_s0, pt_s1);
1165 ret = Vector3::LengthSq(ret);
1167 if (point_on_segment0) *point_on_segment0 = pt_s0;
1168 if (point_on_segment1) *point_on_segment1 = pt_s1;
1177 SimdVector u = F128::Sub(line_point, ray_point);
1178 f128 b = Vector3::Dot(line_dir_normalized, ray_dir_normalized);
1179 f128 d = Vector3::Dot(line_dir_normalized, u);
1180 f128 e = Vector3::Dot(ray_dir_normalized, u);
1181 f128 one = F128::SetOne();
1182 f128 det = F128::MultSub(b, b, one);
1183 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1188 f128 t_num = F128::MultSub(b, d, e);
1189 t_num = F128::Select(parallel, e, t_num);
1190 f128 t_num_negative = F128::CmpLtZero(t_num);
1195 f128 minus_d = F128::Negate(d);
1196 f128 s_num = F128::MultAdd(b, e, minus_d);
1197 s_num = F128::AndNot(parallel, s_num);
1202 f128 t_denom = F128::Select(parallel, one, det);
1207 f128 s_denom = F128::Select(F128::Or(t_num_negative, parallel), one, det);
1212 s_num = F128::Select(t_num_negative, minus_d, s_num);
1217 t_num = F128::AndNot(t_num_negative, t_num);
1219 f128 s = F128::Div(s_num, s_denom);
1220 f128 t = F128::Div(t_num, t_denom);
1222 f128 pt_l = F128::MultAdd(s, line_dir_normalized, line_point);
1223 f128 pt_r = F128::MultAdd(t, ray_dir_normalized, ray_point);
1225 ret = Vector3::LengthSq(ret);
1227 if (point_on_line) *point_on_line = pt_l;
1228 if (point_on_ray) *point_on_ray = pt_r;
1237 SimdVector seg_dir = F128::Sub(segment_point1, segment_point0);
1238 SimdVector u = F128::Sub(line_point, segment_point0);
1239 f128 b = Vector3::Dot(line_dir_normalized, seg_dir);
1240 f128 c = Vector3::LengthSq(seg_dir);
1241 f128 d = Vector3::Dot(line_dir_normalized, u);
1242 f128 e = Vector3::Dot(seg_dir, u);
1243 f128 det = F128::MultSub(b, b, c);
1244 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1249 f128 t_num = F128::Select(parallel, e, F128::MultSub(b, d, e));
1254 f128 t_denom = F128::Select(parallel, c, det);
1259 f128 tmp = F128::Mult(b, e);
1260 tmp = F128::MultSub(c, d, tmp);
1261 f128 s_num = F128::AndNot(parallel, tmp);
1267 f128 tNum_under = F128::CmpLtZero(t_num);
1268 f128 tNum_out = F128::Or(tNum_under, F128::CmpGt(t_num, t_denom));
1269 tmp = F128::Select(tNum_under, F128::Negate(d), F128::Sub(b, d));
1270 s_num = F128::Select(tNum_out, tmp, s_num);
1275 f128 s_denom = F128::Select(F128::Or(tNum_out, parallel), F128::SetOne(), det);
1280 t_num = F128::Clamp(t_num, F128::SetZero(), t_denom);
1282 f128 s = F128::Div(s_num, s_denom);
1283 f128 t = F128::Div(t_num, t_denom);
1285 f128 pt_l = F128::MultAdd(s, line_dir_normalized, line_point);
1286 f128 pt_s = F128::MultAdd(t, seg_dir, segment_point0);
1288 ret = Vector3::LengthSq(ret);
1290 if (point_on_line) *point_on_line = pt_l;
1291 if (point_on_segment) *point_on_segment = pt_s;
1300 SimdVector u = F128::Sub(ray0_point, ray1_point);
1301 f128 b = Vector3::Dot(ray0_dir_normalized, ray1_dir_normalized);
1302 f128 d = Vector3::Dot(ray0_dir_normalized, u);
1303 f128 e = Vector3::Dot(ray1_dir_normalized, u);
1304 f128 one = F128::SetOne();
1305 f128 det = F128::MultSub(b, b, one);
1306 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1311 f128 minus_d = F128::Negate(d);
1312 f128 s_num = F128::AndNot(parallel, F128::MultAdd(b, e, minus_d));
1313 f128 s_num_negative = F128::CmpLtZero(s_num);
1314 f128 parallel_or_sNum_negative = F128::Or(parallel, s_num_negative);
1319 f128 t_num = F128::Select(parallel_or_sNum_negative, e, F128::MultSub(b, d, e));
1324 f128 t_denom = F128::Select(parallel_or_sNum_negative, one, det);
1329 s_num = F128::AndNot(s_num_negative, s_num);
1335 f128 t_num_negative = F128::CmpLtZero(t_num);
1336 f128 d_negative = F128::CmpLeZero(d);
1337 f128 tmp = F128::And(d_negative, minus_d);
1338 s_num = F128::Select(t_num_negative, tmp, s_num);
1343 tmp = F128::Or(parallel, F128::And(t_num_negative, d_negative));
1344 f128 s_denom = F128::Select(tmp, one, det);
1349 t_num = F128::AndNot(t_num_negative, t_num);
1351 f128 s = F128::Div(s_num, s_denom);
1352 f128 t = F128::Div(t_num, t_denom);
1354 f128 pt_r0 = F128::MultAdd(s, ray0_dir_normalized, ray0_point);
1355 f128 pt_r1 = F128::MultAdd(t, ray1_dir_normalized, ray1_point);
1357 ret = Vector3::LengthSq(ret);
1359 if (point_on_ray0) *point_on_ray0 = pt_r0;
1360 if (point_on_ray1) *point_on_ray1 = pt_r1;
1369 SimdVector seg_dir = F128::Sub(segment_point1, segment_point0);
1370 SimdVector u = F128::Sub(ray_point0, segment_point0);
1371 f128 b = Vector3::Dot(ray_dir_normalized, seg_dir);
1372 f128 c = Vector3::LengthSq(seg_dir);
1373 f128 d = Vector3::Dot(ray_dir_normalized, u);
1374 f128 e = Vector3::Dot(seg_dir, u);
1375 f128 det = F128::MultSub(b, b, c);
1376 f128 one = F128::SetOne();
1377 f128 parallel = F128::CmpLt(det, F128::SetEpsilon());
1383 tmp0 = F128::Mult(b, e);
1384 tmp0 = F128::MultSub(c, d, tmp0);
1385 f128 s_num = F128::AndNot(parallel, tmp0);
1390 f128 sNum_negative = F128::CmpLtZero(s_num);
1391 f128 parallel_or_sNum_negative = F128::Or(parallel, sNum_negative);
1392 tmp1 = F128::MultSub(b, d, e);
1393 f128 t_num = F128::Select(parallel_or_sNum_negative, e, tmp1);
1398 f128 t_denom = F128::Select(parallel_or_sNum_negative, c, det);
1403 s_num = F128::AndNot(sNum_negative, s_num);
1411 f128 minus_d = F128::Negate(d);
1412 f128 b_minus_d = F128::Sub(b, d);
1413 f128 tNum_negative = F128::CmpLtZero(t_num);
1414 f128 tNum_out = F128::Or(tNum_negative, F128::CmpGt(t_num, t_denom));
1415 tmp0 = F128::Select(tNum_negative, minus_d, b_minus_d);
1416 f128 cmp = F128::CmpGeZero(tmp0);
1417 tmp1 = F128::And(cmp, tmp0);
1418 s_num = F128::Select(tNum_out, tmp1, s_num);
1425 tmp0 = F128::Or(parallel, F128::And(tNum_out, cmp));
1426 f128 s_denom = F128::Select(tmp0, one, det);
1432 t_num = F128::Clamp(t_num, F128::SetZero(), t_denom);
1434 f128 s = F128::Div(s_num, s_denom);
1435 f128 t = F128::Div(t_num, t_denom);
1437 f128 pt_r = F128::MultAdd(s, ray_dir_normalized, ray_point0);
1438 f128 pt_s = F128::MultAdd(t, seg_dir, segment_point0);
1440 ret = Vector3::LengthSq(ret);
1442 if (point_on_ray) *point_on_ray = pt_r;
1443 if (point_on_segment) *point_on_segment = pt_s;
1448 #pragma endregion DistanceSq function implementation 1455 #pragma region Intersection 1463 f128 dot = Plane::DotNormal(plane, line_dir_normalized);
1464 SimdVector t = Plane::DotCoord(plane, line_point);
1465 t = F128::Div(t, dot);
1466 SimdVector ret = F128::MultSub(t, line_dir_normalized, line_point);
1468 f128 eps = F128::SetEpsilon();
1469 f128 dotzero = F128::CmpNearEqZero(dot, eps);
1470 f128 nan = F128::SetNaN();
1472 return F128::Select(dotzero, nan, ret);
1479 f128 dot = Plane::DotNormal(plane, ray_dir_normalized);
1480 SimdVector t = Plane::DotCoord(plane, ray_point);
1481 t = F128::Div(t, dot);
1482 SimdVector ret = F128::MultSub(t, ray_dir_normalized, ray_point);
1484 f128 eps = F128::SetEpsilon();
1485 f128 dotzero = F128::CmpNearEqZero(dot, eps);
1486 f128 t_gt_0 = F128::CmpGtZero(t);
1487 f128 nan = F128::SetNaN();
1489 return F128::Select(F128::Or(t_gt_0, dotzero), nan, ret);
1496 SimdVector dir = F128::Sub(segment_point1, segment_point0);
1497 f128 recp_len = Vector3::RecpLength(dir);
1498 dir = F128::Mult(dir, recp_len);
1500 f128 dot = Plane::DotNormal(plane, dir);
1501 SimdVector t = Plane::DotCoord(plane, segment_point1);
1502 t = F128::Div(t, dot);
1503 SimdVector ret = F128::MultSub(t, dir, segment_point1);
1505 f128 t_gt_len = F128::CmpGt(F128::Mult(t, recp_len), F128::SetOne());
1506 f128 t_lt_0 = F128::CmpLtZero(t);
1507 f128 nan = F128::SetNaN();
1509 return F128::Select(F128::Or(t_gt_len, t_lt_0), nan, ret);
1515 SimdVector pt_c = F128::Sub(sphere, ray_point);
1517 f128 len_on_ray = Vector3::Dot(pt_c, ray_dir_normalized);
1518 f128 lensq_pt_c = Vector3::LengthSq(pt_c);
1520 r_sq = F128::Mult(r_sq, r_sq);
1521 f128 distsq = F128::MultSub(len_on_ray, len_on_ray, lensq_pt_c);
1523 f128 origin_inside = F128::CmpLe(lensq_pt_c, r_sq);
1524 f128 intersection_none;
1525 intersection_none = F128::CmpLt(len_on_ray, F128::SetZero());
1526 intersection_none = F128::AndNot(origin_inside, intersection_none);
1527 intersection_none = F128::Or(intersection_none, F128::CmpGt(distsq, r_sq));
1529 if (F128::IsAllMaskFalse(intersection_none)) {
1533 f128 q = F128::Sqrt(F128::Sub(r_sq, distsq));
1534 f128 t0 = F128::Sub(len_on_ray, q);
1535 f128 t1 = F128::Add(len_on_ray, q);
1536 f128 t = F128::Select(origin_inside, t1, t0);
1537 *distance = F128::GetFloatFromLane<0>(t);
1547 Intersection::TriangleRay(
float* distance,
SimdVectorArg triangle_point0,
1552 SimdVector E1 = F128::Sub(triangle_point1, triangle_point0);
1553 SimdVector E2 = F128::Sub(triangle_point2, triangle_point0);
1554 SimdVector P = Vector3::Cross(ray_dir_normalized, E2);
1556 f128 det = Vector3::Dot(E1, P);
1557 f128 inv_det = F128::Recp(det);
1560 f128 intersection_none = F128::InBound(det, F128::SetEpsilon());
1563 SimdVector T = F128::Sub(ray_point, triangle_point0);
1567 f128 u = Vector3::Dot(T, P);
1569 f128 v = Vector3::Dot(ray_dir_normalized, Q);
1570 f128 uv = F128::Mult(F128::Permute<0, 1, 4, 5>(u, v), inv_det);
1572 f128 t = F128::Mult(Vector3::Dot(E2, Q), inv_det);
1575 intersection_none = F128::Or(intersection_none, F128::CmpLt(uv, F128::SetZero()));
1576 intersection_none = F128::Or(intersection_none, F128::CmpGt(uv, F128::SetOne()));
1577 intersection_none = F128::Or(intersection_none, F128::CmpLt(t, F128::SetZero()));
1579 if (F128::IsAllMaskFalse(intersection_none)) {
1581 *distance = F128::GetFloatFromLane<0>(t);
1590 NLIB_M(Intersection::PlaneResult)
1594 SimdVector tp0 = F128::SetFloatToLane<3>(triangle_point0, 1.f);
1595 SimdVector tp1 = F128::SetFloatToLane<3>(triangle_point1, 1.f);
1596 SimdVector tp2 = F128::SetFloatToLane<3>(triangle_point2, 1.f);
1599 f128 dist0 = Vector4::Dot(plane_normalized, tp0);
1600 f128 dist1 = Vector4::Dot(plane_normalized, tp1);
1601 f128 dist2 = Vector4::Dot(plane_normalized, tp2);
1603 f128 dist012 = Vector4::Dot3(plane_normalized, tp0, tp1, tp2);
1608 f128 min_dist = F128::Min(dist0, dist1);
1609 f128 max_dist = F128::Max(dist0, dist1);
1610 min_dist = F128::Min(min_dist, dist2);
1611 max_dist = F128::Max(max_dist, dist2);
1613 f128 outside = F128::CmpGtZero(min_dist);
1614 f128 inside = F128::CmpLtZero(max_dist);
1616 if (F128::IsAllMaskTrue(outside))
return kPlaneFront;
1617 if (F128::IsAllMaskTrue(inside))
return kPlaneBack;
1618 return kPlaneInterect;
1622 NLIB_M(Intersection::PlaneResult)
1624 f128 c = F128::SetFloatToLane<3>(sphere, 1.f);
1626 f128 dist = Vector4::Dot(plane_normalized, c);
1627 f128 outside = F128::CmpGt(dist, r);
1628 f128 inside = F128::CmpLt(dist, F128::Negate(r));
1630 if (F128::IsAllMaskTrue(outside))
return kPlaneFront;
1631 if (F128::IsAllMaskTrue(inside))
return kPlaneBack;
1632 return kPlaneInterect;
1637 f128 distsq = Vector3::LengthSq(F128::Sub(sphere0, sphere1));
1639 radsq = F128::Mult(radsq, radsq);
1640 return F128::IsAllMaskFalse(F128::CmpGt(distsq, radsq));
1647 SimdVector linevec = Vector3::Cross(plane1, plane0);
1648 f128 linevec_lensq = Vector3::LengthSq(linevec);
1652 SimdVector p1_line = Vector3::Cross(plane1, linevec);
1657 SimdVector line_p0 = Vector3::Cross(linevec, plane0);
1658 point = F128::MultAdd<3>(plane1, line_p0, point,
each_select32);
1660 SimdVector point0 = F128::Div(point, linevec_lensq);
1661 SimdVector point1 = F128::Add(point0, linevec);
1662 f128 eps = F128::SetEpsilon();
1663 f128 nan = F128::SetNaN();
1664 f128 parallel = F128::CmpNearEq(F128::SetZero(), linevec_lensq, eps);
1666 ret.val[0] = F128::Select(parallel, nan, point0);
1667 ret.val[1] = F128::Select(parallel, nan, point1);
1675 SimdPlane plane = Plane::FromPoint(triangle_point0, triangle_point1, triangle_point2);
1679 f128 distsq = DistanceSq::PointPlane(&q, sphere, plane);
1681 r_sq = F128::Mult(r_sq, r_sq);
1682 f128 cmp = F128::CmpLe(distsq, r_sq);
1683 if (F128::IsAllMaskFalse(cmp))
return false;
1688 Vector3::Cross(F128::Sub(q, triangle_point0), F128::Sub(triangle_point1, triangle_point0));
1690 Vector3::Cross(F128::Sub(q, triangle_point1), F128::Sub(triangle_point2, triangle_point1));
1692 Vector3::Cross(F128::Sub(q, triangle_point2), F128::Sub(triangle_point0, triangle_point2));
1693 plane = F128::SetZeroToLane<3>(plane);
1694 f128 three_dots = Vector4::Dot3(plane, c0, c1, c2);
1695 three_dots = F128::Swizzle<0, 1, 2, 2>(three_dots);
1696 cmp = F128::CmpGeZero(three_dots);
1697 if (F128::IsAllMaskFalse(cmp) || F128::IsAllMaskTrue(cmp))
return true;
1701 f128 seg_dist01 = DistanceSq::PointSegment(sphere, triangle_point0, triangle_point1);
1702 f128 seg_dist02 = DistanceSq::PointSegment(sphere, triangle_point0, triangle_point2);
1703 f128 seg_dist = F128::Min(seg_dist01, seg_dist02);
1704 f128 seg_dist12 = DistanceSq::PointSegment(sphere, triangle_point1, triangle_point2);
1705 seg_dist = F128::Min(seg_dist, seg_dist12);
1706 cmp = F128::CmpLe(seg_dist, r_sq);
1707 return !F128::IsAllMaskFalse(cmp);
1711 NLIB_M(Intersection::PlaneResult)
1712 Intersection::AxisAlignedBoxPlane(
const AxisAlignedBox& aabb,
1716 SimdVector center = F128::Add(aabb_max, aabb_min);
1717 center = F128::Mult(0.5f, center);
1718 SimdVector extents = F128::Sub(aabb_max, center);
1719 center = F128::SetFloatToLane<3>(center, 1.f);
1721 f128 dist = Vector4::Dot(center, plane_normalized);
1722 f128 radius = Vector3::Dot(extents, F128::Abs(plane_normalized));
1723 if (F128::IsAllMaskFalse(F128::CmpLe(dist, radius))) {
1726 if (F128::IsAllMaskFalse(F128::CmpGe(dist, F128::Negate(radius)))) {
1729 return kPlaneInterect;
1733 NLIB_B Intersection::AxisAlignedBoxRay(
const AxisAlignedBox& aabb,
SimdVectorArg ray_point,
1737 f128 inv_dir = F128::Recp(ray_dir_normalized);
1738 f128 selector = F128::CmpGeZero(ray_dir_normalized);
1741 f128 tmin = F128::Select(selector, aabb_min, aabb_max);
1742 f128 tmax = F128::Select(selector, aabb_max, aabb_min);
1743 tmin = F128::Sub(tmin, ray_point);
1744 tmax = F128::Sub(tmax, ray_point);
1745 tmin = F128::Mult(tmin, inv_dir);
1746 tmax = F128::Mult(tmax, inv_dir);
1751 tmin = F128::Swizzle<0, 1, 2, 0>(tmin);
1752 tmax = F128::Swizzle<2, 0, 0, 1>(tmax);
1753 f128 result = F128::CmpGeZero(tmax);
1754 if (!F128::IsAllMaskFalse(F128::CmpGt(tmin, tmax)))
return false;
1757 return F128::IsAllMaskTrue(result);
1765 f128 max_center = F128::Sub(sphere, aabb_max);
1766 f128 min_center = F128::Sub(sphere, aabb_min);
1767 f128 max_mask = F128::CmpGt(sphere, aabb_max);
1768 f128 min_mask = F128::CmpLt(sphere, aabb_min);
1769 f128 dist_sq = F128::SetZero();
1770 dist_sq = F128::Select(max_mask, max_center, dist_sq);
1771 dist_sq = F128::Select(min_mask, min_center, dist_sq);
1772 dist_sq = Vector3::LengthSq(dist_sq);
1774 r_sq = F128::Mult(r_sq, r_sq);
1775 return F128::IsAllMaskTrue(F128::CmpLe(dist_sq, r_sq));
1779 NLIB_B Intersection::AxisAlignedBoxAxisAlignedBox(
const AxisAlignedBox& aabb0,
1781 f128 cond0 = F128::CmpGt(aabb0.point_min, aabb1.point_max);
1782 f128 cond1 = F128::CmpGt(aabb1.point_min, aabb0.point_max);
1783 return F128::IsAllMaskFalse(F128::Or(cond0, cond1));
1788 Intersection::AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
SimdVectorArg triangle_point0,
1800 SimdVector tri_min = F128::Min(F128::Min(tri0, tri1), tri2);
1801 SimdVector tri_max = F128::Max(F128::Max(tri0, tri1), tri2);
1802 f128 cond0 = F128::CmpGt(tri_min, box_max);
1803 f128 cond1 = F128::CmpGt(box_min, tri_max);
1804 if (!F128::IsAllMaskFalse(F128::Or(cond0, cond1))) {
1811 point_in = F128::And(F128::CmpGe(tri0, box_min), F128::CmpLe(tri0, box_max));
1812 if (F128::IsAllMaskTrue(point_in))
return true;
1813 point_in = F128::And(F128::CmpGe(tri1, box_min), F128::CmpLe(tri1, box_max));
1814 if (F128::IsAllMaskTrue(point_in))
return true;
1815 point_in = F128::And(F128::CmpGe(tri2, box_min), 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);
1944 SimdVector box_center = F128::Sub(box.center, aabb_center);
1945 box_center = F128::SetZeroToLane<3>(box_center);
1946 SimdVector box_extent = F128::SetZeroToLane<3>(box.extent);
1952 SimdMatrix rot = Matrix::FromRotationQuaternion(box.rotation);
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));
2076 obox.center = Vector3::InvRotate(F128::Sub(box1.center, box0.center), box0_rot);
2077 obox.extent = box1.extent;
2079 AxisAlignedBox aabb;
2080 aabb.point_max = box0.extent;
2081 aabb.point_min = F128::Negate(aabb.point_max);
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);
2114 NLIB_B Intersection::OrientedBoxTriangle(
const OrientedBox& box,
SimdVectorArg triangle_point0,
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);
2127 AxisAlignedBox aabb;
2128 aabb.point_max = box.extent;
2129 aabb.point_min = F128::Negate(aabb.point_max);
2131 return Intersection::AxisAlignedBoxTriangle(aabb, tp0, tp1, tp2);
2135 inline Intersection::PlaneResult __vectorcall Intersection::OrientedBoxPlane(
2138 SimdVector new_plane = Vector3::InvRotate(plane_normalized, box.rotation);
2139 f128 new_d = F128::Sub(plane_normalized, Vector3::Dot(plane_normalized, box.center));
2140 new_plane = F128::Permute<0, 1, 2, 7>(new_plane, new_d);
2142 AxisAlignedBox aabb;
2143 aabb.point_max = box.extent;
2144 aabb.point_min = F128::Negate(aabb.point_max);
2146 return Intersection::AxisAlignedBoxPlane(aabb, new_plane);
2150 NLIB_B Intersection::OrientedBoxRay(
const OrientedBox& box,
SimdVectorArg ray_point,
2153 SimdVector P = F128::Sub(ray_point, box.center);
2154 P = Vector3::InvRotate(P, box_rotation);
2155 SimdVector D = Vector3::InvRotate(ray_dir_normalized, box_rotation);
2157 AxisAlignedBox aabb;
2158 aabb.point_max = box.extent;
2159 aabb.point_min = F128::Negate(aabb.point_max);
2161 return Intersection::AxisAlignedBoxRay(aabb, P, D);
2165 SimdPlane near_plane = frustum.near_plane_;
2166 SimdPlane far_plane = frustum.far_plane_;
2167 SimdPlane left_plane = frustum.left_plane_;
2168 SimdPlane right_plane = frustum.right_plane_;
2169 SimdPlane top_plane = frustum.top_plane_;
2170 SimdPlane bottom_plane = frustum.bottom_plane_;
2177 center = Vector3::InvRotate(F128::Sub(center, frustum_center), frustum_rot);
2178 center = F128::SetFloatToLane<3>(center, 1.f);
2182 dist0 = Vector4::Dot4(center, near_plane, far_plane, left_plane, right_plane);
2183 dist1 = Vector4::Dot2(center, top_plane, bottom_plane);
2184 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2187 f128 outside = F128::CmpGt(dist0, radius);
2188 outside = F128::Or(F128::CmpGt(dist1, radius), outside);
2189 if (!F128::IsAllMaskFalse(outside))
return false;
2192 f128 center_inside = F128::CmpLeZero(dist0);
2193 center_inside = F128::And(F128::CmpLeZero(dist0), center_inside);
2194 if (F128::IsAllMaskTrue(center_inside))
return true;
2203 dist_plane = Vector4::Dot4(center, near_plane, far_plane, left_plane, right_plane);
2206 pt_plane = F128::MultSub(near_plane, F128::SetValue<0>(dist0,
each_select32), center);
2207 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2208 inside = Vector4::Dot4(pt_plane, left_plane, right_plane, top_plane, bottom_plane);
2209 inside = F128::CmpLeZero(inside);
2210 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<0>(dist_plane,
each_select32)));
2211 if (F128::IsAllMaskTrue(inside))
return true;
2214 pt_plane = F128::MultSub(far_plane, F128::SetValue<1>(dist0,
each_select32), center);
2215 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2216 inside = Vector4::Dot4(pt_plane, left_plane, right_plane, top_plane, bottom_plane);
2217 inside = F128::CmpLeZero(inside);
2218 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<1>(dist_plane,
each_select32)));
2219 if (F128::IsAllMaskTrue(inside))
return true;
2222 pt_plane = F128::MultSub(left_plane, F128::SetValue<2>(dist0,
each_select32), center);
2223 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2224 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, top_plane, bottom_plane);
2225 inside = F128::CmpLeZero(inside);
2226 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<2>(dist_plane,
each_select32)));
2227 if (F128::IsAllMaskTrue(inside))
return true;
2230 pt_plane = F128::MultSub(right_plane, F128::SetValue<3>(dist0,
each_select32), center);
2231 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2232 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, top_plane, bottom_plane);
2233 inside = F128::CmpLeZero(inside);
2234 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<3>(dist_plane,
each_select32)));
2235 if (F128::IsAllMaskTrue(inside))
return true;
2237 dist_plane = Vector4::Dot2(center, top_plane, bottom_plane);
2240 pt_plane = F128::MultSub(top_plane, F128::SetValue<0>(dist1,
each_select32), center);
2241 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2242 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, left_plane, right_plane);
2243 inside = F128::CmpLeZero(inside);
2244 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<0>(dist_plane,
each_select32)));
2245 if (F128::IsAllMaskTrue(inside))
return true;
2248 pt_plane = F128::MultSub(bottom_plane, F128::SetValue<1>(dist1,
each_select32), center);
2249 pt_plane = F128::SetFloatToLane<3>(pt_plane, 1.f);
2250 inside = Vector4::Dot4(pt_plane, near_plane, far_plane, left_plane, right_plane);
2251 inside = F128::CmpLeZero(inside);
2252 inside = F128::And(inside, F128::CmpGtZero(F128::SetValue<1>(dist_plane,
each_select32)));
2253 if (F128::IsAllMaskTrue(inside))
return true;
2257 f128 radius_sq = F128::Mult(radius, radius);
2263 frustum.GetCorners(&corners[0]);
2264 SimdVector left_top = Vector3::LoadFloat3(&corners[0]);
2265 SimdVector right_top = Vector3::LoadFloat3(&corners[1]);
2266 SimdVector right_bottom = Vector3::LoadFloat3(&corners[2]);
2267 SimdVector left_bottom = Vector3::LoadFloat3(&corners[3]);
2268 SimdVector left_top_far = Vector3::LoadFloat3(&corners[4]);
2269 SimdVector right_top_far = Vector3::LoadFloat3(&corners[5]);
2270 SimdVector right_bottom_far = Vector3::LoadFloat3(&corners[6]);
2271 SimdVector left_bottom_far = Vector3::LoadFloat3(&corners[7]);
2274 dist_sq = DistanceSq::PointSegment(center, left_top, right_top);
2275 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_top, right_bottom));
2276 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_bottom, left_bottom));
2277 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_bottom, left_top));
2279 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_top_far, right_top_far));
2280 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_top_far, right_bottom_far));
2282 F128::Min(dist_sq, DistanceSq::PointSegment(center, right_bottom_far, left_bottom_far));
2283 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_bottom_far, left_top_far));
2285 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_top_far, left_top));
2286 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_top_far, right_top));
2287 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, right_bottom_far, right_bottom));
2288 dist_sq = F128::Min(dist_sq, DistanceSq::PointSegment(center, left_bottom_far, left_bottom));
2290 return F128::IsAllMaskTrue(F128::CmpLe(dist_sq, radius_sq));
2294 SimdVector pt = F128::Sub(point, frustum.center_);
2295 pt = Vector3::InvRotate(pt, frustum.rotation_);
2296 pt = F128::SetFloatToLane<3>(pt, 1.f);
2298 f128 dot1 = Vector4::Dot4(pt, frustum.near_plane_, frustum.far_plane_, frustum.top_plane_,
2299 frustum.bottom_plane_);
2300 f128 dot2 = Vector4::Dot2(pt, frustum.left_plane_, frustum.right_plane_);
2301 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
2302 dot1 = F128::Max(dot1, dot2);
2303 f128 outside = F128::CmpGt(dot1, F128::SetZero());
2304 return F128::IsAllMaskFalse(outside);
2307 NLIB_B Intersection::FrustumAxisAlignedBox(
const Frustum& frustum,
2312 SimdVector C = F128::Mult(0.5f, F128::Add(aabb.point_max, aabb.point_min));
2313 if (Containment::FrustumPoint(frustum, C))
return true;
2318 SimdVector extent = F128::Sub(aabb.point_max, C);
2320 frustum.Transform(&fstm, 1.f, F128::Set0001(), F128::Negate(C));
2323 fstm.GetCorners(&corners_[0]);
2326 for (
size_t i = 0; i < 8; ++i) {
2327 corners[i] = Vector3::LoadFloat3(&corners_[i]);
2328 corners[i] = F128::SetFloatToLane<3>(corners[i], 1.f);
2333 pt_min = pt_max = corners[0];
2334 for (
size_t i = 1; i < 8; ++i) {
2336 pt_min = F128::Min(vec, pt_min);
2337 pt_max = F128::Max(vec, pt_max);
2340 F128::Or(F128::CmpGt(pt_min, extent), F128::CmpLt(pt_max, F128::Negate(extent)));
2341 disjoint = F128::SetZeroToLane<3>(disjoint);
2342 if (!F128::IsAllMaskFalse(disjoint))
return false;
2350 f128 dist0_frustum, dist1_frustum;
2351 f128 dist_aabb_max, dist_aabb_min;
2355 plane = fstm.near_plane_;
2356 N = Vector3::Rotate(plane, frustum_rot);
2357 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2358 plane = F128::Permute<0, 1, 2, 7>(N, D);
2360 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2361 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2362 N = Vector3::Dot(F128::Abs(N), extent);
2363 dist_aabb_max = F128::Add(D, N);
2364 dist_aabb_min = F128::Sub(D, N);
2365 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2366 F128::CmpGe(dist1_frustum, dist_aabb_min));
2367 if (F128::IsAllMaskFalse(intersect))
return false;
2368 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2369 F128::CmpLe(dist1_frustum, dist_aabb_max));
2370 if (F128::IsAllMaskFalse(intersect))
return false;
2373 plane = fstm.left_plane_;
2374 N = Vector3::Rotate(plane, frustum_rot);
2375 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2376 plane = F128::Permute<0, 1, 2, 7>(N, D);
2378 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2379 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2380 N = Vector3::Dot(F128::Abs(N), extent);
2381 dist_aabb_max = F128::Add(D, N);
2382 dist_aabb_min = F128::Sub(D, N);
2383 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2384 F128::CmpGe(dist1_frustum, dist_aabb_min));
2385 if (F128::IsAllMaskFalse(intersect))
return false;
2386 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2387 F128::CmpLe(dist1_frustum, dist_aabb_max));
2388 if (F128::IsAllMaskFalse(intersect))
return false;
2391 plane = fstm.right_plane_;
2392 N = Vector3::Rotate(plane, frustum_rot);
2393 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2394 plane = F128::Permute<0, 1, 2, 7>(N, D);
2396 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2397 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2398 N = Vector3::Dot(F128::Abs(N), extent);
2399 dist_aabb_max = F128::Add(D, N);
2400 dist_aabb_min = F128::Sub(D, N);
2401 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2402 F128::CmpGe(dist1_frustum, dist_aabb_min));
2403 if (F128::IsAllMaskFalse(intersect))
return false;
2404 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2405 F128::CmpLe(dist1_frustum, dist_aabb_max));
2406 if (F128::IsAllMaskFalse(intersect))
return false;
2409 plane = fstm.top_plane_;
2410 N = Vector3::Rotate(plane, frustum_rot);
2411 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2412 plane = F128::Permute<0, 1, 2, 7>(N, D);
2414 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2415 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2416 N = Vector3::Dot(F128::Abs(N), extent);
2417 dist_aabb_max = F128::Add(D, N);
2418 dist_aabb_min = F128::Sub(D, N);
2419 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2420 F128::CmpGe(dist1_frustum, dist_aabb_min));
2421 if (F128::IsAllMaskFalse(intersect))
return false;
2422 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2423 F128::CmpLe(dist1_frustum, dist_aabb_max));
2424 if (F128::IsAllMaskFalse(intersect))
return false;
2427 plane = fstm.bottom_plane_;
2428 N = Vector3::Rotate(plane, frustum_rot);
2429 D = F128::Sub(plane, Vector3::Dot(N, frustum_center));
2430 plane = F128::Permute<0, 1, 2, 7>(N, D);
2432 dist0_frustum = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2433 dist1_frustum = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2434 N = Vector3::Dot(F128::Abs(N), extent);
2435 dist_aabb_max = F128::Add(D, N);
2436 dist_aabb_min = F128::Sub(D, N);
2437 intersect = F128::Or(F128::CmpGe(dist0_frustum, dist_aabb_min),
2438 F128::CmpGe(dist1_frustum, dist_aabb_min));
2439 if (F128::IsAllMaskFalse(intersect))
return false;
2440 intersect = F128::Or(F128::CmpLe(dist0_frustum, dist_aabb_max),
2441 F128::CmpLe(dist1_frustum, dist_aabb_max));
2442 if (F128::IsAllMaskFalse(intersect))
return false;
2446 E0[0] = F128::Set1000();
2447 E0[1] = F128::Set0100();
2448 E0[2] = F128::Set0010();
2450 E1[0] = F128::Sub(corners[0], corners[4]);
2451 E1[1] = F128::Sub(corners[1], corners[5]);
2452 E1[2] = F128::Sub(corners[2], corners[6]);
2453 E1[3] = F128::Sub(corners[3], corners[7]);
2454 E1[4] = F128::Sub(corners[1], corners[0]);
2455 E1[5] = F128::Sub(corners[1], corners[2]);
2458 for (
size_t i = 0; i < 3; ++i) {
2459 for (
size_t j = 0; j < 6; ++j) {
2460 SimdVector axis = Vector3::Cross(E0[i], E1[j]);
2461 axis = F128::SetZeroToLane<3>(axis);
2462 N = Vector3::Dot(F128::Abs(axis), extent);
2464 f128 aabb_min = F128::Sub(D, N);
2465 f128 aabb_max = F128::Add(D, N);
2466 dot0 = Vector4::Dot4(axis, corners[0], corners[1], corners[2], corners[3]);
2467 dot1 = Vector4::Dot4(axis, corners[4], corners[5], corners[6], corners[7]);
2469 intersect = F128::CmpGe(F128::Max(dot0, dot1), aabb_min);
2470 if (F128::IsAllMaskFalse(intersect))
return false;
2471 intersect = F128::CmpLe(F128::Min(dot0, dot1), aabb_max);
2472 if (F128::IsAllMaskFalse(intersect))
return false;
2479 Intersection::FrustumOrientedBox(
const Frustum& frustum,
const OrientedBox& obb)
NLIB_NOEXCEPT {
2481 frustum.Transform(&frstm, 1.f, F128::Set0001(), F128::Negate(obb.center));
2482 frstm.Transform(&frstm, 1.f, Quaternion::Conjugate(obb.rotation), F128::SetZero());
2484 AxisAlignedBox aabb;
2485 aabb.point_max = obb.extent;
2486 aabb.point_min = F128::Negate(aabb.point_max);
2487 return Intersection::FrustumAxisAlignedBox(frstm, aabb);
2490 NLIB_B Intersection::FrustumTriangle(
const Frustum& frustum,
SimdVectorArg triangle_point0,
2496 SimdVector pt0 = Vector3::InvRotate(F128::Sub(triangle_point0, frustum_center), frustum_rot);
2497 SimdVector pt1 = Vector3::InvRotate(F128::Sub(triangle_point1, frustum_center), frustum_rot);
2498 SimdVector pt2 = Vector3::InvRotate(F128::Sub(triangle_point2, frustum_center), frustum_rot);
2499 pt0 = F128::SetFloatToLane<3>(pt0, 1.f);
2500 pt1 = F128::SetFloatToLane<3>(pt1, 1.f);
2501 pt2 = F128::SetFloatToLane<3>(pt2, 1.f);
2503 SimdPlane near_plane = frustum.near_plane_;
2504 SimdPlane far_plane = frustum.far_plane_;
2505 SimdPlane left_plane = frustum.left_plane_;
2506 SimdPlane right_plane = frustum.right_plane_;
2507 SimdPlane top_plane = frustum.top_plane_;
2508 SimdPlane bottom_plane = frustum.bottom_plane_;
2510 f128 dist0, dist1, dist_max;
2511 f128 dist0_min, dist1_min;
2515 dist0 = Vector4::Dot4(pt0, near_plane, far_plane, left_plane, right_plane);
2517 dist1 = Vector4::Dot2(pt0, top_plane, bottom_plane);
2518 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2520 dist_max = F128::Max(dist0, dist1);
2521 outside = F128::CmpGtZero(dist_max);
2522 if (F128::IsAllMaskFalse(outside))
return true;
2525 dist0 = Vector4::Dot4(pt1, near_plane, far_plane, left_plane, right_plane);
2526 dist0_min = F128::Min(dist0, dist0_min);
2527 dist1 = Vector4::Dot2(pt1, top_plane, bottom_plane);
2528 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2529 dist1_min = F128::Min(dist1, dist1_min);
2530 dist_max = F128::Max(dist0, dist1);
2531 outside = F128::CmpGtZero(dist_max);
2532 if (F128::IsAllMaskFalse(outside))
return true;
2535 dist0 = Vector4::Dot4(pt2, near_plane, far_plane, left_plane, right_plane);
2536 dist0_min = F128::Min(dist0, dist0_min);
2537 dist1 = Vector4::Dot2(pt2, top_plane, bottom_plane);
2538 dist1 = F128::Swizzle<0, 1, 0, 1>(dist1);
2539 dist1_min = F128::Min(dist1, dist1_min);
2540 dist_max = F128::Max(dist0, dist1);
2541 outside = F128::CmpGtZero(dist_max);
2542 if (F128::IsAllMaskFalse(outside))
return true;
2545 if (!F128::IsAllMaskFalse(F128::Or(F128::CmpGtZero(dist0_min), F128::CmpGtZero(dist1_min))))
2551 pt0 = triangle_point0;
2552 pt1 = triangle_point1;
2553 pt2 = triangle_point2;
2556 SimdPlane triangle = Plane::FromPoint(pt0, pt1, pt2);
2558 frustum.GetCorners(&corners_[0]);
2560 for (
size_t i = 0; i < 8; ++i) {
2561 corners[i] = Vector3::LoadFloat3(&corners_[i]);
2562 corners[i] = F128::SetFloatToLane<3>(corners[i], 1.f);
2564 f128 dot0 = Vector4::Dot4(triangle, corners[0], corners[1], corners[2], corners[3]);
2565 f128 dot1 = Vector4::Dot4(triangle, corners[4], corners[5], corners[6], corners[7]);
2567 if (F128::IsAllMaskFalse(F128::CmpGeZero(F128::Max(dot0, dot1))))
return false;
2569 if (F128::IsAllMaskFalse(F128::CmpLeZero(F128::Min(dot0, dot1))))
return false;
2573 E0[0] = F128::Sub(pt1, pt0);
2574 E0[1] = F128::Sub(pt2, pt1);
2575 E0[2] = F128::Sub(pt0, pt2);
2577 E1[0] = F128::Sub(corners[0], corners[4]);
2578 E1[1] = F128::Sub(corners[1], corners[5]);
2579 E1[2] = F128::Sub(corners[2], corners[6]);
2580 E1[3] = F128::Sub(corners[3], corners[7]);
2581 E1[4] = F128::Sub(corners[1], corners[0]);
2582 E1[5] = F128::Sub(corners[1], corners[2]);
2584 for (
size_t i = 0; i < 3; ++i) {
2585 for (
size_t j = 0; j < 6; ++j) {
2586 SimdVector axis = Vector3::Cross(E0[i], E1[j]);
2587 axis = F128::SetZeroToLane<3>(axis);
2588 f128 tri_min, tri_max;
2590 f128 tmp0 = Vector3::Dot(axis, pt0);
2591 f128 tmp1 = Vector3::Dot(axis, pt1);
2592 f128 tmp2 = Vector3::Dot(axis, pt2);
2593 tri_min = F128::Min(tmp0, tmp1);
2594 tri_max = F128::Max(tmp0, tmp1);
2595 tri_min = F128::Min(tri_min, tmp2);
2596 tri_max = F128::Max(tri_max, tmp2);
2598 dot0 = Vector4::Dot4(axis, corners[0], corners[1], corners[2], corners[3]);
2599 dot1 = Vector4::Dot4(axis, corners[4], corners[5], corners[6], corners[7]);
2601 if (F128::IsAllMaskFalse(F128::CmpGe(F128::Max(dot0, dot1), tri_min)))
return false;
2603 if (F128::IsAllMaskFalse(F128::CmpLe(F128::Min(dot0, dot1), tri_max)))
return false;
2609 inline Intersection::PlaneResult __vectorcall Intersection::FrustumPlane(
2612 frustum.GetCorners(&corners_[0]);
2614 for (
size_t i = 0; i < 8; ++i) {
2615 corners[i] = Vector3::LoadFloat3(&corners_[i]);
2616 corners[i] = F128::SetFloatToLane<3>(corners[i], 1.f);
2618 f128 dot0 = Vector4::Dot4(plane, corners[0], corners[1], corners[2], corners[3]);
2619 f128 dot1 = Vector4::Dot4(plane, corners[4], corners[5], corners[6], corners[7]);
2622 f128 outside = F128::CmpLeZero(F128::Min(dot0, dot1));
2623 if (F128::IsAllMaskFalse(outside))
return Intersection::kPlaneFront;
2626 f128 inside = F128::CmpGeZero(F128::Max(dot0, dot1));
2627 if (F128::IsAllMaskFalse(inside))
return Intersection::kPlaneBack;
2629 return Intersection::kPlaneInterect;
2632 NLIB_B Intersection::FrustumRay(
const Frustum& frustum,
SimdVectorArg ray_point,
2635 if (Containment::FrustumPoint(frustum, ray_point))
return true;
2638 SimdVector rp = F128::Sub(ray_point, frustum.center_);
2639 rp = Vector3::InvRotate(rp, frustum.rotation_);
2640 rp = F128::SetFloatToLane<3>(rp, 1.f);
2641 SimdVector rd = Vector3::InvRotate(ray_dir_normalized, frustum.rotation_);
2642 rd = F128::SetZeroToLane<3>(rd);
2644 f128 dot_rp0, dot_rp1;
2645 dot_rp0 = Vector4::Dot4(rp, frustum.near_plane_, frustum.far_plane_, frustum.left_plane_,
2646 frustum.right_plane_);
2647 dot_rp1 = Vector4::Dot2(rp, frustum.top_plane_, frustum.bottom_plane_);
2648 dot_rp1 = F128::Swizzle<0, 1, 0, 1>(dot_rp1);
2650 f128 dot_rd0, dot_rd1;
2651 dot_rd0 = Vector4::Dot4(rd, frustum.near_plane_, frustum.far_plane_, frustum.left_plane_,
2652 frustum.right_plane_);
2653 dot_rd1 = Vector4::Dot2(rd, frustum.top_plane_, frustum.bottom_plane_);
2654 dot_rd1 = F128::Swizzle<0, 1, 0, 1>(dot_rd1);
2657 f128 eps = F128::SetEpsilon();
2658 f128 parallel0 = F128::CmpLe(F128::Abs(dot_rd0), eps);
2659 f128 parallel1 = F128::CmpLe(F128::Abs(dot_rd1), eps);
2660 f128 mask0 = F128::And(parallel0, F128::CmpGtZero(dot_rp0));
2661 f128 mask1 = F128::And(parallel1, F128::CmpGtZero(dot_rp1));
2662 if (!F128::IsAllMaskFalse(F128::Or(mask0, mask1)))
return false;
2664 f128 t0 = F128::Negate(F128::Div(dot_rp0, dot_rd0));
2665 f128 t1 = F128::Negate(F128::Div(dot_rp1, dot_rd1));
2666 f128 inf = F128::SetInfinity();
2669 mask0 = F128::AndNot(parallel0, F128::CmpGtZero(dot_rd0));
2670 mask1 = F128::AndNot(parallel1, F128::CmpGtZero(dot_rd1));
2671 f128 to = F128::Min(F128::Select(mask0, t0, inf), F128::Select(mask1, t1, inf));
2672 to = F128::PairwiseMin(to, to);
2673 to = F128::PairwiseMin(to, to);
2676 inf = F128::Negate(inf);
2677 mask0 = F128::AndNot(parallel0, F128::CmpLtZero(dot_rd0));
2678 mask1 = F128::AndNot(parallel1, F128::CmpLtZero(dot_rd1));
2679 f128 from = F128::Max(F128::Select(mask0, t0, inf), F128::Select(mask1, t1, inf));
2680 from = F128::PairwiseMax(from, from);
2681 from = F128::PairwiseMax(from, from);
2683 float n = F128::GetFloatFromLane<0>(from);
2684 float f = F128::GetFloatFromLane<0>(to);
2685 return n <= f && (n >= 0.f || f >= 0.f);
2689 #pragma endregion Intersection function implementation 2696 #pragma region Containment 2702 f128 dist_sq = Vector3::LengthSq(F128::Sub(sphere, point));
2704 return F128::IsAllMaskFalse(F128::CmpGt(dist_sq, rsq));
2713 SimdVector tp0_c = F128::Sub(triangle_point0, sphere);
2714 SimdVector tp1_c = F128::Sub(triangle_point1, sphere);
2715 SimdVector tp2_c = F128::Sub(triangle_point2, sphere);
2716 r_sq = F128::Mult(r_sq, r_sq);
2717 tp0_c = Vector3::LengthSq(tp0_c);
2718 tp1_c = Vector3::LengthSq(tp1_c);
2719 tp2_c = Vector3::LengthSq(tp2_c);
2720 f128 dist_sq = F128::Max(F128::Max(tp0_c, tp1_c), tp2_c);
2721 return F128::IsAllMaskFalse(F128::CmpGt(dist_sq, r_sq));
2729 SimdVector aabb_max = F128::Sub(aabb.point_max, sphere);
2730 SimdVector aabb_min = F128::Sub(aabb.point_min, sphere);
2731 r_sq = F128::Mult(r_sq, r_sq);
2732 aabb_max = F128::Abs(aabb_max);
2733 aabb_min = F128::Abs(aabb_min);
2734 f128 dist_sq = Vector3::LengthSq(F128::Max(aabb_max, aabb_min));
2735 return F128::IsAllMaskFalse(F128::CmpGt(dist_sq, r_sq));
2741 SimdVector new_sphere = F128::Sub(sphere, obb.center);
2742 new_sphere = Vector3::InvRotate(new_sphere, obb.rotation);
2743 new_sphere = F128::Permute<0, 1, 2, 7>(new_sphere, sphere);
2745 AxisAlignedBox aabb;
2746 aabb.point_max = box_extent;
2747 aabb.point_min = F128::Negate(box_extent);
2748 return Containment::SphereAxisAlignedBox(new_sphere, aabb);
2755 float dist = F128::GetFloatFromLane<0>(Vector3::Length(F128::Sub(sphere, contained_sphere)));
2756 float r0 = F128::GetFloatFromLane<3>(sphere);
2757 float r1 = F128::GetFloatFromLane<3>(contained_sphere);
2758 return (r0 - r1) >= dist;
2765 frustum.GetCorners(&corners[0]);
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);
2787 f128 out = F128::Or(F128::CmpGt(point, aabb.point_max), F128::CmpLt(point, aabb.point_min));
2788 out = F128::SetZeroToLane<3>(out);
2789 return F128::IsAllMaskFalse(out);
2795 Containment::AxisAlignedBoxTriangle(
const AxisAlignedBox& aabb,
SimdVectorArg triangle_point0,
2799 pt_max = F128::Max(triangle_point0, triangle_point1);
2800 pt_min = F128::Min(triangle_point0, triangle_point1);
2801 pt_max = F128::Max(pt_max, triangle_point2);
2802 pt_min = F128::Min(pt_min, triangle_point2);
2803 f128 out = F128::Or(F128::CmpGt(pt_max, aabb.point_max), F128::CmpLt(pt_min, aabb.point_min));
2804 out = F128::SetZeroToLane<3>(out);
2805 return F128::IsAllMaskFalse(out);
2810 NLIB_B Containment::AxisAlignedBoxOrientedBox(
const AxisAlignedBox& aabb,
2812 f128 zero = F128::SetZero();
2814 SimdVector P = F128::Splat<false, true, true, true>(box_extent, zero);
2815 SimdVector Q = F128::Splat<true, false, true, true>(box_extent, zero);
2816 SimdVector R = F128::Splat<true, true, false, true>(box_extent, zero);
2818 P = Vector3::Rotate(P, box_rotation);
2819 Q = Vector3::Rotate(Q, box_rotation);
2820 R = Vector3::Rotate(R, box_rotation);
2826 v = F128::Add(F128::Add(P, Q), R);
2827 v_neg = F128::Negate(v);
2828 pt_min = F128::Min(v, v_neg);
2829 pt_max = F128::Max(v, v_neg);
2832 v = F128::Sub(F128::Add(P, Q), R);
2833 v_neg = F128::Negate(v);
2834 pt_min = F128::Min(pt_min, v);
2835 pt_max = F128::Max(pt_max, v);
2836 pt_min = F128::Min(pt_min, v_neg);
2837 pt_max = F128::Max(pt_max, v_neg);
2840 v = F128::Sub(F128::Add(P, R), Q);
2841 v_neg = F128::Negate(v);
2842 pt_min = F128::Min(pt_min, v);
2843 pt_max = F128::Max(pt_max, v);
2844 pt_min = F128::Min(pt_min, v_neg);
2845 pt_max = F128::Max(pt_max, v_neg);
2848 SimdVector aabb_min = F128::Sub(aabb.point_min, box_center);
2849 SimdVector aabb_max = F128::Sub(aabb.point_max, box_center);
2850 f128 out = F128::Or(F128::CmpGt(pt_max, aabb_max), F128::CmpLt(pt_min, aabb_min));
2851 out = F128::SetZeroToLane<3>(out);
2852 return F128::IsAllMaskFalse(out);
2858 Containment::AxisAlignedBoxAxisAlignedBox(
const AxisAlignedBox& aabb,
2860 f128 out = F128::Or(F128::CmpGt(contained_aabb.point_max, aabb.point_max),
2861 F128::CmpLt(contained_aabb.point_min, aabb.point_min));
2862 out = F128::SetZeroToLane<3>(out);
2863 return F128::IsAllMaskFalse(out);
2871 SimdVector pt_min = F128::Sub(sphere, radius);
2872 SimdVector pt_max = F128::Add(sphere, radius);
2873 f128 out = F128::Or(F128::CmpGt(pt_max, aabb.point_max), F128::CmpLt(pt_min, aabb.point_min));
2874 out = F128::SetZeroToLane<3>(out);
2875 return F128::IsAllMaskFalse(out);
2880 NLIB_B Containment::AxisAlignedBoxFrustum(
const AxisAlignedBox& aabb,
2883 frustum.GetCorners(&corners[0]);
2884 SimdVector frustum_max = Vector3::LoadFloat3(&corners[0]);
2886 for (
size_t i = 1; i < 8; ++i) {
2887 SimdVector tmp = Vector3::LoadFloat3(&corners[i]);
2888 frustum_max = F128::Max(tmp, frustum_max);
2889 frustum_min = F128::Min(tmp, frustum_min);
2891 AxisAlignedBox contained;
2892 contained.point_max = frustum_max;
2893 contained.point_min = frustum_min;
2894 return Containment::AxisAlignedBoxAxisAlignedBox(aabb, contained);
2900 SimdVector pt = F128::Sub(point, box.center);
2901 pt = Vector3::InvRotate(pt, box.rotation);
2902 return Vector3::InBound(pt, box.extent);
2907 NLIB_B Containment::OrientedBoxTriangle(
const OrientedBox& box,
SimdVectorArg triangle_point0,
2911 SimdVector pt0 = F128::Sub(triangle_point0, center);
2912 SimdVector pt1 = F128::Sub(triangle_point1, center);
2913 SimdVector pt2 = F128::Sub(triangle_point2, center);
2915 pt0 = Vector3::InvRotate(pt0, rot);
2916 pt1 = Vector3::InvRotate(pt1, rot);
2917 pt2 = Vector3::InvRotate(pt2, rot);
2918 pt0 = F128::Abs(pt0);
2919 pt1 = F128::Abs(pt1);
2920 pt2 = F128::Abs(pt2);
2922 pt_absmax = F128::Max(pt_absmax, pt2);
2923 return Vector3::CmpLe(pt_absmax, box.extent);
2928 NLIB_B Containment::OrientedBoxAxisAlignedBox(
const OrientedBox& box,
2930 OrientedBox new_aabb;
2933 SimdVector aabb_center = F128::Add(aabb_min, aabb_max);
2934 aabb_center = F128::Mult(0.5f, aabb_center);
2935 new_aabb.extent = F128::Sub(aabb_max, aabb_center);
2936 aabb_center = F128::Sub(aabb_center, box.center);
2937 new_aabb.center = aabb_center;
2938 new_aabb.rotation = Quaternion::Inverse(box.rotation);
2940 AxisAlignedBox new_box;
2941 new_box.point_max = box.extent;
2942 new_box.point_min = F128::Negate(new_box.point_max);
2944 return Containment::AxisAlignedBoxOrientedBox(new_box, new_aabb);
2949 NLIB_B Containment::OrientedBoxOrientedBox(
const OrientedBox& box,
2952 OrientedBox contained_obb;
2954 contained_obb.extent = box_contained.extent;
2955 contained_obb.center = Vector3::Rotate(F128::Sub(box_contained.center, box.center), inv_rot);
2956 contained_obb.rotation = Quaternion::Mult(box_contained.rotation, inv_rot);
2958 AxisAlignedBox aabb;
2959 aabb.point_max = box.extent;
2960 aabb.point_min = F128::Negate(aabb.point_max);
2962 return Containment::AxisAlignedBoxOrientedBox(aabb, contained_obb);
2968 AxisAlignedBox aabb;
2970 aabb.point_max = box_extent;
2971 aabb.point_min = F128::Negate(box_extent);
2973 SimdSphere new_sphere = Vector3::InvRotate(F128::Sub(sphere, box.center), box.rotation);
2974 new_sphere = F128::Permute<0, 1, 2, 7>(new_sphere, sphere);
2976 return Containment::AxisAlignedBoxSphere(aabb, new_sphere);
2980 Containment::OrientedBoxFrustum(
const OrientedBox& box,
const Frustum& frustum)
NLIB_NOEXCEPT {
2982 frustum.Transform(&frstm, 1.f, F128::Set0001(), F128::Negate(box.center));
2983 frstm.Transform(&frstm, 1.f, Quaternion::Conjugate(box.rotation), F128::SetZero());
2984 AxisAlignedBox aabb;
2985 aabb.point_max = box.extent;
2986 aabb.point_min = F128::Negate(box.extent);
2987 return Containment::AxisAlignedBoxFrustum(aabb, frstm);
2990 NLIB_B Containment::FrustumTriangle(
const Frustum& frustum,
SimdVectorArg triangle_point0,
2994 f128 dot, dot1, dot2;
2995 SimdPlane near_plane = frustum.near_plane_;
2996 SimdPlane far_plane = frustum.far_plane_;
2997 SimdPlane top_plane = frustum.top_plane_;
2998 SimdPlane bottom_plane = frustum.bottom_plane_;
2999 SimdPlane left_plane = frustum.left_plane_;
3000 SimdPlane right_plane = frustum.right_plane_;
3004 pt = F128::Sub(triangle_point0, center);
3005 pt = Vector3::InvRotate(pt, rot);
3006 pt = F128::SetFloatToLane<3>(pt, 1.f);
3007 dot1 = Vector4::Dot4(pt, near_plane, far_plane, top_plane, bottom_plane);
3008 dot2 = Vector4::Dot2(pt, left_plane, right_plane);
3009 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3010 dot = F128::Max(dot1, dot2);
3012 pt = F128::Sub(triangle_point1, center);
3013 pt = Vector3::InvRotate(pt, rot);
3014 pt = F128::SetFloatToLane<3>(pt, 1.f);
3015 dot1 = Vector4::Dot4(pt, near_plane, far_plane, top_plane, bottom_plane);
3016 dot2 = Vector4::Dot2(pt, left_plane, right_plane);
3017 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3018 dot = F128::Max(dot, F128::Max(dot1, dot2));
3020 pt = F128::Sub(triangle_point2, center);
3021 pt = Vector3::InvRotate(pt, rot);
3022 pt = F128::SetFloatToLane<3>(pt, 1.f);
3023 dot1 = Vector4::Dot4(pt, near_plane, far_plane, top_plane, bottom_plane);
3024 dot2 = Vector4::Dot2(pt, left_plane, right_plane);
3025 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3026 dot = F128::Max(dot, F128::Max(dot1, dot2));
3028 f128 outside = F128::CmpGt(dot, F128::SetZero());
3029 return F128::IsAllMaskFalse(outside);
3034 dot = F128::Negate(dot);
3036 SimdVector pt = F128::Sub(sphere, frustum.center_);
3037 pt = Vector3::InvRotate(pt, frustum.rotation_);
3038 pt = F128::SetFloatToLane<3>(pt, 1.f);
3040 f128 dot1 = Vector4::Dot4(pt, frustum.near_plane_, frustum.far_plane_, frustum.top_plane_,
3041 frustum.bottom_plane_);
3042 f128 dot2 = Vector4::Dot2(pt, frustum.left_plane_, frustum.right_plane_);
3043 dot2 = F128::Swizzle<0, 1, 0, 1>(dot2);
3044 dot1 = F128::Max(dot1, dot2);
3045 f128 outside = F128::CmpGt(dot1, dot);
3046 return F128::IsAllMaskFalse(outside);
3049 NLIB_B Containment::FrustumAxisAlignedBox(
const Frustum& frustum,
3053 SimdVector center = F128::Mult(0.5f, F128::Add(pt_min, pt_max));
3054 center = F128::SetFloatToLane<3>(center, 1.f);
3055 SimdVector extent_neg = F128::Sub(center, pt_max);
3056 extent_neg = F128::SetZeroToLane<3>(extent_neg);
3066 tmp = frustum.near_plane_;
3067 N = Vector3::Rotate(tmp, rot);
3068 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3069 SimdPlane near_plane = F128::Permute<0, 1, 2, 7>(N, D);
3071 tmp = frustum.far_plane_;
3072 N = Vector3::Rotate(tmp, rot);
3073 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3074 SimdPlane far_plane = F128::Permute<0, 1, 2, 7>(N, D);
3076 tmp = frustum.right_plane_;
3077 N = Vector3::Rotate(tmp, rot);
3078 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3079 SimdPlane right_plane = F128::Permute<0, 1, 2, 7>(N, D);
3081 tmp = frustum.left_plane_;
3082 N = Vector3::Rotate(tmp, rot);
3083 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3084 SimdPlane left_plane = F128::Permute<0, 1, 2, 7>(N, D);
3086 tmp = frustum.top_plane_;
3087 N = Vector3::Rotate(tmp, rot);
3088 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3089 SimdPlane top_plane = F128::Permute<0, 1, 2, 7>(N, D);
3091 tmp = frustum.bottom_plane_;
3092 N = Vector3::Rotate(tmp, rot);
3093 D = F128::Sub(tmp, Vector3::Dot(N, frustum_center));
3094 SimdPlane bottom_plane = F128::Permute<0, 1, 2, 7>(N, D);
3098 f128 all_points_inside;
3101 dist = Vector4::Dot4(center, near_plane, far_plane, right_plane, left_plane);
3103 radius_neg = Vector4::Dot4(extent_neg, F128::Abs(near_plane), F128::Abs(far_plane),
3104 F128::Abs(right_plane), F128::Abs(left_plane));
3106 all_points_inside = F128::CmpLe(dist, radius_neg);
3108 dist = Vector4::Dot2(center, top_plane, bottom_plane);
3109 radius_neg = Vector4::Dot2(extent_neg, F128::Abs(top_plane), F128::Abs(bottom_plane));
3111 F128::And(all_points_inside, F128::Swizzle<0, 1, 0, 1>(F128::CmpLe(dist, radius_neg)));
3113 return F128::IsAllMaskTrue(all_points_inside);
3117 Containment::FrustumOrientedBox(
const Frustum& frustum,
const OrientedBox& box)
NLIB_NOEXCEPT {
3120 frustum.Transform(&frstm, 1.f, F128::Set0001(), F128::Negate(box.center));
3122 frstm.Transform(&frstm, 1.f, Quaternion::Conjugate(box.rotation), F128::SetZero());
3124 AxisAlignedBox aabb;
3125 aabb.point_max = box.extent;
3126 aabb.point_min = F128::Negate(box.extent);
3127 return Containment::FrustumAxisAlignedBox(frstm, aabb);
3130 NLIB_B Containment::FrustumFrustum(
const Frustum& frustum,
const Frustum& contained)
NLIB_NOEXCEPT {
3132 contained.GetCorners(&corners[0]);
3133 for (
size_t i = 0; i < 8; ++i) {
3134 SimdVector pt = Vector3::LoadFloat3(&corners[i]);
3135 if (!Containment::FrustumPoint(frustum, pt))
return false;
3141 #pragma endregion Containment function implementation 3147 #endif // NLIB_DOXYGEN 3152 #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.
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...
nlib_f128x2_t f128x2
nlib_f128x2_t is defined using typedef.
f128 SimdSphere
f128 is defined using typedef. Used when handling spheres.
SimdVector center
The center coordinates of the OBB. A 3D vector.
#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.
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...