Skip to content

Commit cf15e6b

Browse files
Implement Meshable for some 3D primitives (#11688)
# Objective Split up from #11007, fixing most of the remaining work for #10569. Implement `Meshable` for `Cuboid`, `Sphere`, `Cylinder`, `Capsule`, `Torus`, and `Plane3d`. This covers all shapes that Bevy has mesh structs for in `bevy_render::mesh::shapes`. `Cone` and `ConicalFrustum` are new shapes, so I can add them in a follow-up, or I could just add them here directly if that's preferrable. ## Solution Implement `Meshable` for `Cuboid`, `Sphere`, `Cylinder`, `Capsule`, `Torus`, and `Plane3d`. The logic is mostly just a copy of the the existing `bevy_render` shapes, but `Plane3d` has a configurable surface normal that affects the orientation. Some property names have also been changed to be more consistent. The default values differ from the old shapes to make them a bit more logical: - Spheres now have a radius of 0.5 instead of 1.0. The default capsule is equivalent to the default cylinder with the sphere's halves glued on. - The inner and outer radius of the torus are now 0.5 and 1.0 instead of 0.5 and 1.5 (i.e. the new minor and major radii are 0.25 and 0.75). It's double the width of the default cuboid, half of its height, and the default sphere matches the size of the hole. - `Cuboid` is 1x1x1 by default unlike the dreaded `Box` which is 2x1x1. Before, with "old" shapes: ![old](https://github.com/bevyengine/bevy/assets/57632562/733f3dda-258c-4491-8152-9829e056a1a3) Now, with primitive meshing: ![new](https://github.com/bevyengine/bevy/assets/57632562/5a1af14f-bb98-401d-82cf-de8072fea4ec) I only changed the `3d_shapes` example to use primitives for now. I can change them all in this PR or a follow-up though, whichever way is preferrable. ### Sphere API Spheres have had separate `Icosphere` and `UVSphere` structs, but with primitives we only have one `Sphere`. We need to handle this with builders: ```rust // Existing structs let ico = Mesh::try_from(Icophere::default()).unwrap(); let uv = Mesh::from(UVSphere::default()); // Primitives let ico = Sphere::default().mesh().ico(5).unwrap(); let uv = Sphere::default().mesh().uv(32, 18); ``` We could add methods on `Sphere` directly to skip calling `.mesh()`. I also added a `SphereKind` enum that can be used with the `kind` method: ```rust let ico = Sphere::default() .mesh() .kind(SphereKind::Ico { subdivisions: 8 }) .build(); ``` The default mesh for a `Sphere` is an icosphere with 5 subdivisions (like the default `Icosphere`). --- ## Changelog - Implement `Meshable` and `Default` for `Cuboid`, `Sphere`, `Cylinder`, `Capsule`, `Torus`, and `Plane3d` - Use primitives in `3d_shapes` example --------- Co-authored-by: Alice Cecile <[email protected]>
1 parent 9f2eabb commit cf15e6b

File tree

10 files changed

+1330
-9
lines changed

10 files changed

+1330
-9
lines changed

crates/bevy_math/src/primitives/dim3.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,13 @@ pub struct Sphere {
155155
}
156156
impl Primitive3d for Sphere {}
157157

158+
impl Default for Sphere {
159+
/// Returns the default [`Sphere`] with a radius of `0.5`.
160+
fn default() -> Self {
161+
Self { radius: 0.5 }
162+
}
163+
}
164+
158165
impl Sphere {
159166
/// Create a new [`Sphere`] from a `radius`
160167
#[inline(always)]
@@ -210,6 +217,15 @@ pub struct Plane3d {
210217
}
211218
impl Primitive3d for Plane3d {}
212219

220+
impl Default for Plane3d {
221+
/// Returns the default [`Plane3d`] with a normal pointing in the `+Y` direction.
222+
fn default() -> Self {
223+
Self {
224+
normal: Direction3d::Y,
225+
}
226+
}
227+
}
228+
213229
impl Plane3d {
214230
/// Create a new `Plane3d` from a normal
215231
///
@@ -374,6 +390,15 @@ pub struct Cuboid {
374390
}
375391
impl Primitive3d for Cuboid {}
376392

393+
impl Default for Cuboid {
394+
/// Returns the default [`Cuboid`] with a width, height, and depth of `1.0`.
395+
fn default() -> Self {
396+
Self {
397+
half_size: Vec3::splat(0.5),
398+
}
399+
}
400+
}
401+
377402
impl Cuboid {
378403
/// Create a new `Cuboid` from a full x, y, and z length
379404
#[inline(always)]
@@ -439,6 +464,16 @@ pub struct Cylinder {
439464
}
440465
impl Primitive3d for Cylinder {}
441466

467+
impl Default for Cylinder {
468+
/// Returns the default [`Cylinder`] with a radius of `0.5` and a height of `1.0`.
469+
fn default() -> Self {
470+
Self {
471+
radius: 0.5,
472+
half_height: 0.5,
473+
}
474+
}
475+
}
476+
442477
impl Cylinder {
443478
/// Create a new `Cylinder` from a radius and full height
444479
#[inline(always)]
@@ -496,6 +531,17 @@ pub struct Capsule3d {
496531
}
497532
impl Primitive3d for Capsule3d {}
498533

534+
impl Default for Capsule3d {
535+
/// Returns the default [`Capsule3d`] with a radius of `0.5` and a segment length of `1.0`.
536+
/// The total height is `2.0`.
537+
fn default() -> Self {
538+
Self {
539+
radius: 0.5,
540+
half_length: 0.5,
541+
}
542+
}
543+
}
544+
499545
impl Capsule3d {
500546
/// Create a new `Capsule3d` from a radius and length
501547
pub fn new(radius: f32, length: f32) -> Self {
@@ -636,6 +682,16 @@ pub struct Torus {
636682
}
637683
impl Primitive3d for Torus {}
638684

685+
impl Default for Torus {
686+
/// Returns the default [`Torus`] with a minor radius of `0.25` and a major radius of `0.75`.
687+
fn default() -> Self {
688+
Self {
689+
minor_radius: 0.25,
690+
major_radius: 0.75,
691+
}
692+
}
693+
}
694+
639695
impl Torus {
640696
/// Create a new `Torus` from an inner and outer radius.
641697
///

0 commit comments

Comments
 (0)