use crate::{
primitives::{Measured2d, Triangle3d},
ShapeSample, Vec3,
};
use alloc::vec::Vec;
use rand::Rng;
use rand_distr::{
weighted::{Error as WeightedError, WeightedAliasIndex},
Distribution,
};
pub struct UniformMeshSampler {
triangles: Vec<Triangle3d>,
face_distribution: WeightedAliasIndex<f32>,
}
impl Distribution<Vec3> for UniformMeshSampler {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 {
let face_index = self.face_distribution.sample(rng);
self.triangles[face_index].sample_interior(rng)
}
}
impl UniformMeshSampler {
pub fn try_new<T: IntoIterator<Item = Triangle3d>>(
triangles: T,
) -> Result<Self, WeightedError> {
let triangles: Vec<Triangle3d> = triangles.into_iter().collect();
let areas = triangles.iter().map(Measured2d::area).collect();
WeightedAliasIndex::new(areas).map(|face_distribution| Self {
triangles,
face_distribution,
})
}
}