Skip to main content

rapier2d/geometry/
mesh_converter.rs

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