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

        #[allow(unused_variables, deprecated, clippy ::
        used_underscore_binding)]
        match self {
            MeshAttributeCompressionError::MissingAttribute(_0) =>
                match (_0,) {
                    (__field0,) =>
                        __formatter.write_fmt(format_args!("Vertex attribute {0:?} doesn\'t exist",
                                __field0)),
                },
            MeshAttributeCompressionError::EmptyAttribute(_0) =>
                match (_0,) {
                    (__field0,) =>
                        __formatter.write_fmt(format_args!("Vertex attribute {0:?} must not be empty",
                                __field0)),
                },
            MeshAttributeCompressionError::UnsupportedAttributeForCompression {
                attr, expected } =>
                match (attr, expected) {
                    (__field_attr, __field_expected) =>
                        __formatter.write_fmt(format_args!("Vertex attribute {0:?} must have format {1:?} before compressing/quantizing",
                                __field_attr, __field_expected)),
                },
            MeshAttributeCompressionError::UnsupportedAttributeForQuantizing {
                attr } =>
                match (attr,) {
                    (__field_attr,) =>
                        __formatter.write_fmt(format_args!("Vertex attribute {0:?} must have format `Float32`, `Float32x2` or `Float32x4` before quantizing",
                                __field_attr)),
                },
        }
    }
}Error, #[automatically_derived]
impl ::core::fmt::Debug for MeshAttributeCompressionError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::MissingAttribute(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "MissingAttribute", &__self_0),
            Self::EmptyAttribute(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "EmptyAttribute", &__self_0),
            Self::UnsupportedAttributeForCompression {
                attr: __self_0, expected: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "UnsupportedAttributeForCompression", "attr", __self_0,
                    "expected", &__self_1),
            Self::UnsupportedAttributeForQuantizing { attr: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "UnsupportedAttributeForQuantizing", "attr", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for MeshAttributeCompressionError {
    #[inline]
    fn clone(&self) -> Self {
        match self {
            Self::MissingAttribute(__self_0) =>
                Self::MissingAttribute(::core::clone::Clone::clone(__self_0)),
            Self::EmptyAttribute(__self_0) =>
                Self::EmptyAttribute(::core::clone::Clone::clone(__self_0)),
            Self::UnsupportedAttributeForCompression {
                attr: __self_0, expected: __self_1 } =>
                Self::UnsupportedAttributeForCompression {
                    attr: ::core::clone::Clone::clone(__self_0),
                    expected: ::core::clone::Clone::clone(__self_1),
                },
            Self::UnsupportedAttributeForQuantizing { attr: __self_0 } =>
                Self::UnsupportedAttributeForQuantizing {
                    attr: ::core::clone::Clone::clone(__self_0),
                },
        }
    }
}Clone)]
3176pub enum MeshAttributeCompressionError {
3177    #[error("Vertex attribute {0:?} doesn't exist")]
3178    MissingAttribute(MeshVertexAttributeId),
3179    #[error("Vertex attribute {0:?} must not be empty")]
3180    EmptyAttribute(MeshVertexAttribute),
3181    #[error(
3182        "Vertex attribute {attr:?} must have format {expected:?} before compressing/quantizing"
3183    )]
3184    UnsupportedAttributeForCompression {
3185        attr: MeshVertexAttribute,
3186        expected: VertexFormat,
3187    },
3188    #[error("Vertex attribute {attr:?} must have format `Float32`, `Float32x2` or `Float32x4` before quantizing")]
3189    UnsupportedAttributeForQuantizing { attr: MeshVertexAttribute },
3190}
3191
3192/// Error that can occur when calling [`Mesh::merge_duplicate_vertices`]
3193#[derive(#[allow(unused_qualifications)]
#[automatically_derived]
impl ::thiserror::__private21::Error for MeshMergeDuplicateVerticesError {
    fn source(&self)
        ->
            ::core::option::Option<&(dyn ::thiserror::__private21::Error +
            'static)> {
        use ::thiserror::__private21::AsDynError as _;

        #[allow(deprecated)]
        match self {
            MeshMergeDuplicateVerticesError::IndicesAlreadySet { .. } =>
                ::core::option::Option::None,
            MeshMergeDuplicateVerticesError::MeshAccessError { 0: source, .. }
                => ::core::option::Option::Some(source.as_dyn_error()),
        }
    }
}
#[allow(unused_qualifications)]
#[automatically_derived]
impl ::core::fmt::Display for MeshMergeDuplicateVerticesError {
    fn fmt(&self, __formatter: &mut ::core::fmt::Formatter)
        -> ::core::fmt::Result {
        use ::thiserror::__private21::AsDisplay as _;

        #[allow(unused_variables, deprecated, clippy ::
        used_underscore_binding)]
        match self {
            MeshMergeDuplicateVerticesError::IndicesAlreadySet {} =>
                __formatter.write_str("Index attribute already set."),
            MeshMergeDuplicateVerticesError::MeshAccessError(_0) =>
                match (_0.as_display(),) {
                    (__display0,) =>
                        __formatter.write_fmt(format_args!("Mesh access error: {0}",
                                __display0)),
                },
        }
    }
}
MeshMergeDuplicateVerticesError
#[allow(clippy :: redundant_field_names)]
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 {
            Self::IndicesAlreadySet =>
                ::core::fmt::Formatter::write_str(f, "IndicesAlreadySet"),
            Self::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) -> Self {
        match self {
            Self::IndicesAlreadySet => Self::IndicesAlreadySet,
            Self::MeshAccessError(__self_0) =>
                Self::MeshAccessError(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone)]
3194pub enum MeshMergeDuplicateVerticesError {
3195    #[error("Index attribute already set.")]
3196    IndicesAlreadySet,
3197    #[error("Mesh access error: {0}")]
3198    MeshAccessError(#[from] MeshAccessError),
3199}
3200
3201/// Error that can occur when calling [`Mesh::merge`].
3202#[derive(#[allow(unused_qualifications)]
#[automatically_derived]
impl ::thiserror::__private21::Error for MeshMergeError {
    fn source(&self)
        ->
            ::core::option::Option<&(dyn ::thiserror::__private21::Error +
            'static)> {
        use ::thiserror::__private21::AsDynError as _;

        #[allow(deprecated)]
        match self {
            MeshMergeError::IncompatibleVertexAttributes { .. } =>
                ::core::option::Option::None,
            MeshMergeError::IncompatiblePrimitiveTopology { .. } =>
                ::core::option::Option::None,
            MeshMergeError::MeshAccessError { 0: source, .. } =>
                ::core::option::Option::Some(source.as_dyn_error()),
        }
    }
}
#[allow(unused_qualifications)]
#[automatically_derived]
impl ::core::fmt::Display for MeshMergeError {
    fn fmt(&self, __formatter: &mut ::core::fmt::Formatter)
        -> ::core::fmt::Result {
        use ::thiserror::__private21::AsDisplay as _;

        #[allow(unused_variables, deprecated, clippy ::
        used_underscore_binding)]
        match self {
            MeshMergeError::IncompatibleVertexAttributes {
                self_attribute, other_attribute } =>
                __formatter.write_fmt(format_args!("Incompatible vertex attribute types: {0} and {1}",
                        self_attribute.name,
                        other_attribute.map(|a| a.name).unwrap_or("None"))),
            MeshMergeError::IncompatiblePrimitiveTopology {
                self_primitive_topology, other_primitive_topology } =>
                __formatter.write_fmt(format_args!("Incompatible primitive topologies: {0:?} and {1:?}",
                        self_primitive_topology, other_primitive_topology)),
            MeshMergeError::MeshAccessError(_0) =>
                match (_0.as_display(),) {
                    (__display0,) =>
                        __formatter.write_fmt(format_args!("Mesh access error: {0}",
                                __display0)),
                },
        }
    }
}
MeshMergeError
#[allow(clippy :: redundant_field_names)]
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 {
            Self::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),
            Self::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),
            Self::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) -> Self {
        match self {
            Self::IncompatibleVertexAttributes {
                self_attribute: __self_0, other_attribute: __self_1 } =>
                Self::IncompatibleVertexAttributes {
                    self_attribute: ::core::clone::Clone::clone(__self_0),
                    other_attribute: ::core::clone::Clone::clone(__self_1),
                },
            Self::IncompatiblePrimitiveTopology {
                self_primitive_topology: __self_0,
                other_primitive_topology: __self_1 } =>
                Self::IncompatiblePrimitiveTopology {
                    self_primitive_topology: ::core::clone::Clone::clone(__self_0),
                    other_primitive_topology: ::core::clone::Clone::clone(__self_1),
                },
            Self::MeshAccessError(__self_0) =>
                Self::MeshAccessError(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone)]
3203pub enum MeshMergeError {
3204    #[error("Incompatible vertex attribute types: {} and {}", self_attribute.name, other_attribute.map(|a| a.name).unwrap_or("None"))]
3205    IncompatibleVertexAttributes {
3206        self_attribute: MeshVertexAttribute,
3207        other_attribute: Option<MeshVertexAttribute>,
3208    },
3209    #[error(
3210        "Incompatible primitive topologies: {:?} and {:?}",
3211        self_primitive_topology,
3212        other_primitive_topology
3213    )]
3214    IncompatiblePrimitiveTopology {
3215        self_primitive_topology: PrimitiveTopology,
3216        other_primitive_topology: PrimitiveTopology,
3217    },
3218    #[error("Mesh access error: {0}")]
3219    MeshAccessError(#[from] MeshAccessError),
3220}
3221
3222#[cfg(test)]
3223mod tests {
3224    use super::Mesh;
3225    #[cfg(feature = "serialize")]
3226    use super::SerializedMesh;
3227    use crate::mesh::{Indices, MeshWindingInvertError, VertexAttributeValues};
3228    use crate::{
3229        AttributeQuantization, MeshAttributeCompressionFlags, MeshVertexAttribute,
3230        PrimitiveTopology,
3231    };
3232    use bevy_asset::RenderAssetUsages;
3233    use bevy_math::{Vec2, Vec3, Vec3A, Vec4};
3234    use bevy_shape::{Aabb2d, Aabb3d, Triangle3d};
3235    use bevy_transform::components::Transform;
3236
3237    #[test]
3238    #[should_panic]
3239    fn panic_invalid_format() {
3240        let _mesh = Mesh::new(
3241            PrimitiveTopology::TriangleList,
3242            RenderAssetUsages::default(),
3243        )
3244        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.0, 0.0, 0.0]]);
3245    }
3246
3247    #[test]
3248    fn transform_mesh() {
3249        let mesh = Mesh::new(
3250            PrimitiveTopology::TriangleList,
3251            RenderAssetUsages::default(),
3252        )
3253        .with_inserted_attribute(
3254            Mesh::ATTRIBUTE_POSITION,
3255            vec![[-1., -1., 2.], [1., -1., 2.], [0., 1., 2.]],
3256        )
3257        .with_inserted_attribute(
3258            Mesh::ATTRIBUTE_NORMAL,
3259            vec![
3260                Vec3::new(-1., -1., 1.).normalize().to_array(),
3261                Vec3::new(1., -1., 1.).normalize().to_array(),
3262                [0., 0., 1.],
3263            ],
3264        )
3265        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0., 0.], [1., 0.], [0.5, 1.]]);
3266
3267        let mesh = mesh.transformed_by(
3268            Transform::from_translation(Vec3::splat(-2.)).with_scale(Vec3::new(2., 0., -1.)),
3269        );
3270
3271        if let Some(VertexAttributeValues::Float32x3(positions)) =
3272            mesh.attribute(Mesh::ATTRIBUTE_POSITION)
3273        {
3274            // All positions are first scaled resulting in `vec![[-2, 0., -2.], [2., 0., -2.], [0., 0., -2.]]`
3275            // and then shifted by `-2.` along each axis
3276            assert_eq!(
3277                positions,
3278                &vec![[-4.0, -2.0, -4.0], [0.0, -2.0, -4.0], [-2.0, -2.0, -4.0]]
3279            );
3280        } else {
3281            panic!("Mesh does not have a position attribute");
3282        }
3283
3284        if let Some(VertexAttributeValues::Float32x3(normals)) =
3285            mesh.attribute(Mesh::ATTRIBUTE_NORMAL)
3286        {
3287            assert_eq!(normals, &vec![[0., -1., 0.], [0., -1., 0.], [0., 0., -1.]]);
3288        } else {
3289            panic!("Mesh does not have a normal attribute");
3290        }
3291
3292        if let Some(VertexAttributeValues::Float32x2(uvs)) = mesh.attribute(Mesh::ATTRIBUTE_UV_0) {
3293            assert_eq!(uvs, &vec![[0., 0.], [1., 0.], [0.5, 1.]]);
3294        } else {
3295            panic!("Mesh does not have a uv attribute");
3296        }
3297    }
3298
3299    #[test]
3300    fn point_list_mesh_invert_winding() {
3301        let mesh = Mesh::new(PrimitiveTopology::PointList, RenderAssetUsages::default())
3302            .with_inserted_indices(Indices::U32(vec![]));
3303        assert!(matches!(
3304            mesh.with_inverted_winding(),
3305            Err(MeshWindingInvertError::WrongTopology)
3306        ));
3307    }
3308
3309    #[test]
3310    fn line_list_mesh_invert_winding() {
3311        let mesh = Mesh::new(PrimitiveTopology::LineList, RenderAssetUsages::default())
3312            .with_inserted_indices(Indices::U32(vec![0, 1, 1, 2, 2, 3]));
3313        let mesh = mesh.with_inverted_winding().unwrap();
3314        assert_eq!(
3315            mesh.indices().unwrap().iter().collect::<Vec<usize>>(),
3316            vec![3, 2, 2, 1, 1, 0]
3317        );
3318    }
3319
3320    #[test]
3321    fn line_list_mesh_invert_winding_fail() {
3322        let mesh = Mesh::new(PrimitiveTopology::LineList, RenderAssetUsages::default())
3323            .with_inserted_indices(Indices::U32(vec![0, 1, 1]));
3324        assert!(matches!(
3325            mesh.with_inverted_winding(),
3326            Err(MeshWindingInvertError::AbruptIndicesEnd)
3327        ));
3328    }
3329
3330    #[test]
3331    fn line_strip_mesh_invert_winding() {
3332        let mesh = Mesh::new(PrimitiveTopology::LineStrip, RenderAssetUsages::default())
3333            .with_inserted_indices(Indices::U32(vec![0, 1, 2, 3]));
3334        let mesh = mesh.with_inverted_winding().unwrap();
3335        assert_eq!(
3336            mesh.indices().unwrap().iter().collect::<Vec<usize>>(),
3337            vec![3, 2, 1, 0]
3338        );
3339    }
3340
3341    #[test]
3342    fn triangle_list_mesh_invert_winding() {
3343        let mesh = Mesh::new(
3344            PrimitiveTopology::TriangleList,
3345            RenderAssetUsages::default(),
3346        )
3347        .with_inserted_indices(Indices::U32(vec![
3348            0, 3, 1, // First triangle
3349            1, 3, 2, // Second triangle
3350        ]));
3351        let mesh = mesh.with_inverted_winding().unwrap();
3352        assert_eq!(
3353            mesh.indices().unwrap().iter().collect::<Vec<usize>>(),
3354            vec![
3355                0, 1, 3, // First triangle
3356                1, 2, 3, // Second triangle
3357            ]
3358        );
3359    }
3360
3361    #[test]
3362    fn triangle_list_mesh_invert_winding_fail() {
3363        let mesh = Mesh::new(
3364            PrimitiveTopology::TriangleList,
3365            RenderAssetUsages::default(),
3366        )
3367        .with_inserted_indices(Indices::U32(vec![0, 3, 1, 2]));
3368        assert!(matches!(
3369            mesh.with_inverted_winding(),
3370            Err(MeshWindingInvertError::AbruptIndicesEnd)
3371        ));
3372    }
3373
3374    #[test]
3375    fn triangle_strip_mesh_invert_winding() {
3376        let mesh = Mesh::new(
3377            PrimitiveTopology::TriangleStrip,
3378            RenderAssetUsages::default(),
3379        )
3380        .with_inserted_indices(Indices::U32(vec![0, 1, 2, 3]));
3381        let mesh = mesh.with_inverted_winding().unwrap();
3382        assert_eq!(
3383            mesh.indices().unwrap().iter().collect::<Vec<usize>>(),
3384            vec![3, 2, 1, 0]
3385        );
3386    }
3387
3388    #[test]
3389    fn compute_area_weighted_normals() {
3390        let mut mesh = Mesh::new(
3391            PrimitiveTopology::TriangleList,
3392            RenderAssetUsages::default(),
3393        );
3394
3395        //  z      y
3396        //  |    /
3397        //  3---2
3398        //  | /  \
3399        //  0-----1--x
3400
3401        mesh.insert_attribute(
3402            Mesh::ATTRIBUTE_POSITION,
3403            vec![[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [0., 0., 1.]],
3404        );
3405        mesh.insert_indices(Indices::U16(vec![0, 1, 2, 0, 2, 3]));
3406        mesh.compute_area_weighted_normals();
3407        let normals = mesh
3408            .attribute(Mesh::ATTRIBUTE_NORMAL)
3409            .unwrap()
3410            .as_float3()
3411            .unwrap();
3412        assert_eq!(4, normals.len());
3413        // 0
3414        assert_eq!(Vec3::new(1., 0., 1.).normalize().to_array(), normals[0]);
3415        // 1
3416        assert_eq!([0., 0., 1.], normals[1]);
3417        // 2
3418        assert_eq!(Vec3::new(1., 0., 1.).normalize().to_array(), normals[2]);
3419        // 3
3420        assert_eq!([1., 0., 0.], normals[3]);
3421    }
3422
3423    #[test]
3424    fn compute_area_weighted_normals_proportionate() {
3425        let mut mesh = Mesh::new(
3426            PrimitiveTopology::TriangleList,
3427            RenderAssetUsages::default(),
3428        );
3429
3430        //  z      y
3431        //  |    /
3432        //  3---2..
3433        //  | /    \
3434        //  0-------1---x
3435
3436        mesh.insert_attribute(
3437            Mesh::ATTRIBUTE_POSITION,
3438            vec![[0., 0., 0.], [2., 0., 0.], [0., 1., 0.], [0., 0., 1.]],
3439        );
3440        mesh.insert_indices(Indices::U16(vec![0, 1, 2, 0, 2, 3]));
3441        mesh.compute_area_weighted_normals();
3442        let normals = mesh
3443            .attribute(Mesh::ATTRIBUTE_NORMAL)
3444            .unwrap()
3445            .as_float3()
3446            .unwrap();
3447        assert_eq!(4, normals.len());
3448        // 0
3449        assert_eq!(Vec3::new(1., 0., 2.).normalize().to_array(), normals[0]);
3450        // 1
3451        assert_eq!([0., 0., 1.], normals[1]);
3452        // 2
3453        assert_eq!(Vec3::new(1., 0., 2.).normalize().to_array(), normals[2]);
3454        // 3
3455        assert_eq!([1., 0., 0.], normals[3]);
3456    }
3457
3458    #[test]
3459    fn compute_angle_weighted_normals() {
3460        // CuboidMeshBuilder duplicates vertices (even though it is indexed)
3461
3462        //   5---------4
3463        //  /|        /|
3464        // 1-+-------0 |
3465        // | 6-------|-7
3466        // |/        |/
3467        // 2---------3
3468        let verts = vec![
3469            [1.0, 1.0, 1.0],
3470            [-1.0, 1.0, 1.0],
3471            [-1.0, -1.0, 1.0],
3472            [1.0, -1.0, 1.0],
3473            [1.0, 1.0, -1.0],
3474            [-1.0, 1.0, -1.0],
3475            [-1.0, -1.0, -1.0],
3476            [1.0, -1.0, -1.0],
3477        ];
3478
3479        let indices = Indices::U16(vec![
3480            0, 1, 2, 2, 3, 0, // front
3481            5, 4, 7, 7, 6, 5, // back
3482            1, 5, 6, 6, 2, 1, // left
3483            4, 0, 3, 3, 7, 4, // right
3484            4, 5, 1, 1, 0, 4, // top
3485            3, 2, 6, 6, 7, 3, // bottom
3486        ]);
3487        let mut mesh = Mesh::new(
3488            PrimitiveTopology::TriangleList,
3489            RenderAssetUsages::default(),
3490        );
3491        mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, verts);
3492        mesh.insert_indices(indices);
3493        mesh.compute_smooth_normals();
3494
3495        let normals = mesh
3496            .attribute(Mesh::ATTRIBUTE_NORMAL)
3497            .unwrap()
3498            .as_float3()
3499            .unwrap();
3500
3501        for new in normals.iter().copied().flatten() {
3502            // std impl is unstable
3503            const FRAC_1_SQRT_3: f32 = 0.57735026;
3504            const MIN: f32 = FRAC_1_SQRT_3 - f32::EPSILON;
3505            const MAX: f32 = FRAC_1_SQRT_3 + f32::EPSILON;
3506            assert!(new.abs() >= MIN, "{new} < {MIN}");
3507            assert!(new.abs() <= MAX, "{new} > {MAX}");
3508        }
3509    }
3510
3511    #[test]
3512    fn triangles_from_triangle_list() {
3513        let mut mesh = Mesh::new(
3514            PrimitiveTopology::TriangleList,
3515            RenderAssetUsages::default(),
3516        );
3517        mesh.insert_attribute(
3518            Mesh::ATTRIBUTE_POSITION,
3519            vec![[0., 0., 0.], [1., 0., 0.], [1., 1., 0.], [0., 1., 0.]],
3520        );
3521        mesh.insert_indices(Indices::U32(vec![0, 1, 2, 2, 3, 0]));
3522        assert_eq!(
3523            vec![
3524                Triangle3d {
3525                    vertices: [
3526                        Vec3::new(0., 0., 0.),
3527                        Vec3::new(1., 0., 0.),
3528                        Vec3::new(1., 1., 0.),
3529                    ]
3530                },
3531                Triangle3d {
3532                    vertices: [
3533                        Vec3::new(1., 1., 0.),
3534                        Vec3::new(0., 1., 0.),
3535                        Vec3::new(0., 0., 0.),
3536                    ]
3537                }
3538            ],
3539            mesh.triangles().unwrap().collect::<Vec<Triangle3d>>()
3540        );
3541    }
3542
3543    #[test]
3544    fn triangles_from_triangle_strip() {
3545        let mut mesh = Mesh::new(
3546            PrimitiveTopology::TriangleStrip,
3547            RenderAssetUsages::default(),
3548        );
3549        // Triangles: (0, 1, 2), (2, 1, 3), (2, 3, 4), (4, 3, 5)
3550        //
3551        // 4 - 5
3552        // | \ |
3553        // 2 - 3
3554        // | \ |
3555        // 0 - 1
3556        let positions: Vec<Vec3> = [
3557            [0., 0., 0.],
3558            [1., 0., 0.],
3559            [0., 1., 0.],
3560            [1., 1., 0.],
3561            [0., 2., 0.],
3562            [1., 2., 0.],
3563        ]
3564        .into_iter()
3565        .map(Vec3::from_array)
3566        .collect();
3567        mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, positions.clone());
3568        mesh.insert_indices(Indices::U32(vec![0, 1, 2, 3, 4, 5]));
3569        assert_eq!(
3570            vec![
3571                Triangle3d {
3572                    vertices: [positions[0], positions[1], positions[2]]
3573                },
3574                Triangle3d {
3575                    vertices: [positions[2], positions[1], positions[3]]
3576                },
3577                Triangle3d {
3578                    vertices: [positions[2], positions[3], positions[4]]
3579                },
3580                Triangle3d {
3581                    vertices: [positions[4], positions[3], positions[5]]
3582                },
3583            ],
3584            mesh.triangles().unwrap().collect::<Vec<Triangle3d>>()
3585        );
3586    }
3587
3588    #[test]
3589    fn take_gpu_data_calculates_aabb() {
3590        let mut mesh = Mesh::new(
3591            PrimitiveTopology::TriangleList,
3592            RenderAssetUsages::default(),
3593        );
3594        mesh.insert_attribute(
3595            Mesh::ATTRIBUTE_POSITION,
3596            vec![
3597                [-0.5, 0., 0.],
3598                [-1., 0., 0.],
3599                [-1., -1., 0.],
3600                [-0.5, -1., 0.],
3601            ],
3602        );
3603        mesh.insert_indices(Indices::U32(vec![0, 1, 2, 2, 3, 0]));
3604        mesh = mesh.take_gpu_data().unwrap();
3605        assert_eq!(
3606            mesh.final_aabb,
3607            Some(Aabb3d::from_min_max([-1., -1., 0.], [-0.5, 0., 0.]))
3608        );
3609    }
3610
3611    #[cfg(feature = "serialize")]
3612    #[test]
3613    fn serialize_deserialize_mesh() {
3614        let mut mesh = Mesh::new(
3615            PrimitiveTopology::TriangleList,
3616            RenderAssetUsages::default(),
3617        );
3618
3619        mesh.insert_attribute(
3620            Mesh::ATTRIBUTE_POSITION,
3621            vec![[0., 0., 0.], [2., 0., 0.], [0., 1., 0.], [0., 0., 1.]],
3622        );
3623        mesh.insert_indices(Indices::U16(vec![0, 1, 2, 0, 2, 3]));
3624
3625        let serialized_mesh = SerializedMesh::from_mesh(mesh.clone());
3626        let serialized_string = serde_json::to_string(&serialized_mesh).unwrap();
3627        let serialized_mesh_from_string: SerializedMesh =
3628            serde_json::from_str(&serialized_string).unwrap();
3629        let deserialized_mesh = serialized_mesh_from_string.into_mesh();
3630        assert_eq!(mesh, deserialized_mesh);
3631    }
3632
3633    #[test]
3634    fn merge_duplicate_vertices() {
3635        let mut mesh = Mesh::new(
3636            PrimitiveTopology::TriangleList,
3637            RenderAssetUsages::default(),
3638        );
3639        // Quad made of two triangles.
3640        let positions = vec![
3641            [0.0, 0.0, 0.0],
3642            [1.0, 0.0, 0.0],
3643            [1.0, 1.0, 0.0],
3644            // This will be deduplicated.
3645            [1.0, 1.0, 0.0],
3646            [0.0, 1.0, 0.0],
3647            // Position is equal to the first one but UV is different so it won't be deduplicated.
3648            [0.0, 0.0, 0.0],
3649        ];
3650        let uvs = vec![
3651            [0.0, 0.0],
3652            [1.0, 0.0],
3653            [1.0, 1.0],
3654            // This will be deduplicated.
3655            [1.0, 1.0],
3656            [0.0, 1.0],
3657            // Use different UV here so it won't be deduplicated.
3658            [0.0, 0.5],
3659        ];
3660        mesh.insert_attribute(
3661            Mesh::ATTRIBUTE_POSITION,
3662            VertexAttributeValues::Float32x3(positions.clone()),
3663        );
3664        mesh.insert_attribute(
3665            Mesh::ATTRIBUTE_UV_0,
3666            VertexAttributeValues::Float32x2(uvs.clone()),
3667        );
3668
3669        let res = mesh.merge_duplicate_vertices();
3670        assert!(res.is_ok());
3671        assert_eq!(6, mesh.indices().unwrap().len());
3672        // Note we have 5 unique vertices, not 6.
3673        assert_eq!(5, mesh.attribute(Mesh::ATTRIBUTE_POSITION).unwrap().len());
3674        assert_eq!(5, mesh.attribute(Mesh::ATTRIBUTE_UV_0).unwrap().len());
3675
3676        // Duplicate back.
3677        mesh.duplicate_vertices();
3678        assert!(mesh.indices().is_none());
3679        let VertexAttributeValues::Float32x3(new_positions) =
3680            mesh.attribute(Mesh::ATTRIBUTE_POSITION).unwrap()
3681        else {
3682            panic!("Unexpected attribute type")
3683        };
3684        let VertexAttributeValues::Float32x2(new_uvs) =
3685            mesh.attribute(Mesh::ATTRIBUTE_UV_0).unwrap()
3686        else {
3687            panic!("Unexpected attribute type")
3688        };
3689        assert_eq!(&positions, new_positions);
3690        assert_eq!(&uvs, new_uvs);
3691    }
3692
3693    #[test]
3694    fn compress_mesh_positions() {
3695        let mut mesh = Mesh::new(
3696            PrimitiveTopology::TriangleList,
3697            RenderAssetUsages::default(),
3698        )
3699        .with_inserted_attribute(
3700            Mesh::ATTRIBUTE_POSITION,
3701            vec![
3702                [0.0, 1.0, -1.0],
3703                [1.0, -0.5, -1.0],
3704                [-1.0, -0.5, -1.0],
3705                [0.0, -0.5, 1.0],
3706            ],
3707        );
3708        mesh.compress_positions().unwrap();
3709        assert_eq!(
3710            mesh.final_aabb,
3711            Some(Aabb3d::from_min_max(
3712                Vec3A::new(-1.0, -0.5, -1.0),
3713                Vec3A::new(1.0, 1.0, 1.0)
3714            ))
3715        );
3716        assert_eq!(
3717            mesh.attribute_compression,
3718            MeshAttributeCompressionFlags::COMPRESS_POSITION
3719        );
3720        assert_eq!(
3721            mesh.attribute(Mesh::ATTRIBUTE_POSITION),
3722            Some(&VertexAttributeValues::Snorm16x4(vec![
3723                [0, 32767, -32767, 0],
3724                [32767, -32767, -32767, 0],
3725                [-32767, -32767, -32767, 0],
3726                [0, -32767, 32767, 0],
3727            ]))
3728        );
3729    }
3730
3731    #[test]
3732    fn compress_mesh_uvs() {
3733        let mut mesh = Mesh::new(
3734            PrimitiveTopology::TriangleList,
3735            RenderAssetUsages::default(),
3736        )
3737        .with_inserted_attribute(
3738            Mesh::ATTRIBUTE_UV_0,
3739            vec![[0.126, 0.497], [0.126, 1.0], [0.05, 0.0], [0.0, 0.5]],
3740        )
3741        .with_inserted_attribute(
3742            Mesh::ATTRIBUTE_UV_1,
3743            vec![[12.6, 0.497], [0.126, 1.0], [-4.05, 0.0], [1.0, -0.5]],
3744        );
3745        mesh.compress_uv0().unwrap();
3746        assert_eq!(
3747            mesh.final_uv_ranges,
3748            [
3749                Some(Aabb2d {
3750                    min: Vec2::new(0.0, 0.0),
3751                    max: Vec2::new(0.126, 1.0)
3752                }),
3753                None
3754            ]
3755        );
3756        assert_eq!(
3757            mesh.attribute_compression,
3758            MeshAttributeCompressionFlags::COMPRESS_UV0
3759        );
3760        assert_eq!(
3761            mesh.attribute(Mesh::ATTRIBUTE_UV_0),
3762            Some(&VertexAttributeValues::Unorm16x2(vec![
3763                [65535, 32571],
3764                [65535, 65535],
3765                [26006, 0],
3766                [0, 32768],
3767            ]))
3768        );
3769
3770        mesh.compress_uv1().unwrap();
3771        assert_eq!(
3772            mesh.final_uv_ranges,
3773            [
3774                Some(Aabb2d {
3775                    min: Vec2::new(0.0, 0.0),
3776                    max: Vec2::new(0.126, 1.0)
3777                }),
3778                Some(Aabb2d {
3779                    min: Vec2::new(-4.05, -0.5),
3780                    max: Vec2::new(12.6, 1.0)
3781                })
3782            ]
3783        );
3784        assert_eq!(
3785            mesh.attribute_compression,
3786            MeshAttributeCompressionFlags::COMPRESS_UV0
3787                | MeshAttributeCompressionFlags::COMPRESS_UV1
3788        );
3789        assert_eq!(
3790            mesh.attribute(Mesh::ATTRIBUTE_UV_1),
3791            Some(&VertexAttributeValues::Unorm16x2(vec![
3792                [65535, 43559],
3793                [16437, 65535],
3794                [0, 21845],
3795                [19877, 0]
3796            ]))
3797        );
3798    }
3799
3800    #[test]
3801    fn compress_mesh_normals() {
3802        let mut mesh = Mesh::new(
3803            PrimitiveTopology::TriangleList,
3804            RenderAssetUsages::default(),
3805        )
3806        .with_inserted_attribute(
3807            Mesh::ATTRIBUTE_NORMAL,
3808            vec![
3809                Vec3::new(0.0, 1.0, -1.0).normalize().to_array(),
3810                Vec3::new(1.0, 0.0, -1.0).normalize().to_array(),
3811                Vec3::new(-1.0, 0.0, -1.0).normalize().to_array(),
3812                [0.0, 0.0, 1.0],
3813            ],
3814        );
3815        mesh.compress_normals().unwrap();
3816        assert_eq!(
3817            mesh.attribute_compression,
3818            MeshAttributeCompressionFlags::COMPRESS_NORMAL
3819        );
3820        assert_eq!(
3821            mesh.attribute(Mesh::ATTRIBUTE_NORMAL),
3822            Some(&VertexAttributeValues::Snorm16x2(vec![
3823                [16384, 32767],
3824                [32767, 16384],
3825                [-32767, 16384],
3826                [0, 0],
3827            ]))
3828        );
3829    }
3830
3831    #[test]
3832    fn compress_mesh_tangents() {
3833        let mut mesh = Mesh::new(
3834            PrimitiveTopology::TriangleList,
3835            RenderAssetUsages::default(),
3836        )
3837        .with_inserted_attribute(
3838            Mesh::ATTRIBUTE_TANGENT,
3839            vec![
3840                Vec3::new(0.0, 1.0, 1.0).normalize().extend(1.0).to_array(),
3841                Vec3::new(1.0, 0.0, 1.0).normalize().extend(-1.0).to_array(),
3842                Vec3::new(-1.0, 0.0, 1.0).normalize().extend(1.0).to_array(),
3843                [1.0, 0.0, 0.0, 1.0],
3844            ],
3845        );
3846        mesh.compress_tangents().unwrap();
3847        assert_eq!(
3848            mesh.attribute_compression,
3849            MeshAttributeCompressionFlags::COMPRESS_TANGENT
3850        );
3851        assert_eq!(
3852            mesh.attribute(Mesh::ATTRIBUTE_TANGENT),
3853            Some(&VertexAttributeValues::Snorm16x2(vec![
3854                [0, 24575],
3855                [16384, -16384],
3856                [-16384, 16384],
3857                [32767, 16384],
3858            ]))
3859        );
3860    }
3861
3862    #[test]
3863    fn quantize_mesh_colors() {
3864        let mut mesh = Mesh::new(
3865            PrimitiveTopology::TriangleList,
3866            RenderAssetUsages::default(),
3867        )
3868        .with_inserted_attribute(
3869            Mesh::ATTRIBUTE_COLOR,
3870            vec![
3871                [0.05, 1.0, 0.15, 1.0],
3872                [0.75, 0.07, 1.0, 1.0],
3873                [0.04, 0.11, 1.0, 1.0],
3874                [1.0, 0.11, 0.13, 1.0],
3875            ],
3876        );
3877        let mut mesh_color_f16 = mesh.clone();
3878
3879        mesh.quantize_colors(AttributeQuantization::Unorm8).unwrap();
3880        assert_eq!(
3881            mesh.attribute_compression,
3882            MeshAttributeCompressionFlags::empty()
3883        );
3884        assert_eq!(
3885            mesh.attribute(Mesh::ATTRIBUTE_COLOR),
3886            Some(&VertexAttributeValues::Unorm8x4(vec![
3887                [13, 255, 38, 255],
3888                [191, 18, 255, 255],
3889                [10, 28, 255, 255],
3890                [255, 28, 33, 255],
3891            ]))
3892        );
3893
3894        mesh_color_f16
3895            .quantize_colors(AttributeQuantization::Float16)
3896            .unwrap();
3897        assert_eq!(
3898            mesh_color_f16.attribute_compression,
3899            MeshAttributeCompressionFlags::empty()
3900        );
3901        let VertexAttributeValues::Float16x4(color_f16) =
3902            mesh_color_f16.attribute(Mesh::ATTRIBUTE_COLOR).unwrap()
3903        else {
3904            panic!("Color attribute is not quantized to Float16x4")
3905        };
3906        assert!(color_f16
3907            .iter()
3908            .flatten()
3909            .zip(
3910                [
3911                    [0.049987793, 1.0, 0.15002441, 1.0].map(half::f16::from_f32),
3912                    [0.75, 0.070007324, 1.0, 1.0].map(half::f16::from_f32),
3913                    [0.040008545, 0.10998535, 1.0, 1.0].map(half::f16::from_f32),
3914                    [1.0, 0.10998535, 0.13000488, 1.0].map(half::f16::from_f32)
3915                ]
3916                .iter()
3917                .flatten()
3918            )
3919            .all(|(a, b)| approx::relative_eq!(a.to_f32(), b.to_f32())));
3920    }
3921
3922    #[test]
3923    fn quantize_mesh_joint_weights() {
3924        let mut mesh = Mesh::new(
3925            PrimitiveTopology::TriangleList,
3926            RenderAssetUsages::default(),
3927        )
3928        .with_inserted_attribute(
3929            Mesh::ATTRIBUTE_JOINT_WEIGHT,
3930            vec![
3931                [1.0, 0.0, 0.0, 0.0],
3932                [0.0, 1.0, 0.0, 0.0],
3933                [0.0, 0.0, 1.0, 0.0],
3934                [0.0, 0.0, 0.0, 1.0],
3935                [0.1, 0.9, 0.0, 0.0],
3936                [0.1, 0.2, 0.7, 0.0],
3937                [0.1, 0.2, 0.4, 0.3],
3938            ],
3939        );
3940
3941        mesh.quantize_joint_weights(AttributeQuantization::Unorm16)
3942            .unwrap();
3943        assert_eq!(
3944            mesh.attribute_compression,
3945            MeshAttributeCompressionFlags::empty()
3946        );
3947        assert_eq!(
3948            mesh.attribute(Mesh::ATTRIBUTE_JOINT_WEIGHT),
3949            Some(&VertexAttributeValues::Unorm16x4(vec![
3950                [65535, 0, 0, 0],
3951                [0, 65535, 0, 0],
3952                [0, 0, 65535, 0],
3953                [0, 0, 0, 65535],
3954                [6554, 58982, 0, 0],
3955                [6554, 13107, 45875, 0],
3956                [6554, 13107, 26214, 19661]
3957            ]))
3958        );
3959    }
3960
3961    #[test]
3962    fn compress_mesh_indices() {
3963        let mut mesh = Mesh::new(
3964            PrimitiveTopology::TriangleList,
3965            RenderAssetUsages::default(),
3966        )
3967        .with_inserted_indices(Indices::U32(vec![0, 1, 2, 0, 3, 1, 0, 2, 3, 1, 3, 2]));
3968
3969        mesh.compress_indices();
3970        assert_eq!(
3971            mesh.attribute_compression,
3972            MeshAttributeCompressionFlags::empty()
3973        );
3974        assert_eq!(
3975            mesh.indices(),
3976            Some(&Indices::U16(vec![0, 1, 2, 0, 3, 1, 0, 2, 3, 1, 3, 2]))
3977        );
3978    }
3979
3980    #[test]
3981    fn quantize_mesh_float32_attributes() {
3982        let f4 = MeshVertexAttribute::new("f32x4", 10, wgpu_types::VertexFormat::Float32x4);
3983        let f2 = MeshVertexAttribute::new("f32x2", 11, wgpu_types::VertexFormat::Float32x2);
3984        let f1 = MeshVertexAttribute::new("f32x1", 12, wgpu_types::VertexFormat::Float32);
3985        let mut mesh = Mesh::new(
3986            PrimitiveTopology::TriangleList,
3987            RenderAssetUsages::default(),
3988        )
3989        .with_inserted_attribute(
3990            f4,
3991            vec![
3992                [1.0, 0.0, -2.0, 0.0],
3993                [0.0, 5.0, 0.0, 0.0],
3994                [0.0, 0.0, -1.0, 0.0],
3995                [0.0, 0.0, 0.0, 1.0],
3996                [0.1, -0.9, 0.0, 0.0],
3997                [0.1, 0.2, -0.7, 0.0],
3998                [0.1, 0.2, 0.4, 0.3],
3999            ],
4000        )
4001        .with_inserted_attribute(
4002            f2,
4003            vec![
4004                [10.0, 0.0],
4005                [0.0, 1.0],
4006                [-2.0, 0.0],
4007                [-0.5, 0.0],
4008                [0.1, 0.9],
4009                [0.1, 0.2],
4010                [0.1, 0.2],
4011            ],
4012        )
4013        .with_inserted_attribute(f1, vec![10.0, 0.0, 2.0, 0.0, 0.1, 0.1, 0.1]);
4014
4015        mesh.quantize_float32_attribute(f4, AttributeQuantization::Unorm16)
4016            .unwrap();
4017        assert_eq!(
4018            mesh.attribute(f4),
4019            Some(&VertexAttributeValues::Unorm16x4(vec![
4020                [65535, 0, 0, 0],
4021                [0, 65535, 0, 0],
4022                [0, 0, 0, 0],
4023                [0, 0, 0, 65535],
4024                [6554, 0, 0, 0],
4025                [6554, 13107, 0, 0],
4026                [6554, 13107, 26214, 19661]
4027            ]))
4028        );
4029
4030        mesh.quantize_float32_attribute(f2, AttributeQuantization::Snorm8)
4031            .unwrap();
4032        assert_eq!(
4033            mesh.attribute(f2),
4034            Some(&VertexAttributeValues::Snorm8x2(vec![
4035                [127, 0],
4036                [0, 127],
4037                [-127, 0],
4038                [-64, 0],
4039                [13, 114],
4040                [13, 25],
4041                [13, 25]
4042            ]))
4043        );
4044
4045        mesh.quantize_float32_attribute(f1, AttributeQuantization::Float16)
4046            .unwrap();
4047        let VertexAttributeValues::Float16(f16_values) = mesh.attribute(f1).unwrap() else {
4048            panic!("Attribute f1 is not quantized to Float16")
4049        };
4050        assert!(f16_values
4051            .iter()
4052            .zip([10.0, 0.0, 2.0, 0.0, 0.1, 0.1, 0.1].map(half::f16::from_f32))
4053            .all(|(a, b)| approx::relative_eq!(a.to_f32(), b.to_f32())));
4054    }
4055
4056    #[test]
4057    fn get_attributes_mut_test() {
4058        let mut mesh = Mesh::new(PrimitiveTopology::PointList, RenderAssetUsages::default());
4059
4060        mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, vec![Vec3::new(0., 0., 0.)]);
4061        mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, vec![Vec3::new(1., 1., 1.)]);
4062        mesh.insert_attribute(Mesh::ATTRIBUTE_COLOR, vec![Vec4::new(2., 2., 2., 2.)]);
4063        {
4064            let Ok([pos, normal, color]) = mesh.try_disjoint_attributes_mut([
4065                &Mesh::ATTRIBUTE_POSITION.id,
4066                &Mesh::ATTRIBUTE_NORMAL.id,
4067                &Mesh::ATTRIBUTE_COLOR.id,
4068            ]) else {
4069                unreachable!("Data shouldn't have been extracted.");
4070            };
4071            assert_eq!(pos.unwrap().0, &Mesh::ATTRIBUTE_POSITION);
4072            assert_eq!(normal.unwrap().0, &Mesh::ATTRIBUTE_NORMAL);
4073            assert_eq!(color.unwrap().0, &Mesh::ATTRIBUTE_COLOR);
4074        }
4075        {
4076            let Ok([pos, color, normal]) = mesh.try_disjoint_attributes_mut([
4077                &Mesh::ATTRIBUTE_POSITION.id,
4078                &Mesh::ATTRIBUTE_COLOR.id,
4079                &Mesh::ATTRIBUTE_NORMAL.id,
4080            ]) else {
4081                unreachable!("Data shouldn't have been extracted.");
4082            };
4083            assert_eq!(pos.unwrap().0, &Mesh::ATTRIBUTE_POSITION);
4084            assert_eq!(color.unwrap().0, &Mesh::ATTRIBUTE_COLOR);
4085            assert_eq!(normal.unwrap().0, &Mesh::ATTRIBUTE_NORMAL);
4086        }
4087        {
4088            let Ok([pos1, pos2, pos3]) = mesh.try_disjoint_attributes_mut([
4089                &Mesh::ATTRIBUTE_POSITION.id,
4090                &Mesh::ATTRIBUTE_POSITION.id,
4091                &Mesh::ATTRIBUTE_POSITION.id,
4092            ]) else {
4093                unreachable!("Data shouldn't have been extracted.");
4094            };
4095            assert_eq!(pos1.unwrap().0, &Mesh::ATTRIBUTE_POSITION);
4096            assert!(pos2.is_none());
4097            assert!(pos3.is_none());
4098        }
4099        {
4100            let Ok([pos1, pos2, pos3, normal, color]) = mesh.try_disjoint_attributes_mut([
4101                &Mesh::ATTRIBUTE_POSITION.id,
4102                &Mesh::ATTRIBUTE_POSITION.id,
4103                &Mesh::ATTRIBUTE_POSITION.id,
4104                &Mesh::ATTRIBUTE_NORMAL.id,
4105                &Mesh::ATTRIBUTE_COLOR.id,
4106            ]) else {
4107                unreachable!("Data shouldn't have been extracted.");
4108            };
4109            assert_eq!(pos1.unwrap().0, &Mesh::ATTRIBUTE_POSITION);
4110            assert!(pos2.is_none());
4111            assert!(pos3.is_none());
4112            assert_eq!(normal.unwrap().0, &Mesh::ATTRIBUTE_NORMAL);
4113            assert_eq!(color.unwrap().0, &Mesh::ATTRIBUTE_COLOR);
4114        }
4115        {
4116            let Ok([color, uv0, normal, uv1, pos]) = mesh.try_disjoint_attributes_mut([
4117                &Mesh::ATTRIBUTE_COLOR.id,
4118                &Mesh::ATTRIBUTE_UV_0.id,
4119                &Mesh::ATTRIBUTE_NORMAL.id,
4120                &Mesh::ATTRIBUTE_UV_1.id,
4121                &Mesh::ATTRIBUTE_POSITION.id,
4122            ]) else {
4123                unreachable!("Data shouldn't have been extracted.");
4124            };
4125            assert_eq!(color.unwrap().0, &Mesh::ATTRIBUTE_COLOR);
4126            assert!(uv0.is_none());
4127            assert_eq!(normal.unwrap().0, &Mesh::ATTRIBUTE_NORMAL);
4128            assert!(uv1.is_none());
4129            assert_eq!(pos.unwrap().0, &Mesh::ATTRIBUTE_POSITION);
4130        }
4131    }
4132}