aboutsummaryrefslogtreecommitdiff
path: root/crates/rapier3d-meshloader/src
diff options
context:
space:
mode:
authorThierry Berger <contact@thierryberger.com>2024-11-12 09:02:55 +0100
committerGitHub <noreply@github.com>2024-11-12 09:02:55 +0100
commit71f65fe55a5918a721252a1f7bb74531137ee665 (patch)
tree9fc460a012f5846bb62651486a431eea192cebb4 /crates/rapier3d-meshloader/src
parent0d791eb794d616c983145853e9c7594baef8f66c (diff)
downloadrapier-71f65fe55a5918a721252a1f7bb74531137ee665.tar.gz
rapier-71f65fe55a5918a721252a1f7bb74531137ee665.tar.bz2
rapier-71f65fe55a5918a721252a1f7bb74531137ee665.zip
Use meshloader to support multiple file formats loading (#744)
Co-authored-by: Tin Lai <tin@tinyiu.com>
Diffstat (limited to 'crates/rapier3d-meshloader/src')
-rw-r--r--crates/rapier3d-meshloader/src/lib.rs86
1 files changed, 86 insertions, 0 deletions
diff --git a/crates/rapier3d-meshloader/src/lib.rs b/crates/rapier3d-meshloader/src/lib.rs
new file mode 100644
index 0000000..32051e5
--- /dev/null
+++ b/crates/rapier3d-meshloader/src/lib.rs
@@ -0,0 +1,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)
+}