Created
August 25, 2024 20:49
-
-
Save Elabajaba/d4a69ac814a610c786ad12e5a522b9c0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// Checks if 2 spheres intersects the frustum. | |
| pub fn intersects_sphere( | |
| &self, | |
| sphere_a: &Sphere, | |
| sphere_b: &Sphere, | |
| intersect_far_a: bool, | |
| intersect_far_b: bool, | |
| ) -> (bool, bool) { | |
| let pos_a_xxxx = Vec4::splat(sphere_a.center.x); | |
| let pos_a_yyyy = Vec4::splat(sphere_a.center.y); | |
| let pos_a_zzzz = Vec4::splat(sphere_a.center.z); | |
| // -radius so that we include objects who's center is outside the frustum, | |
| // but who's bounding sphere intersects the frustum | |
| let pos_a_rrrr = Vec4::splat(-sphere_a.radius); | |
| // dot product 4 frustums at a time | |
| let mut dot_a_0123 = pos_a_zzzz.mul_add(self.z0z1z2z3, self.w0w1w2w3); | |
| dot_a_0123 = pos_a_yyyy.mul_add(self.y0y1y2y3, dot_a_0123); | |
| dot_a_0123 = pos_a_xxxx.mul_add(self.x0x1x2x3, dot_a_0123); | |
| let pos_b_xxxx = Vec4::splat(sphere_b.center.x); | |
| let pos_b_yyyy = Vec4::splat(sphere_b.center.y); | |
| let pos_b_zzzz = Vec4::splat(sphere_b.center.z); | |
| // -radius so that we include objects who's center is outside the frustum, | |
| // but who's bounding sphere intersects the frustum | |
| let pos_b_rrrr = Vec4::splat(-sphere_b.radius); | |
| // dot product 4 frustums at a time | |
| let mut dot_b_0123 = pos_b_zzzz.mul_add(self.z0z1z2z3, self.w0w1w2w3); | |
| dot_b_0123 = pos_b_yyyy.mul_add(self.y0y1y2y3, dot_b_0123); | |
| dot_b_0123 = pos_b_xxxx.mul_add(self.x0x1x2x3, dot_b_0123); | |
| let pos_axx_bxx = Vec4::new( | |
| sphere_a.center.x, | |
| sphere_a.center.x, | |
| sphere_b.center.x, | |
| sphere_b.center.x, | |
| ); | |
| let pos_ayy_byy = Vec4::new( | |
| sphere_a.center.y, | |
| sphere_a.center.y, | |
| sphere_b.center.y, | |
| sphere_b.center.y, | |
| ); | |
| let pos_azz_bzz = Vec4::new( | |
| sphere_a.center.z, | |
| sphere_a.center.z, | |
| sphere_b.center.z, | |
| sphere_b.center.z, | |
| ); | |
| let pos_arr_brr = Vec4::new( | |
| -sphere_a.radius, | |
| -sphere_a.radius, | |
| -sphere_b.radius, | |
| -sphere_b.radius, | |
| ); | |
| let mut dot_a45_b45 = pos_azz_bzz.mul_add(self.z4z5z4z5, self.w4w5w4w5); | |
| dot_a45_b45 = pos_ayy_byy.mul_add(self.y4y5y4y5, dot_a45_b45); | |
| dot_a45_b45 = pos_axx_bxx.mul_add(self.x4x5x4x5, dot_a45_b45); | |
| if !intersect_far_a && !intersect_far_b { | |
| // Swizzle to skip both far planes | |
| dot_a45_b45 = dot_a45_b45.xxzz(); | |
| } | |
| else if !intersect_far_a { | |
| // Swizzle to skip the far plane | |
| dot_a45_b45 = dot_a45_b45.xxzw(); | |
| } else if !intersect_far_b { | |
| // Swizzle to skip the far plane | |
| dot_a45_b45 = dot_a45_b45.xyzz(); | |
| } | |
| let mask_a_0123 = dot_a_0123.cmpgt(pos_a_rrrr); | |
| let mask_a45_b45 = dot_a45_b45.cmpgt(pos_arr_brr); | |
| let mask_b_0123 = dot_b_0123.cmpgt(pos_b_rrrr); | |
| // FFTT for MASK_A since we OR it then check if it's all 1s, so we only want | |
| // the first 2 values and need to set the 2nd to to 1s to ignore them. | |
| const MASK_A: BVec4A = BVec4A::from_array([false, false, true, true]); | |
| const MASK_B: BVec4A = BVec4A::from_array([true, true, false, false]); | |
| ( | |
| mask_a_0123.all() && (mask_a45_b45 | MASK_A).all(), | |
| mask_b_0123.all() && (mask_a45_b45 | MASK_B).all(), | |
| ) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment