Skip to main content

bevy_mesh/
mesh.rs

1use bevy_transform::components::Transform;
2pub use wgpu_types::PrimitiveTopology;
3
4use super::{
5    skinning::{SkinnedMeshBounds, SkinnedMeshBoundsError},
6    triangle_area_normal, triangle_normal, FourIterators, Indices, MeshAttributeData,
7    MeshTrianglesError, MeshVertexAttribute, MeshVertexAttributeId, MeshVertexBufferLayout,
8    MeshVertexBufferLayoutRef, MeshVertexBufferLayouts, MeshWindingInvertError,
9    VertexAttributeValues, VertexBufferLayout,
10};
11#[cfg(feature = "morph")]
12use crate::morph::MorphAttributes;
13#[cfg(feature = "serialize")]
14use crate::SerializedMeshAttributeData;
15use alloc::collections::BTreeMap;
16use bevy_asset::{Asset, RenderAssetUsages};
17use bevy_math::{bounding::Aabb3d, primitives::Triangle3d, *};
18use bevy_platform::collections::{hash_map, HashMap};
19use bevy_reflect::{std_traits::ReflectDefault, Reflect};
20use bytemuck::cast_slice;
21use core::hash::{Hash, Hasher};
22use core::ptr;
23#[cfg(feature = "serialize")]
24use serde::{Deserialize, Serialize};
25use thiserror::Error;
26use tracing::warn;
27use wgpu_types::{VertexAttribute, VertexFormat, VertexStepMode, WriteOnly};
28
29pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0;
30pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
31
32/// Error from accessing mesh vertex attributes or indices
33#[derive(#[allow(unused_qualifications)]
#[automatically_derived]
impl ::core::fmt::Display for MeshAccessError {
    fn fmt(&self, __formatter: &mut ::core::fmt::Formatter)
        -> ::core::fmt::Result {

        #[allow(unused_variables, deprecated, clippy ::
        used_underscore_binding)]
        match self {
            MeshAccessError::ExtractedToRenderWorld {} =>
                __formatter.write_str("The mesh vertex/index data has been extracted to the RenderWorld (via `Mesh::asset_usage`)"),
            MeshAccessError::NotFound {} =>
                __formatter.write_str("The requested mesh data wasn't found in this mesh"),
        }
    }
}Error, #[automatically_derived]
impl ::core::fmt::Debug for MeshAccessError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                MeshAccessError::ExtractedToRenderWorld =>
                    "ExtractedToRenderWorld",
                MeshAccessError::NotFound => "NotFound",
            })
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for MeshAccessError {
    #[inline]
    fn clone(&self) -> MeshAccessError {
        match self {
            MeshAccessError::ExtractedToRenderWorld =>
                MeshAccessError::ExtractedToRenderWorld,
            MeshAccessError::NotFound => MeshAccessError::NotFound,
        }
    }
}Clone)]
34pub enum MeshAccessError {
35    #[error("The mesh vertex/index data has been extracted to the RenderWorld (via `Mesh::asset_usage`)")]
36    ExtractedToRenderWorld,
37    #[error("The requested mesh data wasn't found in this mesh")]
38    NotFound,
39}
40
41const MESH_EXTRACTED_ERROR: &str = "Mesh has been extracted to RenderWorld. To access vertex attributes, the mesh `asset_usage` must include `MAIN_WORLD`";
42
43// storage for extractable data with access methods which return errors if the
44// contents have already been extracted
45#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for MeshExtractableData<T> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            MeshExtractableData::Data(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Data",
                    &__self_0),
            MeshExtractableData::NoData =>
                ::core::fmt::Formatter::write_str(f, "NoData"),
            MeshExtractableData::ExtractedToRenderWorld =>
                ::core::fmt::Formatter::write_str(f,
                    "ExtractedToRenderWorld"),
        }
    }
}Debug, #[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for MeshExtractableData<T>
    {
    #[inline]
    fn clone(&self) -> MeshExtractableData<T> {
        match self {
            MeshExtractableData::Data(__self_0) =>
                MeshExtractableData::Data(::core::clone::Clone::clone(__self_0)),
            MeshExtractableData::NoData => MeshExtractableData::NoData,
            MeshExtractableData::ExtractedToRenderWorld =>
                MeshExtractableData::ExtractedToRenderWorld,
        }
    }
}Clone, #[automatically_derived]
impl<T: ::core::cmp::PartialEq> ::core::cmp::PartialEq for
    MeshExtractableData<T> {
    #[inline]
    fn eq(&self, other: &MeshExtractableData<T>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (MeshExtractableData::Data(__self_0),
                    MeshExtractableData::Data(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, const _: () =
    {
        impl<T> bevy_reflect::GetTypeRegistration for MeshExtractableData<T>
            where MeshExtractableData<T>: ::core::any::Any +
            ::core::marker::Send + ::core::marker::Sync,
            T: bevy_reflect::TypePath, T: bevy_reflect::FromReflect +
            bevy_reflect::TypePath + bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <T as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl<T> bevy_reflect::Typed for MeshExtractableData<T> where
            MeshExtractableData<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            T: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::GenericTypeInfoCell =
                    bevy_reflect::utility::GenericTypeInfoCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Data",
                                                            &[bevy_reflect::UnnamedField::new::<T>(0usize)])),
                                                    bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("NoData")),
                                                    bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("ExtractedToRenderWorld"))]).with_generics(bevy_reflect::Generics::from_iter([bevy_reflect::GenericInfo::Type(bevy_reflect::TypeParamInfo::new::<T>(bevy_reflect::__macro_exports::alloc_utils::Cow::Borrowed("T")))])))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl<T> bevy_reflect::TypePath for MeshExtractableData<T> where
            MeshExtractableData<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            fn type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("bevy_mesh::mesh::MeshExtractableData<"),
                                    <T as bevy_reflect::TypePath>::type_path()), ">")
                        })
            }
            fn short_type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("MeshExtractableData<"),
                                    <T as bevy_reflect::TypePath>::short_type_path()), ">")
                        })
            }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("MeshExtractableData")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_mesh::mesh".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_mesh::mesh")
            }
        }
        impl<T> bevy_reflect::Reflect for MeshExtractableData<T> where
            MeshExtractableData<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            T: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl<T> bevy_reflect::enums::Enum for MeshExtractableData<T> where
            MeshExtractableData<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            T: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn field(&self, __name_param: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at(&self, __index_param: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    MeshExtractableData::Data { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, __name_param: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at_mut(&mut self, __index_param: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self {
                    MeshExtractableData::Data { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of(&self, __name_param: &str)
                -> ::core::option::Option<usize> {
                match self { _ => ::core::option::Option::None, }
            }
            fn name_at(&self, __index_param: usize)
                -> ::core::option::Option<&str> {
                match self { _ => ::core::option::Option::None, }
            }
            fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
                bevy_reflect::enums::VariantFieldIter::new(self)
            }
            #[inline]
            fn field_len(&self) -> usize {
                match self {
                    MeshExtractableData::Data { .. } => 1usize,
                    MeshExtractableData::NoData { .. } => 0usize,
                    MeshExtractableData::ExtractedToRenderWorld { .. } =>
                        0usize,
                    _ => 0,
                }
            }
            #[inline]
            fn variant_name(&self) -> &str {
                match self {
                    MeshExtractableData::Data { .. } => "Data",
                    MeshExtractableData::NoData { .. } => "NoData",
                    MeshExtractableData::ExtractedToRenderWorld { .. } =>
                        "ExtractedToRenderWorld",
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_index(&self) -> usize {
                match self {
                    MeshExtractableData::Data { .. } => 0usize,
                    MeshExtractableData::NoData { .. } => 1usize,
                    MeshExtractableData::ExtractedToRenderWorld { .. } =>
                        2usize,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_type(&self) -> bevy_reflect::enums::VariantType {
                match self {
                    MeshExtractableData::Data { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    MeshExtractableData::NoData { .. } =>
                        bevy_reflect::enums::VariantType::Unit,
                    MeshExtractableData::ExtractedToRenderWorld { .. } =>
                        bevy_reflect::enums::VariantType::Unit,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            fn to_dynamic_enum(&self) -> bevy_reflect::enums::DynamicEnum {
                bevy_reflect::enums::DynamicEnum::from_ref::<Self>(self)
            }
        }
        impl<T> bevy_reflect::PartialReflect for MeshExtractableData<T> where
            MeshExtractableData<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            T: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self,
                __value_param: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Enum(__value_param) =
                        bevy_reflect::PartialReflect::reflect_ref(__value_param) {
                    if bevy_reflect::enums::Enum::variant_name(self) ==
                            bevy_reflect::enums::Enum::variant_name(__value_param) {
                        match bevy_reflect::enums::Enum::variant_type(__value_param)
                            {
                            bevy_reflect::enums::VariantType::Struct => {
                                for field in
                                    bevy_reflect::enums::Enum::iter_fields(__value_param) {
                                    let name = field.name().unwrap();
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_mut(self, name) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            bevy_reflect::enums::VariantType::Tuple => {
                                for (index, field) in
                                    ::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
                                    {
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_at_mut(self, index) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            _ => {}
                        }
                    } else {
                        match bevy_reflect::enums::Enum::variant_name(__value_param)
                            {
                            "Data" => {
                                *self =
                                    MeshExtractableData::Data {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Data"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <T as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<T as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "NoData" => { *self = MeshExtractableData::NoData {} }
                            "ExtractedToRenderWorld" => {
                                *self = MeshExtractableData::ExtractedToRenderWorld {}
                            }
                            name => {
                                return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
                                            enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
                                            variant_name: ::core::convert::Into::into(name),
                                        });
                            }
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
                                to_kind: bevy_reflect::ReflectKind::Enum,
                            });
                }
                ::core::result::Result::Ok(())
            }
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Enum
            }
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Enum(self)
            }
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Enum(self)
            }
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Enum(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_hash(&self) -> ::core::option::Option<u64> {
                (bevy_reflect::enums::enum_hash)(self)
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::enums::enum_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::enums::enum_partial_cmp)(self, value)
            }
            #[inline]
            #[allow(unreachable_code, reason =
            "Ignored fields without a `clone` attribute will early-return with an error")]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                let this = self;
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(match this
                            {
                            MeshExtractableData::Data { 0: __0 } =>
                                MeshExtractableData::Data {
                                    0: <T as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__0)?,
                                },
                            MeshExtractableData::NoData {} =>
                                MeshExtractableData::NoData {},
                            MeshExtractableData::ExtractedToRenderWorld {} =>
                                MeshExtractableData::ExtractedToRenderWorld {},
                        }))
            }
        }
        impl<T> bevy_reflect::FromReflect for MeshExtractableData<T> where
            MeshExtractableData<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            T: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Enum(__param0) =
                        bevy_reflect::PartialReflect::reflect_ref(__param0) {
                    match bevy_reflect::enums::Enum::variant_name(__param0) {
                        "Data" =>
                            ::core::option::Option::Some(MeshExtractableData::Data {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <T as bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        "NoData" =>
                            ::core::option::Option::Some(MeshExtractableData::NoData {}),
                        "ExtractedToRenderWorld" =>
                            ::core::option::Option::Some(MeshExtractableData::ExtractedToRenderWorld {}),
                        name => ::core::option::Option::None,
                    }
                } else { ::core::option::Option::None }
            }
        }
    };Reflect, #[automatically_derived]
impl<T> ::core::default::Default for MeshExtractableData<T> {
    #[inline]
    fn default() -> MeshExtractableData<T> { Self::NoData }
}Default)]
46enum MeshExtractableData<T> {
47    Data(T),
48    #[default]
49    NoData,
50    ExtractedToRenderWorld,
51}
52
53impl<T> MeshExtractableData<T> {
54    // get a reference to internal data. returns error if data has been extracted, or if no
55    // data exists
56    fn as_ref(&self) -> Result<&T, MeshAccessError> {
57        match self {
58            MeshExtractableData::Data(data) => Ok(data),
59            MeshExtractableData::NoData => Err(MeshAccessError::NotFound),
60            MeshExtractableData::ExtractedToRenderWorld => {
61                Err(MeshAccessError::ExtractedToRenderWorld)
62            }
63        }
64    }
65
66    // get an optional reference to internal data. returns error if data has been extracted
67    fn as_ref_option(&self) -> Result<Option<&T>, MeshAccessError> {
68        match self {
69            MeshExtractableData::Data(data) => Ok(Some(data)),
70            MeshExtractableData::NoData => Ok(None),
71            MeshExtractableData::ExtractedToRenderWorld => {
72                Err(MeshAccessError::ExtractedToRenderWorld)
73            }
74        }
75    }
76
77    // get a mutable reference to internal data. returns error if data has been extracted,
78    // or if no data exists
79    fn as_mut(&mut self) -> Result<&mut T, MeshAccessError> {
80        match self {
81            MeshExtractableData::Data(data) => Ok(data),
82            MeshExtractableData::NoData => Err(MeshAccessError::NotFound),
83            MeshExtractableData::ExtractedToRenderWorld => {
84                Err(MeshAccessError::ExtractedToRenderWorld)
85            }
86        }
87    }
88
89    // get an optional mutable reference to internal data. returns error if data has been extracted
90    fn as_mut_option(&mut self) -> Result<Option<&mut T>, MeshAccessError> {
91        match self {
92            MeshExtractableData::Data(data) => Ok(Some(data)),
93            MeshExtractableData::NoData => Ok(None),
94            MeshExtractableData::ExtractedToRenderWorld => {
95                Err(MeshAccessError::ExtractedToRenderWorld)
96            }
97        }
98    }
99
100    // extract data and replace self with `ExtractedToRenderWorld`. returns error if
101    // data has been extracted
102    fn extract(&mut self) -> Result<MeshExtractableData<T>, MeshAccessError> {
103        match core::mem::replace(self, MeshExtractableData::ExtractedToRenderWorld) {
104            MeshExtractableData::ExtractedToRenderWorld => {
105                Err(MeshAccessError::ExtractedToRenderWorld)
106            }
107            not_extracted => Ok(not_extracted),
108        }
109    }
110
111    // replace internal data. returns the existing data, or an error if data has been extracted
112    fn replace(
113        &mut self,
114        data: impl Into<MeshExtractableData<T>>,
115    ) -> Result<Option<T>, MeshAccessError> {
116        match core::mem::replace(self, data.into()) {
117            MeshExtractableData::ExtractedToRenderWorld => {
118                *self = MeshExtractableData::ExtractedToRenderWorld;
119                Err(MeshAccessError::ExtractedToRenderWorld)
120            }
121            MeshExtractableData::Data(t) => Ok(Some(t)),
122            MeshExtractableData::NoData => Ok(None),
123        }
124    }
125}
126
127impl<T> From<Option<T>> for MeshExtractableData<T> {
128    fn from(value: Option<T>) -> Self {
129        match value {
130            Some(data) => MeshExtractableData::Data(data),
131            None => MeshExtractableData::NoData,
132        }
133    }
134}
135
136/// A 3D object made out of vertices representing triangles, lines, or points,
137/// with "attribute" values for each vertex.
138///
139/// Meshes can be automatically generated by a bevy `AssetLoader` (generally by loading a `Gltf` file),
140/// or by converting a [primitive](bevy_math::primitives) using [`into`](Into).
141/// It is also possible to create one manually. They can be edited after creation.
142///
143/// Meshes can be rendered with a [`Mesh2d`](crate::Mesh2d) and `MeshMaterial2d`
144/// or [`Mesh3d`](crate::Mesh3d) and `MeshMaterial3d` for 2D and 3D respectively.
145///
146/// A [`Mesh`] in Bevy is equivalent to a "primitive" in the glTF format, for a
147/// glTF Mesh representation, see `GltfMesh`.
148///
149/// ## Manual creation
150///
151/// The following function will construct a flat mesh, to be rendered with a
152/// `StandardMaterial` or `ColorMaterial`:
153///
154/// ```
155/// # use bevy_mesh::{Mesh, Indices, PrimitiveTopology};
156/// # use bevy_asset::RenderAssetUsages;
157/// fn create_simple_parallelogram() -> Mesh {
158///     // Create a new mesh using a triangle list topology, where each set of 3 vertices composes a triangle.
159///     Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default())
160///         // Add 4 vertices, each with its own position attribute (coordinate in
161///         // 3D space), for each of the corners of the parallelogram.
162///         .with_inserted_attribute(
163///             Mesh::ATTRIBUTE_POSITION,
164///             vec![[0.0, 0.0, 0.0], [1.0, 2.0, 0.0], [2.0, 2.0, 0.0], [1.0, 0.0, 0.0]]
165///         )
166///         // Assign a UV coordinate to each vertex.
167///         .with_inserted_attribute(
168///             Mesh::ATTRIBUTE_UV_0,
169///             vec![[0.0, 1.0], [0.5, 0.0], [1.0, 0.0], [0.5, 1.0]]
170///         )
171///         // Assign normals (everything points outwards)
172///         .with_inserted_attribute(
173///             Mesh::ATTRIBUTE_NORMAL,
174///             vec![[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]]
175///         )
176///         // After defining all the vertices and their attributes, build each triangle using the
177///         // indices of the vertices that make it up in a counter-clockwise order.
178///         .with_inserted_indices(Indices::U32(vec![
179///             // First triangle
180///             0, 3, 1,
181///             // Second triangle
182///             1, 3, 2
183///         ]))
184/// }
185/// ```
186///
187/// You can see how it looks like [here](https://github.com/bevyengine/bevy/blob/main/assets/docs/Mesh.png),
188/// used in a [`Mesh3d`](crate::Mesh3d) with a square bevy logo texture, with added axis, points,
189/// lines and text for clarity.
190///
191/// ## Other examples
192///
193/// For further visualization, explanation, and examples, see the built-in Bevy examples,
194/// and the [implementation of the built-in shapes](https://github.com/bevyengine/bevy/tree/main/crates/bevy_mesh/src/primitives).
195/// In particular, [generate_custom_mesh](https://github.com/bevyengine/bevy/blob/main/examples/3d/generate_custom_mesh.rs)
196/// teaches you to access and modify the attributes of a [`Mesh`] after creating it.
197///
198/// ## Common points of confusion
199///
200/// - UV maps in Bevy start at the top-left, see [`ATTRIBUTE_UV_0`](Mesh::ATTRIBUTE_UV_0),
201///   other APIs can have other conventions, `OpenGL` starts at bottom-left.
202/// - It is possible and sometimes useful for multiple vertices to have the same
203///   [position attribute](Mesh::ATTRIBUTE_POSITION) value,
204///   it's a common technique in 3D modeling for complex UV mapping or other calculations.
205/// - Bevy performs frustum culling based on the `Aabb` of meshes, which is calculated
206///   and added automatically for new meshes only. If a mesh is modified, the entity's `Aabb`
207///   needs to be updated manually or deleted so that it is re-calculated.
208///
209/// ## Use with `StandardMaterial`
210///
211/// To render correctly with `StandardMaterial`, a mesh needs to have properly defined:
212/// - [`UVs`](Mesh::ATTRIBUTE_UV_0): Bevy needs to know how to map a texture onto the mesh
213///   (also true for `ColorMaterial`).
214/// - [`Normals`](Mesh::ATTRIBUTE_NORMAL): Bevy needs to know how light interacts with your mesh.
215///   [0.0, 0.0, 1.0] is very common for simple flat meshes on the XY plane,
216///   because simple meshes are smooth and they don't require complex light calculations.
217/// - Vertex winding order: by default, `StandardMaterial.cull_mode` is `Some(Face::Back)`,
218///   which means that Bevy would *only* render the "front" of each triangle, which
219///   is the side of the triangle from where the vertices appear in a *counter-clockwise* order.
220///
221/// ## Remote Inspection
222///
223/// To transmit a [`Mesh`] between two running Bevy apps, e.g. through BRP, use [`SerializedMesh`].
224/// This type is only meant for short-term transmission between same versions and should not be stored anywhere.
225#[derive(impl bevy_asset::VisitAssetDependencies for Mesh {
    fn visit_dependencies(&self,
        visit: &mut impl ::core::ops::FnMut(bevy_asset::UntypedAssetId)) {}
}Asset, #[automatically_derived]
impl ::core::fmt::Debug for Mesh {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["primitive_topology", "attributes", "indices", "morph_targets",
                        "morph_target_names", "asset_usage", "enable_raytracing",
                        "final_aabb", "skinned_mesh_bounds"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.primitive_topology, &self.attributes, &self.indices,
                        &self.morph_targets, &self.morph_target_names,
                        &self.asset_usage, &self.enable_raytracing,
                        &self.final_aabb, &&self.skinned_mesh_bounds];
        ::core::fmt::Formatter::debug_struct_fields_finish(f, "Mesh", names,
            values)
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Mesh {
    #[inline]
    fn clone(&self) -> Mesh {
        Mesh {
            primitive_topology: ::core::clone::Clone::clone(&self.primitive_topology),
            attributes: ::core::clone::Clone::clone(&self.attributes),
            indices: ::core::clone::Clone::clone(&self.indices),
            morph_targets: ::core::clone::Clone::clone(&self.morph_targets),
            morph_target_names: ::core::clone::Clone::clone(&self.morph_target_names),
            asset_usage: ::core::clone::Clone::clone(&self.asset_usage),
            enable_raytracing: ::core::clone::Clone::clone(&self.enable_raytracing),
            final_aabb: ::core::clone::Clone::clone(&self.final_aabb),
            skinned_mesh_bounds: ::core::clone::Clone::clone(&self.skinned_mesh_bounds),
        }
    }
}Clone, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for Mesh where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <MeshExtractableData<Indices> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <MeshExtractableData<Vec<MorphAttributes>> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <MeshExtractableData<Vec<String>> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <RenderAssetUsages as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <bool as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Option<Aabb3d> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Option<SkinnedMeshBounds> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for Mesh where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<MeshExtractableData<Indices>>("indices"),
                                                bevy_reflect::NamedField::new::<MeshExtractableData<Vec<MorphAttributes>>>("morph_targets"),
                                                bevy_reflect::NamedField::new::<MeshExtractableData<Vec<String>>>("morph_target_names"),
                                                bevy_reflect::NamedField::new::<RenderAssetUsages>("asset_usage"),
                                                bevy_reflect::NamedField::new::<bool>("enable_raytracing"),
                                                bevy_reflect::NamedField::new::<Option<Aabb3d>>("final_aabb"),
                                                bevy_reflect::NamedField::new::<Option<SkinnedMeshBounds>>("skinned_mesh_bounds")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for Mesh where  {
            fn type_path() -> &'static str { "bevy_mesh::mesh::Mesh" }
            fn short_type_path() -> &'static str { "Mesh" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("Mesh")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_mesh::mesh".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_mesh::mesh")
            }
        }
        impl bevy_reflect::Reflect for Mesh where  {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        #[allow(non_upper_case_globals)]
        const _: () =
            {
                static __INVENTORY: ::inventory::Node =
                    ::inventory::Node {
                        value: &{
                                bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<Mesh
                                        as
                                        bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
                            },
                        next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
                    };
                #[link_section = ".text.startup"]
                unsafe extern "C" fn __ctor() {
                    unsafe {
                        ::inventory::ErasedNode::submit(__INVENTORY.value,
                            &__INVENTORY)
                    }
                }
                #[used]
                #[link_section = ".init_array"]
                static __CTOR: unsafe extern "C" fn() = __ctor;
            };
        impl bevy_reflect::structs::Struct for Mesh where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "indices" => ::core::option::Option::Some(&self.indices),
                    "morph_targets" =>
                        ::core::option::Option::Some(&self.morph_targets),
                    "morph_target_names" =>
                        ::core::option::Option::Some(&self.morph_target_names),
                    "asset_usage" =>
                        ::core::option::Option::Some(&self.asset_usage),
                    "enable_raytracing" =>
                        ::core::option::Option::Some(&self.enable_raytracing),
                    "final_aabb" =>
                        ::core::option::Option::Some(&self.final_aabb),
                    "skinned_mesh_bounds" =>
                        ::core::option::Option::Some(&self.skinned_mesh_bounds),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "indices" =>
                        ::core::option::Option::Some(&mut self.indices),
                    "morph_targets" =>
                        ::core::option::Option::Some(&mut self.morph_targets),
                    "morph_target_names" =>
                        ::core::option::Option::Some(&mut self.morph_target_names),
                    "asset_usage" =>
                        ::core::option::Option::Some(&mut self.asset_usage),
                    "enable_raytracing" =>
                        ::core::option::Option::Some(&mut self.enable_raytracing),
                    "final_aabb" =>
                        ::core::option::Option::Some(&mut self.final_aabb),
                    "skinned_mesh_bounds" =>
                        ::core::option::Option::Some(&mut self.skinned_mesh_bounds),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&self.indices),
                    1usize => ::core::option::Option::Some(&self.morph_targets),
                    2usize =>
                        ::core::option::Option::Some(&self.morph_target_names),
                    3usize => ::core::option::Option::Some(&self.asset_usage),
                    4usize =>
                        ::core::option::Option::Some(&self.enable_raytracing),
                    5usize => ::core::option::Option::Some(&self.final_aabb),
                    6usize =>
                        ::core::option::Option::Some(&self.skinned_mesh_bounds),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&mut self.indices),
                    1usize =>
                        ::core::option::Option::Some(&mut self.morph_targets),
                    2usize =>
                        ::core::option::Option::Some(&mut self.morph_target_names),
                    3usize =>
                        ::core::option::Option::Some(&mut self.asset_usage),
                    4usize =>
                        ::core::option::Option::Some(&mut self.enable_raytracing),
                    5usize =>
                        ::core::option::Option::Some(&mut self.final_aabb),
                    6usize =>
                        ::core::option::Option::Some(&mut self.skinned_mesh_bounds),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("indices"),
                    1usize => ::core::option::Option::Some("morph_targets"),
                    2usize =>
                        ::core::option::Option::Some("morph_target_names"),
                    3usize => ::core::option::Option::Some("asset_usage"),
                    4usize => ::core::option::Option::Some("enable_raytracing"),
                    5usize => ::core::option::Option::Some("final_aabb"),
                    6usize =>
                        ::core::option::Option::Some("skinned_mesh_bounds"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "indices" => ::core::option::Option::Some(0usize),
                    "morph_targets" => ::core::option::Option::Some(1usize),
                    "morph_target_names" =>
                        ::core::option::Option::Some(2usize),
                    "asset_usage" => ::core::option::Option::Some(3usize),
                    "enable_raytracing" => ::core::option::Option::Some(4usize),
                    "final_aabb" => ::core::option::Option::Some(5usize),
                    "skinned_mesh_bounds" =>
                        ::core::option::Option::Some(6usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 7usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                -> bevy_reflect::structs::DynamicStruct {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("indices",
                    bevy_reflect::PartialReflect::to_dynamic(&self.indices));
                dynamic.insert_boxed("morph_targets",
                    bevy_reflect::PartialReflect::to_dynamic(&self.morph_targets));
                dynamic.insert_boxed("morph_target_names",
                    bevy_reflect::PartialReflect::to_dynamic(&self.morph_target_names));
                dynamic.insert_boxed("asset_usage",
                    bevy_reflect::PartialReflect::to_dynamic(&self.asset_usage));
                dynamic.insert_boxed("enable_raytracing",
                    bevy_reflect::PartialReflect::to_dynamic(&self.enable_raytracing));
                dynamic.insert_boxed("final_aabb",
                    bevy_reflect::PartialReflect::to_dynamic(&self.final_aabb));
                dynamic.insert_boxed("skinned_mesh_bounds",
                    bevy_reflect::PartialReflect::to_dynamic(&self.skinned_mesh_bounds));
                dynamic
            }
        }
        impl bevy_reflect::PartialReflect for Mesh where  {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Struct(struct_value) =
                        bevy_reflect::PartialReflect::reflect_ref(value) {
                    for (name, value) in
                        bevy_reflect::structs::Struct::iter_fields(struct_value) {
                        if let ::core::option::Option::Some(v) =
                                bevy_reflect::structs::Struct::field_mut(self, name) {
                            bevy_reflect::PartialReflect::try_apply(v, value)?;
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
                                to_kind: bevy_reflect::ReflectKind::Struct,
                            });
                }
                ::core::result::Result::Ok(())
            }
            #[inline]
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Struct
            }
            #[inline]
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Struct(self)
            }
            #[inline]
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Struct(self)
            }
            #[inline]
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Struct(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::structs::struct_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::structs::struct_partial_cmp)(self, value)
            }
            #[inline]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for Mesh where  {
            fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
                        bevy_reflect::PartialReflect::reflect_ref(reflect) {
                    let __this =
                        Self {
                            indices: <MeshExtractableData<Indices> as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "indices")?)?,
                            morph_targets: <MeshExtractableData<Vec<MorphAttributes>> as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "morph_targets")?)?,
                            morph_target_names: <MeshExtractableData<Vec<String>> as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "morph_target_names")?)?,
                            asset_usage: <RenderAssetUsages as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "asset_usage")?)?,
                            enable_raytracing: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "enable_raytracing")?)?,
                            final_aabb: <Option<Aabb3d> as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "final_aabb")?)?,
                            skinned_mesh_bounds: <Option<SkinnedMeshBounds> as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "skinned_mesh_bounds")?)?,
                            primitive_topology: ::core::default::Default::default(),
                            attributes: ::core::default::Default::default(),
                        };
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect, #[automatically_derived]
impl ::core::cmp::PartialEq for Mesh {
    #[inline]
    fn eq(&self, other: &Mesh) -> bool {
        self.enable_raytracing == other.enable_raytracing &&
                                        self.primitive_topology == other.primitive_topology &&
                                    self.attributes == other.attributes &&
                                self.indices == other.indices &&
                            self.morph_targets == other.morph_targets &&
                        self.morph_target_names == other.morph_target_names &&
                    self.asset_usage == other.asset_usage &&
                self.final_aabb == other.final_aabb &&
            self.skinned_mesh_bounds == other.skinned_mesh_bounds
    }
}PartialEq)]
226#[reflect(Clone)]
227pub struct Mesh {
228    #[reflect(ignore, clone)]
229    primitive_topology: PrimitiveTopology,
230    /// `std::collections::BTreeMap` with all defined vertex attributes (Positions, Normals, ...)
231    /// for this mesh. Attribute ids to attribute values.
232    /// Uses a [`BTreeMap`] because, unlike `HashMap`, it has a defined iteration order,
233    /// which allows easy stable `VertexBuffers` (i.e. same buffer order)
234    #[reflect(ignore, clone)]
235    attributes: MeshExtractableData<BTreeMap<MeshVertexAttributeId, MeshAttributeData>>,
236    indices: MeshExtractableData<Indices>,
237    #[cfg(feature = "morph")]
238    morph_targets: MeshExtractableData<Vec<MorphAttributes>>,
239    #[cfg(feature = "morph")]
240    morph_target_names: MeshExtractableData<Vec<String>>,
241    pub asset_usage: RenderAssetUsages,
242    /// Whether or not to build a BLAS for use with `bevy_solari` raytracing.
243    ///
244    /// Note that this is _not_ whether the mesh is _compatible_ with `bevy_solari` raytracing.
245    /// This field just controls whether or not a BLAS gets built for this mesh, assuming that
246    /// the mesh is compatible.
247    ///
248    /// The use case for this field is using lower-resolution proxy meshes for raytracing (to save on BLAS memory usage),
249    /// while using higher-resolution meshes for raster. You can set this field to true for the lower-resolution proxy mesh,
250    /// and to false for the high-resolution raster mesh.
251    ///
252    /// Alternatively, you can use the same mesh for both raster and raytracing, with this field set to true.
253    ///
254    /// Does nothing if not used with `bevy_solari`, or if the mesh is not compatible
255    /// with `bevy_solari` (see `bevy_solari`'s docs).
256    pub enable_raytracing: bool,
257    /// Precomputed min and max extents of the mesh position data. Used mainly for constructing `Aabb`s for frustum culling.
258    /// This data will be set if/when a mesh is extracted to the GPU
259    pub final_aabb: Option<Aabb3d>,
260    skinned_mesh_bounds: Option<SkinnedMeshBounds>,
261}
262
263impl Mesh {
264    /// Where the vertex is located in space. Use in conjunction with [`Mesh::insert_attribute`]
265    /// or [`Mesh::with_inserted_attribute`].
266    ///
267    /// The format of this attribute is [`VertexFormat::Float32x3`].
268    pub const ATTRIBUTE_POSITION: MeshVertexAttribute =
269        MeshVertexAttribute::new("Vertex_Position", 0, VertexFormat::Float32x3);
270
271    /// The direction the vertex normal is facing in.
272    /// Use in conjunction with [`Mesh::insert_attribute`] or [`Mesh::with_inserted_attribute`].
273    ///
274    /// The format of this attribute is [`VertexFormat::Float32x3`].
275    pub const ATTRIBUTE_NORMAL: MeshVertexAttribute =
276        MeshVertexAttribute::new("Vertex_Normal", 1, VertexFormat::Float32x3);
277
278    /// Texture coordinates for the vertex. Use in conjunction with [`Mesh::insert_attribute`]
279    /// or [`Mesh::with_inserted_attribute`].
280    ///
281    /// Generally `[0.,0.]` is mapped to the top left of the texture, and `[1.,1.]` to the bottom-right.
282    ///
283    /// By default values outside will be clamped per pixel not for the vertex,
284    /// "stretching" the borders of the texture.
285    /// This behavior can be useful in some cases, usually when the borders have only
286    /// one color, for example a logo, and you want to "extend" those borders.
287    ///
288    /// For different mapping outside of `0..=1` range,
289    /// see [`ImageAddressMode`](https://docs.rs/bevy_image/latest/bevy_image/enum.ImageAddressMode.html).
290    ///
291    /// The format of this attribute is [`VertexFormat::Float32x2`].
292    pub const ATTRIBUTE_UV_0: MeshVertexAttribute =
293        MeshVertexAttribute::new("Vertex_Uv", 2, VertexFormat::Float32x2);
294
295    /// Alternate texture coordinates for the vertex. Use in conjunction with
296    /// [`Mesh::insert_attribute`] or [`Mesh::with_inserted_attribute`].
297    ///
298    /// Typically, these are used for lightmaps, textures that provide
299    /// precomputed illumination.
300    ///
301    /// The format of this attribute is [`VertexFormat::Float32x2`].
302    pub const ATTRIBUTE_UV_1: MeshVertexAttribute =
303        MeshVertexAttribute::new("Vertex_Uv_1", 3, VertexFormat::Float32x2);
304
305    /// The direction of the vertex tangent. Used for normal mapping.
306    /// Usually generated with [`generate_tangents`](Mesh::generate_tangents) or
307    /// [`with_generated_tangents`](Mesh::with_generated_tangents).
308    ///
309    /// The format of this attribute is [`VertexFormat::Float32x4`].
310    pub const ATTRIBUTE_TANGENT: MeshVertexAttribute =
311        MeshVertexAttribute::new("Vertex_Tangent", 4, VertexFormat::Float32x4);
312
313    /// Per vertex coloring. Use in conjunction with [`Mesh::insert_attribute`]
314    /// or [`Mesh::with_inserted_attribute`].
315    ///
316    /// The format of this attribute is [`VertexFormat::Float32x4`].
317    pub const ATTRIBUTE_COLOR: MeshVertexAttribute =
318        MeshVertexAttribute::new("Vertex_Color", 5, VertexFormat::Float32x4);
319
320    /// Per vertex joint transform matrix weight. Use in conjunction with [`Mesh::insert_attribute`]
321    /// or [`Mesh::with_inserted_attribute`].
322    ///
323    /// The format of this attribute is [`VertexFormat::Float32x4`].
324    pub const ATTRIBUTE_JOINT_WEIGHT: MeshVertexAttribute =
325        MeshVertexAttribute::new("Vertex_JointWeight", 6, VertexFormat::Float32x4);
326
327    /// Per vertex joint transform matrix index. Use in conjunction with [`Mesh::insert_attribute`]
328    /// or [`Mesh::with_inserted_attribute`].
329    ///
330    /// The format of this attribute is [`VertexFormat::Uint16x4`].
331    pub const ATTRIBUTE_JOINT_INDEX: MeshVertexAttribute =
332        MeshVertexAttribute::new("Vertex_JointIndex", 7, VertexFormat::Uint16x4);
333
334    /// The first index that can be used for custom vertex attributes.
335    /// Only the attributes with an index below this are used by Bevy.
336    pub const FIRST_AVAILABLE_CUSTOM_ATTRIBUTE: u64 = 8;
337
338    /// Construct a new mesh. You need to provide a [`PrimitiveTopology`] so that the
339    /// renderer knows how to treat the vertex data. Most of the time this will be
340    /// [`PrimitiveTopology::TriangleList`].
341    pub fn new(primitive_topology: PrimitiveTopology, asset_usage: RenderAssetUsages) -> Self {
342        Mesh {
343            primitive_topology,
344            attributes: MeshExtractableData::Data(Default::default()),
345            indices: MeshExtractableData::NoData,
346            #[cfg(feature = "morph")]
347            morph_targets: MeshExtractableData::NoData,
348            #[cfg(feature = "morph")]
349            morph_target_names: MeshExtractableData::NoData,
350            asset_usage,
351            enable_raytracing: true,
352            final_aabb: None,
353            skinned_mesh_bounds: None,
354        }
355    }
356
357    /// Returns the topology of the mesh.
358    pub fn primitive_topology(&self) -> PrimitiveTopology {
359        self.primitive_topology
360    }
361
362    /// Sets the data for a vertex attribute (position, normal, etc.). The name will
363    /// often be one of the associated constants such as [`Mesh::ATTRIBUTE_POSITION`].
364    ///
365    /// `Aabb` of entities with modified mesh are not updated automatically.
366    ///
367    /// # Panics
368    /// Panics when the format of the values does not match the attribute's format.
369    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
370    /// this as an error use [`Mesh::try_insert_attribute`]
371    #[inline]
372    pub fn insert_attribute(
373        &mut self,
374        attribute: MeshVertexAttribute,
375        values: impl Into<VertexAttributeValues>,
376    ) {
377        self.try_insert_attribute(attribute, values)
378            .expect(MESH_EXTRACTED_ERROR);
379    }
380
381    /// Sets the data for a vertex attribute (position, normal, etc.). The name will
382    /// often be one of the associated constants such as [`Mesh::ATTRIBUTE_POSITION`].
383    ///
384    /// `Aabb` of entities with modified mesh are not updated automatically.
385    ///
386    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
387    ///
388    /// # Panics
389    /// Panics when the format of the values does not match the attribute's format.
390    #[inline]
391    pub fn try_insert_attribute(
392        &mut self,
393        attribute: MeshVertexAttribute,
394        values: impl Into<VertexAttributeValues>,
395    ) -> Result<(), MeshAccessError> {
396        let values = values.into();
397        let values_format = VertexFormat::from(&values);
398        if values_format != attribute.format {
399            {
    ::core::panicking::panic_fmt(format_args!("Failed to insert attribute. Invalid attribute format for {0}. Given format is {2:?} but expected {1:?}",
            attribute.name, attribute.format, values_format));
};panic!(
400                "Failed to insert attribute. Invalid attribute format for {}. Given format is {values_format:?} but expected {:?}",
401                attribute.name, attribute.format
402            );
403        }
404
405        self.attributes
406            .as_mut()?
407            .insert(attribute.id, MeshAttributeData { attribute, values });
408        Ok(())
409    }
410
411    /// Consumes the mesh and returns a mesh with data set for a vertex attribute (position, normal, etc.).
412    /// The name will often be one of the associated constants such as [`Mesh::ATTRIBUTE_POSITION`].
413    ///
414    /// (Alternatively, you can use [`Mesh::insert_attribute`] to mutate an existing mesh in-place)
415    ///
416    /// `Aabb` of entities with modified mesh are not updated automatically.
417    ///
418    /// # Panics
419    /// Panics when the format of the values does not match the attribute's format.
420    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
421    /// this as an error use [`Mesh::try_with_inserted_attribute`]
422    #[must_use]
423    #[inline]
424    pub fn with_inserted_attribute(
425        mut self,
426        attribute: MeshVertexAttribute,
427        values: impl Into<VertexAttributeValues>,
428    ) -> Self {
429        self.insert_attribute(attribute, values);
430        self
431    }
432
433    /// Consumes the mesh and returns a mesh with data set for a vertex attribute (position, normal, etc.).
434    /// The name will often be one of the associated constants such as [`Mesh::ATTRIBUTE_POSITION`].
435    ///
436    /// (Alternatively, you can use [`Mesh::insert_attribute`] to mutate an existing mesh in-place)
437    ///
438    /// `Aabb` of entities with modified mesh are not updated automatically.
439    ///
440    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
441    #[inline]
442    pub fn try_with_inserted_attribute(
443        mut self,
444        attribute: MeshVertexAttribute,
445        values: impl Into<VertexAttributeValues>,
446    ) -> Result<Self, MeshAccessError> {
447        self.try_insert_attribute(attribute, values)?;
448        Ok(self)
449    }
450
451    /// Removes the data for a vertex attribute
452    ///
453    /// # Panics
454    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
455    /// this as an error use [`Mesh::try_remove_attribute`]
456    pub fn remove_attribute(
457        &mut self,
458        attribute: impl Into<MeshVertexAttributeId>,
459    ) -> Option<VertexAttributeValues> {
460        self.attributes
461            .as_mut()
462            .expect(MESH_EXTRACTED_ERROR)
463            .remove(&attribute.into())
464            .map(|data| data.values)
465    }
466
467    /// Removes the data for a vertex attribute
468    /// Returns an error if the mesh data has been extracted to `RenderWorld`or
469    /// if the attribute does not exist.
470    pub fn try_remove_attribute(
471        &mut self,
472        attribute: impl Into<MeshVertexAttributeId>,
473    ) -> Result<VertexAttributeValues, MeshAccessError> {
474        Ok(self
475            .attributes
476            .as_mut()?
477            .remove(&attribute.into())
478            .ok_or(MeshAccessError::NotFound)?
479            .values)
480    }
481
482    /// Consumes the mesh and returns a mesh without the data for a vertex attribute
483    ///
484    /// (Alternatively, you can use [`Mesh::remove_attribute`] to mutate an existing mesh in-place)
485    ///
486    /// # Panics
487    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
488    /// this as an error use [`Mesh::try_with_removed_attribute`]
489    #[must_use]
490    pub fn with_removed_attribute(mut self, attribute: impl Into<MeshVertexAttributeId>) -> Self {
491        self.remove_attribute(attribute);
492        self
493    }
494
495    /// Consumes the mesh and returns a mesh without the data for a vertex attribute
496    ///
497    /// (Alternatively, you can use [`Mesh::remove_attribute`] to mutate an existing mesh in-place)
498    ///
499    /// Returns an error if the mesh data has been extracted to `RenderWorld`or
500    /// if the attribute does not exist.
501    pub fn try_with_removed_attribute(
502        mut self,
503        attribute: impl Into<MeshVertexAttributeId>,
504    ) -> Result<Self, MeshAccessError> {
505        self.try_remove_attribute(attribute)?;
506        Ok(self)
507    }
508
509    /// Returns a bool indicating if the attribute is present in this mesh's vertex data.
510    ///
511    /// # Panics
512    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
513    /// this as an error use [`Mesh::try_contains_attribute`]
514    #[inline]
515    pub fn contains_attribute(&self, id: impl Into<MeshVertexAttributeId>) -> bool {
516        self.attributes
517            .as_ref()
518            .expect(MESH_EXTRACTED_ERROR)
519            .contains_key(&id.into())
520    }
521
522    /// Returns a bool indicating if the attribute is present in this mesh's vertex data.
523    ///
524    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
525    #[inline]
526    pub fn try_contains_attribute(
527        &self,
528        id: impl Into<MeshVertexAttributeId>,
529    ) -> Result<bool, MeshAccessError> {
530        Ok(self.attributes.as_ref()?.contains_key(&id.into()))
531    }
532
533    /// Retrieves the data currently set to the vertex attribute with the specified [`MeshVertexAttributeId`].
534    ///
535    /// # Panics
536    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
537    /// this as an error use [`Mesh::try_attribute`] or [`Mesh::try_attribute_option`]
538    #[inline]
539    pub fn attribute(
540        &self,
541        id: impl Into<MeshVertexAttributeId>,
542    ) -> Option<&VertexAttributeValues> {
543        self.try_attribute_option(id).expect(MESH_EXTRACTED_ERROR)
544    }
545
546    /// Retrieves the data currently set to the vertex attribute with the specified [`MeshVertexAttributeId`].
547    ///
548    /// Returns an error if the mesh data has been extracted to `RenderWorld`or
549    /// if the attribute does not exist.
550    #[inline]
551    pub fn try_attribute(
552        &self,
553        id: impl Into<MeshVertexAttributeId>,
554    ) -> Result<&VertexAttributeValues, MeshAccessError> {
555        self.try_attribute_option(id)?
556            .ok_or(MeshAccessError::NotFound)
557    }
558
559    /// Retrieves the data currently set to the vertex attribute with the specified [`MeshVertexAttributeId`].
560    ///
561    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
562    #[inline]
563    pub fn try_attribute_option(
564        &self,
565        id: impl Into<MeshVertexAttributeId>,
566    ) -> Result<Option<&VertexAttributeValues>, MeshAccessError> {
567        Ok(self
568            .attributes
569            .as_ref()?
570            .get(&id.into())
571            .map(|data| &data.values))
572    }
573
574    /// Retrieves the full data currently set to the vertex attribute with the specified [`MeshVertexAttributeId`].
575    #[inline]
576    pub(crate) fn try_attribute_data(
577        &self,
578        id: impl Into<MeshVertexAttributeId>,
579    ) -> Result<Option<&MeshAttributeData>, MeshAccessError> {
580        Ok(self.attributes.as_ref()?.get(&id.into()))
581    }
582
583    /// Retrieves the data currently set to the vertex attribute with the specified `name` mutably.
584    ///
585    /// # Panics
586    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
587    /// this as an error use [`Mesh::try_attribute_mut`]
588    #[inline]
589    pub fn attribute_mut(
590        &mut self,
591        id: impl Into<MeshVertexAttributeId>,
592    ) -> Option<&mut VertexAttributeValues> {
593        self.try_attribute_mut_option(id)
594            .expect(MESH_EXTRACTED_ERROR)
595    }
596
597    /// Retrieves the data currently set to the vertex attribute with the specified `name` mutably.
598    ///
599    /// Returns an error if the mesh data has been extracted to `RenderWorld`or
600    /// if the attribute does not exist.
601    #[inline]
602    pub fn try_attribute_mut(
603        &mut self,
604        id: impl Into<MeshVertexAttributeId>,
605    ) -> Result<&mut VertexAttributeValues, MeshAccessError> {
606        self.try_attribute_mut_option(id)?
607            .ok_or(MeshAccessError::NotFound)
608    }
609
610    /// Retrieves the data currently set to the vertex attribute with the specified `name` mutably.
611    ///
612    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
613    #[inline]
614    pub fn try_attribute_mut_option(
615        &mut self,
616        id: impl Into<MeshVertexAttributeId>,
617    ) -> Result<Option<&mut VertexAttributeValues>, MeshAccessError> {
618        Ok(self
619            .attributes
620            .as_mut()?
621            .get_mut(&id.into())
622            .map(|data| &mut data.values))
623    }
624
625    /// Returns an iterator that yields references to the data of each vertex attribute.
626    ///
627    /// # Panics
628    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
629    /// this as an error use [`Mesh::try_attributes`]
630    pub fn attributes(
631        &self,
632    ) -> impl Iterator<Item = (&MeshVertexAttribute, &VertexAttributeValues)> {
633        self.try_attributes().expect(MESH_EXTRACTED_ERROR)
634    }
635
636    /// Returns an iterator that yields references to the data of each vertex attribute.
637    /// Returns an error if data has been extracted to `RenderWorld`
638    pub fn try_attributes(
639        &self,
640    ) -> Result<impl Iterator<Item = (&MeshVertexAttribute, &VertexAttributeValues)>, MeshAccessError>
641    {
642        Ok(self
643            .attributes
644            .as_ref()?
645            .values()
646            .map(|data| (&data.attribute, &data.values)))
647    }
648
649    /// Returns an iterator that yields mutable references to the data of each vertex attribute.
650    ///
651    /// # Panics
652    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
653    /// this as an error use [`Mesh::try_attributes_mut`]
654    pub fn attributes_mut(
655        &mut self,
656    ) -> impl Iterator<Item = (&MeshVertexAttribute, &mut VertexAttributeValues)> {
657        self.try_attributes_mut().expect(MESH_EXTRACTED_ERROR)
658    }
659
660    /// Returns an iterator that yields mutable references to the data of each vertex attribute.
661    ///
662    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
663    pub fn try_attributes_mut(
664        &mut self,
665    ) -> Result<
666        impl Iterator<Item = (&MeshVertexAttribute, &mut VertexAttributeValues)>,
667        MeshAccessError,
668    > {
669        Ok(self
670            .attributes
671            .as_mut()?
672            .values_mut()
673            .map(|data| (&data.attribute, &mut data.values)))
674    }
675
676    /// Sets the vertex indices of the mesh. They describe how triangles are constructed out of the
677    /// vertex attributes and are therefore only useful for the [`PrimitiveTopology`] variants
678    /// that use triangles.
679    ///
680    /// # Panics
681    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
682    /// this as an error use [`Mesh::try_insert_indices`]
683    #[inline]
684    pub fn insert_indices(&mut self, indices: Indices) {
685        self.indices
686            .replace(Some(indices))
687            .expect(MESH_EXTRACTED_ERROR);
688    }
689
690    /// Sets the vertex indices of the mesh. They describe how triangles are constructed out of the
691    /// vertex attributes and are therefore only useful for the [`PrimitiveTopology`] variants
692    /// that use triangles.
693    ///
694    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
695    #[inline]
696    pub fn try_insert_indices(&mut self, indices: Indices) -> Result<(), MeshAccessError> {
697        self.indices.replace(Some(indices))?;
698        Ok(())
699    }
700
701    /// Consumes the mesh and returns a mesh with the given vertex indices. They describe how triangles
702    /// are constructed out of the vertex attributes and are therefore only useful for the
703    /// [`PrimitiveTopology`] variants that use triangles.
704    ///
705    /// (Alternatively, you can use [`Mesh::insert_indices`] to mutate an existing mesh in-place)
706    ///
707    /// # Panics
708    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
709    /// this as an error use [`Mesh::try_with_inserted_indices`]
710    #[must_use]
711    #[inline]
712    pub fn with_inserted_indices(mut self, indices: Indices) -> Self {
713        self.insert_indices(indices);
714        self
715    }
716
717    /// Consumes the mesh and returns a mesh with the given vertex indices. They describe how triangles
718    /// are constructed out of the vertex attributes and are therefore only useful for the
719    /// [`PrimitiveTopology`] variants that use triangles.
720    ///
721    /// (Alternatively, you can use [`Mesh::try_insert_indices`] to mutate an existing mesh in-place)
722    ///
723    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
724    #[inline]
725    pub fn try_with_inserted_indices(mut self, indices: Indices) -> Result<Self, MeshAccessError> {
726        self.try_insert_indices(indices)?;
727        Ok(self)
728    }
729
730    /// Retrieves the vertex `indices` of the mesh, returns None if not found.
731    ///
732    /// # Panics
733    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
734    /// this as an error use [`Mesh::try_indices`]
735    #[inline]
736    pub fn indices(&self) -> Option<&Indices> {
737        self.indices.as_ref_option().expect(MESH_EXTRACTED_ERROR)
738    }
739
740    /// Retrieves the vertex `indices` of the mesh.
741    ///
742    /// Returns an error if the mesh data has been extracted to `RenderWorld`or
743    /// if the attribute does not exist.
744    #[inline]
745    pub fn try_indices(&self) -> Result<&Indices, MeshAccessError> {
746        self.indices.as_ref()
747    }
748
749    /// Retrieves the vertex `indices` of the mesh, returns None if not found.
750    ///
751    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
752    #[inline]
753    pub fn try_indices_option(&self) -> Result<Option<&Indices>, MeshAccessError> {
754        self.indices.as_ref_option()
755    }
756
757    /// Retrieves the vertex `indices` of the mesh mutably.
758    #[inline]
759    pub fn indices_mut(&mut self) -> Option<&mut Indices> {
760        self.try_indices_mut_option().expect(MESH_EXTRACTED_ERROR)
761    }
762
763    /// Retrieves the vertex `indices` of the mesh mutably.
764    ///
765    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
766    #[inline]
767    pub fn try_indices_mut(&mut self) -> Result<&mut Indices, MeshAccessError> {
768        self.indices.as_mut()
769    }
770
771    /// Retrieves the vertex `indices` of the mesh mutably.
772    ///
773    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
774    #[inline]
775    pub fn try_indices_mut_option(&mut self) -> Result<Option<&mut Indices>, MeshAccessError> {
776        self.indices.as_mut_option()
777    }
778
779    /// Removes the vertex `indices` from the mesh and returns them.
780    ///
781    /// # Panics
782    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
783    /// this as an error use [`Mesh::try_remove_indices`]
784    #[inline]
785    pub fn remove_indices(&mut self) -> Option<Indices> {
786        self.try_remove_indices().expect(MESH_EXTRACTED_ERROR)
787    }
788
789    /// Removes the vertex `indices` from the mesh and returns them.
790    ///
791    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
792    #[inline]
793    pub fn try_remove_indices(&mut self) -> Result<Option<Indices>, MeshAccessError> {
794        self.indices.replace(None)
795    }
796
797    /// Consumes the mesh and returns a mesh without the vertex `indices` of the mesh.
798    ///
799    /// (Alternatively, you can use [`Mesh::remove_indices`] to mutate an existing mesh in-place)
800    ///
801    /// # Panics
802    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
803    /// this as an error use [`Mesh::try_with_removed_indices`]
804    #[must_use]
805    pub fn with_removed_indices(mut self) -> Self {
806        self.remove_indices();
807        self
808    }
809
810    /// Consumes the mesh and returns a mesh without the vertex `indices` of the mesh.
811    ///
812    /// (Alternatively, you can use [`Mesh::try_remove_indices`] to mutate an existing mesh in-place)
813    ///
814    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
815    pub fn try_with_removed_indices(mut self) -> Result<Self, MeshAccessError> {
816        self.try_remove_indices()?;
817        Ok(self)
818    }
819
820    /// Returns the size of a vertex in bytes.
821    ///
822    /// # Panics
823    /// Panics when the mesh data has already been extracted to `RenderWorld`.
824    pub fn get_vertex_size(&self) -> u64 {
825        self.attributes
826            .as_ref()
827            .expect(MESH_EXTRACTED_ERROR)
828            .values()
829            .map(|data| data.attribute.format.size())
830            .sum()
831    }
832
833    /// Returns the size required for the vertex buffer in bytes.
834    ///
835    /// # Panics
836    /// Panics when the mesh data has already been extracted to `RenderWorld`.
837    pub fn get_vertex_buffer_size(&self) -> usize {
838        let vertex_size = self.get_vertex_size() as usize;
839        let vertex_count = self.count_vertices();
840        vertex_count * vertex_size
841    }
842
843    /// Computes and returns the index data of the mesh as bytes.
844    /// This is used to transform the index data into a GPU friendly format.
845    ///
846    /// # Panics
847    /// Panics when the mesh data has already been extracted to `RenderWorld`.
848    pub fn get_index_buffer_bytes(&self) -> Option<&[u8]> {
849        let mesh_indices = self.indices.as_ref_option().expect(MESH_EXTRACTED_ERROR);
850
851        mesh_indices.as_ref().map(|indices| match &indices {
852            Indices::U16(indices) => cast_slice(&indices[..]),
853            Indices::U32(indices) => cast_slice(&indices[..]),
854        })
855    }
856
857    /// If any morph displacements are present, returns them as a
858    /// [`MorphAttributes`] array.
859    ///
860    /// # Panics
861    /// Panics when the mesh data has already been extracted to the render
862    /// world.
863    #[cfg(feature = "morph")]
864    pub fn get_morph_targets(&self) -> Option<&[MorphAttributes]> {
865        self.morph_targets
866            .as_ref_option()
867            .expect(MESH_EXTRACTED_ERROR)
868            .map(|morph_attributes| &morph_attributes[..])
869    }
870
871    /// Get this `Mesh`'s [`MeshVertexBufferLayout`], used in `SpecializedMeshPipeline`.
872    ///
873    /// # Panics
874    /// Panics when the mesh data has already been extracted to `RenderWorld`.
875    pub fn get_mesh_vertex_buffer_layout(
876        &self,
877        mesh_vertex_buffer_layouts: &mut MeshVertexBufferLayouts,
878    ) -> MeshVertexBufferLayoutRef {
879        let mesh_attributes = self.attributes.as_ref().expect(MESH_EXTRACTED_ERROR);
880
881        let mut attributes = Vec::with_capacity(mesh_attributes.len());
882        let mut attribute_ids = Vec::with_capacity(mesh_attributes.len());
883        let mut accumulated_offset = 0;
884        for (index, data) in mesh_attributes.values().enumerate() {
885            attribute_ids.push(data.attribute.id);
886            attributes.push(VertexAttribute {
887                offset: accumulated_offset,
888                format: data.attribute.format,
889                shader_location: index as u32,
890            });
891            accumulated_offset += data.attribute.format.size();
892        }
893
894        let layout = MeshVertexBufferLayout {
895            layout: VertexBufferLayout {
896                array_stride: accumulated_offset,
897                step_mode: VertexStepMode::Vertex,
898                attributes,
899            },
900            attribute_ids,
901        };
902        mesh_vertex_buffer_layouts.insert(layout)
903    }
904
905    /// Counts all vertices of the mesh.
906    ///
907    /// If the attributes have different vertex counts, the smallest is returned.
908    ///
909    /// # Panics
910    /// Panics when the mesh data has already been extracted to `RenderWorld`.
911    pub fn count_vertices(&self) -> usize {
912        let mut vertex_count: Option<usize> = None;
913        let mesh_attributes = self.attributes.as_ref().expect(MESH_EXTRACTED_ERROR);
914
915        for (attribute_id, attribute_data) in mesh_attributes {
916            let attribute_len = attribute_data.values.len();
917            if let Some(previous_vertex_count) = vertex_count {
918                if previous_vertex_count != attribute_len {
919                    let name = mesh_attributes
920                        .get(attribute_id)
921                        .map(|data| data.attribute.name.to_string())
922                        .unwrap_or_else(|| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", attribute_id))
    })format!("{attribute_id:?}"));
923
924                    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event src/mesh.rs:924",
                        "bevy_mesh::mesh", ::tracing::Level::WARN,
                        ::tracing_core::__macro_support::Option::Some("src/mesh.rs"),
                        ::tracing_core::__macro_support::Option::Some(924u32),
                        ::tracing_core::__macro_support::Option::Some("bevy_mesh::mesh"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::WARN <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("{0} has a different vertex count ({1}) than other attributes ({2}) in this mesh, all attributes will be truncated to match the smallest.",
                                                    name, attribute_len, previous_vertex_count) as
                                            &dyn ::tracing::field::Value))])
            });
    } else { ; }
};warn!("{name} has a different vertex count ({attribute_len}) than other attributes ({previous_vertex_count}) in this mesh, \
925                        all attributes will be truncated to match the smallest.");
926                    vertex_count = Some(core::cmp::min(previous_vertex_count, attribute_len));
927                }
928            } else {
929                vertex_count = Some(attribute_len);
930            }
931        }
932
933        vertex_count.unwrap_or(0)
934    }
935
936    /// Computes and returns the vertex data of the mesh as bytes.
937    /// Therefore the attributes are located in the order of their [`MeshVertexAttribute::id`].
938    /// This is used to transform the vertex data into a GPU friendly format.
939    ///
940    /// If the vertex attributes have different lengths, they are all truncated to
941    /// the length of the smallest.
942    ///
943    /// This is a convenience method which allocates a Vec.
944    /// Prefer pre-allocating and using [`Mesh::write_packed_vertex_buffer_data`] when possible.
945    ///
946    /// # Panics
947    /// Panics when the mesh data has already been extracted to `RenderWorld`.
948    pub fn create_packed_vertex_buffer_data(&self) -> Vec<u8> {
949        let mut attributes_interleaved_buffer = ::alloc::vec::from_elem(0, self.get_vertex_buffer_size())vec![0; self.get_vertex_buffer_size()];
950        self.write_packed_vertex_buffer_data(WriteOnly::from_mut(
951            &mut attributes_interleaved_buffer,
952        ));
953        attributes_interleaved_buffer
954    }
955
956    /// Computes and write the vertex data of the mesh into a mutable byte slice.
957    /// The attributes are located in the order of their [`MeshVertexAttribute::id`].
958    /// This is used to transform the vertex data into a GPU friendly format.
959    ///
960    /// If the vertex attributes have different lengths, they are all truncated to
961    /// the length of the smallest.
962    ///
963    /// # Panics
964    /// Panics when the mesh data has already been extracted to `RenderWorld`.
965    pub fn write_packed_vertex_buffer_data(&self, mut slice: WriteOnly<'_, [u8]>) {
966        let mesh_attributes = self.attributes.as_ref().expect(MESH_EXTRACTED_ERROR);
967
968        let vertex_size = self.get_vertex_size() as usize;
969        let vertex_count = self.count_vertices();
970        // bundle into interleaved buffers
971        let mut attribute_offset = 0;
972        for attribute_data in mesh_attributes.values() {
973            let attribute_size = attribute_data.attribute.format.size() as usize;
974            let attributes_bytes = attribute_data.values.get_bytes();
975            for (vertex_index, attribute_bytes) in attributes_bytes
976                .chunks_exact(attribute_size)
977                .take(vertex_count)
978                .enumerate()
979            {
980                let offset = vertex_index * vertex_size + attribute_offset;
981                slice
982                    .slice(offset..offset + attribute_size)
983                    .copy_from_slice(attribute_bytes);
984            }
985
986            attribute_offset += attribute_size;
987        }
988    }
989
990    /// Duplicates the vertex attributes so that no vertices are shared.
991    ///
992    /// This can dramatically increase the vertex count, so make sure this is what you want.
993    /// Does nothing if no [Indices] are set.
994    ///
995    /// # Panics
996    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
997    /// this as an error use [`Mesh::try_duplicate_vertices`]
998    pub fn duplicate_vertices(&mut self) {
999        self.try_duplicate_vertices().expect(MESH_EXTRACTED_ERROR);
1000    }
1001
1002    /// Duplicates the vertex attributes so that no vertices are shared.
1003    ///
1004    /// This can dramatically increase the vertex count, so make sure this is what you want.
1005    /// Does nothing if no [Indices] are set.
1006    ///
1007    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
1008    pub fn try_duplicate_vertices(&mut self) -> Result<(), MeshAccessError> {
1009        fn duplicate<T: Copy>(values: &[T], indices: impl Iterator<Item = usize>) -> Vec<T> {
1010            indices.map(|i| values[i]).collect()
1011        }
1012
1013        let Some(indices) = self.indices.replace(None)? else {
1014            return Ok(());
1015        };
1016
1017        let mesh_attributes = self.attributes.as_mut()?;
1018
1019        for attributes in mesh_attributes.values_mut() {
1020            let indices = indices.iter();
1021            #[expect(
1022                clippy::match_same_arms,
1023                reason = "Although the `vec` binding on some match arms may have different types, each variant has different semantics; thus it's not guaranteed that they will use the same type forever."
1024            )]
1025            match &mut attributes.values {
1026                VertexAttributeValues::Float32(vec) => *vec = duplicate(vec, indices),
1027                VertexAttributeValues::Sint32(vec) => *vec = duplicate(vec, indices),
1028                VertexAttributeValues::Uint32(vec) => *vec = duplicate(vec, indices),
1029                VertexAttributeValues::Float32x2(vec) => *vec = duplicate(vec, indices),
1030                VertexAttributeValues::Sint32x2(vec) => *vec = duplicate(vec, indices),
1031                VertexAttributeValues::Uint32x2(vec) => *vec = duplicate(vec, indices),
1032                VertexAttributeValues::Float32x3(vec) => *vec = duplicate(vec, indices),
1033                VertexAttributeValues::Sint32x3(vec) => *vec = duplicate(vec, indices),
1034                VertexAttributeValues::Uint32x3(vec) => *vec = duplicate(vec, indices),
1035                VertexAttributeValues::Sint32x4(vec) => *vec = duplicate(vec, indices),
1036                VertexAttributeValues::Uint32x4(vec) => *vec = duplicate(vec, indices),
1037                VertexAttributeValues::Float32x4(vec) => *vec = duplicate(vec, indices),
1038                VertexAttributeValues::Sint16x2(vec) => *vec = duplicate(vec, indices),
1039                VertexAttributeValues::Snorm16x2(vec) => *vec = duplicate(vec, indices),
1040                VertexAttributeValues::Uint16x2(vec) => *vec = duplicate(vec, indices),
1041                VertexAttributeValues::Unorm16x2(vec) => *vec = duplicate(vec, indices),
1042                VertexAttributeValues::Sint16x4(vec) => *vec = duplicate(vec, indices),
1043                VertexAttributeValues::Snorm16x4(vec) => *vec = duplicate(vec, indices),
1044                VertexAttributeValues::Uint16x4(vec) => *vec = duplicate(vec, indices),
1045                VertexAttributeValues::Unorm16x4(vec) => *vec = duplicate(vec, indices),
1046                VertexAttributeValues::Sint8x2(vec) => *vec = duplicate(vec, indices),
1047                VertexAttributeValues::Snorm8x2(vec) => *vec = duplicate(vec, indices),
1048                VertexAttributeValues::Uint8x2(vec) => *vec = duplicate(vec, indices),
1049                VertexAttributeValues::Unorm8x2(vec) => *vec = duplicate(vec, indices),
1050                VertexAttributeValues::Sint8x4(vec) => *vec = duplicate(vec, indices),
1051                VertexAttributeValues::Snorm8x4(vec) => *vec = duplicate(vec, indices),
1052                VertexAttributeValues::Uint8x4(vec) => *vec = duplicate(vec, indices),
1053                VertexAttributeValues::Unorm8x4(vec) => *vec = duplicate(vec, indices),
1054                VertexAttributeValues::Uint8(vec) => *vec = duplicate(vec, indices),
1055                VertexAttributeValues::Sint8(vec) => *vec = duplicate(vec, indices),
1056                VertexAttributeValues::Unorm8(vec) => *vec = duplicate(vec, indices),
1057                VertexAttributeValues::Snorm8(vec) => *vec = duplicate(vec, indices),
1058                VertexAttributeValues::Uint16(vec) => *vec = duplicate(vec, indices),
1059                VertexAttributeValues::Sint16(vec) => *vec = duplicate(vec, indices),
1060                VertexAttributeValues::Unorm16(vec) => *vec = duplicate(vec, indices),
1061                VertexAttributeValues::Snorm16(vec) => *vec = duplicate(vec, indices),
1062                VertexAttributeValues::Float16(vec) => *vec = duplicate(vec, indices),
1063                VertexAttributeValues::Float16x2(vec) => *vec = duplicate(vec, indices),
1064                VertexAttributeValues::Float16x4(vec) => *vec = duplicate(vec, indices),
1065                VertexAttributeValues::Float64(vec) => *vec = duplicate(vec, indices),
1066                VertexAttributeValues::Float64x2(vec) => *vec = duplicate(vec, indices),
1067                VertexAttributeValues::Float64x3(vec) => *vec = duplicate(vec, indices),
1068                VertexAttributeValues::Float64x4(vec) => *vec = duplicate(vec, indices),
1069                VertexAttributeValues::Unorm10_10_10_2(vec) => *vec = duplicate(vec, indices),
1070                VertexAttributeValues::Unorm8x4Bgra(vec) => *vec = duplicate(vec, indices),
1071            }
1072        }
1073
1074        Ok(())
1075    }
1076
1077    /// Consumes the mesh and returns a mesh with no shared vertices.
1078    ///
1079    /// This can dramatically increase the vertex count, so make sure this is what you want.
1080    /// Does nothing if no [`Indices`] are set.
1081    ///
1082    /// (Alternatively, you can use [`Mesh::duplicate_vertices`] to mutate an existing mesh in-place)
1083    ///
1084    /// # Panics
1085    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1086    /// this as an error use [`Mesh::try_with_duplicated_vertices`]
1087    #[must_use]
1088    pub fn with_duplicated_vertices(mut self) -> Self {
1089        self.duplicate_vertices();
1090        self
1091    }
1092
1093    /// Consumes the mesh and returns a mesh with no shared vertices.
1094    ///
1095    /// This can dramatically increase the vertex count, so make sure this is what you want.
1096    /// Does nothing if no [`Indices`] are set.
1097    ///
1098    /// (Alternatively, you can use [`Mesh::try_duplicate_vertices`] to mutate an existing mesh in-place)
1099    ///
1100    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
1101    pub fn try_with_duplicated_vertices(mut self) -> Result<Self, MeshAccessError> {
1102        self.try_duplicate_vertices()?;
1103        Ok(self)
1104    }
1105
1106    /// Remove duplicate vertices and create the index pointing to the unique vertices.
1107    ///
1108    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
1109    /// Returns an error if the mesh already has [`Indices`] set, even if there
1110    /// are duplicate vertices. If deduplication is needed with indices already set,
1111    /// consider calling [`Mesh::duplicate_vertices`] and then this function.
1112    pub fn merge_duplicate_vertices(&mut self) -> Result<(), MeshMergeDuplicateVerticesError> {
1113        match self.try_indices() {
1114            Ok(_) => return Err(MeshMergeDuplicateVerticesError::IndicesAlreadySet),
1115            Err(err) => match err {
1116                MeshAccessError::ExtractedToRenderWorld => return Err(err.into()),
1117                MeshAccessError::NotFound => (),
1118            },
1119        }
1120
1121        #[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for VertexRef<'a> { }Copy, #[automatically_derived]
impl<'a> ::core::clone::Clone for VertexRef<'a> {
    #[inline]
    fn clone(&self) -> VertexRef<'a> {
        let _:
                ::core::clone::AssertParamIsClone<&'a BTreeMap<MeshVertexAttributeId,
                MeshAttributeData>>;
        let _: ::core::clone::AssertParamIsClone<usize>;
        *self
    }
}Clone)]
1122        struct VertexRef<'a> {
1123            mesh_attributes: &'a BTreeMap<MeshVertexAttributeId, MeshAttributeData>,
1124            i: usize,
1125        }
1126        impl<'a> VertexRef<'a> {
1127            fn push_to(&self, target: &mut BTreeMap<MeshVertexAttributeId, MeshAttributeData>) {
1128                for (key, this_attribute_data) in self.mesh_attributes.iter() {
1129                    let target_attribute_data = target.get_mut(key).unwrap(); // ok to unwrap, all keys added to new_attributes below
1130                    target_attribute_data
1131                        .values
1132                        .push_from(&this_attribute_data.values, self.i);
1133                }
1134            }
1135        }
1136        impl<'a> PartialEq for VertexRef<'a> {
1137            fn eq(&self, other: &Self) -> bool {
1138                if !ptr::eq(self.mesh_attributes, other.mesh_attributes) {
    ::core::panicking::panic("assertion failed: ptr::eq(self.mesh_attributes, other.mesh_attributes)")
};assert!(ptr::eq(self.mesh_attributes, other.mesh_attributes));
1139                for values in self.mesh_attributes.values() {
1140                    if values.values.get_bytes_at(self.i) != values.values.get_bytes_at(other.i) {
1141                        return false;
1142                    }
1143                }
1144                true
1145            }
1146        }
1147        impl<'a> Eq for VertexRef<'a> {}
1148        impl<'a> Hash for VertexRef<'a> {
1149            fn hash<H: Hasher>(&self, state: &mut H) {
1150                for values in self.mesh_attributes.values() {
1151                    values.values.get_bytes_at(self.i).hash(state);
1152                }
1153            }
1154        }
1155
1156        let old_attributes = self.attributes.as_ref()?;
1157
1158        let mut new_attributes: BTreeMap<MeshVertexAttributeId, MeshAttributeData> = self
1159            .attributes
1160            .as_ref()?
1161            .iter()
1162            .map(|(k, v)| {
1163                (
1164                    *k,
1165                    MeshAttributeData {
1166                        attribute: v.attribute,
1167                        values: VertexAttributeValues::new(VertexFormat::from(&v.values)),
1168                    },
1169                )
1170            })
1171            .collect();
1172
1173        let mut vertex_to_new_index: HashMap<VertexRef, u32> = HashMap::new();
1174        let mut indices = Vec::with_capacity(self.count_vertices());
1175        for i in 0..self.count_vertices() {
1176            let len: u32 = vertex_to_new_index
1177                .len()
1178                .try_into()
1179                .expect("The number of vertices exceeds u32::MAX");
1180            let vertex_ref = VertexRef {
1181                mesh_attributes: old_attributes,
1182                i,
1183            };
1184            let j = match vertex_to_new_index.entry(vertex_ref) {
1185                hash_map::Entry::Occupied(e) => *e.get(),
1186                hash_map::Entry::Vacant(e) => {
1187                    e.insert(len);
1188                    vertex_ref.push_to(&mut new_attributes);
1189                    len
1190                }
1191            };
1192            indices.push(j);
1193        }
1194        drop(vertex_to_new_index);
1195
1196        for v in new_attributes.values_mut() {
1197            v.values.shrink_to_fit();
1198        }
1199
1200        self.attributes = MeshExtractableData::Data(new_attributes);
1201        self.indices = MeshExtractableData::Data(Indices::U32(indices));
1202
1203        Ok(())
1204    }
1205
1206    /// Consumes the mesh and returns a mesh with merged vertices.
1207    ///
1208    /// (Alternatively, you can use [`Mesh::merge_duplicate_vertices`] to mutate an existing mesh in-place)
1209    ///
1210    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
1211    /// Returns an error if the mesh already has [`Indices`] set, even if there
1212    /// are duplicate vertices. If deduplication is needed with indices already set,
1213    /// consider calling [`Mesh::duplicate_vertices`] and then this function.
1214    pub fn with_merge_duplicate_vertices(
1215        mut self,
1216    ) -> Result<Self, MeshMergeDuplicateVerticesError> {
1217        self.merge_duplicate_vertices()?;
1218        Ok(self)
1219    }
1220
1221    /// Inverts the winding of the indices such that all counter-clockwise triangles are now
1222    /// clockwise and vice versa.
1223    /// For lines, their start and end indices are flipped.
1224    ///
1225    /// Does nothing if no [`Indices`] are set.
1226    /// If this operation succeeded, an [`Ok`] result is returned.
1227    pub fn invert_winding(&mut self) -> Result<(), MeshWindingInvertError> {
1228        fn invert<I>(
1229            indices: &mut [I],
1230            topology: PrimitiveTopology,
1231        ) -> Result<(), MeshWindingInvertError> {
1232            match topology {
1233                PrimitiveTopology::TriangleList => {
1234                    let (chunks, []) = indices.as_chunks_mut() else {
1235                        // Early return if the index count doesn't match
1236                        return Err(MeshWindingInvertError::AbruptIndicesEnd);
1237                    };
1238
1239                    for [_, b, c] in chunks {
1240                        core::mem::swap(b, c);
1241                    }
1242                    Ok(())
1243                }
1244                PrimitiveTopology::LineList => {
1245                    // Early return if the index count doesn't match
1246                    if !indices.len().is_multiple_of(2) {
1247                        return Err(MeshWindingInvertError::AbruptIndicesEnd);
1248                    }
1249                    indices.reverse();
1250                    Ok(())
1251                }
1252                PrimitiveTopology::TriangleStrip | PrimitiveTopology::LineStrip => {
1253                    indices.reverse();
1254                    Ok(())
1255                }
1256                _ => Err(MeshWindingInvertError::WrongTopology),
1257            }
1258        }
1259
1260        let mesh_indices = self.indices.as_mut_option()?;
1261
1262        match mesh_indices {
1263            Some(Indices::U16(vec)) => invert(vec, self.primitive_topology),
1264            Some(Indices::U32(vec)) => invert(vec, self.primitive_topology),
1265            None => Ok(()),
1266        }
1267    }
1268
1269    /// Consumes the mesh and returns a mesh with inverted winding of the indices such
1270    /// that all counter-clockwise triangles are now clockwise and vice versa.
1271    ///
1272    /// Does nothing if no [`Indices`] are set.
1273    pub fn with_inverted_winding(mut self) -> Result<Self, MeshWindingInvertError> {
1274        self.invert_winding().map(|_| self)
1275    }
1276
1277    /// Calculates the [`Mesh::ATTRIBUTE_NORMAL`] of a mesh.
1278    /// If the mesh is indexed, this defaults to smooth normals. Otherwise, it defaults to flat
1279    /// normals.
1280    ///
1281    /// # Panics
1282    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1283    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].=
1284    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1285    /// this as an error use [`Mesh::try_compute_normals`]
1286    pub fn compute_normals(&mut self) {
1287        self.try_compute_normals().expect(MESH_EXTRACTED_ERROR);
1288    }
1289
1290    /// Calculates the [`Mesh::ATTRIBUTE_NORMAL`] of a mesh.
1291    /// If the mesh is indexed, this defaults to smooth normals. Otherwise, it defaults to flat
1292    /// normals.
1293    ///
1294    /// # Panics
1295    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1296    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].=
1297    pub fn try_compute_normals(&mut self) -> Result<(), MeshAccessError> {
1298        if !#[allow(non_exhaustive_omitted_patterns)] match self.primitive_topology {
            PrimitiveTopology::TriangleList => true,
            _ => false,
        } {
    {
        ::core::panicking::panic_fmt(format_args!("`compute_normals` can only work on `TriangleList`s"));
    }
};assert!(
1299            matches!(self.primitive_topology, PrimitiveTopology::TriangleList),
1300            "`compute_normals` can only work on `TriangleList`s"
1301        );
1302        if self.try_indices_option()?.is_none() {
1303            self.try_compute_flat_normals()
1304        } else {
1305            self.try_compute_smooth_normals()
1306        }
1307    }
1308
1309    /// Calculates the [`Mesh::ATTRIBUTE_NORMAL`] of a mesh.
1310    ///
1311    /// # Panics
1312    /// Panics if [`Indices`] are set or [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1313    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1314    /// Consider calling [`Mesh::duplicate_vertices`] or exporting your mesh with normal
1315    /// attributes.
1316    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1317    /// this as an error use [`Mesh::try_compute_flat_normals`]
1318    ///
1319    /// FIXME: This should handle more cases since this is called as a part of gltf
1320    /// mesh loading where we can't really blame users for loading meshes that might
1321    /// not conform to the limitations here!
1322    pub fn compute_flat_normals(&mut self) {
1323        self.try_compute_flat_normals().expect(MESH_EXTRACTED_ERROR);
1324    }
1325
1326    /// Calculates the [`Mesh::ATTRIBUTE_NORMAL`] of a mesh.
1327    ///
1328    /// # Panics
1329    /// Panics if [`Indices`] are set or [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1330    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1331    /// Consider calling [`Mesh::duplicate_vertices`] or exporting your mesh with normal
1332    /// attributes.
1333    ///
1334    /// FIXME: This should handle more cases since this is called as a part of gltf
1335    /// mesh loading where we can't really blame users for loading meshes that might
1336    /// not conform to the limitations here!
1337    pub fn try_compute_flat_normals(&mut self) -> Result<(), MeshAccessError> {
1338        if !self.try_indices_option()?.is_none() {
    {
        ::core::panicking::panic_fmt(format_args!("`compute_flat_normals` can\'t work on indexed geometry. Consider calling either `Mesh::compute_smooth_normals` or `Mesh::duplicate_vertices` followed by `Mesh::compute_flat_normals`."));
    }
};assert!(
1339            self.try_indices_option()?.is_none(),
1340            "`compute_flat_normals` can't work on indexed geometry. Consider calling either `Mesh::compute_smooth_normals` or `Mesh::duplicate_vertices` followed by `Mesh::compute_flat_normals`."
1341        );
1342        if !#[allow(non_exhaustive_omitted_patterns)] match self.primitive_topology {
            PrimitiveTopology::TriangleList => true,
            _ => false,
        } {
    {
        ::core::panicking::panic_fmt(format_args!("`compute_flat_normals` can only work on `TriangleList`s"));
    }
};assert!(
1343            matches!(self.primitive_topology, PrimitiveTopology::TriangleList),
1344            "`compute_flat_normals` can only work on `TriangleList`s"
1345        );
1346
1347        let positions = self
1348            .try_attribute(Mesh::ATTRIBUTE_POSITION)?
1349            .as_float3()
1350            .expect("`Mesh::ATTRIBUTE_POSITION` vertex attributes should be of type `float3`");
1351
1352        let normals: Vec<_> = positions
1353            .as_chunks()
1354            .0
1355            .iter()
1356            .flat_map(|&[a, b, c]| [triangle_normal(a, b, c); 3])
1357            .collect();
1358
1359        self.try_insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
1360    }
1361
1362    /// Calculates the [`Mesh::ATTRIBUTE_NORMAL`] of an indexed mesh, smoothing normals for shared
1363    /// vertices.
1364    ///
1365    /// This method weights normals by the angles of the corners of connected triangles, thus
1366    /// eliminating triangle area and count as factors in the final normal. This does make it
1367    /// somewhat slower than [`Mesh::compute_area_weighted_normals`] which does not need to
1368    /// greedily normalize each triangle's normal or calculate corner angles.
1369    ///
1370    /// If you would rather have the computed normals be weighted by triangle area, see
1371    /// [`Mesh::compute_area_weighted_normals`] instead. If you need to weight them in some other
1372    /// way, see [`Mesh::compute_custom_smooth_normals`].
1373    ///
1374    /// # Panics
1375    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1376    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1377    /// Panics if the mesh does not have indices defined.
1378    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1379    /// this as an error use [`Mesh::try_compute_smooth_normals`]
1380    pub fn compute_smooth_normals(&mut self) {
1381        self.try_compute_smooth_normals()
1382            .expect(MESH_EXTRACTED_ERROR);
1383    }
1384
1385    /// Calculates the [`Mesh::ATTRIBUTE_NORMAL`] of an indexed mesh, smoothing normals for shared
1386    /// vertices.
1387    ///
1388    /// This method weights normals by the angles of the corners of connected triangles, thus
1389    /// eliminating triangle area and count as factors in the final normal. This does make it
1390    /// somewhat slower than [`Mesh::compute_area_weighted_normals`] which does not need to
1391    /// greedily normalize each triangle's normal or calculate corner angles.
1392    ///
1393    /// If you would rather have the computed normals be weighted by triangle area, see
1394    /// [`Mesh::compute_area_weighted_normals`] instead. If you need to weight them in some other
1395    /// way, see [`Mesh::compute_custom_smooth_normals`].
1396    ///
1397    /// # Panics
1398    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1399    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1400    /// Panics if the mesh does not have indices defined.
1401    pub fn try_compute_smooth_normals(&mut self) -> Result<(), MeshAccessError> {
1402        self.try_compute_custom_smooth_normals(|[a, b, c], positions, normals| {
1403            let pa = Vec3::from(positions[a]);
1404            let pb = Vec3::from(positions[b]);
1405            let pc = Vec3::from(positions[c]);
1406
1407            let ab = pb - pa;
1408            let ba = pa - pb;
1409            let bc = pc - pb;
1410            let cb = pb - pc;
1411            let ca = pa - pc;
1412            let ac = pc - pa;
1413
1414            const EPS: f32 = f32::EPSILON;
1415            let weight_a = if ab.length_squared() * ac.length_squared() > EPS {
1416                ab.angle_between(ac)
1417            } else {
1418                0.0
1419            };
1420            let weight_b = if ba.length_squared() * bc.length_squared() > EPS {
1421                ba.angle_between(bc)
1422            } else {
1423                0.0
1424            };
1425            let weight_c = if ca.length_squared() * cb.length_squared() > EPS {
1426                ca.angle_between(cb)
1427            } else {
1428                0.0
1429            };
1430
1431            let normal = Vec3::from(triangle_normal(positions[a], positions[b], positions[c]));
1432
1433            normals[a] += normal * weight_a;
1434            normals[b] += normal * weight_b;
1435            normals[c] += normal * weight_c;
1436        })
1437    }
1438
1439    /// Calculates the [`Mesh::ATTRIBUTE_NORMAL`] of an indexed mesh, smoothing normals for shared
1440    /// vertices.
1441    ///
1442    /// This method weights normals by the area of each triangle containing the vertex. Thus,
1443    /// larger triangles will skew the normals of their vertices towards their own normal more
1444    /// than smaller triangles will.
1445    ///
1446    /// This method is actually somewhat faster than [`Mesh::compute_smooth_normals`] because an
1447    /// intermediate result of triangle normal calculation is already scaled by the triangle's area.
1448    ///
1449    /// If you would rather have the computed normals be influenced only by the angles of connected
1450    /// edges, see [`Mesh::compute_smooth_normals`] instead. If you need to weight them in some
1451    /// other way, see [`Mesh::compute_custom_smooth_normals`].
1452    ///
1453    /// # Panics
1454    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1455    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1456    /// Panics if the mesh does not have indices defined.
1457    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1458    /// this as an error use [`Mesh::try_compute_area_weighted_normals`]
1459    pub fn compute_area_weighted_normals(&mut self) {
1460        self.try_compute_area_weighted_normals()
1461            .expect(MESH_EXTRACTED_ERROR);
1462    }
1463
1464    /// Calculates the [`Mesh::ATTRIBUTE_NORMAL`] of an indexed mesh, smoothing normals for shared
1465    /// vertices.
1466    ///
1467    /// This method weights normals by the area of each triangle containing the vertex. Thus,
1468    /// larger triangles will skew the normals of their vertices towards their own normal more
1469    /// than smaller triangles will.
1470    ///
1471    /// This method is actually somewhat faster than [`Mesh::compute_smooth_normals`] because an
1472    /// intermediate result of triangle normal calculation is already scaled by the triangle's area.
1473    ///
1474    /// If you would rather have the computed normals be influenced only by the angles of connected
1475    /// edges, see [`Mesh::compute_smooth_normals`] instead. If you need to weight them in some
1476    /// other way, see [`Mesh::compute_custom_smooth_normals`].
1477    ///
1478    /// # Panics
1479    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1480    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1481    /// Panics if the mesh does not have indices defined.
1482    pub fn try_compute_area_weighted_normals(&mut self) -> Result<(), MeshAccessError> {
1483        self.try_compute_custom_smooth_normals(|[a, b, c], positions, normals| {
1484            let normal = Vec3::from(triangle_area_normal(
1485                positions[a],
1486                positions[b],
1487                positions[c],
1488            ));
1489            [a, b, c].into_iter().for_each(|pos| {
1490                normals[pos] += normal;
1491            });
1492        })
1493    }
1494
1495    /// Calculates the [`Mesh::ATTRIBUTE_NORMAL`] of an indexed mesh, smoothing normals for shared
1496    /// vertices.
1497    ///
1498    /// This method allows you to customize how normals are weighted via the `per_triangle` parameter,
1499    /// which must be a function or closure that accepts 3 parameters:
1500    /// - The indices of the three vertices of the triangle as a `[usize; 3]`.
1501    /// - A reference to the values of the [`Mesh::ATTRIBUTE_POSITION`] of the mesh (`&[[f32; 3]]`).
1502    /// - A mutable reference to the sums of all normals so far.
1503    ///
1504    /// See also the standard methods included in Bevy for calculating smooth normals:
1505    /// - [`Mesh::compute_smooth_normals`]
1506    /// - [`Mesh::compute_area_weighted_normals`]
1507    ///
1508    /// An example that would weight each connected triangle's normal equally, thus skewing normals
1509    /// towards the planes divided into the most triangles:
1510    /// ```
1511    /// # use bevy_asset::RenderAssetUsages;
1512    /// # use bevy_mesh::{Mesh, PrimitiveTopology, Meshable, MeshBuilder};
1513    /// # use bevy_math::{Vec3, primitives::Cuboid};
1514    /// # let mut mesh = Cuboid::default().mesh().build();
1515    /// mesh.compute_custom_smooth_normals(|[a, b, c], positions, normals| {
1516    ///     let normal = Vec3::from(bevy_mesh::triangle_normal(positions[a], positions[b], positions[c]));
1517    ///     for idx in [a, b, c] {
1518    ///         normals[idx] += normal;
1519    ///     }
1520    /// });
1521    /// ```
1522    ///
1523    /// # Panics
1524    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1525    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1526    /// Panics if the mesh does not have indices defined.
1527    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1528    /// this as an error use [`Mesh::try_compute_custom_smooth_normals`]
1529    //
1530    // FIXME: This should handle more cases since this is called as a part of gltf
1531    // mesh loading where we can't really blame users for loading meshes that might
1532    // not conform to the limitations here!
1533    //
1534    // When fixed, also update "Panics" sections of
1535    // - [Mesh::compute_smooth_normals]
1536    // - [Mesh::with_computed_smooth_normals]
1537    // - [Mesh::compute_area_weighted_normals]
1538    // - [Mesh::with_computed_area_weighted_normals]
1539    pub fn compute_custom_smooth_normals(
1540        &mut self,
1541        per_triangle: impl FnMut([usize; 3], &[[f32; 3]], &mut [Vec3]),
1542    ) {
1543        self.try_compute_custom_smooth_normals(per_triangle)
1544            .expect(MESH_EXTRACTED_ERROR);
1545    }
1546
1547    /// Calculates the [`Mesh::ATTRIBUTE_NORMAL`] of an indexed mesh, smoothing normals for shared
1548    /// vertices.
1549    ///
1550    /// This method allows you to customize how normals are weighted via the `per_triangle` parameter,
1551    /// which must be a function or closure that accepts 3 parameters:
1552    /// - The indices of the three vertices of the triangle as a `[usize; 3]`.
1553    /// - A reference to the values of the [`Mesh::ATTRIBUTE_POSITION`] of the mesh (`&[[f32; 3]]`).
1554    /// - A mutable reference to the sums of all normals so far.
1555    ///
1556    /// See also the standard methods included in Bevy for calculating smooth normals:
1557    /// - [`Mesh::compute_smooth_normals`]
1558    /// - [`Mesh::compute_area_weighted_normals`]
1559    ///
1560    /// An example that would weight each connected triangle's normal equally, thus skewing normals
1561    /// towards the planes divided into the most triangles:
1562    /// ```
1563    /// # use bevy_asset::RenderAssetUsages;
1564    /// # use bevy_mesh::{Mesh, PrimitiveTopology, Meshable, MeshBuilder};
1565    /// # use bevy_math::{Vec3, primitives::Cuboid};
1566    /// # let mut mesh = Cuboid::default().mesh().build();
1567    /// mesh.compute_custom_smooth_normals(|[a, b, c], positions, normals| {
1568    ///     let normal = Vec3::from(bevy_mesh::triangle_normal(positions[a], positions[b], positions[c]));
1569    ///     for idx in [a, b, c] {
1570    ///         normals[idx] += normal;
1571    ///     }
1572    /// });
1573    /// ```
1574    ///
1575    /// # Panics
1576    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1577    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1578    /// Panics if the mesh does not have indices defined.
1579    //
1580    // FIXME: This should handle more cases since this is called as a part of gltf
1581    // mesh loading where we can't really blame users for loading meshes that might
1582    // not conform to the limitations here!
1583    //
1584    // When fixed, also update "Panics" sections of
1585    // - [Mesh::compute_smooth_normals]
1586    // - [Mesh::with_computed_smooth_normals]
1587    // - [Mesh::compute_area_weighted_normals]
1588    // - [Mesh::with_computed_area_weighted_normals]
1589    pub fn try_compute_custom_smooth_normals(
1590        &mut self,
1591        mut per_triangle: impl FnMut([usize; 3], &[[f32; 3]], &mut [Vec3]),
1592    ) -> Result<(), MeshAccessError> {
1593        if !#[allow(non_exhaustive_omitted_patterns)] match self.primitive_topology {
            PrimitiveTopology::TriangleList => true,
            _ => false,
        } {
    {
        ::core::panicking::panic_fmt(format_args!("smooth normals can only be computed on `TriangleList`s"));
    }
};assert!(
1594            matches!(self.primitive_topology, PrimitiveTopology::TriangleList),
1595            "smooth normals can only be computed on `TriangleList`s"
1596        );
1597        if !self.try_indices_option()?.is_some() {
    {
        ::core::panicking::panic_fmt(format_args!("smooth normals can only be computed on indexed meshes"));
    }
};assert!(
1598            self.try_indices_option()?.is_some(),
1599            "smooth normals can only be computed on indexed meshes"
1600        );
1601
1602        let positions = self
1603            .try_attribute(Mesh::ATTRIBUTE_POSITION)?
1604            .as_float3()
1605            .expect("`Mesh::ATTRIBUTE_POSITION` vertex attributes should be of type `float3`");
1606
1607        let mut normals = ::alloc::vec::from_elem(Vec3::ZERO, positions.len())vec![Vec3::ZERO; positions.len()];
1608
1609        match self.try_indices()? {
1610            Indices::U16(vec) => vec.as_chunks().0.iter().for_each(|&chunk| {
1611                per_triangle(chunk.map(|i| i as usize), positions, &mut normals);
1612            }),
1613            Indices::U32(vec) => vec.as_chunks().0.iter().for_each(|&chunk| {
1614                per_triangle(chunk.map(|i| i as usize), positions, &mut normals);
1615            }),
1616        }
1617
1618        for normal in &mut normals {
1619            *normal = normal.try_normalize().unwrap_or(Vec3::ZERO);
1620        }
1621
1622        self.try_insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
1623    }
1624
1625    /// Consumes the mesh and returns a mesh with calculated [`Mesh::ATTRIBUTE_NORMAL`].
1626    /// If the mesh is indexed, this defaults to smooth normals. Otherwise, it defaults to flat
1627    /// normals.
1628    ///
1629    /// (Alternatively, you can use [`Mesh::compute_normals`] to mutate an existing mesh in-place)
1630    ///
1631    /// # Panics
1632    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1633    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1634    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1635    /// this as an error use [`Mesh::try_with_computed_normals`]
1636    #[must_use]
1637    pub fn with_computed_normals(self) -> Self {
1638        self.try_with_computed_normals()
1639            .expect(MESH_EXTRACTED_ERROR)
1640    }
1641
1642    /// Consumes the mesh and returns a mesh with calculated [`Mesh::ATTRIBUTE_NORMAL`].
1643    /// If the mesh is indexed, this defaults to smooth normals. Otherwise, it defaults to flat
1644    /// normals.
1645    ///
1646    /// (Alternatively, you can use [`Mesh::compute_normals`] to mutate an existing mesh in-place)
1647    ///
1648    /// # Panics
1649    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1650    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1651    pub fn try_with_computed_normals(mut self) -> Result<Self, MeshAccessError> {
1652        self.try_compute_normals()?;
1653        Ok(self)
1654    }
1655
1656    /// Consumes the mesh and returns a mesh with calculated [`Mesh::ATTRIBUTE_NORMAL`].
1657    ///
1658    /// (Alternatively, you can use [`Mesh::compute_flat_normals`] to mutate an existing mesh in-place)
1659    ///
1660    /// # Panics
1661    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1662    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1663    /// Panics if the mesh has indices defined
1664    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1665    /// this as an error use [`Mesh::try_with_computed_flat_normals`]
1666    pub fn with_computed_flat_normals(mut self) -> Self {
1667        self.compute_flat_normals();
1668        self
1669    }
1670
1671    /// Consumes the mesh and returns a mesh with calculated [`Mesh::ATTRIBUTE_NORMAL`].
1672    ///
1673    /// (Alternatively, you can use [`Mesh::compute_flat_normals`] to mutate an existing mesh in-place)
1674    ///
1675    /// # Panics
1676    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1677    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1678    /// Panics if the mesh has indices defined
1679    pub fn try_with_computed_flat_normals(mut self) -> Result<Self, MeshAccessError> {
1680        self.try_compute_flat_normals()?;
1681        Ok(self)
1682    }
1683
1684    /// Consumes the mesh and returns a mesh with calculated [`Mesh::ATTRIBUTE_NORMAL`].
1685    ///
1686    /// (Alternatively, you can use [`Mesh::compute_smooth_normals`] to mutate an existing mesh in-place)
1687    ///
1688    /// This method weights normals by the angles of triangle corners connected to each vertex. If
1689    /// you would rather have the computed normals be weighted by triangle area, see
1690    /// [`Mesh::with_computed_area_weighted_normals`] instead.
1691    ///
1692    /// # Panics
1693    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1694    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1695    /// Panics if the mesh does not have indices defined.
1696    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1697    /// this as an error use [`Mesh::try_with_computed_smooth_normals`]
1698    pub fn with_computed_smooth_normals(mut self) -> Self {
1699        self.compute_smooth_normals();
1700        self
1701    }
1702    /// Consumes the mesh and returns a mesh with calculated [`Mesh::ATTRIBUTE_NORMAL`].
1703    ///
1704    /// (Alternatively, you can use [`Mesh::compute_smooth_normals`] to mutate an existing mesh in-place)
1705    ///
1706    /// This method weights normals by the angles of triangle corners connected to each vertex. If
1707    /// you would rather have the computed normals be weighted by triangle area, see
1708    /// [`Mesh::with_computed_area_weighted_normals`] instead.
1709    ///
1710    /// # Panics
1711    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1712    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1713    /// Panics if the mesh does not have indices defined.
1714    pub fn try_with_computed_smooth_normals(mut self) -> Result<Self, MeshAccessError> {
1715        self.try_compute_smooth_normals()?;
1716        Ok(self)
1717    }
1718
1719    /// Consumes the mesh and returns a mesh with calculated [`Mesh::ATTRIBUTE_NORMAL`].
1720    ///
1721    /// (Alternatively, you can use [`Mesh::compute_area_weighted_normals`] to mutate an existing mesh in-place)
1722    ///
1723    /// This method weights normals by the area of each triangle containing the vertex. Thus,
1724    /// larger triangles will skew the normals of their vertices towards their own normal more
1725    /// than smaller triangles will. If you would rather have the computed normals be influenced
1726    /// only by the angles of connected edges, see [`Mesh::with_computed_smooth_normals`] instead.
1727    ///
1728    /// # Panics
1729    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1730    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1731    /// Panics if the mesh does not have indices defined.
1732    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1733    /// this as an error use [`Mesh::try_with_computed_area_weighted_normals`]
1734    pub fn with_computed_area_weighted_normals(mut self) -> Self {
1735        self.compute_area_weighted_normals();
1736        self
1737    }
1738
1739    /// Consumes the mesh and returns a mesh with calculated [`Mesh::ATTRIBUTE_NORMAL`].
1740    ///
1741    /// (Alternatively, you can use [`Mesh::compute_area_weighted_normals`] to mutate an existing mesh in-place)
1742    ///
1743    /// This method weights normals by the area of each triangle containing the vertex. Thus,
1744    /// larger triangles will skew the normals of their vertices towards their own normal more
1745    /// than smaller triangles will. If you would rather have the computed normals be influenced
1746    /// only by the angles of connected edges, see [`Mesh::with_computed_smooth_normals`] instead.
1747    ///
1748    /// # Panics
1749    /// Panics if [`Mesh::ATTRIBUTE_POSITION`] is not of type `float3`.
1750    /// Panics if the mesh has any other topology than [`PrimitiveTopology::TriangleList`].
1751    /// Panics if the mesh does not have indices defined.
1752    pub fn try_with_computed_area_weighted_normals(mut self) -> Result<Self, MeshAccessError> {
1753        self.try_compute_area_weighted_normals()?;
1754        Ok(self)
1755    }
1756
1757    /// Generate tangents for the mesh using the `mikktspace` algorithm.
1758    ///
1759    /// Sets the [`Mesh::ATTRIBUTE_TANGENT`] attribute if successful.
1760    /// Requires a [`PrimitiveTopology::TriangleList`] topology and the [`Mesh::ATTRIBUTE_POSITION`], [`Mesh::ATTRIBUTE_NORMAL`] and [`Mesh::ATTRIBUTE_UV_0`] attributes set.
1761    #[cfg(feature = "bevy_mikktspace")]
1762    pub fn generate_tangents(&mut self) -> Result<(), super::GenerateTangentsError> {
1763        let tangents = super::generate_tangents_for_mesh(self)?;
1764        self.try_insert_attribute(Mesh::ATTRIBUTE_TANGENT, tangents)?;
1765        Ok(())
1766    }
1767
1768    /// Consumes the mesh and returns a mesh with tangents generated using the `mikktspace` algorithm.
1769    ///
1770    /// The resulting mesh will have the [`Mesh::ATTRIBUTE_TANGENT`] attribute if successful.
1771    ///
1772    /// (Alternatively, you can use [`Mesh::generate_tangents`] to mutate an existing mesh in-place)
1773    ///
1774    /// Requires a [`PrimitiveTopology::TriangleList`] topology and the [`Mesh::ATTRIBUTE_POSITION`], [`Mesh::ATTRIBUTE_NORMAL`] and [`Mesh::ATTRIBUTE_UV_0`] attributes set.
1775    #[cfg(feature = "bevy_mikktspace")]
1776    pub fn with_generated_tangents(mut self) -> Result<Mesh, super::GenerateTangentsError> {
1777        self.generate_tangents()?;
1778        Ok(self)
1779    }
1780
1781    /// Merges the [`Mesh`] data of `other` with `self`. The attributes and indices of `other` will be appended to `self`.
1782    ///
1783    /// Note that attributes of `other` that don't exist on `self` will be ignored.
1784    ///
1785    /// `Aabb` of entities with modified mesh are not updated automatically.
1786    ///
1787    /// # Errors
1788    ///
1789    /// If any of the following conditions are not met, this function errors:
1790    /// * All of the vertex attributes that have the same attribute id, must also
1791    ///   have the same attribute type.
1792    ///   For example two attributes with the same id, but where one is a
1793    ///   [`VertexAttributeValues::Float32`] and the other is a
1794    ///   [`VertexAttributeValues::Float32x3`], would be invalid.
1795    /// * Both meshes must have the same primitive topology.
1796    pub fn merge(&mut self, other: &Mesh) -> Result<(), MeshMergeError> {
1797        use VertexAttributeValues::*;
1798
1799        // Check if the meshes `primitive_topology` field is the same,
1800        // as if that is not the case, the resulting mesh could (and most likely would)
1801        // be invalid.
1802        if self.primitive_topology != other.primitive_topology {
1803            return Err(MeshMergeError::IncompatiblePrimitiveTopology {
1804                self_primitive_topology: self.primitive_topology,
1805                other_primitive_topology: other.primitive_topology,
1806            });
1807        }
1808
1809        // The indices of `other` should start after the last vertex of `self`.
1810        let index_offset = self.count_vertices();
1811
1812        // Extend attributes of `self` with attributes of `other`.
1813        for (attribute, values) in self.try_attributes_mut()? {
1814            if let Some(other_values) = other.try_attribute_option(attribute.id)? {
1815                #[expect(
1816                    clippy::match_same_arms,
1817                    reason = "Although the bindings on some match arms may have different types, each variant has different semantics; thus it's not guaranteed that they will use the same type forever."
1818                )]
1819                match (values, other_values) {
1820                    (Float32(vec1), Float32(vec2)) => vec1.extend(vec2),
1821                    (Sint32(vec1), Sint32(vec2)) => vec1.extend(vec2),
1822                    (Uint32(vec1), Uint32(vec2)) => vec1.extend(vec2),
1823                    (Float32x2(vec1), Float32x2(vec2)) => vec1.extend(vec2),
1824                    (Sint32x2(vec1), Sint32x2(vec2)) => vec1.extend(vec2),
1825                    (Uint32x2(vec1), Uint32x2(vec2)) => vec1.extend(vec2),
1826                    (Float32x3(vec1), Float32x3(vec2)) => vec1.extend(vec2),
1827                    (Sint32x3(vec1), Sint32x3(vec2)) => vec1.extend(vec2),
1828                    (Uint32x3(vec1), Uint32x3(vec2)) => vec1.extend(vec2),
1829                    (Sint32x4(vec1), Sint32x4(vec2)) => vec1.extend(vec2),
1830                    (Uint32x4(vec1), Uint32x4(vec2)) => vec1.extend(vec2),
1831                    (Float32x4(vec1), Float32x4(vec2)) => vec1.extend(vec2),
1832                    (Sint16x2(vec1), Sint16x2(vec2)) => vec1.extend(vec2),
1833                    (Snorm16x2(vec1), Snorm16x2(vec2)) => vec1.extend(vec2),
1834                    (Uint16x2(vec1), Uint16x2(vec2)) => vec1.extend(vec2),
1835                    (Unorm16x2(vec1), Unorm16x2(vec2)) => vec1.extend(vec2),
1836                    (Sint16x4(vec1), Sint16x4(vec2)) => vec1.extend(vec2),
1837                    (Snorm16x4(vec1), Snorm16x4(vec2)) => vec1.extend(vec2),
1838                    (Uint16x4(vec1), Uint16x4(vec2)) => vec1.extend(vec2),
1839                    (Unorm16x4(vec1), Unorm16x4(vec2)) => vec1.extend(vec2),
1840                    (Sint8x2(vec1), Sint8x2(vec2)) => vec1.extend(vec2),
1841                    (Snorm8x2(vec1), Snorm8x2(vec2)) => vec1.extend(vec2),
1842                    (Uint8x2(vec1), Uint8x2(vec2)) => vec1.extend(vec2),
1843                    (Unorm8x2(vec1), Unorm8x2(vec2)) => vec1.extend(vec2),
1844                    (Sint8x4(vec1), Sint8x4(vec2)) => vec1.extend(vec2),
1845                    (Snorm8x4(vec1), Snorm8x4(vec2)) => vec1.extend(vec2),
1846                    (Uint8x4(vec1), Uint8x4(vec2)) => vec1.extend(vec2),
1847                    (Unorm8x4(vec1), Unorm8x4(vec2)) => vec1.extend(vec2),
1848                    _ => {
1849                        return Err(MeshMergeError::IncompatibleVertexAttributes {
1850                            self_attribute: *attribute,
1851                            other_attribute: other
1852                                .try_attribute_data(attribute.id)?
1853                                .map(|data| data.attribute),
1854                        })
1855                    }
1856                }
1857            }
1858        }
1859
1860        // Extend indices of `self` with indices of `other`.
1861        if let (Some(indices), Some(other_indices)) =
1862            (self.try_indices_mut_option()?, other.try_indices_option()?)
1863        {
1864            indices.extend(other_indices.iter().map(|i| (i + index_offset) as u32));
1865        }
1866        Ok(())
1867    }
1868
1869    /// Transforms the vertex positions, normals, and tangents of the mesh by the given [`Transform`].
1870    ///
1871    /// `Aabb` of entities with modified mesh are not updated automatically.
1872    ///
1873    /// # Panics
1874    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1875    /// this as an error use [`Mesh::try_transformed_by`]
1876    pub fn transformed_by(mut self, transform: Transform) -> Self {
1877        self.transform_by(transform);
1878        self
1879    }
1880
1881    /// Transforms the vertex positions, normals, and tangents of the mesh by the given [`Transform`].
1882    ///
1883    /// `Aabb` of entities with modified mesh are not updated automatically.
1884    pub fn try_transformed_by(mut self, transform: Transform) -> Result<Self, MeshAccessError> {
1885        self.try_transform_by(transform)?;
1886        Ok(self)
1887    }
1888
1889    /// Transforms the vertex positions, normals, and tangents of the mesh in place by the given [`Transform`].
1890    ///
1891    /// `Aabb` of entities with modified mesh are not updated automatically.
1892    ///
1893    /// # Panics
1894    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1895    /// this as an error use [`Mesh::try_transform_by`]
1896    pub fn transform_by(&mut self, transform: Transform) {
1897        self.try_transform_by(transform)
1898            .expect(MESH_EXTRACTED_ERROR);
1899    }
1900
1901    /// Transforms the vertex positions, normals, and tangents of the mesh in place by the given [`Transform`].
1902    ///
1903    /// `Aabb` of entities with modified mesh are not updated automatically.
1904    pub fn try_transform_by(&mut self, transform: Transform) -> Result<(), MeshAccessError> {
1905        // Needed when transforming normals and tangents
1906        let scale_recip = 1. / transform.scale;
1907        if true {
    if !(transform.scale.yzx() * transform.scale.zxy() != Vec3::ZERO) {
        {
            ::core::panicking::panic_fmt(format_args!("mesh transform scale cannot be zero on more than one axis"));
        }
    };
};debug_assert!(
1908            transform.scale.yzx() * transform.scale.zxy() != Vec3::ZERO,
1909            "mesh transform scale cannot be zero on more than one axis"
1910        );
1911
1912        if let Some(VertexAttributeValues::Float32x3(positions)) =
1913            self.try_attribute_mut_option(Mesh::ATTRIBUTE_POSITION)?
1914        {
1915            // Apply scale, rotation, and translation to vertex positions
1916            positions
1917                .iter_mut()
1918                .for_each(|pos| *pos = transform.transform_point(Vec3::from_slice(pos)).to_array());
1919        }
1920
1921        // No need to transform normals or tangents if rotation is near identity and scale is uniform
1922        if transform.rotation.is_near_identity()
1923            && transform.scale.x == transform.scale.y
1924            && transform.scale.y == transform.scale.z
1925        {
1926            return Ok(());
1927        }
1928
1929        if let Some(VertexAttributeValues::Float32x3(normals)) =
1930            self.try_attribute_mut_option(Mesh::ATTRIBUTE_NORMAL)?
1931        {
1932            // Transform normals, taking into account non-uniform scaling and rotation
1933            normals.iter_mut().for_each(|normal| {
1934                *normal = (transform.rotation
1935                    * scale_normal(Vec3::from_array(*normal), scale_recip))
1936                .to_array();
1937            });
1938        }
1939
1940        if let Some(VertexAttributeValues::Float32x4(tangents)) =
1941            self.try_attribute_mut_option(Mesh::ATTRIBUTE_TANGENT)?
1942        {
1943            // Transform tangents, taking into account non-uniform scaling and rotation
1944            tangents.iter_mut().for_each(|tangent| {
1945                let handedness = tangent[3];
1946                let scaled_tangent = Vec3::from_slice(tangent) * transform.scale;
1947                *tangent = (transform.rotation * scaled_tangent.normalize_or_zero())
1948                    .extend(handedness)
1949                    .to_array();
1950            });
1951        }
1952
1953        Ok(())
1954    }
1955
1956    /// Translates the vertex positions of the mesh by the given [`Vec3`].
1957    ///
1958    /// `Aabb` of entities with modified mesh are not updated automatically.
1959    ///
1960    /// # Panics
1961    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1962    /// this as an error use [`Mesh::try_translated_by`]
1963    pub fn translated_by(mut self, translation: Vec3) -> Self {
1964        self.translate_by(translation);
1965        self
1966    }
1967
1968    /// Translates the vertex positions of the mesh by the given [`Vec3`].
1969    ///
1970    /// `Aabb` of entities with modified mesh are not updated automatically.
1971    pub fn try_translated_by(mut self, translation: Vec3) -> Result<Self, MeshAccessError> {
1972        self.try_translate_by(translation)?;
1973        Ok(self)
1974    }
1975
1976    /// Translates the vertex positions of the mesh in place by the given [`Vec3`].
1977    ///
1978    /// `Aabb` of entities with modified mesh are not updated automatically.
1979    ///
1980    /// # Panics
1981    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
1982    /// this as an error use [`Mesh::try_translate_by`]
1983    pub fn translate_by(&mut self, translation: Vec3) {
1984        self.try_translate_by(translation)
1985            .expect(MESH_EXTRACTED_ERROR);
1986    }
1987
1988    /// Translates the vertex positions of the mesh in place by the given [`Vec3`].
1989    ///
1990    /// `Aabb` of entities with modified mesh are not updated automatically.
1991    pub fn try_translate_by(&mut self, translation: Vec3) -> Result<(), MeshAccessError> {
1992        if translation == Vec3::ZERO {
1993            return Ok(());
1994        }
1995
1996        if let Some(VertexAttributeValues::Float32x3(positions)) =
1997            self.try_attribute_mut_option(Mesh::ATTRIBUTE_POSITION)?
1998        {
1999            // Apply translation to vertex positions
2000            positions
2001                .iter_mut()
2002                .for_each(|pos| *pos = (Vec3::from_slice(pos) + translation).to_array());
2003        }
2004
2005        Ok(())
2006    }
2007
2008    /// Rotates the vertex positions, normals, and tangents of the mesh by the given [`Quat`].
2009    ///
2010    /// `Aabb` of entities with modified mesh are not updated automatically.
2011    ///
2012    /// # Panics
2013    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
2014    /// this as an error use [`Mesh::try_rotated_by`]
2015    pub fn rotated_by(mut self, rotation: Quat) -> Self {
2016        self.try_rotate_by(rotation).expect(MESH_EXTRACTED_ERROR);
2017        self
2018    }
2019
2020    /// Rotates the vertex positions, normals, and tangents of the mesh by the given [`Quat`].
2021    ///
2022    /// `Aabb` of entities with modified mesh are not updated automatically.
2023    pub fn try_rotated_by(mut self, rotation: Quat) -> Result<Self, MeshAccessError> {
2024        self.try_rotate_by(rotation)?;
2025        Ok(self)
2026    }
2027
2028    /// Rotates the vertex positions, normals, and tangents of the mesh in place by the given [`Quat`].
2029    ///
2030    /// `Aabb` of entities with modified mesh are not updated automatically.
2031    ///
2032    /// # Panics
2033    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
2034    /// this as an error use [`Mesh::try_rotate_by`]
2035    pub fn rotate_by(&mut self, rotation: Quat) {
2036        self.try_rotate_by(rotation).expect(MESH_EXTRACTED_ERROR);
2037    }
2038
2039    /// Rotates the vertex positions, normals, and tangents of the mesh in place by the given [`Quat`].
2040    ///
2041    /// `Aabb` of entities with modified mesh are not updated automatically.
2042    pub fn try_rotate_by(&mut self, rotation: Quat) -> Result<(), MeshAccessError> {
2043        if let Some(VertexAttributeValues::Float32x3(positions)) =
2044            self.try_attribute_mut_option(Mesh::ATTRIBUTE_POSITION)?
2045        {
2046            // Apply rotation to vertex positions
2047            positions
2048                .iter_mut()
2049                .for_each(|pos| *pos = (rotation * Vec3::from_slice(pos)).to_array());
2050        }
2051
2052        // No need to transform normals or tangents if rotation is near identity
2053        if rotation.is_near_identity() {
2054            return Ok(());
2055        }
2056
2057        if let Some(VertexAttributeValues::Float32x3(normals)) =
2058            self.try_attribute_mut_option(Mesh::ATTRIBUTE_NORMAL)?
2059        {
2060            // Transform normals
2061            normals.iter_mut().for_each(|normal| {
2062                *normal = (rotation * Vec3::from_slice(normal).normalize_or_zero()).to_array();
2063            });
2064        }
2065
2066        if let Some(VertexAttributeValues::Float32x4(tangents)) =
2067            self.try_attribute_mut_option(Mesh::ATTRIBUTE_TANGENT)?
2068        {
2069            // Transform tangents
2070            tangents.iter_mut().for_each(|tangent| {
2071                let handedness = tangent[3];
2072                *tangent = (rotation * Vec3::from_slice(tangent).normalize_or_zero())
2073                    .extend(handedness)
2074                    .to_array();
2075            });
2076        }
2077
2078        Ok(())
2079    }
2080
2081    /// Scales the vertex positions, normals, and tangents of the mesh by the given [`Vec3`].
2082    ///
2083    /// `Aabb` of entities with modified mesh are not updated automatically.
2084    ///
2085    /// # Panics
2086    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
2087    /// this as an error use [`Mesh::try_scaled_by`]
2088    pub fn scaled_by(mut self, scale: Vec3) -> Self {
2089        self.scale_by(scale);
2090        self
2091    }
2092
2093    /// Scales the vertex positions, normals, and tangents of the mesh by the given [`Vec3`].
2094    ///
2095    /// `Aabb` of entities with modified mesh are not updated automatically.
2096    pub fn try_scaled_by(mut self, scale: Vec3) -> Result<Self, MeshAccessError> {
2097        self.try_scale_by(scale)?;
2098        Ok(self)
2099    }
2100
2101    /// Scales the vertex positions, normals, and tangents of the mesh in place by the given [`Vec3`].
2102    ///
2103    /// `Aabb` of entities with modified mesh are not updated automatically.
2104    ///
2105    /// # Panics
2106    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
2107    /// this as an error use [`Mesh::try_scale_by`]
2108    pub fn scale_by(&mut self, scale: Vec3) {
2109        self.try_scale_by(scale).expect(MESH_EXTRACTED_ERROR);
2110    }
2111
2112    /// Scales the vertex positions, normals, and tangents of the mesh in place by the given [`Vec3`].
2113    ///
2114    /// `Aabb` of entities with modified mesh are not updated automatically.
2115    pub fn try_scale_by(&mut self, scale: Vec3) -> Result<(), MeshAccessError> {
2116        // Needed when transforming normals and tangents
2117        let scale_recip = 1. / scale;
2118        if true {
    if !(scale.yzx() * scale.zxy() != Vec3::ZERO) {
        {
            ::core::panicking::panic_fmt(format_args!("mesh transform scale cannot be zero on more than one axis"));
        }
    };
};debug_assert!(
2119            scale.yzx() * scale.zxy() != Vec3::ZERO,
2120            "mesh transform scale cannot be zero on more than one axis"
2121        );
2122
2123        if let Some(VertexAttributeValues::Float32x3(positions)) =
2124            self.try_attribute_mut_option(Mesh::ATTRIBUTE_POSITION)?
2125        {
2126            // Apply scale to vertex positions
2127            positions
2128                .iter_mut()
2129                .for_each(|pos| *pos = (scale * Vec3::from_slice(pos)).to_array());
2130        }
2131
2132        // No need to transform normals or tangents if scale is uniform
2133        if scale.x == scale.y && scale.y == scale.z {
2134            return Ok(());
2135        }
2136
2137        if let Some(VertexAttributeValues::Float32x3(normals)) =
2138            self.try_attribute_mut_option(Mesh::ATTRIBUTE_NORMAL)?
2139        {
2140            // Transform normals, taking into account non-uniform scaling
2141            normals.iter_mut().for_each(|normal| {
2142                *normal = scale_normal(Vec3::from_array(*normal), scale_recip).to_array();
2143            });
2144        }
2145
2146        if let Some(VertexAttributeValues::Float32x4(tangents)) =
2147            self.try_attribute_mut_option(Mesh::ATTRIBUTE_TANGENT)?
2148        {
2149            // Transform tangents, taking into account non-uniform scaling
2150            tangents.iter_mut().for_each(|tangent| {
2151                let handedness = tangent[3];
2152                let scaled_tangent = Vec3::from_slice(tangent) * scale;
2153                *tangent = scaled_tangent
2154                    .normalize_or_zero()
2155                    .extend(handedness)
2156                    .to_array();
2157            });
2158        }
2159
2160        Ok(())
2161    }
2162
2163    /// Normalize joint weights so they sum to 1.
2164    ///
2165    /// # Panics
2166    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
2167    /// this as an error use [`Mesh::try_normalize_joint_weights`]
2168    pub fn normalize_joint_weights(&mut self) {
2169        self.try_normalize_joint_weights()
2170            .expect(MESH_EXTRACTED_ERROR);
2171    }
2172
2173    /// Normalize joint weights so they sum to 1.
2174    pub fn try_normalize_joint_weights(&mut self) -> Result<(), MeshAccessError> {
2175        if let Some(VertexAttributeValues::Float32x4(joints)) =
2176            self.try_attribute_mut_option(Self::ATTRIBUTE_JOINT_WEIGHT)?
2177        {
2178            for weights in joints.iter_mut() {
2179                // force negative weights to zero
2180                weights.iter_mut().for_each(|w| *w = w.max(0.0));
2181
2182                let sum: f32 = weights.iter().sum();
2183                if sum == 0.0 {
2184                    // all-zero weights are invalid
2185                    weights[0] = 1.0;
2186                } else {
2187                    let recip = sum.recip();
2188                    for weight in weights.iter_mut() {
2189                        *weight *= recip;
2190                    }
2191                }
2192            }
2193        }
2194
2195        Ok(())
2196    }
2197
2198    /// Get a list of this Mesh's [triangles] as an iterator if possible.
2199    ///
2200    /// Returns an error if any of the following conditions are met (see [`MeshTrianglesError`]):
2201    /// * The Mesh's [primitive topology] is not `TriangleList` or `TriangleStrip`.
2202    /// * The Mesh is missing position or index data.
2203    /// * The Mesh's position data has the wrong format (not `Float32x3`).
2204    ///
2205    /// [primitive topology]: PrimitiveTopology
2206    /// [triangles]: Triangle3d
2207    pub fn triangles(&self) -> Result<impl Iterator<Item = Triangle3d> + '_, MeshTrianglesError> {
2208        fn indices_to_triangle<T: TryInto<usize> + Copy>(
2209            vertices: &[[f32; 3]],
2210            indices: &[T; 3],
2211        ) -> Option<Triangle3d> {
2212            let vert0 = Vec3::from(*vertices.get(indices[0].try_into().ok()?)?);
2213            let vert1 = Vec3::from(*vertices.get(indices[1].try_into().ok()?)?);
2214            let vert2 = Vec3::from(*vertices.get(indices[2].try_into().ok()?)?);
2215            Some(Triangle3d {
2216                vertices: [vert0, vert1, vert2],
2217            })
2218        }
2219
2220        let position_data = self.try_attribute(Mesh::ATTRIBUTE_POSITION)?;
2221
2222        let Some(vertices) = position_data.as_float3() else {
2223            return Err(MeshTrianglesError::PositionsFormat);
2224        };
2225
2226        let indices = self.try_indices()?;
2227
2228        match self.primitive_topology {
2229            PrimitiveTopology::TriangleList => {
2230                // When indices reference out-of-bounds vertex data, the triangle is omitted.
2231                // This implicitly truncates the indices to a multiple of 3.
2232                let iterator = match indices {
2233                    Indices::U16(vec) => FourIterators::First(
2234                        vec.as_chunks()
2235                            .0
2236                            .iter()
2237                            .flat_map(|indices| indices_to_triangle(vertices, indices)),
2238                    ),
2239                    Indices::U32(vec) => FourIterators::Second(
2240                        vec.as_chunks()
2241                            .0
2242                            .iter()
2243                            .flat_map(|indices| indices_to_triangle(vertices, indices)),
2244                    ),
2245                };
2246
2247                Ok(iterator)
2248            }
2249            PrimitiveTopology::TriangleStrip => {
2250                // When indices reference out-of-bounds vertex data, the triangle is omitted.
2251                // If there aren't enough indices to make a triangle, then an empty vector will be
2252                // returned.
2253                let iterator = match indices {
2254                    Indices::U16(vec) => {
2255                        FourIterators::Third(vec.array_windows().enumerate().flat_map(
2256                            |(i, indices @ &[idx0, idx1, idx2])| {
2257                                if i % 2 == 0 {
2258                                    indices_to_triangle(vertices, indices)
2259                                } else {
2260                                    indices_to_triangle(vertices, &[idx1, idx0, idx2])
2261                                }
2262                            },
2263                        ))
2264                    }
2265                    Indices::U32(vec) => {
2266                        FourIterators::Fourth(vec.array_windows().enumerate().flat_map(
2267                            |(i, indices @ &[idx0, idx1, idx2])| {
2268                                if i % 2 == 0 {
2269                                    indices_to_triangle(vertices, indices)
2270                                } else {
2271                                    indices_to_triangle(vertices, &[idx1, idx0, idx2])
2272                                }
2273                            },
2274                        ))
2275                    }
2276                };
2277
2278                Ok(iterator)
2279            }
2280            _ => Err(MeshTrianglesError::WrongTopology),
2281        }
2282    }
2283
2284    /// Extracts the mesh vertex, index and morph target data for GPU upload.
2285    /// This function is called internally in render world extraction, it is
2286    /// unlikely to be useful outside of that context.
2287    ///
2288    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
2289    pub fn take_gpu_data(&mut self) -> Result<Self, MeshAccessError> {
2290        let attributes = self.attributes.extract()?;
2291        let indices = self.indices.extract()?;
2292        #[cfg(feature = "morph")]
2293        let morph_targets = self.morph_targets.extract()?;
2294        #[cfg(feature = "morph")]
2295        let morph_target_names = self.morph_target_names.extract()?;
2296
2297        // store the aabb extents as they cannot be computed after extraction
2298        if let Some(MeshAttributeData {
2299            values: VertexAttributeValues::Float32x3(position_values),
2300            ..
2301        }) = attributes
2302            .as_ref_option()?
2303            .and_then(|attrs| attrs.get(&Self::ATTRIBUTE_POSITION.id))
2304            && !position_values.is_empty()
2305        {
2306            let mut iter = position_values.iter().map(|p| Vec3::from_slice(p));
2307            let mut min = iter.next().unwrap();
2308            let mut max = min;
2309            for v in iter {
2310                min = Vec3::min(min, v);
2311                max = Vec3::max(max, v);
2312            }
2313            self.final_aabb = Some(Aabb3d::from_min_max(min, max));
2314        }
2315
2316        Ok(Self {
2317            attributes,
2318            indices,
2319            #[cfg(feature = "morph")]
2320            morph_targets,
2321            #[cfg(feature = "morph")]
2322            morph_target_names,
2323            ..self.clone()
2324        })
2325    }
2326
2327    /// Get this mesh's [`SkinnedMeshBounds`].
2328    pub fn skinned_mesh_bounds(&self) -> Option<&SkinnedMeshBounds> {
2329        self.skinned_mesh_bounds.as_ref()
2330    }
2331
2332    /// Set this mesh's [`SkinnedMeshBounds`].
2333    pub fn set_skinned_mesh_bounds(&mut self, skinned_mesh_bounds: Option<SkinnedMeshBounds>) {
2334        self.skinned_mesh_bounds = skinned_mesh_bounds;
2335    }
2336
2337    /// Consumes the mesh and returns a mesh with the given [`SkinnedMeshBounds`].
2338    pub fn with_skinned_mesh_bounds(
2339        mut self,
2340        skinned_mesh_bounds: Option<SkinnedMeshBounds>,
2341    ) -> Self {
2342        self.set_skinned_mesh_bounds(skinned_mesh_bounds);
2343        self
2344    }
2345
2346    /// Generate [`SkinnedMeshBounds`] for this mesh.
2347    pub fn generate_skinned_mesh_bounds(&mut self) -> Result<(), SkinnedMeshBoundsError> {
2348        self.skinned_mesh_bounds = Some(SkinnedMeshBounds::from_mesh(self)?);
2349        Ok(())
2350    }
2351
2352    /// Consumes the mesh and returns a mesh with generated [`SkinnedMeshBounds`].
2353    pub fn with_generated_skinned_mesh_bounds(mut self) -> Result<Self, SkinnedMeshBoundsError> {
2354        self.generate_skinned_mesh_bounds()?;
2355        Ok(self)
2356    }
2357}
2358
2359#[cfg(feature = "morph")]
2360impl Mesh {
2361    /// Whether this mesh has morph targets.
2362    ///
2363    /// # Panics
2364    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
2365    /// this as an error use [`Mesh::try_has_morph_targets`]
2366    pub fn has_morph_targets(&self) -> bool {
2367        self.try_has_morph_targets().expect(MESH_EXTRACTED_ERROR)
2368    }
2369
2370    /// Whether this mesh has morph targets.
2371    pub fn try_has_morph_targets(&self) -> Result<bool, MeshAccessError> {
2372        Ok(self.morph_targets.as_ref_option()?.is_some())
2373    }
2374
2375    /// Set the [morph target] displacements for this mesh.
2376    ///
2377    /// [morph target]: https://en.wikipedia.org/wiki/Morph_target_animation
2378    ///
2379    /// # Panics
2380    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
2381    /// this as an error use [`Mesh::try_set_morph_targets`]
2382    #[cfg(feature = "morph")]
2383    pub fn set_morph_targets(&mut self, morph_targets: Vec<MorphAttributes>) {
2384        self.try_set_morph_targets(morph_targets)
2385            .expect(MESH_EXTRACTED_ERROR);
2386    }
2387
2388    /// Set the [morph target] displacements for this mesh.
2389    ///
2390    /// [morph targets]: https://en.wikipedia.org/wiki/Morph_target_animation
2391    #[cfg(feature = "morph")]
2392    pub fn try_set_morph_targets(
2393        &mut self,
2394        morph_targets: Vec<MorphAttributes>,
2395    ) -> Result<(), MeshAccessError> {
2396        self.morph_targets.replace(Some(morph_targets))?;
2397        Ok(())
2398    }
2399
2400    /// Retrieve the morph target displacements for this mesh, or None if there
2401    /// are no morph targets.
2402    ///
2403    /// # Panics
2404    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
2405    /// this as an error use [`Mesh::try_morph_targets`]
2406    #[cfg(feature = "morph")]
2407    pub fn morph_targets(&self) -> Option<&Vec<MorphAttributes>> {
2408        self.morph_targets
2409            .as_ref_option()
2410            .expect(MESH_EXTRACTED_ERROR)
2411    }
2412
2413    /// Retrieve the morph displacements for this mesh, or None if there are no
2414    /// morph targets.
2415    ///
2416    /// Returns an error if the mesh data has been extracted to `RenderWorld`or
2417    /// if the morph targets do not exist.
2418    #[cfg(feature = "morph")]
2419    pub fn try_morph_targets(&self) -> Result<&Vec<MorphAttributes>, MeshAccessError> {
2420        self.morph_targets.as_ref()
2421    }
2422
2423    /// Consumes the mesh and returns a mesh with the given [morph target]
2424    /// displacements.
2425    ///
2426    /// (Alternatively, you can use [`Mesh::set_morph_targets`] to mutate an existing mesh in-place)
2427    ///
2428    /// [morph target]: https://en.wikipedia.org/wiki/Morph_target_animation
2429    ///
2430    /// # Panics
2431    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
2432    /// this as an error use [`Mesh::try_with_morph_targets`]
2433    #[must_use]
2434    #[cfg(feature = "morph")]
2435    pub fn with_morph_targets(mut self, morph_targets: Vec<MorphAttributes>) -> Self {
2436        self.set_morph_targets(morph_targets);
2437        self
2438    }
2439
2440    /// Consumes the mesh and returns a mesh with the given [morph targets].
2441    ///
2442    /// (Alternatively, you can use [`Mesh::set_morph_targets`] to mutate an existing mesh in-place)
2443    ///
2444    /// [morph targets]: https://en.wikipedia.org/wiki/Morph_target_animation
2445    ///
2446    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
2447    #[cfg(feature = "morph")]
2448    pub fn try_with_morph_targets(
2449        mut self,
2450        morph_targets: Vec<MorphAttributes>,
2451    ) -> Result<Self, MeshAccessError> {
2452        self.try_set_morph_targets(morph_targets)?;
2453        Ok(self)
2454    }
2455
2456    /// Sets the names of each morph target. This should correspond to the order of the morph targets in `set_morph_targets`.
2457    ///
2458    /// # Panics
2459    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
2460    /// this as an error use [`Mesh::try_set_morph_target_names`]
2461    pub fn set_morph_target_names(&mut self, names: Vec<String>) {
2462        self.try_set_morph_target_names(names)
2463            .expect(MESH_EXTRACTED_ERROR);
2464    }
2465
2466    /// Sets the names of each morph target. This should correspond to the order of the morph targets in `set_morph_targets`.
2467    ///
2468    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
2469    pub fn try_set_morph_target_names(
2470        &mut self,
2471        names: Vec<String>,
2472    ) -> Result<(), MeshAccessError> {
2473        self.morph_target_names.replace(Some(names))?;
2474        Ok(())
2475    }
2476
2477    /// Consumes the mesh and returns a mesh with morph target names.
2478    /// Names should correspond to the order of the morph targets in `set_morph_targets`.
2479    ///
2480    /// (Alternatively, you can use [`Mesh::set_morph_target_names`] to mutate an existing mesh in-place)
2481    ///
2482    /// # Panics
2483    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
2484    /// this as an error use [`Mesh::try_set_morph_target_names`]
2485    #[must_use]
2486    pub fn with_morph_target_names(self, names: Vec<String>) -> Self {
2487        self.try_with_morph_target_names(names)
2488            .expect(MESH_EXTRACTED_ERROR)
2489    }
2490
2491    /// Consumes the mesh and returns a mesh with morph target names.
2492    /// Names should correspond to the order of the morph targets in `set_morph_targets`.
2493    ///
2494    /// (Alternatively, you can use [`Mesh::set_morph_target_names`] to mutate an existing mesh in-place)
2495    ///
2496    /// Returns an error if the mesh data has been extracted to `RenderWorld`.
2497    pub fn try_with_morph_target_names(
2498        mut self,
2499        names: Vec<String>,
2500    ) -> Result<Self, MeshAccessError> {
2501        self.try_set_morph_target_names(names)?;
2502        Ok(self)
2503    }
2504
2505    /// Gets a list of all morph target names, if they exist.
2506    ///
2507    /// # Panics
2508    /// Panics when the mesh data has already been extracted to `RenderWorld`. To handle
2509    /// this as an error use [`Mesh::try_morph_target_names`]
2510    pub fn morph_target_names(&self) -> Option<&[String]> {
2511        self.try_morph_target_names().expect(MESH_EXTRACTED_ERROR)
2512    }
2513
2514    /// Gets a list of all morph target names, if they exist.
2515    ///
2516    /// Returns an error if the mesh data has been extracted to `RenderWorld`or
2517    /// if the morph targets do not exist.
2518    pub fn try_morph_target_names(&self) -> Result<Option<&[String]>, MeshAccessError> {
2519        Ok(self
2520            .morph_target_names
2521            .as_ref_option()?
2522            .map(core::ops::Deref::deref))
2523    }
2524}
2525
2526/// An enum to define which UV attribute to use for a texture.
2527///
2528/// It only supports two UV attributes, [`Mesh::ATTRIBUTE_UV_0`] and
2529/// [`Mesh::ATTRIBUTE_UV_1`].
2530/// The default is [`UvChannel::Uv0`].
2531#[derive(const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for UvChannel where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration.register_type_data::<ReflectDefault, Self>();
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {}
        }
        impl bevy_reflect::Typed for UvChannel where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Uv0")),
                                                bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Uv1"))]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for UvChannel where  {
            fn type_path() -> &'static str { "bevy_mesh::mesh::UvChannel" }
            fn short_type_path() -> &'static str { "UvChannel" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("UvChannel")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_mesh::mesh".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_mesh::mesh")
            }
        }
        impl bevy_reflect::Reflect for UvChannel where  {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        #[allow(non_upper_case_globals)]
        const _: () =
            {
                static __INVENTORY: ::inventory::Node =
                    ::inventory::Node {
                        value: &{
                                bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<UvChannel
                                        as
                                        bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
                            },
                        next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
                    };
                #[link_section = ".text.startup"]
                unsafe extern "C" fn __ctor() {
                    unsafe {
                        ::inventory::ErasedNode::submit(__INVENTORY.value,
                            &__INVENTORY)
                    }
                }
                #[used]
                #[link_section = ".init_array"]
                static __CTOR: unsafe extern "C" fn() = __ctor;
            };
        impl bevy_reflect::enums::Enum for UvChannel where  {
            fn field(&self, __name_param: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at(&self, __index_param: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_mut(&mut self, __name_param: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at_mut(&mut self, __index_param: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn index_of(&self, __name_param: &str)
                -> ::core::option::Option<usize> {
                match self { _ => ::core::option::Option::None, }
            }
            fn name_at(&self, __index_param: usize)
                -> ::core::option::Option<&str> {
                match self { _ => ::core::option::Option::None, }
            }
            fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
                bevy_reflect::enums::VariantFieldIter::new(self)
            }
            #[inline]
            fn field_len(&self) -> usize {
                match self {
                    UvChannel::Uv0 { .. } => 0usize,
                    UvChannel::Uv1 { .. } => 0usize,
                    _ => 0,
                }
            }
            #[inline]
            fn variant_name(&self) -> &str {
                match self {
                    UvChannel::Uv0 { .. } => "Uv0",
                    UvChannel::Uv1 { .. } => "Uv1",
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_index(&self) -> usize {
                match self {
                    UvChannel::Uv0 { .. } => 0usize,
                    UvChannel::Uv1 { .. } => 1usize,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_type(&self) -> bevy_reflect::enums::VariantType {
                match self {
                    UvChannel::Uv0 { .. } =>
                        bevy_reflect::enums::VariantType::Unit,
                    UvChannel::Uv1 { .. } =>
                        bevy_reflect::enums::VariantType::Unit,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            fn to_dynamic_enum(&self) -> bevy_reflect::enums::DynamicEnum {
                bevy_reflect::enums::DynamicEnum::from_ref::<Self>(self)
            }
        }
        impl bevy_reflect::PartialReflect for UvChannel where  {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self,
                __value_param: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Enum(__value_param) =
                        bevy_reflect::PartialReflect::reflect_ref(__value_param) {
                    if bevy_reflect::enums::Enum::variant_name(self) ==
                            bevy_reflect::enums::Enum::variant_name(__value_param) {
                        match bevy_reflect::enums::Enum::variant_type(__value_param)
                            {
                            bevy_reflect::enums::VariantType::Struct => {
                                for field in
                                    bevy_reflect::enums::Enum::iter_fields(__value_param) {
                                    let name = field.name().unwrap();
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_mut(self, name) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            bevy_reflect::enums::VariantType::Tuple => {
                                for (index, field) in
                                    ::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
                                    {
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_at_mut(self, index) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            _ => {}
                        }
                    } else {
                        match bevy_reflect::enums::Enum::variant_name(__value_param)
                            {
                            "Uv0" => { *self = UvChannel::Uv0 {} }
                            "Uv1" => { *self = UvChannel::Uv1 {} }
                            name => {
                                return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
                                            enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
                                            variant_name: ::core::convert::Into::into(name),
                                        });
                            }
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
                                to_kind: bevy_reflect::ReflectKind::Enum,
                            });
                }
                ::core::result::Result::Ok(())
            }
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Enum
            }
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Enum(self)
            }
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Enum(self)
            }
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Enum(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_hash(&self) -> ::core::option::Option<u64> {
                (bevy_reflect::enums::enum_hash)(self)
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                let value =
                    <dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
                if let ::core::option::Option::Some(value) = value {
                    ::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
                            value))
                } else { ::core::option::Option::Some(false) }
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::enums::enum_partial_cmp)(self, value)
            }
            fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
                -> ::core::fmt::Result {
                ::core::fmt::Debug::fmt(self, f)
            }
            #[inline]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for UvChannel where  {
            fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Enum(__param0) =
                        bevy_reflect::PartialReflect::reflect_ref(__param0) {
                    match bevy_reflect::enums::Enum::variant_name(__param0) {
                        "Uv0" => ::core::option::Option::Some(UvChannel::Uv0 {}),
                        "Uv1" => ::core::option::Option::Some(UvChannel::Uv1 {}),
                        name => ::core::option::Option::None,
                    }
                } else { ::core::option::Option::None }
            }
        }
    };Reflect, #[automatically_derived]
impl ::core::default::Default for UvChannel {
    #[inline]
    fn default() -> UvChannel { Self::Uv0 }
}Default, #[automatically_derived]
impl ::core::fmt::Debug for UvChannel {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self { UvChannel::Uv0 => "Uv0", UvChannel::Uv1 => "Uv1", })
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for UvChannel {
    #[inline]
    fn clone(&self) -> UvChannel {
        match self {
            UvChannel::Uv0 => UvChannel::Uv0,
            UvChannel::Uv1 => UvChannel::Uv1,
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for UvChannel {
    #[inline]
    fn eq(&self, other: &UvChannel) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for UvChannel {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq)]
2532#[reflect(Default, Debug, Clone, PartialEq)]
2533pub enum UvChannel {
2534    #[default]
2535    Uv0,
2536    Uv1,
2537}
2538
2539/// Correctly scales and renormalizes an already normalized `normal` by the scale determined by its reciprocal `scale_recip`
2540pub(crate) fn scale_normal(normal: Vec3, scale_recip: Vec3) -> Vec3 {
2541    // This is basically just `normal * scale_recip` but with the added rule that `0. * anything == 0.`
2542    // This is necessary because components of `scale_recip` may be infinities, which do not multiply to zero
2543    let n = Vec3::select(normal.cmpeq(Vec3::ZERO), Vec3::ZERO, normal * scale_recip);
2544
2545    // If n is finite, no component of `scale_recip` was infinite or the normal was perpendicular to the scale
2546    // else the scale had at least one zero-component and the normal needs to point along the direction of that component
2547    if n.is_finite() {
2548        n.normalize_or_zero()
2549    } else {
2550        Vec3::select(n.abs().cmpeq(Vec3::INFINITY), n.signum(), Vec3::ZERO).normalize()
2551    }
2552}
2553
2554impl core::ops::Mul<Mesh> for Transform {
2555    type Output = Mesh;
2556
2557    fn mul(self, rhs: Mesh) -> Self::Output {
2558        rhs.transformed_by(self)
2559    }
2560}
2561
2562/// A version of [`Mesh`] suitable for serializing for short-term transfer.
2563///
2564/// [`Mesh`] does not implement [`Serialize`] / [`Deserialize`] because it is made with the renderer in mind.
2565/// It is not a general-purpose mesh implementation, and its internals are subject to frequent change.
2566/// As such, storing a [`Mesh`] on disk is highly discouraged.
2567///
2568/// But there are still some valid use cases for serializing a [`Mesh`], namely transferring meshes between processes.
2569/// To support this, you can create a [`SerializedMesh`] from a [`Mesh`] with [`SerializedMesh::from_mesh`],
2570/// and then deserialize it with [`SerializedMesh::deserialize`]. The caveats are:
2571/// - The mesh representation is not valid across different versions of Bevy.
2572/// - This conversion is lossy. Only the following information is preserved:
2573///   - Primitive topology
2574///   - Vertex attributes
2575///   - Indices
2576/// - Custom attributes that were not specified with [`MeshDeserializer::add_custom_vertex_attribute`] will be ignored while deserializing.
2577#[cfg(feature = "serialize")]
2578#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SerializedMesh {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "SerializedMesh", "primitive_topology", &self.primitive_topology,
            "attributes", &self.attributes, "indices", &&self.indices)
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SerializedMesh {
    #[inline]
    fn clone(&self) -> SerializedMesh {
        SerializedMesh {
            primitive_topology: ::core::clone::Clone::clone(&self.primitive_topology),
            attributes: ::core::clone::Clone::clone(&self.attributes),
            indices: ::core::clone::Clone::clone(&self.indices),
        }
    }
}Clone, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl _serde::Serialize for SerializedMesh {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private228::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                let mut __serde_state =
                    _serde::Serializer::serialize_struct(__serializer,
                            "SerializedMesh", false as usize + 1 + 1 + 1)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "primitive_topology", &self.primitive_topology)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "attributes", &self.attributes)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "indices", &self.indices)?;
                _serde::ser::SerializeStruct::end(__serde_state)
            }
        }
    };Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<'de> _serde::Deserialize<'de> for SerializedMesh {
            fn deserialize<__D>(__deserializer: __D)
                -> _serde::__private228::Result<Self, __D::Error> where
                __D: _serde::Deserializer<'de> {
                #[allow(non_camel_case_types)]
                #[doc(hidden)]
                enum __Field { __field0, __field1, __field2, __ignore, }
                #[doc(hidden)]
                struct __FieldVisitor;
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                    type Value = __Field;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "field identifier")
                    }
                    fn visit_u64<__E>(self, __value: u64)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            0u64 => _serde::__private228::Ok(__Field::__field0),
                            1u64 => _serde::__private228::Ok(__Field::__field1),
                            2u64 => _serde::__private228::Ok(__Field::__field2),
                            _ => _serde::__private228::Ok(__Field::__ignore),
                        }
                    }
                    fn visit_str<__E>(self, __value: &str)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            "primitive_topology" =>
                                _serde::__private228::Ok(__Field::__field0),
                            "attributes" => _serde::__private228::Ok(__Field::__field1),
                            "indices" => _serde::__private228::Ok(__Field::__field2),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                    fn visit_bytes<__E>(self, __value: &[u8])
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            b"primitive_topology" =>
                                _serde::__private228::Ok(__Field::__field0),
                            b"attributes" =>
                                _serde::__private228::Ok(__Field::__field1),
                            b"indices" => _serde::__private228::Ok(__Field::__field2),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                }
                #[automatically_derived]
                impl<'de> _serde::Deserialize<'de> for __Field {
                    #[inline]
                    fn deserialize<__D>(__deserializer: __D)
                        -> _serde::__private228::Result<Self, __D::Error> where
                        __D: _serde::Deserializer<'de> {
                        _serde::Deserializer::deserialize_identifier(__deserializer,
                            __FieldVisitor)
                    }
                }
                #[doc(hidden)]
                struct __Visitor<'de> {
                    marker: _serde::__private228::PhantomData<SerializedMesh>,
                    lifetime: _serde::__private228::PhantomData<&'de ()>,
                }
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                    type Value = SerializedMesh;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "struct SerializedMesh")
                    }
                    #[inline]
                    fn visit_seq<__A>(self, mut __seq: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::SeqAccess<'de> {
                        let __field0 =
                            match _serde::de::SeqAccess::next_element::<PrimitiveTopology>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
                                                &"struct SerializedMesh with 3 elements")),
                            };
                        let __field1 =
                            match _serde::de::SeqAccess::next_element::<Vec<(MeshVertexAttributeId,
                                            SerializedMeshAttributeData)>>(&mut __seq)? {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
                                                &"struct SerializedMesh with 3 elements")),
                            };
                        let __field2 =
                            match _serde::de::SeqAccess::next_element::<Option<Indices>>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(2usize,
                                                &"struct SerializedMesh with 3 elements")),
                            };
                        _serde::__private228::Ok(SerializedMesh {
                                primitive_topology: __field0,
                                attributes: __field1,
                                indices: __field2,
                            })
                    }
                    #[inline]
                    fn visit_map<__A>(self, mut __map: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::MapAccess<'de> {
                        let mut __field0:
                                _serde::__private228::Option<PrimitiveTopology> =
                            _serde::__private228::None;
                        let mut __field1:
                                _serde::__private228::Option<Vec<(MeshVertexAttributeId,
                                SerializedMeshAttributeData)>> = _serde::__private228::None;
                        let mut __field2:
                                _serde::__private228::Option<Option<Indices>> =
                            _serde::__private228::None;
                        while let _serde::__private228::Some(__key) =
                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                            match __key {
                                __Field::__field0 => {
                                    if _serde::__private228::Option::is_some(&__field0) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("primitive_topology"));
                                    }
                                    __field0 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<PrimitiveTopology>(&mut __map)?);
                                }
                                __Field::__field1 => {
                                    if _serde::__private228::Option::is_some(&__field1) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("attributes"));
                                    }
                                    __field1 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec<(MeshVertexAttributeId,
                                                        SerializedMeshAttributeData)>>(&mut __map)?);
                                }
                                __Field::__field2 => {
                                    if _serde::__private228::Option::is_some(&__field2) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("indices"));
                                    }
                                    __field2 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Option<Indices>>(&mut __map)?);
                                }
                                _ => {
                                    let _ =
                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                }
                            }
                        }
                        let __field0 =
                            match __field0 {
                                _serde::__private228::Some(__field0) => __field0,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("primitive_topology")?,
                            };
                        let __field1 =
                            match __field1 {
                                _serde::__private228::Some(__field1) => __field1,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("attributes")?,
                            };
                        let __field2 =
                            match __field2 {
                                _serde::__private228::Some(__field2) => __field2,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("indices")?,
                            };
                        _serde::__private228::Ok(SerializedMesh {
                                primitive_topology: __field0,
                                attributes: __field1,
                                indices: __field2,
                            })
                    }
                }
                #[doc(hidden)]
                const FIELDS: &'static [&'static str] =
                    &["primitive_topology", "attributes", "indices"];
                _serde::Deserializer::deserialize_struct(__deserializer,
                    "SerializedMesh", FIELDS,
                    __Visitor {
                        marker: _serde::__private228::PhantomData::<SerializedMesh>,
                        lifetime: _serde::__private228::PhantomData,
                    })
            }
        }
    };Deserialize)]
2579pub struct SerializedMesh {
2580    primitive_topology: PrimitiveTopology,
2581    attributes: Vec<(MeshVertexAttributeId, SerializedMeshAttributeData)>,
2582    indices: Option<Indices>,
2583}
2584
2585#[cfg(feature = "serialize")]
2586impl SerializedMesh {
2587    /// Create a [`SerializedMesh`] from a [`Mesh`]. See the documentation for [`SerializedMesh`] for caveats.
2588    pub fn from_mesh(mut mesh: Mesh) -> Self {
2589        Self {
2590            primitive_topology: mesh.primitive_topology,
2591            attributes: mesh
2592                .attributes
2593                .replace(None)
2594                .expect(MESH_EXTRACTED_ERROR)
2595                .unwrap()
2596                .into_iter()
2597                .map(|(id, data)| {
2598                    (
2599                        id,
2600                        SerializedMeshAttributeData::from_mesh_attribute_data(data),
2601                    )
2602                })
2603                .collect(),
2604            indices: mesh.indices.replace(None).expect(MESH_EXTRACTED_ERROR),
2605        }
2606    }
2607
2608    /// Create a [`Mesh`] from a [`SerializedMesh`]. See the documentation for [`SerializedMesh`] for caveats.
2609    ///
2610    /// Use [`MeshDeserializer`] if you need to pass extra options to the deserialization process, such as specifying custom vertex attributes.
2611    pub fn into_mesh(self) -> Mesh {
2612        MeshDeserializer::default().deserialize(self)
2613    }
2614}
2615
2616/// Use to specify extra options when deserializing a [`SerializedMesh`] into a [`Mesh`].
2617#[cfg(feature = "serialize")]
2618pub struct MeshDeserializer {
2619    custom_vertex_attributes: HashMap<Box<str>, MeshVertexAttribute>,
2620}
2621
2622#[cfg(feature = "serialize")]
2623impl Default for MeshDeserializer {
2624    fn default() -> Self {
2625        // Written like this so that the compiler can validate that we use all the built-in attributes.
2626        // If you just added a new attribute and got a compile error, please add it to this list :)
2627        const BUILTINS: [MeshVertexAttribute; Mesh::FIRST_AVAILABLE_CUSTOM_ATTRIBUTE as usize] = [
2628            Mesh::ATTRIBUTE_POSITION,
2629            Mesh::ATTRIBUTE_NORMAL,
2630            Mesh::ATTRIBUTE_UV_0,
2631            Mesh::ATTRIBUTE_UV_1,
2632            Mesh::ATTRIBUTE_TANGENT,
2633            Mesh::ATTRIBUTE_COLOR,
2634            Mesh::ATTRIBUTE_JOINT_WEIGHT,
2635            Mesh::ATTRIBUTE_JOINT_INDEX,
2636        ];
2637        Self {
2638            custom_vertex_attributes: BUILTINS
2639                .into_iter()
2640                .map(|attribute| (attribute.name.into(), attribute))
2641                .collect(),
2642        }
2643    }
2644}
2645
2646#[cfg(feature = "serialize")]
2647impl MeshDeserializer {
2648    /// Create a new [`MeshDeserializer`].
2649    pub fn new() -> Self {
2650        Self::default()
2651    }
2652
2653    /// Register a custom vertex attribute to the deserializer. Custom vertex attributes that were not added with this method will be ignored while deserializing.
2654    pub fn add_custom_vertex_attribute(
2655        &mut self,
2656        name: &str,
2657        attribute: MeshVertexAttribute,
2658    ) -> &mut Self {
2659        self.custom_vertex_attributes.insert(name.into(), attribute);
2660        self
2661    }
2662
2663    /// Deserialize a [`SerializedMesh`] into a [`Mesh`].
2664    ///
2665    /// See the documentation for [`SerializedMesh`] for caveats.
2666    pub fn deserialize(&self, serialized_mesh: SerializedMesh) -> Mesh {
2667        Mesh {
2668            attributes: MeshExtractableData::Data(
2669                serialized_mesh
2670                .attributes
2671                .into_iter()
2672                .filter_map(|(id, data)| {
2673                    let attribute = data.attribute.clone();
2674                    let Some(data) =
2675                        data.try_into_mesh_attribute_data(&self.custom_vertex_attributes)
2676                    else {
2677                        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event src/mesh.rs:2677",
                        "bevy_mesh::mesh", ::tracing::Level::WARN,
                        ::tracing_core::__macro_support::Option::Some("src/mesh.rs"),
                        ::tracing_core::__macro_support::Option::Some(2677u32),
                        ::tracing_core::__macro_support::Option::Some("bevy_mesh::mesh"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::WARN <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Deserialized mesh contains custom vertex attribute {0:?} that was not specified with `MeshDeserializer::add_custom_vertex_attribute`. Ignoring.",
                                                    attribute) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};warn!(
2678                            "Deserialized mesh contains custom vertex attribute {attribute:?} that \
2679                            was not specified with `MeshDeserializer::add_custom_vertex_attribute`. Ignoring."
2680                        );
2681                        return None;
2682                    };
2683                    Some((id, data))
2684                })
2685                .collect()),
2686            indices: serialized_mesh.indices.into(),
2687            ..Mesh::new(serialized_mesh.primitive_topology, RenderAssetUsages::default())
2688        }
2689    }
2690}
2691
2692/// Error that can occur when calling [`Mesh::merge_duplicate_vertices`]
2693#[derive(fn from(source: MeshAccessError) -> Self {
    MeshMergeDuplicateVerticesError::MeshAccessError { 0: source }
}Error, #[automatically_derived]
impl ::core::fmt::Debug for MeshMergeDuplicateVerticesError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            MeshMergeDuplicateVerticesError::IndicesAlreadySet =>
                ::core::fmt::Formatter::write_str(f, "IndicesAlreadySet"),
            MeshMergeDuplicateVerticesError::MeshAccessError(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "MeshAccessError", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for MeshMergeDuplicateVerticesError {
    #[inline]
    fn clone(&self) -> MeshMergeDuplicateVerticesError {
        match self {
            MeshMergeDuplicateVerticesError::IndicesAlreadySet =>
                MeshMergeDuplicateVerticesError::IndicesAlreadySet,
            MeshMergeDuplicateVerticesError::MeshAccessError(__self_0) =>
                MeshMergeDuplicateVerticesError::MeshAccessError(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone)]
2694pub enum MeshMergeDuplicateVerticesError {
2695    #[error("Index attribute already set.")]
2696    IndicesAlreadySet,
2697    #[error("Mesh access error: {0}")]
2698    MeshAccessError(#[from] MeshAccessError),
2699}
2700
2701/// Error that can occur when calling [`Mesh::merge`].
2702#[derive(fn from(source: MeshAccessError) -> Self {
    MeshMergeError::MeshAccessError { 0: source }
}Error, #[automatically_derived]
impl ::core::fmt::Debug for MeshMergeError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            MeshMergeError::IncompatibleVertexAttributes {
                self_attribute: __self_0, other_attribute: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "IncompatibleVertexAttributes", "self_attribute", __self_0,
                    "other_attribute", &__self_1),
            MeshMergeError::IncompatiblePrimitiveTopology {
                self_primitive_topology: __self_0,
                other_primitive_topology: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "IncompatiblePrimitiveTopology", "self_primitive_topology",
                    __self_0, "other_primitive_topology", &__self_1),
            MeshMergeError::MeshAccessError(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "MeshAccessError", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for MeshMergeError {
    #[inline]
    fn clone(&self) -> MeshMergeError {
        match self {
            MeshMergeError::IncompatibleVertexAttributes {
                self_attribute: __self_0, other_attribute: __self_1 } =>
                MeshMergeError::IncompatibleVertexAttributes {
                    self_attribute: ::core::clone::Clone::clone(__self_0),
                    other_attribute: ::core::clone::Clone::clone(__self_1),
                },
            MeshMergeError::IncompatiblePrimitiveTopology {
                self_primitive_topology: __self_0,
                other_primitive_topology: __self_1 } =>
                MeshMergeError::IncompatiblePrimitiveTopology {
                    self_primitive_topology: ::core::clone::Clone::clone(__self_0),
                    other_primitive_topology: ::core::clone::Clone::clone(__self_1),
                },
            MeshMergeError::MeshAccessError(__self_0) =>
                MeshMergeError::MeshAccessError(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone)]
2703pub enum MeshMergeError {
2704    #[error("Incompatible vertex attribute types: {} and {}", self_attribute.name, other_attribute.map(|a| a.name).unwrap_or("None"))]
2705    IncompatibleVertexAttributes {
2706        self_attribute: MeshVertexAttribute,
2707        other_attribute: Option<MeshVertexAttribute>,
2708    },
2709    #[error(
2710        "Incompatible primitive topologies: {:?} and {:?}",
2711        self_primitive_topology,
2712        other_primitive_topology
2713    )]
2714    IncompatiblePrimitiveTopology {
2715        self_primitive_topology: PrimitiveTopology,
2716        other_primitive_topology: PrimitiveTopology,
2717    },
2718    #[error("Mesh access error: {0}")]
2719    MeshAccessError(#[from] MeshAccessError),
2720}
2721
2722#[cfg(test)]
2723mod tests {
2724    use super::Mesh;
2725    #[cfg(feature = "serialize")]
2726    use super::SerializedMesh;
2727    use crate::mesh::{Indices, MeshWindingInvertError, VertexAttributeValues};
2728    use crate::PrimitiveTopology;
2729    use bevy_asset::RenderAssetUsages;
2730    use bevy_math::bounding::Aabb3d;
2731    use bevy_math::primitives::Triangle3d;
2732    use bevy_math::Vec3;
2733    use bevy_transform::components::Transform;
2734
2735    #[test]
2736    #[should_panic]
2737    fn panic_invalid_format() {
2738        let _mesh = Mesh::new(
2739            PrimitiveTopology::TriangleList,
2740            RenderAssetUsages::default(),
2741        )
2742        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.0, 0.0, 0.0]]);
2743    }
2744
2745    #[test]
2746    fn transform_mesh() {
2747        let mesh = Mesh::new(
2748            PrimitiveTopology::TriangleList,
2749            RenderAssetUsages::default(),
2750        )
2751        .with_inserted_attribute(
2752            Mesh::ATTRIBUTE_POSITION,
2753            vec![[-1., -1., 2.], [1., -1., 2.], [0., 1., 2.]],
2754        )
2755        .with_inserted_attribute(
2756            Mesh::ATTRIBUTE_NORMAL,
2757            vec![
2758                Vec3::new(-1., -1., 1.).normalize().to_array(),
2759                Vec3::new(1., -1., 1.).normalize().to_array(),
2760                [0., 0., 1.],
2761            ],
2762        )
2763        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0., 0.], [1., 0.], [0.5, 1.]]);
2764
2765        let mesh = mesh.transformed_by(
2766            Transform::from_translation(Vec3::splat(-2.)).with_scale(Vec3::new(2., 0., -1.)),
2767        );
2768
2769        if let Some(VertexAttributeValues::Float32x3(positions)) =
2770            mesh.attribute(Mesh::ATTRIBUTE_POSITION)
2771        {
2772            // All positions are first scaled resulting in `vec![[-2, 0., -2.], [2., 0., -2.], [0., 0., -2.]]`
2773            // and then shifted by `-2.` along each axis
2774            assert_eq!(
2775                positions,
2776                &vec![[-4.0, -2.0, -4.0], [0.0, -2.0, -4.0], [-2.0, -2.0, -4.0]]
2777            );
2778        } else {
2779            panic!("Mesh does not have a position attribute");
2780        }
2781
2782        if let Some(VertexAttributeValues::Float32x3(normals)) =
2783            mesh.attribute(Mesh::ATTRIBUTE_NORMAL)
2784        {
2785            assert_eq!(normals, &vec![[0., -1., 0.], [0., -1., 0.], [0., 0., -1.]]);
2786        } else {
2787            panic!("Mesh does not have a normal attribute");
2788        }
2789
2790        if let Some(VertexAttributeValues::Float32x2(uvs)) = mesh.attribute(Mesh::ATTRIBUTE_UV_0) {
2791            assert_eq!(uvs, &vec![[0., 0.], [1., 0.], [0.5, 1.]]);
2792        } else {
2793            panic!("Mesh does not have a uv attribute");
2794        }
2795    }
2796
2797    #[test]
2798    fn point_list_mesh_invert_winding() {
2799        let mesh = Mesh::new(PrimitiveTopology::PointList, RenderAssetUsages::default())
2800            .with_inserted_indices(Indices::U32(vec![]));
2801        assert!(matches!(
2802            mesh.with_inverted_winding(),
2803            Err(MeshWindingInvertError::WrongTopology)
2804        ));
2805    }
2806
2807    #[test]
2808    fn line_list_mesh_invert_winding() {
2809        let mesh = Mesh::new(PrimitiveTopology::LineList, RenderAssetUsages::default())
2810            .with_inserted_indices(Indices::U32(vec![0, 1, 1, 2, 2, 3]));
2811        let mesh = mesh.with_inverted_winding().unwrap();
2812        assert_eq!(
2813            mesh.indices().unwrap().iter().collect::<Vec<usize>>(),
2814            vec![3, 2, 2, 1, 1, 0]
2815        );
2816    }
2817
2818    #[test]
2819    fn line_list_mesh_invert_winding_fail() {
2820        let mesh = Mesh::new(PrimitiveTopology::LineList, RenderAssetUsages::default())
2821            .with_inserted_indices(Indices::U32(vec![0, 1, 1]));
2822        assert!(matches!(
2823            mesh.with_inverted_winding(),
2824            Err(MeshWindingInvertError::AbruptIndicesEnd)
2825        ));
2826    }
2827
2828    #[test]
2829    fn line_strip_mesh_invert_winding() {
2830        let mesh = Mesh::new(PrimitiveTopology::LineStrip, RenderAssetUsages::default())
2831            .with_inserted_indices(Indices::U32(vec![0, 1, 2, 3]));
2832        let mesh = mesh.with_inverted_winding().unwrap();
2833        assert_eq!(
2834            mesh.indices().unwrap().iter().collect::<Vec<usize>>(),
2835            vec![3, 2, 1, 0]
2836        );
2837    }
2838
2839    #[test]
2840    fn triangle_list_mesh_invert_winding() {
2841        let mesh = Mesh::new(
2842            PrimitiveTopology::TriangleList,
2843            RenderAssetUsages::default(),
2844        )
2845        .with_inserted_indices(Indices::U32(vec![
2846            0, 3, 1, // First triangle
2847            1, 3, 2, // Second triangle
2848        ]));
2849        let mesh = mesh.with_inverted_winding().unwrap();
2850        assert_eq!(
2851            mesh.indices().unwrap().iter().collect::<Vec<usize>>(),
2852            vec![
2853                0, 1, 3, // First triangle
2854                1, 2, 3, // Second triangle
2855            ]
2856        );
2857    }
2858
2859    #[test]
2860    fn triangle_list_mesh_invert_winding_fail() {
2861        let mesh = Mesh::new(
2862            PrimitiveTopology::TriangleList,
2863            RenderAssetUsages::default(),
2864        )
2865        .with_inserted_indices(Indices::U32(vec![0, 3, 1, 2]));
2866        assert!(matches!(
2867            mesh.with_inverted_winding(),
2868            Err(MeshWindingInvertError::AbruptIndicesEnd)
2869        ));
2870    }
2871
2872    #[test]
2873    fn triangle_strip_mesh_invert_winding() {
2874        let mesh = Mesh::new(
2875            PrimitiveTopology::TriangleStrip,
2876            RenderAssetUsages::default(),
2877        )
2878        .with_inserted_indices(Indices::U32(vec![0, 1, 2, 3]));
2879        let mesh = mesh.with_inverted_winding().unwrap();
2880        assert_eq!(
2881            mesh.indices().unwrap().iter().collect::<Vec<usize>>(),
2882            vec![3, 2, 1, 0]
2883        );
2884    }
2885
2886    #[test]
2887    fn compute_area_weighted_normals() {
2888        let mut mesh = Mesh::new(
2889            PrimitiveTopology::TriangleList,
2890            RenderAssetUsages::default(),
2891        );
2892
2893        //  z      y
2894        //  |    /
2895        //  3---2
2896        //  | /  \
2897        //  0-----1--x
2898
2899        mesh.insert_attribute(
2900            Mesh::ATTRIBUTE_POSITION,
2901            vec![[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [0., 0., 1.]],
2902        );
2903        mesh.insert_indices(Indices::U16(vec![0, 1, 2, 0, 2, 3]));
2904        mesh.compute_area_weighted_normals();
2905        let normals = mesh
2906            .attribute(Mesh::ATTRIBUTE_NORMAL)
2907            .unwrap()
2908            .as_float3()
2909            .unwrap();
2910        assert_eq!(4, normals.len());
2911        // 0
2912        assert_eq!(Vec3::new(1., 0., 1.).normalize().to_array(), normals[0]);
2913        // 1
2914        assert_eq!([0., 0., 1.], normals[1]);
2915        // 2
2916        assert_eq!(Vec3::new(1., 0., 1.).normalize().to_array(), normals[2]);
2917        // 3
2918        assert_eq!([1., 0., 0.], normals[3]);
2919    }
2920
2921    #[test]
2922    fn compute_area_weighted_normals_proportionate() {
2923        let mut mesh = Mesh::new(
2924            PrimitiveTopology::TriangleList,
2925            RenderAssetUsages::default(),
2926        );
2927
2928        //  z      y
2929        //  |    /
2930        //  3---2..
2931        //  | /    \
2932        //  0-------1---x
2933
2934        mesh.insert_attribute(
2935            Mesh::ATTRIBUTE_POSITION,
2936            vec![[0., 0., 0.], [2., 0., 0.], [0., 1., 0.], [0., 0., 1.]],
2937        );
2938        mesh.insert_indices(Indices::U16(vec![0, 1, 2, 0, 2, 3]));
2939        mesh.compute_area_weighted_normals();
2940        let normals = mesh
2941            .attribute(Mesh::ATTRIBUTE_NORMAL)
2942            .unwrap()
2943            .as_float3()
2944            .unwrap();
2945        assert_eq!(4, normals.len());
2946        // 0
2947        assert_eq!(Vec3::new(1., 0., 2.).normalize().to_array(), normals[0]);
2948        // 1
2949        assert_eq!([0., 0., 1.], normals[1]);
2950        // 2
2951        assert_eq!(Vec3::new(1., 0., 2.).normalize().to_array(), normals[2]);
2952        // 3
2953        assert_eq!([1., 0., 0.], normals[3]);
2954    }
2955
2956    #[test]
2957    fn compute_angle_weighted_normals() {
2958        // CuboidMeshBuilder duplicates vertices (even though it is indexed)
2959
2960        //   5---------4
2961        //  /|        /|
2962        // 1-+-------0 |
2963        // | 6-------|-7
2964        // |/        |/
2965        // 2---------3
2966        let verts = vec![
2967            [1.0, 1.0, 1.0],
2968            [-1.0, 1.0, 1.0],
2969            [-1.0, -1.0, 1.0],
2970            [1.0, -1.0, 1.0],
2971            [1.0, 1.0, -1.0],
2972            [-1.0, 1.0, -1.0],
2973            [-1.0, -1.0, -1.0],
2974            [1.0, -1.0, -1.0],
2975        ];
2976
2977        let indices = Indices::U16(vec![
2978            0, 1, 2, 2, 3, 0, // front
2979            5, 4, 7, 7, 6, 5, // back
2980            1, 5, 6, 6, 2, 1, // left
2981            4, 0, 3, 3, 7, 4, // right
2982            4, 5, 1, 1, 0, 4, // top
2983            3, 2, 6, 6, 7, 3, // bottom
2984        ]);
2985        let mut mesh = Mesh::new(
2986            PrimitiveTopology::TriangleList,
2987            RenderAssetUsages::default(),
2988        );
2989        mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, verts);
2990        mesh.insert_indices(indices);
2991        mesh.compute_smooth_normals();
2992
2993        let normals = mesh
2994            .attribute(Mesh::ATTRIBUTE_NORMAL)
2995            .unwrap()
2996            .as_float3()
2997            .unwrap();
2998
2999        for new in normals.iter().copied().flatten() {
3000            // std impl is unstable
3001            const FRAC_1_SQRT_3: f32 = 0.57735026;
3002            const MIN: f32 = FRAC_1_SQRT_3 - f32::EPSILON;
3003            const MAX: f32 = FRAC_1_SQRT_3 + f32::EPSILON;
3004            assert!(new.abs() >= MIN, "{new} < {MIN}");
3005            assert!(new.abs() <= MAX, "{new} > {MAX}");
3006        }
3007    }
3008
3009    #[test]
3010    fn triangles_from_triangle_list() {
3011        let mut mesh = Mesh::new(
3012            PrimitiveTopology::TriangleList,
3013            RenderAssetUsages::default(),
3014        );
3015        mesh.insert_attribute(
3016            Mesh::ATTRIBUTE_POSITION,
3017            vec![[0., 0., 0.], [1., 0., 0.], [1., 1., 0.], [0., 1., 0.]],
3018        );
3019        mesh.insert_indices(Indices::U32(vec![0, 1, 2, 2, 3, 0]));
3020        assert_eq!(
3021            vec![
3022                Triangle3d {
3023                    vertices: [
3024                        Vec3::new(0., 0., 0.),
3025                        Vec3::new(1., 0., 0.),
3026                        Vec3::new(1., 1., 0.),
3027                    ]
3028                },
3029                Triangle3d {
3030                    vertices: [
3031                        Vec3::new(1., 1., 0.),
3032                        Vec3::new(0., 1., 0.),
3033                        Vec3::new(0., 0., 0.),
3034                    ]
3035                }
3036            ],
3037            mesh.triangles().unwrap().collect::<Vec<Triangle3d>>()
3038        );
3039    }
3040
3041    #[test]
3042    fn triangles_from_triangle_strip() {
3043        let mut mesh = Mesh::new(
3044            PrimitiveTopology::TriangleStrip,
3045            RenderAssetUsages::default(),
3046        );
3047        // Triangles: (0, 1, 2), (2, 1, 3), (2, 3, 4), (4, 3, 5)
3048        //
3049        // 4 - 5
3050        // | \ |
3051        // 2 - 3
3052        // | \ |
3053        // 0 - 1
3054        let positions: Vec<Vec3> = [
3055            [0., 0., 0.],
3056            [1., 0., 0.],
3057            [0., 1., 0.],
3058            [1., 1., 0.],
3059            [0., 2., 0.],
3060            [1., 2., 0.],
3061        ]
3062        .into_iter()
3063        .map(Vec3::from_array)
3064        .collect();
3065        mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, positions.clone());
3066        mesh.insert_indices(Indices::U32(vec![0, 1, 2, 3, 4, 5]));
3067        assert_eq!(
3068            vec![
3069                Triangle3d {
3070                    vertices: [positions[0], positions[1], positions[2]]
3071                },
3072                Triangle3d {
3073                    vertices: [positions[2], positions[1], positions[3]]
3074                },
3075                Triangle3d {
3076                    vertices: [positions[2], positions[3], positions[4]]
3077                },
3078                Triangle3d {
3079                    vertices: [positions[4], positions[3], positions[5]]
3080                },
3081            ],
3082            mesh.triangles().unwrap().collect::<Vec<Triangle3d>>()
3083        );
3084    }
3085
3086    #[test]
3087    fn take_gpu_data_calculates_aabb() {
3088        let mut mesh = Mesh::new(
3089            PrimitiveTopology::TriangleList,
3090            RenderAssetUsages::default(),
3091        );
3092        mesh.insert_attribute(
3093            Mesh::ATTRIBUTE_POSITION,
3094            vec![
3095                [-0.5, 0., 0.],
3096                [-1., 0., 0.],
3097                [-1., -1., 0.],
3098                [-0.5, -1., 0.],
3099            ],
3100        );
3101        mesh.insert_indices(Indices::U32(vec![0, 1, 2, 2, 3, 0]));
3102        mesh = mesh.take_gpu_data().unwrap();
3103        assert_eq!(
3104            mesh.final_aabb,
3105            Some(Aabb3d::from_min_max([-1., -1., 0.], [-0.5, 0., 0.]))
3106        );
3107    }
3108
3109    #[cfg(feature = "serialize")]
3110    #[test]
3111    fn serialize_deserialize_mesh() {
3112        let mut mesh = Mesh::new(
3113            PrimitiveTopology::TriangleList,
3114            RenderAssetUsages::default(),
3115        );
3116
3117        mesh.insert_attribute(
3118            Mesh::ATTRIBUTE_POSITION,
3119            vec![[0., 0., 0.], [2., 0., 0.], [0., 1., 0.], [0., 0., 1.]],
3120        );
3121        mesh.insert_indices(Indices::U16(vec![0, 1, 2, 0, 2, 3]));
3122
3123        let serialized_mesh = SerializedMesh::from_mesh(mesh.clone());
3124        let serialized_string = serde_json::to_string(&serialized_mesh).unwrap();
3125        let serialized_mesh_from_string: SerializedMesh =
3126            serde_json::from_str(&serialized_string).unwrap();
3127        let deserialized_mesh = serialized_mesh_from_string.into_mesh();
3128        assert_eq!(mesh, deserialized_mesh);
3129    }
3130
3131    #[test]
3132    fn merge_duplicate_vertices() {
3133        let mut mesh = Mesh::new(
3134            PrimitiveTopology::TriangleList,
3135            RenderAssetUsages::default(),
3136        );
3137        // Quad made of two triangles.
3138        let positions = vec![
3139            [0.0, 0.0, 0.0],
3140            [1.0, 0.0, 0.0],
3141            [1.0, 1.0, 0.0],
3142            // This will be deduplicated.
3143            [1.0, 1.0, 0.0],
3144            [0.0, 1.0, 0.0],
3145            // Position is equal to the first one but UV is different so it won't be deduplicated.
3146            [0.0, 0.0, 0.0],
3147        ];
3148        let uvs = vec![
3149            [0.0, 0.0],
3150            [1.0, 0.0],
3151            [1.0, 1.0],
3152            // This will be deduplicated.
3153            [1.0, 1.0],
3154            [0.0, 1.0],
3155            // Use different UV here so it won't be deduplicated.
3156            [0.0, 0.5],
3157        ];
3158        mesh.insert_attribute(
3159            Mesh::ATTRIBUTE_POSITION,
3160            VertexAttributeValues::Float32x3(positions.clone()),
3161        );
3162        mesh.insert_attribute(
3163            Mesh::ATTRIBUTE_UV_0,
3164            VertexAttributeValues::Float32x2(uvs.clone()),
3165        );
3166
3167        let res = mesh.merge_duplicate_vertices();
3168        assert!(res.is_ok());
3169        assert_eq!(6, mesh.indices().unwrap().len());
3170        // Note we have 5 unique vertices, not 6.
3171        assert_eq!(5, mesh.attribute(Mesh::ATTRIBUTE_POSITION).unwrap().len());
3172        assert_eq!(5, mesh.attribute(Mesh::ATTRIBUTE_UV_0).unwrap().len());
3173
3174        // Duplicate back.
3175        mesh.duplicate_vertices();
3176        assert!(mesh.indices().is_none());
3177        let VertexAttributeValues::Float32x3(new_positions) =
3178            mesh.attribute(Mesh::ATTRIBUTE_POSITION).unwrap()
3179        else {
3180            panic!("Unexpected attribute type")
3181        };
3182        let VertexAttributeValues::Float32x2(new_uvs) =
3183            mesh.attribute(Mesh::ATTRIBUTE_UV_0).unwrap()
3184        else {
3185            panic!("Unexpected attribute type")
3186        };
3187        assert_eq!(&positions, new_positions);
3188        assert_eq!(&uvs, new_uvs);
3189    }
3190}