rapier3d_meshloader/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
#![doc = include_str!("../README.md")]
#![deny(missing_docs)]
use mesh_loader::Mesh;
use rapier3d::geometry::{MeshConverter, SharedShape};
use rapier3d::math::{Isometry, Point, Real, Vector};
use rapier3d::prelude::MeshConverterError;
use std::path::Path;
/// The result of loading a shape.
pub struct LoadedShape {
/// The shape loaded from the file and converted by the [`MeshConverter`].
pub shape: SharedShape,
/// The shape’s pose.
pub pose: Isometry<Real>,
/// The raw mesh read from the file without any modification.
pub raw_mesh: Mesh,
}
/// Error while loading an STL file.
#[derive(thiserror::Error, Debug)]
pub enum MeshLoaderError {
/// An error triggered by rapier’s [`MeshConverter`].
#[error(transparent)]
MeshConverter(#[from] MeshConverterError),
/// A generic IO error.
#[error(transparent)]
Io(#[from] std::io::Error),
}
/// Loads parry shapes from a file.
///
/// # Parameters
/// - `path`: the file’s path.
/// - `converter`: controls how the shapes are computed from the content. In particular, it lets
/// you specify if the computed [`SharedShape`] is a triangle mesh, its convex hull,
/// bounding box, etc.
/// - `scale`: the scaling factor applied to the geometry input to the `converter`. This scale will
/// affect at the geometric level the [`LoadedShape::shape`]. Note that raw mesh value stored
/// in [`LoadedShape::raw_mesh`] remains unscaled.
pub fn load_from_path(
path: impl AsRef<Path>,
converter: &MeshConverter,
scale: Vector<Real>,
) -> Result<Vec<Result<LoadedShape, MeshConverterError>>, MeshLoaderError> {
let loader = mesh_loader::Loader::default();
let mut colliders = vec![];
let scene = loader.load(path)?;
for (raw_mesh, _) in scene.meshes.into_iter().zip(scene.materials) {
let shape = load_from_raw_mesh(&raw_mesh, converter, scale);
colliders.push(shape.map(|(shape, pose)| LoadedShape {
shape,
pose,
raw_mesh,
}));
}
Ok(colliders)
}
/// Loads an file as a shape from a preloaded raw [`mesh_loader::Mesh`].
///
/// # Parameters
/// - `raw_mesh`: the raw mesh.
/// - `converter`: controls how the shape is computed from the STL content. In particular, it lets
/// you specify if the computed [`SharedShape`] is a triangle mesh, its convex hull,
/// bounding box, etc.
/// - `scale`: the scaling factor applied to the geometry input to the `converter`. This scale will
/// affect at the geometric level the [`LoadedShape::shape`]. Note that raw mesh value stored
/// in [`LoadedShape::raw_mesh`] remains unscaled.
pub fn load_from_raw_mesh(
raw_mesh: &Mesh,
converter: &MeshConverter,
scale: Vector<Real>,
) -> Result<(SharedShape, Isometry<Real>), MeshConverterError> {
let mut vertices: Vec<_> = raw_mesh
.vertices
.iter()
.map(|xyz| Point::new(xyz[0], xyz[1], xyz[2]))
.collect();
vertices
.iter_mut()
.for_each(|pt| pt.coords.component_mul_assign(&scale));
let indices: Vec<_> = raw_mesh.faces.clone();
converter.convert(vertices, indices)
}