bevy_mesh/
index.rs

1use bevy_reflect::Reflect;
2use core::iter;
3use core::iter::FusedIterator;
4#[cfg(feature = "serialize")]
5use serde::{Deserialize, Serialize};
6use thiserror::Error;
7use wgpu_types::IndexFormat;
8
9use crate::MeshAccessError;
10
11/// A disjunction of four iterators. This is necessary to have a well-formed type for the output
12/// of [`Mesh::triangles`](super::Mesh::triangles), which produces iterators of four different types depending on the
13/// branch taken.
14pub(crate) enum FourIterators<A, B, C, D> {
15    First(A),
16    Second(B),
17    Third(C),
18    Fourth(D),
19}
20
21impl<A, B, C, D, I> Iterator for FourIterators<A, B, C, D>
22where
23    A: Iterator<Item = I>,
24    B: Iterator<Item = I>,
25    C: Iterator<Item = I>,
26    D: Iterator<Item = I>,
27{
28    type Item = I;
29
30    fn next(&mut self) -> Option<Self::Item> {
31        match self {
32            FourIterators::First(iter) => iter.next(),
33            FourIterators::Second(iter) => iter.next(),
34            FourIterators::Third(iter) => iter.next(),
35            FourIterators::Fourth(iter) => iter.next(),
36        }
37    }
38
39    fn size_hint(&self) -> (usize, Option<usize>) {
40        match self {
41            FourIterators::First(iter) => iter.size_hint(),
42            FourIterators::Second(iter) => iter.size_hint(),
43            FourIterators::Third(iter) => iter.size_hint(),
44            FourIterators::Fourth(iter) => iter.size_hint(),
45        }
46    }
47}
48
49/// An error that occurred while trying to invert the winding of a [`Mesh`](super::Mesh).
50#[derive(Debug, Error)]
51pub enum MeshWindingInvertError {
52    /// This error occurs when you try to invert the winding for a mesh with [`PrimitiveTopology::PointList`](super::PrimitiveTopology::PointList).
53    #[error("Mesh winding inversion does not work for primitive topology `PointList`")]
54    WrongTopology,
55
56    /// This error occurs when you try to invert the winding for a mesh with
57    /// * [`PrimitiveTopology::TriangleList`](super::PrimitiveTopology::TriangleList), but the indices are not in chunks of 3.
58    /// * [`PrimitiveTopology::LineList`](super::PrimitiveTopology::LineList), but the indices are not in chunks of 2.
59    #[error("Indices weren't in chunks according to topology")]
60    AbruptIndicesEnd,
61    #[error("Mesh access error: {0}")]
62    MeshAccessError(#[from] MeshAccessError),
63}
64
65/// An error that occurred while trying to extract a collection of triangles from a [`Mesh`](super::Mesh).
66#[derive(Debug, Error)]
67pub enum MeshTrianglesError {
68    #[error("Source mesh does not have primitive topology TriangleList or TriangleStrip")]
69    WrongTopology,
70
71    #[error("Source mesh position data is not Float32x3")]
72    PositionsFormat,
73
74    #[error("Face index data references vertices that do not exist")]
75    BadIndices,
76    #[error("mesh access error: {0}")]
77    MeshAccessError(#[from] MeshAccessError),
78}
79
80/// An array of indices into the [`VertexAttributeValues`](super::VertexAttributeValues) for a mesh.
81///
82/// It describes the order in which the vertex attributes should be joined into faces.
83#[derive(Debug, Clone, Reflect, PartialEq)]
84#[reflect(Clone)]
85#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
86pub enum Indices {
87    U16(Vec<u16>),
88    U32(Vec<u32>),
89}
90
91impl Indices {
92    /// Returns an iterator over the indices.
93    pub fn iter(&self) -> impl Iterator<Item = usize> + '_ {
94        match self {
95            Indices::U16(vec) => IndicesIter::U16(vec.iter()),
96            Indices::U32(vec) => IndicesIter::U32(vec.iter()),
97        }
98    }
99
100    /// Returns the number of indices.
101    pub fn len(&self) -> usize {
102        match self {
103            Indices::U16(vec) => vec.len(),
104            Indices::U32(vec) => vec.len(),
105        }
106    }
107
108    /// Returns `true` if there are no indices.
109    pub fn is_empty(&self) -> bool {
110        match self {
111            Indices::U16(vec) => vec.is_empty(),
112            Indices::U32(vec) => vec.is_empty(),
113        }
114    }
115
116    /// Add an index. If the index is greater than `u16::MAX`,
117    /// the storage will be converted to `u32`.
118    pub fn push(&mut self, index: u32) {
119        self.extend([index]);
120    }
121}
122
123/// Extend the indices with indices from an iterator.
124/// Semantically equivalent to calling [`push`](Indices::push) for each element in the iterator,
125/// but more efficient.
126impl Extend<u32> for Indices {
127    fn extend<T: IntoIterator<Item = u32>>(&mut self, iter: T) {
128        let mut iter = iter.into_iter();
129        match self {
130            Indices::U32(indices) => indices.extend(iter),
131            Indices::U16(indices) => {
132                indices.reserve(iter.size_hint().0);
133                while let Some(index) = iter.next() {
134                    match u16::try_from(index) {
135                        Ok(index) => indices.push(index),
136                        Err(_) => {
137                            let new_vec = indices
138                                .iter()
139                                .map(|&index| u32::from(index))
140                                .chain(iter::once(index))
141                                .chain(iter)
142                                .collect::<Vec<u32>>();
143                            *self = Indices::U32(new_vec);
144                            break;
145                        }
146                    }
147                }
148            }
149        }
150    }
151}
152
153/// An Iterator for the [`Indices`].
154enum IndicesIter<'a> {
155    U16(core::slice::Iter<'a, u16>),
156    U32(core::slice::Iter<'a, u32>),
157}
158
159impl Iterator for IndicesIter<'_> {
160    type Item = usize;
161
162    fn next(&mut self) -> Option<Self::Item> {
163        match self {
164            IndicesIter::U16(iter) => iter.next().map(|val| *val as usize),
165            IndicesIter::U32(iter) => iter.next().map(|val| *val as usize),
166        }
167    }
168
169    fn size_hint(&self) -> (usize, Option<usize>) {
170        match self {
171            IndicesIter::U16(iter) => iter.size_hint(),
172            IndicesIter::U32(iter) => iter.size_hint(),
173        }
174    }
175}
176
177impl<'a> ExactSizeIterator for IndicesIter<'a> {}
178
179impl<'a> FusedIterator for IndicesIter<'a> {}
180
181impl From<&Indices> for IndexFormat {
182    fn from(indices: &Indices) -> Self {
183        match indices {
184            Indices::U16(_) => IndexFormat::Uint16,
185            Indices::U32(_) => IndexFormat::Uint32,
186        }
187    }
188}
189
190#[cfg(test)]
191mod tests {
192    use crate::Indices;
193    use wgpu_types::IndexFormat;
194
195    #[test]
196    fn test_indices_push() {
197        let mut indices = Indices::U16(Vec::new());
198        indices.push(10);
199        assert_eq!(IndexFormat::Uint16, IndexFormat::from(&indices));
200        assert_eq!(vec![10], indices.iter().collect::<Vec<_>>());
201
202        // Add a value that is too large for `u16` so the storage should be converted to `U32`.
203        indices.push(0x10000);
204        assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices));
205        assert_eq!(vec![10, 0x10000], indices.iter().collect::<Vec<_>>());
206
207        indices.push(20);
208        indices.push(0x20000);
209        assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices));
210        assert_eq!(
211            vec![10, 0x10000, 20, 0x20000],
212            indices.iter().collect::<Vec<_>>()
213        );
214    }
215
216    #[test]
217    fn test_indices_extend() {
218        let mut indices = Indices::U16(Vec::new());
219        indices.extend([10, 11]);
220        assert_eq!(IndexFormat::Uint16, IndexFormat::from(&indices));
221        assert_eq!(vec![10, 11], indices.iter().collect::<Vec<_>>());
222
223        // Add a value that is too large for `u16` so the storage should be converted to `U32`.
224        indices.extend([12, 0x10013, 0x10014]);
225        assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices));
226        assert_eq!(
227            vec![10, 11, 12, 0x10013, 0x10014],
228            indices.iter().collect::<Vec<_>>()
229        );
230
231        indices.extend([15, 0x10016]);
232        assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices));
233        assert_eq!(
234            vec![10, 11, 12, 0x10013, 0x10014, 15, 0x10016],
235            indices.iter().collect::<Vec<_>>()
236        );
237    }
238}