From 3dd4953b975d2332f52adf113671496543467ad0 Mon Sep 17 00:00:00 2001 From: ickk Date: Tue, 16 Jul 2024 01:01:18 +1000 Subject: [PATCH] bevy_math: faster sphere sampling (#14168) Uses fewer transcendental functions than the existing approach --- .../bevy_math/src/sampling/shape_sampling.rs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/crates/bevy_math/src/sampling/shape_sampling.rs b/crates/bevy_math/src/sampling/shape_sampling.rs index 325134805c..411c4b99f8 100644 --- a/crates/bevy_math/src/sampling/shape_sampling.rs +++ b/crates/bevy_math/src/sampling/shape_sampling.rs @@ -164,30 +164,30 @@ impl ShapeSample for Circle { } } +/// Boundary sampling for unit-spheres +#[inline] +fn sample_unit_sphere_boundary(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(&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(&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) } }