From cb2d848929a6440b160697bd89c22f84fe04f870 Mon Sep 17 00:00:00 2001 From: Joona Aalto Date: Sun, 21 Jan 2024 15:19:21 +0200 Subject: [PATCH 1/4] Add `Mesh::merge` --- crates/bevy_render/src/mesh/mesh/mod.rs | 84 +++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/crates/bevy_render/src/mesh/mesh/mod.rs b/crates/bevy_render/src/mesh/mesh/mod.rs index 270fd86cb1705..b613f8816ebce 100644 --- a/crates/bevy_render/src/mesh/mesh/mod.rs +++ b/crates/bevy_render/src/mesh/mesh/mod.rs @@ -572,6 +572,90 @@ impl Mesh { Ok(self) } + /// Merges the [`Mesh`] data of `other` with `self`. The attributes and indices of `other` will be appended to `self`. + /// + /// # Panics + /// + /// Panics if the vertex attribute values of `other` are incompatible with `self`. + /// For example, [`VertexAttributeValues::Float32`] is incompatible with [`VertexAttributeValues::Float32x3`]. + pub fn merge(&mut self, other: Mesh) { + use VertexAttributeValues::*; + + // The indices of `other` should start after the last vertex of `self`. + let index_offset = self.count_vertices(); + + // Extend attributes of `self` with attributes of `other`. + for (id, values) in self.attributes_mut() { + let enum_variant_name = values.enum_variant_name(); + if let Some(other_values) = other.attribute(id) { + match (values, other_values) { + (Float32(vec1), Float32(vec2)) => vec1.extend(vec2), + (Sint32(vec1), Sint32(vec2)) => vec1.extend(vec2), + (Uint32(vec1), Uint32(vec2)) => vec1.extend(vec2), + (Float32x2(vec1), Float32x2(vec2)) => vec1.extend(vec2), + (Sint32x2(vec1), Sint32x2(vec2)) => vec1.extend(vec2), + (Uint32x2(vec1), Uint32x2(vec2)) => vec1.extend(vec2), + (Float32x3(vec1), Float32x3(vec2)) => vec1.extend(vec2), + (Sint32x3(vec1), Sint32x3(vec2)) => vec1.extend(vec2), + (Uint32x3(vec1), Uint32x3(vec2)) => vec1.extend(vec2), + (Sint32x4(vec1), Sint32x4(vec2)) => vec1.extend(vec2), + (Uint32x4(vec1), Uint32x4(vec2)) => vec1.extend(vec2), + (Float32x4(vec1), Float32x4(vec2)) => vec1.extend(vec2), + (Sint16x2(vec1), Sint16x2(vec2)) | (Snorm16x2(vec1), Snorm16x2(vec2)) => { + vec1.extend(vec2); + } + (Uint16x2(vec1), Uint16x2(vec2)) | (Unorm16x2(vec1), Unorm16x2(vec2)) => { + vec1.extend(vec2); + } + (Sint16x4(vec1), Sint16x4(vec2)) | (Snorm16x4(vec1), Snorm16x4(vec2)) => { + vec1.extend(vec2); + } + (Uint16x4(vec1), Uint16x4(vec2)) | (Unorm16x4(vec1), Unorm16x4(vec2)) => { + vec1.extend(vec2); + } + (Sint8x2(vec1), Sint8x2(vec2)) | (Snorm8x2(vec1), Snorm8x2(vec2)) => { + vec1.extend(vec2); + } + (Uint8x2(vec1), Uint8x2(vec2)) => { + vec1.extend(vec2); + } + (Unorm8x2(vec1), Unorm8x2(vec2)) => vec1.extend(vec2), + (Sint8x4(vec1), Sint8x4(vec2)) => { + vec1.extend(vec2); + } + (Snorm8x4(vec1), Snorm8x4(vec2)) => vec1.extend(vec2), + (Uint8x4(vec1), Uint8x4(vec2)) => { + vec1.extend(vec2); + } + (Unorm8x4(vec1), Unorm8x4(vec2)) => vec1.extend(vec2), + _ => panic!( + "Incompatible vertex attribute types {} and {}", + enum_variant_name, + other_values.enum_variant_name() + ), + } + } + } + + // 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)); + } + } + } + } + /// Compute the Axis-Aligned Bounding Box of the mesh vertices in model space /// /// Returns `None` if `self` doesn't have [`Mesh::ATTRIBUTE_POSITION`] of From 9ade3ee0d9c2c06523f710bd64b639ea25ffb492 Mon Sep 17 00:00:00 2001 From: Joona Aalto Date: Sun, 21 Jan 2024 19:22:39 +0200 Subject: [PATCH 2/4] Clean up match arm formatting --- crates/bevy_render/src/mesh/mesh/mod.rs | 38 +++++++++---------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/crates/bevy_render/src/mesh/mesh/mod.rs b/crates/bevy_render/src/mesh/mesh/mod.rs index b613f8816ebce..0b98876b05bae 100644 --- a/crates/bevy_render/src/mesh/mesh/mod.rs +++ b/crates/bevy_render/src/mesh/mesh/mod.rs @@ -578,6 +578,7 @@ impl Mesh { /// /// Panics if the vertex attribute values of `other` are incompatible with `self`. /// For example, [`VertexAttributeValues::Float32`] is incompatible with [`VertexAttributeValues::Float32x3`]. + #[allow(clippy::match_same_arms)] pub fn merge(&mut self, other: Mesh) { use VertexAttributeValues::*; @@ -601,32 +602,21 @@ impl Mesh { (Sint32x4(vec1), Sint32x4(vec2)) => vec1.extend(vec2), (Uint32x4(vec1), Uint32x4(vec2)) => vec1.extend(vec2), (Float32x4(vec1), Float32x4(vec2)) => vec1.extend(vec2), - (Sint16x2(vec1), Sint16x2(vec2)) | (Snorm16x2(vec1), Snorm16x2(vec2)) => { - vec1.extend(vec2); - } - (Uint16x2(vec1), Uint16x2(vec2)) | (Unorm16x2(vec1), Unorm16x2(vec2)) => { - vec1.extend(vec2); - } - (Sint16x4(vec1), Sint16x4(vec2)) | (Snorm16x4(vec1), Snorm16x4(vec2)) => { - vec1.extend(vec2); - } - (Uint16x4(vec1), Uint16x4(vec2)) | (Unorm16x4(vec1), Unorm16x4(vec2)) => { - vec1.extend(vec2); - } - (Sint8x2(vec1), Sint8x2(vec2)) | (Snorm8x2(vec1), Snorm8x2(vec2)) => { - vec1.extend(vec2); - } - (Uint8x2(vec1), Uint8x2(vec2)) => { - vec1.extend(vec2); - } + (Sint16x2(vec1), Sint16x2(vec2)) => vec1.extend(vec2), + (Snorm16x2(vec1), Snorm16x2(vec2)) => vec1.extend(vec2), + (Uint16x2(vec1), Uint16x2(vec2)) => vec1.extend(vec2), + (Unorm16x2(vec1), Unorm16x2(vec2)) => vec1.extend(vec2), + (Sint16x4(vec1), Sint16x4(vec2)) => vec1.extend(vec2), + (Snorm16x4(vec1), Snorm16x4(vec2)) => vec1.extend(vec2), + (Uint16x4(vec1), Uint16x4(vec2)) => vec1.extend(vec2), + (Unorm16x4(vec1), Unorm16x4(vec2)) => vec1.extend(vec2), + (Sint8x2(vec1), Sint8x2(vec2)) => vec1.extend(vec2), + (Snorm8x2(vec1), Snorm8x2(vec2)) => vec1.extend(vec2), + (Uint8x2(vec1), Uint8x2(vec2)) => vec1.extend(vec2), (Unorm8x2(vec1), Unorm8x2(vec2)) => vec1.extend(vec2), - (Sint8x4(vec1), Sint8x4(vec2)) => { - vec1.extend(vec2); - } + (Sint8x4(vec1), Sint8x4(vec2)) => vec1.extend(vec2), (Snorm8x4(vec1), Snorm8x4(vec2)) => vec1.extend(vec2), - (Uint8x4(vec1), Uint8x4(vec2)) => { - vec1.extend(vec2); - } + (Uint8x4(vec1), Uint8x4(vec2)) => vec1.extend(vec2), (Unorm8x4(vec1), Unorm8x4(vec2)) => vec1.extend(vec2), _ => panic!( "Incompatible vertex attribute types {} and {}", From c9bf41079f70e02845ac8bcb9171b8555a377361 Mon Sep 17 00:00:00 2001 From: Joona Aalto Date: Sun, 21 Jan 2024 19:40:55 +0200 Subject: [PATCH 3/4] Use vertex position count for index offset, document attribute mismatch --- crates/bevy_render/src/mesh/mesh/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/bevy_render/src/mesh/mesh/mod.rs b/crates/bevy_render/src/mesh/mesh/mod.rs index 0b98876b05bae..b72e82f4fc55e 100644 --- a/crates/bevy_render/src/mesh/mesh/mod.rs +++ b/crates/bevy_render/src/mesh/mesh/mod.rs @@ -574,6 +574,8 @@ impl Mesh { /// Merges the [`Mesh`] data of `other` with `self`. The attributes and indices of `other` will be appended to `self`. /// + /// Note that attributes of `other` that don't exist on `self` will be ignored. + /// /// # Panics /// /// Panics if the vertex attribute values of `other` are incompatible with `self`. @@ -583,7 +585,10 @@ impl Mesh { use VertexAttributeValues::*; // The indices of `other` should start after the last vertex of `self`. - let index_offset = self.count_vertices(); + let index_offset = self + .attribute(Mesh::ATTRIBUTE_POSITION) + .get_or_insert(&VertexAttributeValues::Float32x3(Vec::default())) + .len(); // Extend attributes of `self` with attributes of `other`. for (id, values) in self.attributes_mut() { From 3749ca8bf3e127f23d1ddbd98a67b2b13e6f35bc Mon Sep 17 00:00:00 2001 From: Joona Aalto Date: Mon, 12 Feb 2024 22:55:22 +0200 Subject: [PATCH 4/4] Fix missing closing delimiters --- crates/bevy_render/src/mesh/mesh/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_render/src/mesh/mesh/mod.rs b/crates/bevy_render/src/mesh/mesh/mod.rs index 2ae6170cf3e58..07e3dd0af00d6 100644 --- a/crates/bevy_render/src/mesh/mesh/mod.rs +++ b/crates/bevy_render/src/mesh/mesh/mod.rs @@ -666,6 +666,8 @@ impl Mesh { i1.extend(i2.iter().map(|i| *i as u32 + index_offset as u32)); } } + } + } /// Transforms the vertex positions, normals, and tangents of the mesh by the given [`Transform`]. pub fn transformed_by(mut self, transform: Transform) -> Self {