---
# System prepended metadata

title: 3D Mesh Bundles
tags: [Required-Components]

---

# Bundles

## `MaterialMeshBundle`

```rust
pub struct MaterialMeshBundle<M: Material> {
    pub mesh: Handle<Mesh>,
    pub material: Handle<M>,
    pub transform: Transform,
    pub global_transform: GlobalTransform,
    /// User indication of whether an entity is visible
    pub visibility: Visibility,
    /// Inherited visibility of an entity.
    pub inherited_visibility: InheritedVisibility,
    /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
    pub view_visibility: ViewVisibility,
}
```

## `MaterialMesh2dBundle`

```rust
pub struct MaterialMesh2dBundle<M: Material2d> {
    pub mesh: Mesh2dHandle,
    pub material: Handle<M>,
    pub transform: Transform,
    pub global_transform: GlobalTransform,
    /// User indication of whether an entity is visible
    pub visibility: Visibility,
    // Inherited visibility of an entity.
    pub inherited_visibility: InheritedVisibility,
    // Indication of whether an entity is visible in any view.
    pub view_visibility: ViewVisibility,
}
```

## Combined Proposal 1

```rust
#[derive(Component)]
#[require(Transform, Visibility)]
pub struct Mesh3d<M: Material> { 
    pub mesh: Handle<Mesh>
    pub material: Handle<M>
}

#[derive(Component)]
#[require(Transform, Visibility)]
pub struct Mesh2d<M: Material> {
    pub mesh: Handle<Mesh>
    pub material: Handle<M>
}
```

The generic makes it hard to depend on materials, and materials can't require mesh because the default value is unclear.

As a side note, this would be simpler if we removed the `Material` trait to a component, which is something we may want to do anyway for asset-loading reasons.

Name of these components can be bikeshed: `Mesh`, `MaterialMesh`, `Surface` ect.

## Combined Proposal 2

```rust
#[derive(Component)]
#[require(Transform, Visibility)]
pub struct Mesh3d(Handle<Mesh>);

#[derive(Component)]
#[require(Transform, Visibility)]
pub struct Mesh2d(Handle<Mesh>);

#[derive(Component)]
#[require(Transform, Visibility)]
pub struct MeshMaterial<M: Material>(Handle<M>);
```

This keeps meshes and materials seperate, but you have to remember to insert both of them. Would it be a terrible idea to leave around the MeshMaterial bundles?

> but you have to remember to insert both of them

cart: In a way this is already true in the context of required components. I think we should answer the question "how should a Mesh without a Material behave"? If the answer is "use some default / placeholder material", then we can use Proposal 3. If the answer is "don't render", then we can use Proposal 2.


## Combined Proposal 3 (Selected)

```rust
#[derive(Component)]
#[require(Transform, Visibility)]
pub struct Mesh3d(Handle<Mesh>);

#[derive(Component)]
#[require(Transform, Visibility)]
pub struct Mesh2d(Handle<Mesh>);

#[derive(Component)]
#[require(HasMaterial3d, Transform, Visibility)]
pub struct MeshMaterial3d<M: Material>(Handle<M>);

#[derive(Component)]
#[require(HasMaterial2d, Transform, Visibility)]
pub struct MeshMaterial2d<M: Material2d>(Handle<M>);

#[derive(Component)]
pub struct HasMaterial3d;

#[derive(Component)]
pub struct HasMaterial2d;
```

To make the material optional, we could have all generic material components require a `HasMaterial` marker. We could then have a fallback system that renders meshes without `HasMaterial` with a placeholder / default material.