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
							
								
									5ffdc0c93f
								
							
						
					
					
						commit
						291db3e755
					
				| @ -20,7 +20,7 @@ impl BoundedExtrusion for Circle { | |||||||
|         let segment_dir = rotation * Vec3::Z; |         let segment_dir = rotation * Vec3::Z; | ||||||
|         let top = (segment_dir * half_depth).abs(); |         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()); |         let half_size = self.radius * Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt()); | ||||||
| 
 | 
 | ||||||
|         Aabb3d { |         Aabb3d { | ||||||
|  | |||||||
| @ -125,7 +125,7 @@ impl Bounded3d for Cylinder { | |||||||
|         let top = segment_dir * self.half_height; |         let top = segment_dir * self.half_height; | ||||||
|         let bottom = -top; |         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()); |         let half_size = self.radius * Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt()); | ||||||
| 
 | 
 | ||||||
|         Aabb3d { |         Aabb3d { | ||||||
| @ -169,11 +169,11 @@ impl Bounded3d for Cone { | |||||||
|     fn aabb_3d(&self, translation: Vec3, rotation: Quat) -> Aabb3d { |     fn aabb_3d(&self, translation: Vec3, rotation: Quat) -> Aabb3d { | ||||||
|         // Reference: http://iquilezles.org/articles/diskbbox/
 |         // 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 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()); |         let half_extents = Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt()); | ||||||
| 
 | 
 | ||||||
|         Aabb3d { |         Aabb3d { | ||||||
| @ -203,11 +203,11 @@ impl Bounded3d for ConicalFrustum { | |||||||
|     fn aabb_3d(&self, translation: Vec3, rotation: Quat) -> Aabb3d { |     fn aabb_3d(&self, translation: Vec3, rotation: Quat) -> Aabb3d { | ||||||
|         // Reference: http://iquilezles.org/articles/diskbbox/
 |         // 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 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()); |         let half_extents = Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt()); | ||||||
| 
 | 
 | ||||||
|         Aabb3d { |         Aabb3d { | ||||||
| @ -286,7 +286,7 @@ impl Bounded3d for Torus { | |||||||
|         // Compute the AABB of a flat disc with the major radius of the torus.
 |         // Compute the AABB of a flat disc with the major radius of the torus.
 | ||||||
|         // Reference: http://iquilezles.org/articles/diskbbox/
 |         // Reference: http://iquilezles.org/articles/diskbbox/
 | ||||||
|         let normal = rotation * Vec3::Y; |         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()); |         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
 |         // Expand the disc by the minor radius to get the torus half-size
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 IQuick 143
						IQuick 143