bevy_math: faster sphere sampling (#14168)

Uses fewer transcendental functions than the existing approach
This commit is contained in:
ickk 2024-07-16 01:01:18 +10:00 committed by GitHub
parent da997dd0ea
commit 3dd4953b97
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -164,30 +164,30 @@ impl ShapeSample for Circle {
}
}
/// Boundary sampling for unit-spheres
#[inline]
fn sample_unit_sphere_boundary<R: Rng + ?Sized>(rng: &mut R) -> Vec3 {
let z = rng.gen_range(-1f32..=1f32);
let (a_sin, a_cos) = rng.gen_range(-PI..=PI).sin_cos();
let c = (1f32 - z * z).sqrt();
let x = a_sin * c;
let y = a_cos * c;
Vec3::new(x, y, z)
}
impl ShapeSample for Sphere {
type Output = Vec3;
fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 {
// https://mathworld.wolfram.com/SpherePointPicking.html
let theta = rng.gen_range(0.0..TAU);
let phi = rng.gen_range(-1.0_f32..1.0).acos();
let r_cubed = rng.gen_range(0.0..=(self.radius * self.radius * self.radius));
let r = r_cubed.cbrt();
Vec3 {
x: r * phi.sin() * theta.cos(),
y: r * phi.sin() * theta.sin(),
z: r * phi.cos(),
}
r * sample_unit_sphere_boundary(rng)
}
fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 {
let theta = rng.gen_range(0.0..TAU);
let phi = rng.gen_range(-1.0_f32..1.0).acos();
Vec3 {
x: self.radius * phi.sin() * theta.cos(),
y: self.radius * phi.sin() * theta.sin(),
z: self.radius * phi.cos(),
}
self.radius * sample_unit_sphere_boundary(rng)
}
}