Skip to content

Commit 2bf481c

Browse files
Add Meshable trait and implement meshing for 2D primitives (#11431)
# Objective The first part of #10569, split up from #11007. The goal is to implement meshing support for Bevy's new geometric primitives, starting with 2D primitives. 3D meshing will be added in a follow-up, and we can consider removing the old mesh shapes completely. ## Solution Add a `Meshable` trait that primitives need to implement to support meshing, as suggested by the [RFC](https://github.com/bevyengine/rfcs/blob/main/rfcs/12-primitive-shapes.md#meshing). ```rust /// A trait for shapes that can be turned into a [`Mesh`]. pub trait Meshable { /// The output of [`Self::mesh`]. This can either be a [`Mesh`] /// or a builder used for creating a [`Mesh`]. type Output; /// Creates a [`Mesh`] for a shape. fn mesh(&self) -> Self::Output; } ``` This PR implements it for the following primitives: - `Circle` - `Ellipse` - `Rectangle` - `RegularPolygon` - `Triangle2d` The `mesh` method typically returns a builder-like struct such as `CircleMeshBuilder`. This is needed to support shape-specific configuration for things like mesh resolution or UV configuration: ```rust meshes.add(Circle { radius: 0.5 }.mesh().resolution(64)); ``` Note that if no configuration is needed, you can even skip calling `mesh` because `From<MyPrimitive>` is implemented for `Mesh`: ```rust meshes.add(Circle { radius: 0.5 }); ``` I also updated the `2d_shapes` example to use primitives, and tweaked the colors to have better contrast against the dark background. Before: ![Old 2D shapes](https://github.com/bevyengine/bevy/assets/57632562/f1d8c2d5-55be-495f-8ed4-5890154b81ca) After: ![New 2D shapes](https://github.com/bevyengine/bevy/assets/57632562/f166c013-34b8-4752-800a-5517b284d978) Here you can see the UVs and different facing directions: (taken from #11007, so excuse the 3D primitives at the bottom left) ![UVs and facing directions](https://github.com/bevyengine/bevy/assets/57632562/eaf0be4e-187d-4b6d-8fb8-c996ba295a8a) --- ## Changelog - Added `bevy_render::mesh::primitives` module - Added `Meshable` trait and implemented it for: - `Circle` - `Ellipse` - `Rectangle` - `RegularPolygon` - `Triangle2d` - Implemented `Default` and `Copy` for several 2D primitives - Updated `2d_shapes` example to use primitives - Tweaked colors in `2d_shapes` example to have better contrast against the (new-ish) dark background --------- Co-authored-by: Alice Cecile <[email protected]>
1 parent 149a313 commit 2bf481c

File tree

8 files changed

+391
-22
lines changed

8 files changed

+391
-22
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ doc-scrape-examples = true
402402

403403
[package.metadata.example.2d_shapes]
404404
name = "2D Shapes"
405-
description = "Renders a rectangle, circle, and hexagon"
405+
description = "Renders simple 2D primitive shapes like circles and polygons"
406406
category = "2D Rendering"
407407
wasm = true
408408

crates/bevy_math/src/primitives/dim2.rs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ pub struct Circle {
9090
}
9191
impl Primitive2d for Circle {}
9292

93+
impl Default for Circle {
94+
/// Returns the default [`Circle`] with a radius of `0.5`.
95+
fn default() -> Self {
96+
Self { radius: 0.5 }
97+
}
98+
}
99+
93100
impl Circle {
94101
/// Create a new [`Circle`] from a `radius`
95102
#[inline(always)]
@@ -147,6 +154,15 @@ pub struct Ellipse {
147154
}
148155
impl Primitive2d for Ellipse {}
149156

157+
impl Default for Ellipse {
158+
/// Returns the default [`Ellipse`] with a half-width of `1.0` and a half-height of `0.5`.
159+
fn default() -> Self {
160+
Self {
161+
half_size: Vec2::new(1.0, 0.5),
162+
}
163+
}
164+
}
165+
150166
impl Ellipse {
151167
/// Create a new `Ellipse` from half of its width and height.
152168
///
@@ -197,6 +213,15 @@ pub struct Plane2d {
197213
}
198214
impl Primitive2d for Plane2d {}
199215

216+
impl Default for Plane2d {
217+
/// Returns the default [`Plane2d`] with a normal pointing in the `+Y` direction.
218+
fn default() -> Self {
219+
Self {
220+
normal: Direction2d::Y,
221+
}
222+
}
223+
}
224+
200225
impl Plane2d {
201226
/// Create a new `Plane2d` from a normal
202227
///
@@ -343,10 +368,19 @@ pub struct Triangle2d {
343368
}
344369
impl Primitive2d for Triangle2d {}
345370

371+
impl Default for Triangle2d {
372+
/// Returns the default [`Triangle2d`] with the vertices `[0.0, 0.5]`, `[-0.5, -0.5]`, and `[0.5, -0.5]`.
373+
fn default() -> Self {
374+
Self {
375+
vertices: [Vec2::Y * 0.5, Vec2::new(-0.5, -0.5), Vec2::new(0.5, -0.5)],
376+
}
377+
}
378+
}
379+
346380
impl Triangle2d {
347381
/// Create a new `Triangle2d` from points `a`, `b`, and `c`
348382
#[inline(always)]
349-
pub fn new(a: Vec2, b: Vec2, c: Vec2) -> Self {
383+
pub const fn new(a: Vec2, b: Vec2, c: Vec2) -> Self {
350384
Self {
351385
vertices: [a, b, c],
352386
}
@@ -438,6 +472,15 @@ pub struct Rectangle {
438472
pub half_size: Vec2,
439473
}
440474

475+
impl Default for Rectangle {
476+
/// Returns the default [`Rectangle`] with a half-width and half-height of `0.5`.
477+
fn default() -> Self {
478+
Self {
479+
half_size: Vec2::splat(0.5),
480+
}
481+
}
482+
}
483+
441484
impl Rectangle {
442485
/// Create a new `Rectangle` from a full width and height
443486
#[inline(always)]
@@ -559,9 +602,19 @@ pub struct RegularPolygon {
559602
}
560603
impl Primitive2d for RegularPolygon {}
561604

605+
impl Default for RegularPolygon {
606+
/// Returns the default [`RegularPolygon`] with six sides (a hexagon) and a circumradius of `0.5`.
607+
fn default() -> Self {
608+
Self {
609+
circumcircle: Circle { radius: 0.5 },
610+
sides: 6,
611+
}
612+
}
613+
}
614+
562615
impl RegularPolygon {
563616
/// Create a new `RegularPolygon`
564-
/// from the radius of the circumcircle and number of sides
617+
/// from the radius of the circumcircle and a number of sides
565618
///
566619
/// # Panics
567620
///

crates/bevy_render/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub mod prelude {
3434
Projection,
3535
},
3636
color::Color,
37-
mesh::{morph::MorphWeights, shape, Mesh},
37+
mesh::{morph::MorphWeights, primitives::Meshable, shape, Mesh},
3838
render_resource::Shader,
3939
spatial_bundle::SpatialBundle,
4040
texture::{Image, ImagePlugin},

crates/bevy_render/src/mesh/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
#[allow(clippy::module_inception)]
22
mod mesh;
33
pub mod morph;
4+
pub mod primitives;
45
/// Generation for some primitive shape meshes.
56
pub mod shape;
67

78
pub use mesh::*;
9+
pub use primitives::*;
810

911
use crate::{prelude::Image, render_asset::RenderAssetPlugin};
1012
use bevy_app::{App, Plugin};

0 commit comments

Comments
 (0)