mirror of
https://github.com/bevyengine/bevy
synced 2024-09-20 06:22:01 +00:00
fix: Possible NaN due to denormalised quaternions in AABB implementations for round shapes. (#14240)
# Objective With an unlucky denormalised quaternion (or just a regular very denormalised quaternion), it's possible to obtain NaN values for AABB's in shapes which rely on an AABB for a disk. ## Solution Add an additional `.max(Vec3::ZERO)` clamp to get rid of negative values arising due to numerical errors. Fixup some unnecessary calculations and improve variable names in relevant code, aiming for consistency. ## Discussion These two (nontrivial) lines of code are repeated at least 5 times, maybe they could be their own method.
This commit is contained in:
parent
1bc5ecda9b
commit
0e1858bc4f
2 changed files with 9 additions and 9 deletions
|
@ -20,7 +20,7 @@ impl BoundedExtrusion for Circle {
|
|||
let segment_dir = rotation * Vec3::Z;
|
||||
let top = (segment_dir * half_depth).abs();
|
||||
|
||||
let e = Vec3::ONE - segment_dir * segment_dir;
|
||||
let e = (Vec3::ONE - segment_dir * segment_dir).max(Vec3::ZERO);
|
||||
let half_size = self.radius * Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());
|
||||
|
||||
Aabb3d {
|
||||
|
|
|
@ -125,7 +125,7 @@ impl Bounded3d for Cylinder {
|
|||
let top = segment_dir * self.half_height;
|
||||
let bottom = -top;
|
||||
|
||||
let e = Vec3::ONE - segment_dir * segment_dir;
|
||||
let e = (Vec3::ONE - segment_dir * segment_dir).max(Vec3::ZERO);
|
||||
let half_size = self.radius * Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());
|
||||
|
||||
Aabb3d {
|
||||
|
@ -169,11 +169,11 @@ impl Bounded3d for Cone {
|
|||
fn aabb_3d(&self, translation: Vec3, rotation: Quat) -> Aabb3d {
|
||||
// Reference: http://iquilezles.org/articles/diskbbox/
|
||||
|
||||
let top = rotation * Vec3::Y * 0.5 * self.height;
|
||||
let segment_dir = rotation * Vec3::Y;
|
||||
let top = segment_dir * 0.5 * self.height;
|
||||
let bottom = -top;
|
||||
let segment = bottom - top;
|
||||
|
||||
let e = 1.0 - segment * segment / segment.length_squared();
|
||||
let e = (Vec3::ONE - segment_dir * segment_dir).max(Vec3::ZERO);
|
||||
let half_extents = Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());
|
||||
|
||||
Aabb3d {
|
||||
|
@ -203,11 +203,11 @@ impl Bounded3d for ConicalFrustum {
|
|||
fn aabb_3d(&self, translation: Vec3, rotation: Quat) -> Aabb3d {
|
||||
// Reference: http://iquilezles.org/articles/diskbbox/
|
||||
|
||||
let top = rotation * Vec3::Y * 0.5 * self.height;
|
||||
let segment_dir = rotation * Vec3::Y;
|
||||
let top = segment_dir * 0.5 * self.height;
|
||||
let bottom = -top;
|
||||
let segment = bottom - top;
|
||||
|
||||
let e = 1.0 - segment * segment / segment.length_squared();
|
||||
let e = (Vec3::ONE - segment_dir * segment_dir).max(Vec3::ZERO);
|
||||
let half_extents = Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());
|
||||
|
||||
Aabb3d {
|
||||
|
@ -286,7 +286,7 @@ impl Bounded3d for Torus {
|
|||
// Compute the AABB of a flat disc with the major radius of the torus.
|
||||
// Reference: http://iquilezles.org/articles/diskbbox/
|
||||
let normal = rotation * Vec3::Y;
|
||||
let e = 1.0 - normal * normal;
|
||||
let e = (Vec3::ONE - normal * normal).max(Vec3::ZERO);
|
||||
let disc_half_size = self.major_radius * Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());
|
||||
|
||||
// Expand the disc by the minor radius to get the torus half-size
|
||||
|
|
Loading…
Reference in a new issue