bevy_rapier2d/geometry/shape_views/trimesh.rs
1use crate::geometry::Collider;
2use crate::math::{Rot, Vect};
3#[cfg(feature = "dim3")]
4use rapier::parry::shape::TriMeshPseudoNormals;
5use rapier::parry::shape::{
6 FeatureId, TopologyError, TriMesh, TriMeshBuilderError, TriMeshConnectedComponents,
7 TriMeshFlags, TriMeshTopology,
8};
9
10/// Read-only access to the properties of a triangle mesh.
11#[derive(Copy, Clone)]
12pub struct TriMeshView<'a> {
13 /// The raw shape from Rapier.
14 pub raw: &'a TriMesh,
15}
16
17macro_rules! impl_ref_methods(
18 ($View: ident) => {
19 impl<'a> $View<'a> {
20 /// The number of triangles forming this mesh.
21 pub fn num_triangles(&self) -> usize {
22 self.raw.num_triangles()
23 }
24
25 /// An iterator through all the triangles of this mesh.
26 pub fn triangles(&self) -> impl ExactSizeIterator<Item = (Vect, Vect, Vect)> + '_ {
27 self.raw
28 .triangles()
29 .map(|tri| (tri.a.into(), tri.b.into(), tri.c.into()))
30 }
31
32 /// Get the `i`-th triangle of this mesh.
33 pub fn triangle(&self, i: u32) -> (Vect, Vect, Vect) {
34 let tri = self.raw.triangle(i);
35 (tri.a.into(), tri.b.into(), tri.c.into())
36 }
37
38 /// The vertex buffer of this mesh.
39 pub fn vertices(&self) -> impl ExactSizeIterator<Item = Vect> + '_ {
40 self.raw.vertices().iter().map(|pt| (*pt).into())
41 }
42
43 /// The index buffer of this mesh.
44 pub fn indices(&self) -> &[[u32; 3]] {
45 self.raw.indices()
46 }
47
48 /// A flat view of the index buffer of this mesh.
49 pub fn flat_indices(&self) -> &[u32] {
50 self.raw.flat_indices()
51 }
52
53 /// The flags controlling the optional data associated to this mesh.
54 pub fn flags(&self) -> TriMeshFlags {
55 self.raw.flags()
56 }
57
58 /// The outward normal of the `i`-th triangle, or `None` if it is degenerate.
59 #[cfg(feature = "dim3")]
60 pub fn triangle_normal(&self, i: u32) -> Option<Vect> {
61 self.raw.triangle_normal(i)
62 }
63
64 /// Does the given feature (as returned by a ray-cast or point projection on one of
65 /// the triangles) identify the back face of that triangle?
66 pub fn is_backface(&self, feature: FeatureId) -> bool {
67 self.raw.is_backface(feature)
68 }
69
70 /// The half-edge topology of this mesh, if it was computed.
71 ///
72 /// This requires the [`TriMeshFlags::HALF_EDGE_TOPOLOGY`] flag.
73 pub fn topology(&self) -> Option<&TriMeshTopology> {
74 self.raw.topology()
75 }
76
77 /// The connected components of this mesh, if they were computed.
78 ///
79 /// This requires the [`TriMeshFlags::CONNECTED_COMPONENTS`] flag.
80 pub fn connected_components(&self) -> Option<&TriMeshConnectedComponents> {
81 self.raw.connected_components()
82 }
83
84 /// The number of connected components of this mesh, if they were computed.
85 pub fn num_connected_components(&self) -> Option<usize> {
86 self.raw
87 .connected_components()
88 .map(|cc| cc.num_connected_components())
89 }
90
91 /// Builds one triangle mesh collider per connected component of this mesh, each
92 /// built with the given `flags`.
93 ///
94 /// Returns `None` if the connected components were not computed.
95 pub fn connected_component_colliders(
96 &self,
97 flags: TriMeshFlags,
98 ) -> Option<Vec<Result<Collider, TriMeshBuilderError>>> {
99 self.raw.connected_component_meshes(flags).map(|meshes| {
100 meshes
101 .into_iter()
102 .map(|mesh| mesh.map(|mesh| rapier::prelude::SharedShape::new(mesh).into()))
103 .collect()
104 })
105 }
106
107 /// The vertex and edge pseudo-normals of this mesh, if they were computed.
108 ///
109 /// They are computed with the [`TriMeshFlags::ORIENTED`] or
110 /// [`TriMeshFlags::FIX_INTERNAL_EDGES`] flags.
111 #[cfg(feature = "dim3")]
112 pub fn pseudo_normals(&self) -> Option<&TriMeshPseudoNormals> {
113 self.raw.pseudo_normals()
114 }
115 }
116 }
117);
118
119impl_ref_methods!(TriMeshView);
120
121/// Read-write access to the properties of a triangle mesh.
122pub struct TriMeshViewMut<'a> {
123 /// The raw shape from Rapier.
124 pub raw: &'a mut TriMesh,
125}
126
127impl_ref_methods!(TriMeshViewMut);
128
129impl TriMeshViewMut<'_> {
130 /// Sets the flags of this triangle mesh, controlling its optional associated data.
131 pub fn set_flags(&mut self, flags: TriMeshFlags) -> Result<(), TopologyError> {
132 self.raw.set_flags(flags)
133 }
134
135 /// Replaces the vertex positions, keeping the index buffer and topology.
136 ///
137 /// The acceleration structure is refitted and the pseudo-normals (if any) are recomputed.
138 /// This is intended for meshes built with [`TriMeshFlags::DEFORMABLE`].
139 ///
140 /// # Panics
141 /// Panics if `vertices.len()` differs from the current number of vertices.
142 pub fn set_vertices(&mut self, vertices: &[Vect]) {
143 self.raw.set_vertices(vertices)
144 }
145
146 /// Modifies the vertex positions in place through `f`, then refits the acceleration
147 /// structure and recomputes the pseudo-normals (if any).
148 ///
149 /// This is intended for meshes built with [`TriMeshFlags::DEFORMABLE`].
150 pub fn update_vertices(&mut self, f: impl FnOnce(&mut [Vect])) {
151 self.raw.update_vertices(f)
152 }
153
154 /// Applies a rigid transformation to every vertex of this mesh.
155 pub fn transform_vertices(&mut self, translation: Vect, rotation: Rot) {
156 self.raw
157 .transform_vertices(&crate::utils::pose_from(translation, rotation))
158 }
159
160 /// Reverses the orientation of every triangle of this mesh.
161 pub fn reverse(&mut self) {
162 self.raw.reverse()
163 }
164}