Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_math/src/sampling/mesh_sampling.rs
6596 views
1
//! Functionality related to random sampling from triangle meshes.
2
3
use crate::{
4
primitives::{Measured2d, Triangle3d},
5
ShapeSample, Vec3,
6
};
7
use alloc::vec::Vec;
8
use rand::Rng;
9
use rand_distr::{
10
weighted::{Error as WeightedError, WeightedAliasIndex},
11
Distribution,
12
};
13
14
/// A [distribution] that caches data to allow fast sampling from a collection of triangles.
15
/// Generally used through [`sample`] or [`sample_iter`].
16
///
17
/// [distribution]: Distribution
18
/// [`sample`]: Distribution::sample
19
/// [`sample_iter`]: Distribution::sample_iter
20
///
21
/// Example
22
/// ```
23
/// # use bevy_math::{Vec3, primitives::*};
24
/// # use bevy_math::sampling::mesh_sampling::UniformMeshSampler;
25
/// # use rand::{SeedableRng, rngs::StdRng, distr::Distribution};
26
/// let faces = Tetrahedron::default().faces();
27
/// let sampler = UniformMeshSampler::try_new(faces).unwrap();
28
/// let rng = StdRng::seed_from_u64(8765309);
29
/// // 50 random points on the tetrahedron:
30
/// let samples: Vec<Vec3> = sampler.sample_iter(rng).take(50).collect();
31
/// ```
32
pub struct UniformMeshSampler {
33
triangles: Vec<Triangle3d>,
34
face_distribution: WeightedAliasIndex<f32>,
35
}
36
37
impl Distribution<Vec3> for UniformMeshSampler {
38
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 {
39
let face_index = self.face_distribution.sample(rng);
40
self.triangles[face_index].sample_interior(rng)
41
}
42
}
43
44
impl UniformMeshSampler {
45
/// Construct a new [`UniformMeshSampler`] from a list of [triangles].
46
///
47
/// Returns an error if the distribution of areas for the collection of triangles could not be formed
48
/// (most notably if the collection has zero surface area).
49
///
50
/// [triangles]: Triangle3d
51
pub fn try_new<T: IntoIterator<Item = Triangle3d>>(
52
triangles: T,
53
) -> Result<Self, WeightedError> {
54
let triangles: Vec<Triangle3d> = triangles.into_iter().collect();
55
let areas = triangles.iter().map(Measured2d::area).collect();
56
57
WeightedAliasIndex::new(areas).map(|face_distribution| Self {
58
triangles,
59
face_distribution,
60
})
61
}
62
}
63
64