This repository was archived by the owner on Mar 13, 2025. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 94
intersects_aabb can return NaN which fails the filter predicate when checking for intersections #118
Copy link
Copy link
Open
Description
From investigating aevyrie/bevy_mod_picking#341, I've discovered that:
bevy_mod_raycast/src/primitives.rs
Lines 165 to 204 in dbc5ef3
| pub fn intersects_aabb(ray: Ray3d, aabb: &Aabb, model_to_world: &Mat4) -> Option<[f32; 2]> { | |
| // Transform the ray to model space | |
| let world_to_model = model_to_world.inverse(); | |
| let ray_dir: Vec3A = world_to_model.transform_vector3(*ray.direction).into(); | |
| let ray_origin: Vec3A = world_to_model.transform_point3(ray.origin).into(); | |
| // Check if the ray intersects the mesh's AABB. It's useful to work in model space | |
| // because we can do an AABB intersection test, instead of an OBB intersection test. | |
| let t_0: Vec3A = (aabb.min() - ray_origin) / ray_dir; | |
| let t_1: Vec3A = (aabb.max() - ray_origin) / ray_dir; | |
| let t_min: Vec3A = t_0.min(t_1); | |
| let t_max: Vec3A = t_0.max(t_1); | |
| let mut hit_near = t_min.x; | |
| let mut hit_far = t_max.x; | |
| if hit_near > t_max.y || t_min.y > hit_far { | |
| return None; | |
| } | |
| if t_min.y > hit_near { | |
| hit_near = t_min.y; | |
| } | |
| if t_max.y < hit_far { | |
| hit_far = t_max.y; | |
| } | |
| if (hit_near > t_max.z) || (t_min.z > hit_far) { | |
| return None; | |
| } | |
| if t_min.z > hit_near { | |
| hit_near = t_min.z; | |
| } | |
| if t_max.z < hit_far { | |
| hit_far = t_max.z; | |
| } | |
| Some([hit_near, hit_far]) | |
| } | |
| } |
intersects_aabb returns [NaN, NaN] because of a divide by 0 when the intersection check is right on the edge of a mesh, thus failing the filter predicate far > 0.0 here:
bevy_mod_raycast/src/immediate.rs
Line 260 in dbc5ef3
| .filter(|[_, far]| *far >= 0.0) |
It was not apparent to me what the right approach to prevent intersects_aabb from returning NaN. It's possible I'm being naive, and there's a more obvious fix, however, this diff seems to solve the symptom of that issue. (I have no idea if this introduces other side effects, but all the tests seem to pass?)
Index: src/immediate.rs
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/immediate.rs b/src/immediate.rs
--- a/src/immediate.rs (revision Staged)
+++ b/src/immediate.rs (date 1720831909681)
@@ -257,7 +257,7 @@
};
if should_raycast {
if let Some([near, _]) = intersects_aabb(ray, aabb, &transform.compute_matrix())
- .filter(|[_, far]| *far >= 0.0)
+ .filter(|[_, far]| *far >= 0.0 || far.is_nan())
{
aabb_hits_tx.send((FloatOrd(near), entity)).ok();
}
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels