bevy/examples/2d/2d_shapes.rs
Joona Aalto 2bf481c03b
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 <alice.i.cecile@gmail.com>
2024-01-29 16:47:47 +00:00

65 lines
1.9 KiB
Rust

//! Shows how to render simple primitive shapes with a single color.
use bevy::{prelude::*, sprite::MaterialMesh2dBundle};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
commands.spawn(Camera2dBundle::default());
// Circle
commands.spawn(MaterialMesh2dBundle {
mesh: meshes.add(Circle { radius: 50.0 }).into(),
material: materials.add(Color::VIOLET),
transform: Transform::from_translation(Vec3::new(-225.0, 0.0, 0.0)),
..default()
});
// Ellipse
commands.spawn(MaterialMesh2dBundle {
mesh: meshes.add(Ellipse::new(25.0, 50.0)).into(),
material: materials.add(Color::TURQUOISE),
transform: Transform::from_translation(Vec3::new(-100.0, 0.0, 0.0)),
..default()
});
// Rectangle
commands.spawn(MaterialMesh2dBundle {
mesh: meshes.add(Rectangle::new(50.0, 100.0)).into(),
material: materials.add(Color::LIME_GREEN),
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
..default()
});
// Hexagon
commands.spawn(MaterialMesh2dBundle {
mesh: meshes.add(RegularPolygon::new(50.0, 6)).into(),
material: materials.add(Color::YELLOW),
transform: Transform::from_translation(Vec3::new(125.0, 0.0, 0.0)),
..default()
});
// Triangle
commands.spawn(MaterialMesh2dBundle {
mesh: meshes
.add(Triangle2d::new(
Vec2::Y * 50.0,
Vec2::new(-50.0, -50.0),
Vec2::new(50.0, -50.0),
))
.into(),
material: materials.add(Color::ORANGE),
transform: Transform::from_translation(Vec3::new(250.0, 0.0, 0.0)),
..default()
});
}