diff --git a/crates/bevy_mesh/src/index.rs b/crates/bevy_mesh/src/index.rs index af2b3635ba..096cd031d6 100644 --- a/crates/bevy_mesh/src/index.rs +++ b/crates/bevy_mesh/src/index.rs @@ -103,19 +103,36 @@ impl Indices { /// Add an index. If the index is greater than `u16::MAX`, /// the storage will be converted to `u32`. pub fn push(&mut self, index: u32) { + self.extend([index]); + } +} + +/// Extend the indices with indices from an iterator. +/// Semantically equivalent to calling [`push`](Indices::push) for each element in the iterator, +/// but more efficient. +impl Extend for Indices { + fn extend>(&mut self, iter: T) { + let mut iter = iter.into_iter(); match self { - Indices::U32(vec) => vec.push(index), - Indices::U16(vec) => match u16::try_from(index) { - Ok(index) => vec.push(index), - Err(_) => { - let new_vec = vec - .iter() - .map(|&index| u32::from(index)) - .chain(iter::once(index)) - .collect::>(); - *self = Indices::U32(new_vec); + Indices::U32(indices) => indices.extend(iter), + Indices::U16(indices) => { + indices.reserve(iter.size_hint().0); + while let Some(index) = iter.next() { + match u16::try_from(index) { + Ok(index) => indices.push(index), + Err(_) => { + let new_vec = indices + .iter() + .map(|&index| u32::from(index)) + .chain(iter::once(index)) + .chain(iter) + .collect::>(); + *self = Indices::U32(new_vec); + break; + } + } } - }, + } } } } @@ -181,4 +198,27 @@ mod tests { indices.iter().collect::>() ); } + + #[test] + fn test_indices_extend() { + let mut indices = Indices::U16(Vec::new()); + indices.extend([10, 11]); + assert_eq!(IndexFormat::Uint16, IndexFormat::from(&indices)); + assert_eq!(vec![10, 11], indices.iter().collect::>()); + + // Add a value that is too large for `u16` so the storage should be converted to `U32`. + indices.extend([12, 0x10013, 0x10014]); + assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices)); + assert_eq!( + vec![10, 11, 12, 0x10013, 0x10014], + indices.iter().collect::>() + ); + + indices.extend([15, 0x10016]); + assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices)); + assert_eq!( + vec![10, 11, 12, 0x10013, 0x10014, 15, 0x10016], + indices.iter().collect::>() + ); + } } diff --git a/crates/bevy_mesh/src/mesh.rs b/crates/bevy_mesh/src/mesh.rs index f2a9646d04..22698c4e68 100644 --- a/crates/bevy_mesh/src/mesh.rs +++ b/crates/bevy_mesh/src/mesh.rs @@ -842,20 +842,7 @@ impl Mesh { // Extend indices of `self` with indices of `other`. if let (Some(indices), Some(other_indices)) = (self.indices_mut(), other.indices()) { - match (indices, other_indices) { - (Indices::U16(i1), Indices::U16(i2)) => { - i1.extend(i2.iter().map(|i| *i + index_offset as u16)); - } - (Indices::U32(i1), Indices::U32(i2)) => { - i1.extend(i2.iter().map(|i| *i + index_offset as u32)); - } - (Indices::U16(i1), Indices::U32(i2)) => { - i1.extend(i2.iter().map(|i| *i as u16 + index_offset as u16)); - } - (Indices::U32(i1), Indices::U16(i2)) => { - i1.extend(i2.iter().map(|i| *i as u32 + index_offset as u32)); - } - } + indices.extend(other_indices.iter().map(|i| (i + index_offset) as u32)); } }