Skip to main content

bevy_mesh/primitives/dim3/
sphere.rs

1use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
2use bevy_asset::RenderAssetUsages;
3use bevy_math::{ops, primitives::Sphere};
4use bevy_reflect::prelude::*;
5use core::f32::consts::PI;
6use hexasphere::shapes::IcoSphere;
7use thiserror::Error;
8
9/// An error when creating an icosphere [`Mesh`] from a [`SphereMeshBuilder`].
10#[derive(#[automatically_derived]
impl ::core::clone::Clone for IcosphereError {
    #[inline]
    fn clone(&self) -> IcosphereError {
        let _: ::core::clone::AssertParamIsClone<u32>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for IcosphereError { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for IcosphereError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            IcosphereError::TooManyVertices {
                subdivisions: __self_0, number_of_resulting_points: __self_1 }
                =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "TooManyVertices", "subdivisions", __self_0,
                    "number_of_resulting_points", &__self_1),
        }
    }
}Debug, #[allow(unused_qualifications)]
#[automatically_derived]
impl ::core::fmt::Display for IcosphereError {
    fn fmt(&self, __formatter: &mut ::core::fmt::Formatter)
        -> ::core::fmt::Result {
        use ::thiserror::__private18::AsDisplay as _;

        #[allow(unused_variables, deprecated, clippy ::
        used_underscore_binding)]
        match self {
            IcosphereError::TooManyVertices {
                subdivisions, number_of_resulting_points } =>
                match (subdivisions.as_display(),
                        number_of_resulting_points.as_display()) {
                    (__display_subdivisions,
                        __display_number_of_resulting_points) =>
                        __formatter.write_fmt(format_args!("Cannot create an icosphere of {0} subdivisions due to there being too many vertices being generated: {1}. (Limited to 65535 vertices or 79 subdivisions)",
                                __display_subdivisions,
                                __display_number_of_resulting_points)),
                },
        }
    }
}Error)]
11pub enum IcosphereError {
12    /// The icosphere has too many vertices.
13    #[error("Cannot create an icosphere of {subdivisions} subdivisions due to there being too many vertices being generated: {number_of_resulting_points}. (Limited to 65535 vertices or 79 subdivisions)")]
14    TooManyVertices {
15        /// The number of subdivisions used. 79 is the largest allowed value for a mesh to be generated.
16        subdivisions: u32,
17        /// The number of vertices generated. 65535 is the largest allowed value for a mesh to be generated.
18        number_of_resulting_points: u32,
19    },
20}
21
22/// A type of sphere mesh.
23#[derive(#[automatically_derived]
impl ::core::clone::Clone for SphereKind {
    #[inline]
    fn clone(&self) -> SphereKind {
        let _: ::core::clone::AssertParamIsClone<u32>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for SphereKind { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for SphereKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            SphereKind::Ico { subdivisions: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Ico",
                    "subdivisions", &__self_0),
            SphereKind::Uv { sectors: __self_0, stacks: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f, "Uv",
                    "sectors", __self_0, "stacks", &__self_1),
        }
    }
}Debug, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for SphereKind where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration.register_type_data::<ReflectDefault, Self>();
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <u32 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for SphereKind where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Struct(bevy_reflect::enums::StructVariantInfo::new("Ico",
                                                        &[bevy_reflect::NamedField::new::<u32>("subdivisions")])),
                                                bevy_reflect::enums::VariantInfo::Struct(bevy_reflect::enums::StructVariantInfo::new("Uv",
                                                        &[bevy_reflect::NamedField::new::<u32>("sectors"),
                                                                    bevy_reflect::NamedField::new::<u32>("stacks")]))]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for SphereKind where  {
            fn type_path() -> &'static str {
                "bevy_mesh::primitives::dim3::sphere::SphereKind"
            }
            fn short_type_path() -> &'static str { "SphereKind" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("SphereKind")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_mesh::primitives::dim3::sphere".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_mesh::primitives::dim3::sphere")
            }
        }
        impl bevy_reflect::Reflect for SphereKind 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(<SphereKind
                                        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 SphereKind where  {
            fn field(&self, __name_param: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    SphereKind::Ico { subdivisions: __value, .. } if
                        __name_param == "subdivisions" =>
                        ::core::option::Option::Some(__value),
                    SphereKind::Uv { sectors: __value, .. } if
                        __name_param == "sectors" =>
                        ::core::option::Option::Some(__value),
                    SphereKind::Uv { stacks: __value, .. } if
                        __name_param == "stacks" =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, __index_param: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    SphereKind::Ico { subdivisions: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    SphereKind::Uv { sectors: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    SphereKind::Uv { stacks: __value, .. } if
                        __index_param == 1usize =>
                        ::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 {
                    SphereKind::Ico { subdivisions: __value, .. } if
                        __name_param == "subdivisions" =>
                        ::core::option::Option::Some(__value),
                    SphereKind::Uv { sectors: __value, .. } if
                        __name_param == "sectors" =>
                        ::core::option::Option::Some(__value),
                    SphereKind::Uv { stacks: __value, .. } if
                        __name_param == "stacks" =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, __index_param: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self {
                    SphereKind::Ico { subdivisions: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    SphereKind::Uv { sectors: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    SphereKind::Uv { stacks: __value, .. } if
                        __index_param == 1usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of(&self, __name_param: &str)
                -> ::core::option::Option<usize> {
                match self {
                    SphereKind::Ico { .. } if __name_param == "subdivisions" =>
                        ::core::option::Option::Some(0usize),
                    SphereKind::Uv { .. } if __name_param == "sectors" =>
                        ::core::option::Option::Some(0usize),
                    SphereKind::Uv { .. } if __name_param == "stacks" =>
                        ::core::option::Option::Some(1usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, __index_param: usize)
                -> ::core::option::Option<&str> {
                match self {
                    SphereKind::Ico { .. } if __index_param == 0usize =>
                        ::core::option::Option::Some("subdivisions"),
                    SphereKind::Uv { .. } if __index_param == 0usize =>
                        ::core::option::Option::Some("sectors"),
                    SphereKind::Uv { .. } if __index_param == 1usize =>
                        ::core::option::Option::Some("stacks"),
                    _ => ::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 {
                    SphereKind::Ico { .. } => 1usize,
                    SphereKind::Uv { .. } => 2usize,
                    _ => 0,
                }
            }
            #[inline]
            fn variant_name(&self) -> &str {
                match self {
                    SphereKind::Ico { .. } => "Ico",
                    SphereKind::Uv { .. } => "Uv",
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_index(&self) -> usize {
                match self {
                    SphereKind::Ico { .. } => 0usize,
                    SphereKind::Uv { .. } => 1usize,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_type(&self) -> bevy_reflect::enums::VariantType {
                match self {
                    SphereKind::Ico { .. } =>
                        bevy_reflect::enums::VariantType::Struct,
                    SphereKind::Uv { .. } =>
                        bevy_reflect::enums::VariantType::Struct,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            fn to_dynamic_enum(&self) -> bevy_reflect::enums::DynamicEnum {
                bevy_reflect::enums::DynamicEnum::from_ref::<Self>(self)
            }
        }
        impl bevy_reflect::PartialReflect for SphereKind 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)
                            {
                            "Ico" => {
                                *self =
                                    SphereKind::Ico {
                                        subdivisions: {
                                            let __subdivisions = __value_param.field("subdivisions");
                                            let __subdivisions =
                                                __subdivisions.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Ico"),
                                                            field_name: ::core::convert::Into::into("subdivisions"),
                                                        })?;
                                            <u32 as
                                                            bevy_reflect::FromReflect>::from_reflect(__subdivisions).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__subdivisions)),
                                                        to_type: ::core::convert::Into::into(<u32 as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "Uv" => {
                                *self =
                                    SphereKind::Uv {
                                        sectors: {
                                            let __sectors = __value_param.field("sectors");
                                            let __sectors =
                                                __sectors.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Uv"),
                                                            field_name: ::core::convert::Into::into("sectors"),
                                                        })?;
                                            <u32 as
                                                            bevy_reflect::FromReflect>::from_reflect(__sectors).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__sectors)),
                                                        to_type: ::core::convert::Into::into(<u32 as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                        stacks: {
                                            let __stacks = __value_param.field("stacks");
                                            let __stacks =
                                                __stacks.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Uv"),
                                                            field_name: ::core::convert::Into::into("stacks"),
                                                        })?;
                                            <u32 as
                                                            bevy_reflect::FromReflect>::from_reflect(__stacks).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__stacks)),
                                                        to_type: ::core::convert::Into::into(<u32 as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            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)
            }
            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 SphereKind 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) {
                        "Ico" =>
                            ::core::option::Option::Some(SphereKind::Ico {
                                    subdivisions: {
                                        let __subdivisions = __param0.field("subdivisions");
                                        let __subdivisions = __subdivisions?;
                                        <u32 as
                                                    bevy_reflect::FromReflect>::from_reflect(__subdivisions)?
                                    },
                                }),
                        "Uv" =>
                            ::core::option::Option::Some(SphereKind::Uv {
                                    sectors: {
                                        let __sectors = __param0.field("sectors");
                                        let __sectors = __sectors?;
                                        <u32 as bevy_reflect::FromReflect>::from_reflect(__sectors)?
                                    },
                                    stacks: {
                                        let __stacks = __param0.field("stacks");
                                        let __stacks = __stacks?;
                                        <u32 as bevy_reflect::FromReflect>::from_reflect(__stacks)?
                                    },
                                }),
                        name => ::core::option::Option::None,
                    }
                } else { ::core::option::Option::None }
            }
        }
    };Reflect)]
24#[reflect(Default, Debug, Clone)]
25pub enum SphereKind {
26    /// An icosphere, a spherical mesh that consists of similar sized triangles.
27    Ico {
28        /// The number of subdivisions applied.
29        /// The number of faces quadruples with each subdivision.
30        subdivisions: u32,
31    },
32    /// A UV sphere, a spherical mesh that consists of quadrilaterals
33    /// apart from triangles at the top and bottom.
34    Uv {
35        /// The number of longitudinal sectors, aka the horizontal resolution.
36        #[doc(alias = "horizontal_resolution")]
37        sectors: u32,
38        /// The number of latitudinal stacks, aka the vertical resolution.
39        #[doc(alias = "vertical_resolution")]
40        stacks: u32,
41    },
42}
43
44impl Default for SphereKind {
45    fn default() -> Self {
46        Self::Ico { subdivisions: 5 }
47    }
48}
49
50/// A builder used for creating a [`Mesh`] with an [`Sphere`] shape.
51#[derive(#[automatically_derived]
impl ::core::clone::Clone for SphereMeshBuilder {
    #[inline]
    fn clone(&self) -> SphereMeshBuilder {
        let _: ::core::clone::AssertParamIsClone<Sphere>;
        let _: ::core::clone::AssertParamIsClone<SphereKind>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for SphereMeshBuilder { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for SphereMeshBuilder {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "SphereMeshBuilder", "sphere", &self.sphere, "kind", &&self.kind)
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for SphereMeshBuilder {
    #[inline]
    fn default() -> SphereMeshBuilder {
        SphereMeshBuilder {
            sphere: ::core::default::Default::default(),
            kind: ::core::default::Default::default(),
        }
    }
}Default, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for SphereMeshBuilder where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration.register_type_data::<ReflectDefault, Self>();
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Sphere as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <SphereKind as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for SphereMeshBuilder where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<Sphere>("sphere"),
                                                bevy_reflect::NamedField::new::<SphereKind>("kind")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for SphereMeshBuilder where  {
            fn type_path() -> &'static str {
                "bevy_mesh::primitives::dim3::sphere::SphereMeshBuilder"
            }
            fn short_type_path() -> &'static str { "SphereMeshBuilder" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("SphereMeshBuilder")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_mesh::primitives::dim3::sphere".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_mesh::primitives::dim3::sphere")
            }
        }
        impl bevy_reflect::Reflect for SphereMeshBuilder 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(<SphereMeshBuilder
                                        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 SphereMeshBuilder where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "sphere" => ::core::option::Option::Some(&self.sphere),
                    "kind" => ::core::option::Option::Some(&self.kind),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "sphere" => ::core::option::Option::Some(&mut self.sphere),
                    "kind" => ::core::option::Option::Some(&mut self.kind),
                    _ => ::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.sphere),
                    1usize => ::core::option::Option::Some(&self.kind),
                    _ => ::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.sphere),
                    1usize => ::core::option::Option::Some(&mut self.kind),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("sphere"),
                    1usize => ::core::option::Option::Some("kind"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "sphere" => ::core::option::Option::Some(0usize),
                    "kind" => ::core::option::Option::Some(1usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 2usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                -> bevy_reflect::structs::DynamicStruct {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("sphere",
                    bevy_reflect::PartialReflect::to_dynamic(&self.sphere));
                dynamic.insert_boxed("kind",
                    bevy_reflect::PartialReflect::to_dynamic(&self.kind));
                dynamic
            }
        }
        impl bevy_reflect::PartialReflect for SphereMeshBuilder 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)
            }
            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 SphereMeshBuilder 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 mut __this =
                        <Self as ::core::default::Default>::default();
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <Sphere as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "sphere")?))() {
                        __this.sphere = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <SphereKind as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "kind")?))() {
                        __this.kind = __field;
                    }
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect)]
52#[reflect(Default, Debug, Clone)]
53pub struct SphereMeshBuilder {
54    /// The [`Sphere`] shape.
55    pub sphere: Sphere,
56    /// The type of sphere mesh that will be built.
57    pub kind: SphereKind,
58}
59
60impl SphereMeshBuilder {
61    /// Creates a new [`SphereMeshBuilder`] from a radius and [`SphereKind`].
62    #[inline]
63    pub const fn new(radius: f32, kind: SphereKind) -> Self {
64        Self {
65            sphere: Sphere { radius },
66            kind,
67        }
68    }
69
70    /// Sets the [`SphereKind`] that will be used for building the mesh.
71    #[inline]
72    pub const fn kind(mut self, kind: SphereKind) -> Self {
73        self.kind = kind;
74        self
75    }
76
77    /// Creates an icosphere mesh with the given number of subdivisions.
78    ///
79    /// The number of faces quadruples with each subdivision.
80    /// If there are `80` or more subdivisions, the vertex count will be too large,
81    /// and an [`IcosphereError`] is returned.
82    ///
83    /// A good default is `5` subdivisions.
84    pub fn ico(&self, subdivisions: u32) -> Result<Mesh, IcosphereError> {
85        if subdivisions >= 80 {
86            /*
87            Number of triangles:
88            N = 20
89
90            Number of edges:
91            E = 30
92
93            Number of vertices:
94            V = 12
95
96            Number of points within a triangle (triangular numbers):
97            inner(s) = (s^2 + s) / 2
98
99            Number of points on an edge:
100            edges(s) = s
101
102            Add up all vertices on the surface:
103            vertices(s) = edges(s) * E + inner(s - 1) * N + V
104
105            Expand and simplify. Notice that the triangular number formula has roots at -1, and 0, so translating it one to the right fixes it.
106            subdivisions(s) = 30s + 20((s^2 - 2s + 1 + s - 1) / 2) + 12
107            subdivisions(s) = 30s + 10s^2 - 10s + 12
108            subdivisions(s) = 10(s^2 + 2s) + 12
109
110            Factor an (s + 1) term to simplify in terms of calculation
111            subdivisions(s) = 10(s + 1)^2 + 12 - 10
112            resulting_vertices(s) = 10(s + 1)^2 + 2
113            */
114            let temp = subdivisions + 1;
115            let number_of_resulting_points = temp * temp * 10 + 2;
116            return Err(IcosphereError::TooManyVertices {
117                subdivisions,
118                number_of_resulting_points,
119            });
120        }
121        let generated = IcoSphere::new(subdivisions as usize, |point| {
122            let inclination = ops::acos(point.y);
123            let azimuth = ops::atan2(point.z, point.x);
124
125            let norm_inclination = inclination / PI;
126            let norm_azimuth = 0.5 - (azimuth / core::f32::consts::TAU);
127
128            [norm_azimuth, norm_inclination]
129        });
130
131        let raw_points = generated.raw_points();
132
133        let points = raw_points
134            .iter()
135            .map(|&p| (p * self.sphere.radius).into())
136            .collect::<Vec<[f32; 3]>>();
137
138        let normals = raw_points
139            .iter()
140            .copied()
141            .map(Into::into)
142            .collect::<Vec<[f32; 3]>>();
143
144        let uvs = generated.raw_data().to_owned();
145
146        let mut indices = Vec::with_capacity(generated.indices_per_main_triangle() * 20);
147
148        for i in 0..20 {
149            generated.get_indices(i, &mut indices);
150        }
151
152        let indices = Indices::U32(indices);
153
154        Ok(Mesh::new(
155            PrimitiveTopology::TriangleList,
156            RenderAssetUsages::default(),
157        )
158        .with_inserted_indices(indices)
159        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, points)
160        .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
161        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs))
162    }
163
164    /// Creates a UV sphere [`Mesh`] with the given number of
165    /// longitudinal sectors and latitudinal stacks, aka horizontal and vertical resolution.
166    ///
167    /// A good default is `32` sectors and `18` stacks.
168    #[expect(
169        clippy::explicit_counter_loop,
170        reason = "Clippy suggestion was much less clear."
171    )]
172    pub fn uv(&self, sectors: u32, stacks: u32) -> Mesh {
173        // Largely inspired from http://www.songho.ca/opengl/gl_sphere.html
174
175        let sectors_f32 = sectors as f32;
176        let stacks_f32 = stacks as f32;
177        let length_inv = 1. / self.sphere.radius;
178        let sector_step = 2. * PI / sectors_f32;
179        let stack_step = PI / stacks_f32;
180
181        let n_vertices = (stacks * sectors) as usize;
182        let mut vertices: Vec<[f32; 3]> = Vec::with_capacity(n_vertices);
183        let mut normals: Vec<[f32; 3]> = Vec::with_capacity(n_vertices);
184        let mut uvs: Vec<[f32; 2]> = Vec::with_capacity(n_vertices);
185        let mut indices: Vec<u32> = Vec::with_capacity(n_vertices * 2 * 3);
186
187        for i in 0..stacks + 1 {
188            let stack_angle = PI / 2. - (i as f32) * stack_step;
189            let xy = self.sphere.radius * ops::cos(stack_angle);
190            let z = self.sphere.radius * ops::sin(stack_angle);
191
192            for j in 0..sectors + 1 {
193                let sector_angle = (j as f32) * sector_step;
194                let x = xy * ops::cos(sector_angle);
195                let y = xy * ops::sin(sector_angle);
196
197                vertices.push([x, y, z]);
198                normals.push([x * length_inv, y * length_inv, z * length_inv]);
199                uvs.push([(j as f32) / sectors_f32, (i as f32) / stacks_f32]);
200            }
201        }
202
203        // indices
204        //  k1--k1+1
205        //  |  / |
206        //  | /  |
207        //  k2--k2+1
208        for i in 0..stacks {
209            let mut k1 = i * (sectors + 1);
210            let mut k2 = k1 + sectors + 1;
211            for _j in 0..sectors {
212                if i != 0 {
213                    indices.push(k1);
214                    indices.push(k2);
215                    indices.push(k1 + 1);
216                }
217                if i != stacks - 1 {
218                    indices.push(k1 + 1);
219                    indices.push(k2);
220                    indices.push(k2 + 1);
221                }
222                k1 += 1;
223                k2 += 1;
224            }
225        }
226
227        Mesh::new(
228            PrimitiveTopology::TriangleList,
229            RenderAssetUsages::default(),
230        )
231        .with_inserted_indices(Indices::U32(indices))
232        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
233        .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
234        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
235    }
236}
237
238impl MeshBuilder for SphereMeshBuilder {
239    /// Builds a [`Mesh`] according to the configuration in `self`.
240    ///
241    /// # Panics
242    ///
243    /// Panics if the sphere is a [`SphereKind::Ico`] with a subdivision count
244    /// that is greater than or equal to `80` because there will be too many vertices.
245    fn build(&self) -> Mesh {
246        match self.kind {
247            SphereKind::Ico { subdivisions } => self.ico(subdivisions).unwrap(),
248            SphereKind::Uv { sectors, stacks } => self.uv(sectors, stacks),
249        }
250    }
251}
252
253impl Meshable for Sphere {
254    type Output = SphereMeshBuilder;
255
256    fn mesh(&self) -> Self::Output {
257        SphereMeshBuilder {
258            sphere: *self,
259            ..Default::default()
260        }
261    }
262}
263
264impl From<Sphere> for Mesh {
265    fn from(sphere: Sphere) -> Self {
266        sphere.mesh().build()
267    }
268}