rapier3d/geometry/
mesh_converter.rs

1use parry::bounding_volume;
2use parry::math::{Isometry, Point, Real};
3use parry::shape::{Cuboid, SharedShape, TriMeshBuilderError, TriMeshFlags};
4
5#[cfg(feature = "dim3")]
6use parry::transformation::vhacd::VHACDParameters;
7
8/*
9 *
10 * TODO: should all this be part of parry instead?
11 *
12 */
13
14/// Error that can be generated by the [`MeshConverter`].
15#[derive(thiserror::Error, Debug)]
16pub enum MeshConverterError {
17    /// The convex hull calculation carried out by the [`MeshConverter::ConvexHull`] failed.
18    #[error("convex-hull computation failed")]
19    ConvexHullFailed,
20    /// The TriMesh building failed.
21    #[error("TriMesh building failed")]
22    TriMeshBuilderError(TriMeshBuilderError),
23}
24
25/// Determines how meshes (generally when loaded from a file) are converted into Rapier colliders.
26#[derive(Clone, Copy, Debug, PartialEq, Default)]
27pub enum MeshConverter {
28    /// The mesh is loaded as-is without any particular processing.
29    #[default]
30    TriMesh,
31    /// The mesh is loaded with the specified flags.
32    TriMeshWithFlags(TriMeshFlags),
33    /// The mesh is replaced by its Oriented Bounding Box (represented as
34    /// a rotated cuboid).
35    ///
36    /// With this option, the mesh’s index buffer is ignored.
37    Obb,
38    /// The mesh is replaced by its AABB.
39    ///
40    /// With this option, the mesh’s index buffer is ignored.
41    Aabb,
42    /// The mesh is replaced by its convex-hull.
43    ///
44    /// With this option, the mesh’s index buffer is ignored.
45    ConvexHull,
46    /// The mesh is replaced by its convex decomposition.
47    #[cfg(feature = "dim3")]
48    ConvexDecomposition,
49    /// The mesh is replaced by its convex decomposition with parameters specified to adjust
50    /// the convex decomposition algorithm.
51    #[cfg(feature = "dim3")]
52    ConvexDecompositionWithParams(VHACDParameters),
53}
54
55impl MeshConverter {
56    /// Applies the conversion rule described by this [`MeshConverter`] to build a shape from
57    /// the given vertex and index buffers.
58    #[profiling::function]
59    pub fn convert(
60        &self,
61        vertices: Vec<Point<Real>>,
62        indices: Vec<[u32; 3]>,
63    ) -> Result<(SharedShape, Isometry<Real>), MeshConverterError> {
64        let mut transform = Isometry::identity();
65        let shape = match self {
66            MeshConverter::TriMesh => SharedShape::trimesh(vertices, indices)
67                .map_err(MeshConverterError::TriMeshBuilderError)?,
68            MeshConverter::TriMeshWithFlags(flags) => {
69                SharedShape::trimesh_with_flags(vertices, indices, *flags)
70                    .map_err(MeshConverterError::TriMeshBuilderError)?
71            }
72            MeshConverter::Obb => {
73                let (pose, cuboid) = parry::utils::obb(&vertices);
74                transform = pose;
75                SharedShape::new(cuboid)
76            }
77            MeshConverter::Aabb => {
78                let aabb =
79                    bounding_volume::details::local_point_cloud_aabb(vertices.iter().copied());
80                let cuboid = Cuboid::new(aabb.half_extents());
81                transform = Isometry::from(aabb.center().coords);
82                SharedShape::new(cuboid)
83            }
84            MeshConverter::ConvexHull => {
85                SharedShape::convex_hull(&vertices).ok_or(MeshConverterError::ConvexHullFailed)?
86            }
87            #[cfg(feature = "dim3")]
88            MeshConverter::ConvexDecomposition => {
89                SharedShape::convex_decomposition(&vertices, &indices)
90            }
91            #[cfg(feature = "dim3")]
92            MeshConverter::ConvexDecompositionWithParams(params) => {
93                SharedShape::convex_decomposition_with_params(&vertices, &indices, params)
94            }
95        };
96        Ok((shape, transform))
97    }
98}