Commit Graph

200 Commits

Author SHA1 Message Date
Lynn
1196186257
Add segments to ExtrusionBuilder (#13719)
# Objective

- Add support for `segments` for extrusion-meshes, akin to what is
possible with cylinders

## Solution

- Added a `.segments(segments: usize)` function to `ExtrusionBuilder`.
- Implemented support for segments in the meshing algorithm.
- If you set `.segments(0)`, the meshing will fail, just like it does
with cylinders.

## Additional information

Here is a wireframe of some extrusions with 1, 2, 3, etc. segments:

![image_2024-06-06_233205114](https://github.com/bevyengine/bevy/assets/62256001/358081e2-172d-407b-8bdb-9cda88eb4664)

---------

Co-authored-by: Lynn Büttgenbach <62256001+solis-lumine-vorago@users.noreply.github.com>
2024-06-10 12:50:29 +00:00
Mincong Lu
31be32ff10
Made Mesh::merge take a reference of Mesh. (#13710)
# Objective

`Mesh::merge` does not need ownership of the right hand side mesh.

## Solution

Made `Mesh::merge` take a reference.

## Testing

Modified existing tests.

---

## Changelog

Made `Mesh::merge` take a reference.


## Migration Guide

* `Mesh::merge` now take a reference of a mesh instead of an owned mesh.
2024-06-06 11:57:10 +00:00
Lynn
8e4e840a19
Meshable extrusions - Part 2 (#13676)
# Objective

- Implement `Extrudable` for all meshbuilders of shapes that have been
added after #13478 was created

## Solution

- Implemented meshing for extrusions of `CircularSector`,
`CircularSegment` and `Rhombus`

## Testing

- The correctness of these was confirmed visually.

## Additional information

Here is an image of what they look like :)

![Screenshot 2024-06-04
230633](https://github.com/bevyengine/bevy/assets/62256001/d9cca0ba-30ea-4c48-8ae2-007b469739d7)

Co-authored-by: Lynn Büttgenbach <62256001+solis-lumine-vorago@users.noreply.github.com>
2024-06-04 21:53:06 +00:00
Lynn
fd82ef8956
Meshable extrusions (#13478)
# Objective

- Implement `Meshable` for `Extrusion<T>`

## Solution

- `Meshable` requires `Meshable::Output: MeshBuilder` now. This means
that all `some_primitive.mesh()` calls now return a `MeshBuilder`. These
were added for primitives that did not have one prior to this.
- A new trait `Extrudable: MeshBuilder` has been added. This trait
allows you to specify the indices of the perimeter of the mesh created
by this `MeshBuilder` and whether they are to be shaded smooth or flat.
- `Extrusion<P: Primitive2d + Meshable>` is now `Meshable` aswell. The
associated `MeshBuilder` is `ExtrusionMeshBuilder` which is generic over
`P` and uses the `MeshBuilder` of its baseshape internally.
- `ExtrusionMeshBuilder` exposes the configuration functions of its
base-shapes builder.
- Updated the `3d_shapes` example to include `Extrusion`s

## Migration Guide

- Depending on the context, you may need to explicitly call
`.mesh().build()` on primitives where you have previously called
`.mesh()`
- The `Output` type of custom `Meshable` implementations must now derive
`MeshBuilder`.

## Additional information
- The extrusions UVs are done so that 
- the front face (`+Z`) is in the area between `(0, 0)` and `(0.5,
0.5)`,
- the back face (`-Z`) is in the area between `(0.5, 0)` and `(1, 0.5)`
- the mantle is in the area between `(0, 0.5)` and `(1, 1)`. Each
`PerimeterSegment` you specified in the `Extrudable` implementation will
be allocated an equal portion of this area.
- The UVs of the base shape are scaled to be in the front/back area so
whatever method of filling the full UV-space the base shape used is how
these areas will be filled.

Here is an example of what that looks like on a capsule:


https://github.com/bevyengine/bevy/assets/62256001/425ad288-fbbc-4634-9d3f-5e846cdce85f

This is the texture used:

![extrusion
uvs](https://github.com/bevyengine/bevy/assets/62256001/4e54e421-bfda-44b9-8571-412525cebddf)

The `3d_shapes` example now looks like this:


![image_2024-05-22_235915753](https://github.com/bevyengine/bevy/assets/62256001/3d8bc86d-9ed1-47f2-899a-27aac0a265dd)

---------

Co-authored-by: Lynn Büttgenbach <62256001+solis-lumine-vorago@users.noreply.github.com>
Co-authored-by: Matty <weatherleymatthew@gmail.com>
Co-authored-by: Matty <2975848+mweatherley@users.noreply.github.com>
2024-06-04 17:27:32 +00:00
Kxie
1b6bc2c240
document need to update Aabb in Mesh::(with_)insert_attribute (#13349)
# Objective

solves #12475 for functions `Mesh::insert_attribute` and
`Mesh::with_inserted_attribute`.

## Solution

added references to Aabb and suggest solutions in doc strings

## Testing

ran cargo docs, links work.

---------

Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
2024-06-03 23:46:31 +00:00
IceSentry
bb51635481
Add subdivisions to PlaneMeshBuilder (#13580)
# Objective

- Plane subdivision was removed without providing an alternative

## Solution

- Add subdivision to the PlaneMeshBuilder

---

## Migration Guide

If you were using `Plane` `subdivisions`, you now need to use
`Plane3d::default().mesh().subdivisions(10)`

fixes https://github.com/bevyengine/bevy/issues/13258
2024-06-03 13:57:07 +00:00
Félix Lescaudey de Maneville
190d032ae4
Additional options to mesh primitives (#13605)
# Objective

Add new options to some primitives, like anchoring for Cones and
cylinders and custom angle ranges for Torus.
I think these kind of options are useful, but I would understand that
these addition feel overkill

## Solution

Add 

## Testing

- Did you test these changes? If so, how?

> I used the new options in the `3d_shapes` example with various
parameters and got the expected results

## Changelog

- Added `caps` bool option to toggle cylinder circle caps
- Added `angle_range` f32 range option non full torus shapes
- Added `anchor` enum option for cylinders, with either `Top`,
`Midpoint` or `Bottom`
- Added `anchor` enum option for cones, with either `Tip`, `Midpoint` or
`Base`
- **BREAKING** `TorusMeshBuilder` is no longer `Copy` due to
`RangeInclusive`, we can use a `(f32, f32)` if we want it to be `Copy`
2024-06-03 13:27:11 +00:00
Salvador Carvalhinho
7d843e0c08
Implement Rhombus 2D primitive. (#13501)
# Objective

- Create a new 2D primitive, Rhombus, also knows as "Diamond Shape"
- Simplify the creation and handling of isometric projections
- Extend Bevy's arsenal of 2D primitives

## Testing

- New unit tests created in bevy_math/ primitives and bev_math/ bounding
- Tested translations, rotations, wireframe, bounding sphere, aabb and
creation parameters

---------

Co-authored-by: Luís Figueiredo <luispcfigueiredo@tecnico.ulisboa.pt>
2024-05-26 15:27:57 +00:00
Joona Aalto
383314ef62
Add meshing for ConicalFrustum (#11819)
# Objective

The `ConicalFrustum` primitive should support meshing.

## Solution

Implement meshing for the `ConicalFrustum` primitive. The implementation
is nearly identical to `Cylinder` meshing, but supports two radii.

The default conical frustum is equivalent to a cone with a height of 1
and a radius of 0.5, truncated at half-height.


![kuva](https://github.com/bevyengine/bevy/assets/57632562/b4cab136-ff55-4056-b818-1218e4f38845)
2024-05-25 21:56:09 +00:00
Ben Harper
ec01c2dc45
New circular primitives: Arc2d, CircularSector, CircularSegment (#13482)
# Objective

Adopted #11748

## Solution

I've rebased on main to fix the merge conflicts. ~~Not quite ready to
merge yet~~

* Clippy is happy and the tests are passing, but...
* ~~The new shapes in `examples/2d/2d_shapes.rs` don't look right at
all~~ Never mind, looks like radians and degrees just got mixed up at
some point?
* I have updated one doc comment based on a review in the original PR.

---------

Co-authored-by: Alexis "spectria" Horizon <spectria.limina@gmail.com>
Co-authored-by: Alexis "spectria" Horizon <118812919+spectria-limina@users.noreply.github.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Ben Harper <ben@tukom.org>
2024-05-23 16:12:46 +00:00
Matty
c7f7d906ca
Tetrahedron mesh (#13463)
# Objective

Allow the `Tetrahedron` primitive to be used for mesh generation. This
is part of ongoing work to bring unify the capabilities of `bevy_math`
primitives.

## Solution

`Tetrahedron` implements `Meshable`. Essentially, each face is just
meshed as a `Triangle3d`, but first there is an inversion step when the
signed volume of the tetrahedron is negative to ensure that the faces
all actually point outward.

## Testing

I loaded up some examples and hackily exchanged existing meshes with the
new one to see that it works as expected.
2024-05-22 12:22:11 +00:00
Lynn
2857eb6b9d
Fix normals during mesh scaling (#13380)
# Objective

- Fixes scaling normals and tangents of meshes

## Solution

- When scaling a mesh by `Vec3::new(1., 1., -1.)`, the normals should be
flipped along the Z-axis. For example a normal of `Vec3::new(0., 0.,
1.)` should become `Vec3::new(0., 0., -1.)` after scaling. This is
achieved by multiplying the normal by the reciprocal of the scale,
cheking for infinity and normalizing. Before, the normal was multiplied
by a covector of the scale, which is incorrect for normals.
- Tangents need to be multiplied by the `scale`, not its reciprocal as
before

---------

Co-authored-by: vero <11307157+atlv24@users.noreply.github.com>
2024-05-21 18:28:03 +00:00
Lynn
450a9202d0
Common MeshBuilder trait (#13411)
# Objective

- All `ShapeMeshBuilder`s have some methods/implementations in common.
These are `fn build(&self) -> Mesh` and this implementation:
```rust
impl From<ShapeMeshBuilder> for Mesh { 
    fn from(builder: ShapeMeshBuilder) -> { 
        builder.build() 
    } 
}
``` 

- For the sake of consistency, these can be moved into a shared trait

## Solution

- Add `trait MeshBuilder` containing a `fn build(&self) -> Mesh` and
implementing `MeshBuilder for ShapeMeshBuilder`
- Implement `From<T: MeshBuilder> for Mesh`

## Migration Guide

- When calling `.build()` you need to import
`bevy_render::mesh::primitives::MeshBuilder`
2024-05-18 11:58:11 +00:00
Adith Ramachandran
65e62ba5eb
Revert "Support calculating normals for indexed meshes" (#12716) and add support for calculating smooth normals (#13333)
# Objective

- Refactor the changes merged in #11654 to compute flat normals for
indexed meshes instead of smooth normals.
- Fixes #12716 

## Solution

- Partially revert the changes in #11654 to compute flat normals for
both indexed and unindexed meshes in `compute_flat_normals`
- Create a new method, `compute_smooth_normals`, that computes smooth
normals for indexed meshes
- Create a new method, `compute_normals`, that computes smooth normals
for indexed meshes and flat normals for unindexed meshes by default. Use
this new method instead of `compute_flat_normals`.

## Testing

- Run the example with and without the changes to ensure that the
results are identical.
2024-05-16 14:54:35 +00:00
Joona Aalto
ac1f135e20
Add meshing for Cone (#11820)
# Objective

The `Cone` primitive should support meshing.

## Solution

Implement meshing for the `Cone` primitive. The default cone has a
height of 1 and a base radius of 0.5, and is centered at the origin.

An issue with cone meshes is that the tip does not really have a normal
that works, even with duplicated vertices. This PR uses only a single
vertex for the tip, with a normal of zero; this results in an "invalid"
normal that gets ignored by the fragment shader. This seems to be the
only approach we have for perfectly smooth cones. For discussion on the
topic, see #10298 and #5891.

Another thing to note is that the cone uses polar coordinates for the
UVs:

<img
src="https://github.com/bevyengine/bevy/assets/57632562/e101ded9-110a-4ac4-a98d-f1e4d740a24a"
alt="cone" width="400" />

This way, textures are applied as if looking at the cone from above:

<img
src="https://github.com/bevyengine/bevy/assets/57632562/8dea00f1-a283-4bc4-9676-91e8d4adb07a"
alt="texture" width="200" />

<img
src="https://github.com/bevyengine/bevy/assets/57632562/d9d1b5e6-a8ba-4690-b599-904dd85777a1"
alt="cone" width="200" />
2024-05-13 18:00:59 +00:00
robtfm
91a393a9e2
Throttle render assets (#12622)
# Objective

allow throttling of gpu uploads to prevent choppy framerate when many
textures/meshes are loaded in.

## Solution

- `RenderAsset`s can implement `byte_len()` which reports their size.
implemented this for `Mesh` and `Image`
- users can add a `RenderAssetBytesPerFrame` which specifies max bytes
to attempt to upload in a frame
- `render_assets::<A>` checks how many bytes have been written before
attempting to upload assets. the limit is a soft cap: assets will be
written until the total has exceeded the cap, to ensure some forward
progress every frame

notes:
- this is a stopgap until we have multiple wgpu queues for proper
streaming of data
- requires #12606

issues
- ~~fonts sometimes only partially upload. i have no clue why, needs to
be fixed~~ fixed now.
- choosing the #bytes is tricky as it should be hardware / framerate
dependent
- many features are not tested (env maps, light probes, etc) - they
won't break unless `RenderAssetBytesPerFrame` is explicitly used though

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-04-26 23:43:33 +00:00
François Mockers
c40b485095
use a u64 for MeshPipelineKey (#13015)
# Objective

- `MeshPipelineKey` use some bits for two things
- First commit in this PR adds an assertion that doesn't work currently
on main
- This leads to some mesh topology not working anymore, for example
`LineStrip`
- With examples `lines`, there should be two groups of lines, the blue
one doesn't display currently

## Solution

- Change the `MeshPipelineKey` to be backed by a `u64` instead, to have
enough bits
2024-04-21 20:01:45 +00:00
andristarr
2b3e3341d6
separating finite and infinite 3d planes (#12426)
# Objective

Fixes #12388

## Solution

- Removing the plane3d and adding rect3d primitive mesh
2024-04-18 14:13:22 +00:00
BD103
7b8d502083
Fix beta lints (#12980)
# Objective

- Fixes #12976

## Solution

This one is a doozy.

- Run `cargo +beta clippy --workspace --all-targets --all-features` and
fix all issues
- This includes:
- Moving inner attributes to be outer attributes, when the item in
question has both inner and outer attributes
  - Use `ptr::from_ref` in more scenarios
- Extend the valid idents list used by `clippy:doc_markdown` with more
names
  - Use `Clone::clone_from` when possible
  - Remove redundant `ron` import
  - Add backticks to **so many** identifiers and items
    - I'm sorry whoever has to review this

---

## Changelog

- Added links to more identifiers in documentation.
2024-04-16 02:46:46 +00:00
BD103
5c3ae32ab1
Enable clippy::ref_as_ptr (#12918)
# Objective

-
[`clippy::ref_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#/ref_as_ptr)
prevents you from directly casting references to pointers, requiring you
to use `std::ptr::from_ref` instead. This prevents you from accidentally
converting an immutable reference into a mutable pointer (`&x as *mut
T`).
- Follow up to #11818, now that our [`rust-version` is
1.77](11817f4ba4/Cargo.toml (L14)).

## Solution

- Enable lint and fix all warnings.
2024-04-10 20:16:48 +00:00
Robert Swain
ab7cbfa8fc
Consolidate Render(Ui)Materials(2d) into RenderAssets (#12827)
# Objective

- Replace `RenderMaterials` / `RenderMaterials2d` / `RenderUiMaterials`
with `RenderAssets` to enable implementing changes to one thing,
`RenderAssets`, that applies to all use cases rather than duplicating
changes everywhere for multiple things that should be one thing.
- Adopts #8149 

## Solution

- Make RenderAsset generic over the destination type rather than the
source type as in #8149
- Use `RenderAssets<PreparedMaterial<M>>` etc for render materials

---

## Changelog

- Changed:
- The `RenderAsset` trait is now implemented on the destination type.
Its `SourceAsset` associated type refers to the type of the source
asset.
- `RenderMaterials`, `RenderMaterials2d`, and `RenderUiMaterials` have
been replaced by `RenderAssets<PreparedMaterial<M>>` and similar.

## Migration Guide

- `RenderAsset` is now implemented for the destination type rather that
the source asset type. The source asset type is now the `RenderAsset`
trait's `SourceAsset` associated type.
2024-04-09 13:26:34 +00:00
Matty
956604e4c7
Meshing for Triangle3d primitive (#12686)
# Objective

- Ongoing work for #10572 
- Implement the `Meshable` trait for `Triangle3d`, allowing 3d triangle
primitives to produce meshes.

## Solution

The `Meshable` trait for `Triangle3d` directly produces a `Mesh`, much
like that of `Triangle2d`. The mesh consists only of a single triangle
(the triangle itself), and its vertex data consists of:
- Vertex positions, which are the triangle's vertices themselves (i.e.
the triangle provides its own coordinates in mesh space directly)
- Normals, which are all the normal of the triangle itself
- Indices, which are directly inferred from the vertex order (note that
this is slightly different than `Triangle2d` which, because of its lower
dimension, has an orientation which can be corrected for so that it
always faces "the right way")
- UV coordinates, which are produced as follows:
1. The first coordinate is coincident with the `ab` direction of the
triangle.
2. The second coordinate maps to be perpendicular to the first in mesh
space, so that the UV-mapping is skew-free.
3. The UV-coordinates map to the smallest rectangle possible containing
the triangle, given the preceding constraints.

Here is a visual demonstration; here, the `ab` direction of the triangle
is horizontal, left to right — the point `c` moves, expanding the
bounding rectangle of the triangle when it pushes past `a` or `b`:

<img width="1440" alt="Screenshot 2024-03-23 at 5 36 01 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/bef4d786-7b82-4207-abd4-ac4557d0f8b8">

<img width="1440" alt="Screenshot 2024-03-23 at 5 38 12 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/c0f72b8f-8e70-46fa-a750-2041ba6dfb78">

<img width="1440" alt="Screenshot 2024-03-23 at 5 37 15 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/db287e4f-2b0b-4fd4-8d71-88f4e7a03b7c">

The UV-mapping of `Triangle2d` has also been changed to use the same
logic.

---

## Changelog

- Implemented `Meshable` for `Triangle3d`.
- Changed UV-mapping of `Triangle2d` to match that of `Triangle3d`.

## Migration Guide

The UV-mapping of `Triangle2d` has changed with this PR; the main
difference is that the UVs are no longer dependent on the triangle's
absolute coordinates, but instead follow translations of the triangle
itself in its definition. If you depended on the old UV-coordinates for
`Triangle2d`, then you will have to update affected areas to use the new
ones which, briefly, can be described as follows:
- The first coordinate is parallel to the line between the first two
vertices of the triangle.
- The second coordinate is orthogonal to this, pointing in the direction
of the third point.

Generally speaking, this means that the first two points will have
coordinates `[_, 0.]`, while the third coordinate will be `[_, 1.]`,
with the exact values depending on the position of the third point
relative to the first two. For acute triangles, the first two vertices
always have UV-coordinates `[0., 0.]` and `[1., 0.]` respectively. For
obtuse triangles, the third point will have coordinate `[0., 1.]` or
`[1., 1.]`, with the coordinate of one of the two other points shifting
to maintain proportionality.

For example: 
- The default `Triangle2d` has UV-coordinates `[0., 0.]`, `[0., 1.]`,
[`0.5, 1.]`.
- The triangle with vertices `vec2(0., 0.)`, `vec2(1., 0.)`, `vec2(2.,
1.)` has UV-coordinates `[0., 0.]`, `[0.5, 0.]`, `[1., 1.]`.
- The triangle with vertices `vec2(0., 0.)`, `vec2(1., 0.)`, `vec2(-2.,
1.)` has UV-coordinates `[2./3., 0.]`, `[1., 0.]`, `[0., 1.]`.

## Discussion

### Design considerations

1. There are a number of ways to UV-map a triangle (at least two of
which are fairly natural); for instance, we could instead declare the
second axis to be essentially `bc` so that the vertices are always `[0.,
0.]`, `[0., 1.]`, and `[1., 0.]`. I chose this method instead because it
is skew-free, so that the sampling from textures has only bilinear
scaling. I think this is better for cases where a relatively "uniform"
texture is mapped to the triangle, but it's possible that we might want
to support the other thing in the future. Thankfully, we already have
the capability of easily expanding to do that with Builders if the need
arises. This could also allow us to provide things like barycentric
subdivision.
2. Presently, the mesh-creation code for `Triangle3d` is set up to never
fail, even in the case that the triangle is degenerate. I have mixed
feelings about this, but none of our other primitive meshes fail, so I
decided to take the same approach. Maybe this is something that could be
worth revisiting in the future across the board.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Jakub Marcowski <37378746+Chubercik@users.noreply.github.com>
2024-04-08 23:00:04 +00:00
robtfm
452821dd52
more robust gpu image use (#12606)
# Objective

make morph targets and tonemapping more tolerant of delayed image
loading.

neither of these actually fail currently unless using a bespoke loader
(and even then it would be rare), but i am working on adding throttling
for asset gpu uploads (as a stopgap until we can do proper asset
streaming) and they break with that.

## Solution

when a mesh with morph targets is uploaded to the gpu, the prepare
function uploads the morph target texture if it's available, otherwise
it uploads without morph targets. this is generally fine as long as
morph targets are typically loaded from bytes (in gltf loader), but may
fail for a custom loader if the asset server async-loads the target
texture and the texture is not available yet. the mesh fails to render
and doesn't update when the image is loaded
-> if morph targets are specified but not ready yet, retry mesh upload
next frame

tonemapping `unwrap`s on the lookup table image. this is never a problem
since the image is added via `include_bytes!`, but could be a problem in
future with asset gpu throttling/streaming.
-> if the lookup texture is not yet available, use a fallback
-> in the node, check if the fallback was used before caching the bind
group
2024-04-07 17:18:58 +00:00
Multirious
a27ce270d0
Fix broken link in mesh docs (#12872)
# Objective

Fixes #12813

## Solution

Update the link to
`https://github.com/bevyengine/bevy/tree/main/crates/bevy_render/src/mesh/primitives`
2024-04-05 18:22:52 +00:00
Patrick Walton
37522fd0ae
Micro-optimize queue_material_meshes, primarily to remove bit manipulation. (#12791)
This commit makes the following optimizations:

## `MeshPipelineKey`/`BaseMeshPipelineKey` split

`MeshPipelineKey` has been split into `BaseMeshPipelineKey`, which lives
in `bevy_render` and `MeshPipelineKey`, which lives in `bevy_pbr`.
Conceptually, `BaseMeshPipelineKey` is a superclass of
`MeshPipelineKey`. For `BaseMeshPipelineKey`, the bits start at the
highest (most significant) bit and grow downward toward the lowest bit;
for `MeshPipelineKey`, the bits start at the lowest bit and grow upward
toward the highest bit. This prevents them from colliding.

The goal of this is to avoid having to reassemble bits of the pipeline
key for every mesh every frame. Instead, we can just use a bitwise or
operation to combine the pieces that make up a `MeshPipelineKey`.

## `specialize_slow`

Previously, all of `specialize()` was marked as `#[inline]`. This
bloated `queue_material_meshes` unnecessarily, as a large chunk of it
ended up being a slow path that was rarely hit. This commit refactors
the function to move the slow path to `specialize_slow()`.

Together, these two changes shave about 5% off `queue_material_meshes`:

![Screenshot 2024-03-29
130002](https://github.com/bevyengine/bevy/assets/157897/a7e5a994-a807-4328-b314-9003429dcdd2)

## Migration Guide

- The `primitive_topology` field on `GpuMesh` is now an accessor method:
`GpuMesh::primitive_topology()`.
- For performance reasons, `MeshPipelineKey` has been split into
`BaseMeshPipelineKey`, which lives in `bevy_render`, and
`MeshPipelineKey`, which lives in `bevy_pbr`. These two should be
combined with bitwise-or to produce the final `MeshPipelineKey`.
2024-04-01 21:58:53 +00:00
Matty
c8aa3ac7d1
Meshing for Annulus primitive (#12734)
# Objective

Related to #10572 
Allow the `Annulus` primitive to be meshed.

## Solution

We introduce a `Meshable` structure, `AnnulusMeshBuilder`, which allows
the `Annulus` primitive to be meshed, leaving optional configuration of
the number of angular sudivisions to the user. Here is a picture of the
annulus's UV-mapping:
<img width="1440" alt="Screenshot 2024-03-26 at 10 39 48 AM"
src="https://github.com/bevyengine/bevy/assets/2975848/b170291d-cba7-441b-90ee-2ad6841eaedb">

Other features are essentially identical to the implementations for
`Circle`/`Ellipse`.

---

## Changelog

- Introduced `AnnulusMeshBuilder`
- Implemented `Meshable` for `Annulus` with `Output =
AnnulusMeshBuilder`
- Implemented `From<Annulus>` and `From<AnnulusMeshBuilder>` for `Mesh`
- Added `impl_reflect!` declaration for `Annulus` and `Triangle3d` in
`bevy_reflect`

---

## Discussion

### Design considerations

The only interesting wrinkle here is that the existing UV-mapping of
`Ellipse` (and hence of `Circle` and `RegularPolygon`) is non-radial
(it's skew-free, created by situating the mesh in a bounding rectangle),
so the UV-mapping of `Annulus` doesn't limit to that of `Circle` as its
inner radius tends to zero, for instance. I don't see this as a real
issue for `Annulus`, which should almost certainly have this kind of
UV-mapping, but I think we ought to at least consider allowing mesh
configuration for `Circle`/`Ellipse` that performs radial UV-mapping
instead. (In these cases in particular, it would be especially easy,
since we wouldn't need a different parameter set in the builder.)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-04-01 21:55:49 +00:00
Cameron
01649f13e2
Refactor App and SubApp internals for better separation (#9202)
# Objective

This is a necessary precursor to #9122 (this was split from that PR to
reduce the amount of code to review all at once).

Moving `!Send` resource ownership to `App` will make it unambiguously
`!Send`. `SubApp` must be `Send`, so it can't wrap `App`.

## Solution

Refactor `App` and `SubApp` to not have a recursive relationship. Since
`SubApp` no longer wraps `App`, once `!Send` resources are moved out of
`World` and into `App`, `SubApp` will become unambiguously `Send`.

There could be less code duplication between `App` and `SubApp`, but
that would break `App` method chaining.

## Changelog

- `SubApp` no longer wraps `App`.
- `App` fields are no longer publicly accessible.
- `App` can no longer be converted into a `SubApp`.
- Various methods now return references to a `SubApp` instead of an
`App`.
## Migration Guide

- To construct a sub-app, use `SubApp::new()`. `App` can no longer
convert into `SubApp`.
- If you implemented a trait for `App`, you may want to implement it for
`SubApp` as well.
- If you're accessing `app.world` directly, you now have to use
`app.world()` and `app.world_mut()`.
- `App::sub_app` now returns `&SubApp`.
- `App::sub_app_mut`  now returns `&mut SubApp`.
- `App::get_sub_app` now returns `Option<&SubApp>.`
- `App::get_sub_app_mut` now returns `Option<&mut SubApp>.`
2024-03-31 03:16:10 +00:00
Tygyh
e9343b052f
Support calculating normals for indexed meshes (#11654)
# Objective

- Finish #3987

## Solution

- Rebase and fix typo.

Co-authored-by: Robert Bragg <robert@sixbynine.org>
2024-03-25 19:09:24 +00:00
JMS55
4f20faaa43
Meshlet rendering (initial feature) (#10164)
# Objective
- Implements a more efficient, GPU-driven
(https://github.com/bevyengine/bevy/issues/1342) rendering pipeline
based on meshlets.
- Meshes are split into small clusters of triangles called meshlets,
each of which acts as a mini index buffer into the larger mesh data.
Meshlets can be compressed, streamed, culled, and batched much more
efficiently than monolithic meshes.


![image](https://github.com/bevyengine/bevy/assets/47158642/cb2aaad0-7a9a-4e14-93b0-15d4e895b26a)

![image](https://github.com/bevyengine/bevy/assets/47158642/7534035b-1eb7-4278-9b99-5322e4401715)

# Misc
* Future work: https://github.com/bevyengine/bevy/issues/11518
* Nanite reference:
https://advances.realtimerendering.com/s2021/Karis_Nanite_SIGGRAPH_Advances_2021_final.pdf
Two pass occlusion culling explained very well:
https://medium.com/@mil_kru/two-pass-occlusion-culling-4100edcad501

---------

Co-authored-by: Ricky Taylor <rickytaylor26@gmail.com>
Co-authored-by: vero <email@atlasdostal.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: atlas dostal <rodol@rivalrebels.com>
2024-03-25 19:08:27 +00:00
Pablo Reinhardt
40f82b867b
Reflect default in some types on bevy_render (#12580)
# Objective

- Many types in bevy_render doesn't reflect Default even if it could.

## Solution

- Reflect it.

---

---------

Co-authored-by: Pablo Reinhardt <pabloreinhardt@gmail.com>
2024-03-19 22:50:17 +00:00
Emi
16fb995697
change doc for SphereKind::Ico to reflect that the triangles are equa… (#12482)
# Objective
Fixes #12480 
by removing the explicit mention of equally sized triangles from the doc
for icospheres

Co-authored-by: Emi <emanuel.boehm@gmail.com>
2024-03-15 03:32:52 +00:00
James Liu
512b7463a3
Disentangle bevy_utils/bevy_core's reexported dependencies (#12313)
# Objective
Make bevy_utils less of a compilation bottleneck. Tackle #11478.

## Solution
* Move all of the directly reexported dependencies and move them to
where they're actually used.
* Remove the UUID utilities that have gone unused since `TypePath` took
over for `TypeUuid`.
* There was also a extraneous bytemuck dependency on `bevy_core` that
has not been used for a long time (since `encase` became the primary way
to prepare GPU buffers).
* Remove the `all_tuples` macro reexport from bevy_ecs since it's
accessible from `bevy_utils`.

---

## Changelog
Removed: Many of the reexports from bevy_utils (petgraph, uuid, nonmax,
smallvec, and thiserror).
Removed: bevy_core's reexports of bytemuck.

## Migration Guide
bevy_utils' reexports of petgraph, uuid, nonmax, smallvec, and thiserror
have been removed.

bevy_core' reexports of bytemuck's types has been removed. 

Add them as dependencies in your own crate instead.
2024-03-07 02:30:15 +00:00
James Liu
9e5db9abc7
Clean up type registrations (#12314)
# Objective
Fix #12304. Remove unnecessary type registrations thanks to #4154.

## Solution
Conservatively remove type registrations. Keeping the top level
components, resources, and events, but dropping everything else that is
a type of a member of those types.
2024-03-06 16:05:53 +00:00
James Liu
5619bd09d1
Replace bevy_log's tracing reexport with bevy_utils' (#12254)
# Objective
Fixes #11298. Make the use of bevy_log vs bevy_utils::tracing more
consistent.

## Solution
Replace all uses of bevy_log's logging macros with the reexport from
bevy_utils. Remove bevy_log as a dependency where it's no longer needed
anymore.

Ideally we should just be using tracing directly, but given that all of
these crates are already using bevy_utils, this likely isn't that great
of a loss right now.
2024-03-02 18:38:04 +00:00
Patrick Walton
f9cc91d5a1
Intern mesh vertex buffer layouts so that we don't have to compare them over and over. (#12216)
Although we cached hashes of `MeshVertexBufferLayout`, we were paying
the cost of `PartialEq` on `InnerMeshVertexBufferLayout` for every
entity, every frame. This patch changes that logic to place
`MeshVertexBufferLayout`s in `Arc`s so that they can be compared and
hashed by pointer. This results in a 28% speedup in the
`queue_material_meshes` phase of `many_cubes`, with frustum culling
disabled.

Additionally, this patch contains two minor changes:

1. This commit flattens the specialized mesh pipeline cache to one level
of hash tables instead of two. This saves a hash lookup.

2. The example `many_cubes` has been given a `--no-frustum-culling`
flag, to aid in benchmarking.

See the Tracy profile:

<img width="1064" alt="Screenshot 2024-02-29 144406"
src="https://github.com/bevyengine/bevy/assets/157897/18632f1d-1fdd-4ac7-90ed-2d10306b2a1e">

## Migration guide

* Duplicate `MeshVertexBufferLayout`s are now combined into a single
object, `MeshVertexBufferLayoutRef`, which contains an
atomically-reference-counted pointer to the layout. Code that was using
`MeshVertexBufferLayout` may need to be updated to use
`MeshVertexBufferLayoutRef` instead.
2024-03-01 20:56:21 +00:00
Joona Aalto
f418de8eb6
Rename Direction2d/3d to Dir2/3 (#12189)
# Objective

Split up from #12017, rename Bevy's direction types.

Currently, Bevy has the `Direction2d`, `Direction3d`, and `Direction3dA`
types, which provide a type-level guarantee that their contained vectors
remain normalized. They can be very useful for a lot of APIs for safety,
explicitness, and in some cases performance, as they can sometimes avoid
unnecessary normalizations.

However, many consider them to be inconvenient to use, and opt for
standard vector types like `Vec3` because of this. One reason is that
the direction type names are a bit long and can be annoying to write (of
course you can use autocomplete, but just typing `Vec3` is still nicer),
and in some intances, the extra characters can make formatting worse.
The naming is also inconsistent with Glam's shorter type names, and
results in names like `Direction3dA`, which (in my opinion) are
difficult to read and even a bit ugly.

This PR proposes renaming the types to `Dir2`, `Dir3`, and `Dir3A`.
These names are nice and easy to write, consistent with Glam, and work
well for variants like the SIMD aligned `Dir3A`. As a bonus, it can also
result in nicer formatting in a lot of cases, which can be seen from the
diff of this PR.

Some examples of what it looks like: (copied from #12017)

```rust
// Before
let ray_cast = RayCast2d::new(Vec2::ZERO, Direction2d::X, 5.0);

// After
let ray_cast = RayCast2d::new(Vec2::ZERO, Dir2::X, 5.0);
```

```rust
// Before (an example using Bevy XPBD)
let hit = spatial_query.cast_ray(
    Vec3::ZERO,
    Direction3d::X,
    f32::MAX,
    true,
    SpatialQueryFilter::default(),
);

// After
let hit = spatial_query.cast_ray(
    Vec3::ZERO,
    Dir3::X,
    f32::MAX,
    true,
    SpatialQueryFilter::default(),
);
```

```rust
// Before
self.circle(
    Vec3::new(0.0, -2.0, 0.0),
    Direction3d::Y,
    5.0,
    Color::TURQUOISE,
);

// After (formatting is collapsed in this case)
self.circle(Vec3::new(0.0, -2.0, 0.0), Dir3::Y, 5.0, Color::TURQUOISE);
```

## Solution

Rename `Direction2d`, `Direction3d`, and `Direction3dA` to `Dir2`,
`Dir3`, and `Dir3A`.

---

## Migration Guide

The `Direction2d` and `Direction3d` types have been renamed to `Dir2`
and `Dir3`.

## Additional Context

This has been brought up on the Discord a few times, and we had a small
[poll](https://discord.com/channels/691052431525675048/1203087353850364004/1212465038711984158)
on this. `Dir2`/`Dir3`/`Dir3A` was quite unanimously chosen as the best
option, but of course it was a very small poll and inconclusive, so
other opinions are certainly welcome too.

---------

Co-authored-by: IceSentry <c.giguere42@gmail.com>
2024-02-28 22:48:43 +00:00
Joona Aalto
9bd6cc0a5e
Add Direction3dA and move direction types out of primitives (#12018)
# Objective

Split up from #12017, add an aligned version of `Direction3d` for SIMD,
and move direction types out of `primitives`.

## Solution

Add `Direction3dA` and move direction types into a new `direction`
module.

---

## Migration Guide

The `Direction2d`, `Direction3d`, and `InvalidDirectionError` types have
been moved out of `bevy::math::primitives`.

Before:

```rust
use bevy::math::primitives::Direction3d;
```

After:

```rust
use bevy::math::Direction3d;
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-02-26 13:57:49 +00:00
James Liu
bc82749012
Remove APIs deprecated in 0.13 (#11974)
# Objective
We deprecated quite a few APIs in 0.13. 0.13 has shipped already. It
should be OK to remove them in 0.14's release. Fixes #4059. Fixes #9011.

## Solution
Remove them.
2024-02-19 19:04:47 +00:00
Aztro
eef7dbefe8
Add single-f32 constructors for a few (very few) primitives (#11934)
# Objective

- I hated having to do `Cuboid::new(1.0, 1.0, 1.0)` or
`Cuboid::from_size(Vec3::splat(1.0))` when there should be a much easier
way to do this.

## Solution

- Implemented a `from_length()` method that only takes in a single
float, and constructs a primitive of equal size in all directions.
- Ex:
  ```rs
  // These:
  Cuboid::new(1.0, 1.0, 1.0);
  Cuboid::from_size(Vec3::splat(1.0));
  // Are equivalent to this:
  Cuboid::from_length(1.0);
  ```
 - For the rest of the changed primitives:
    ```rs
    Rectangle::from_length(1.0);
    Plane3d::default().mesh().from_length(1.0);
    ```
2024-02-18 07:43:45 +00:00
Joona Aalto
f1f83bf5bc
Add Mesh::merge (#11456)
# Objective

It can sometimes be useful to combine several meshes into one. This
allows constructing more complex meshes out of simple primitives without
needing to use a 3D modeling program or entity hierarchies.

This could also be used internally to increase code reuse by using
existing mesh generation logic for e.g. circles and using that in
cylinder mesh generation logic to add the top and bottom of the
cylinder.

**Note**: This is *not* implementing CSGs (Constructive Solid Geometry)
or any boolean operations, as that is much more complex. This is simply
adding the mesh data of another mesh to a mesh.

## Solution

Add a `merge` method to `Mesh`. It appends the vertex attributes and
indices of `other` to `self`, resulting in a `Mesh` that is the
combination of the two.

For example, you could do this:

```rust
let mut cuboid = Mesh::from(shape::Box::default());
let mut cylinder = Mesh::from(shape::Cylinder::default());
let mut torus = Mesh::from(shape::Torus::default());

cuboid.merge(cylinder);
cuboid.merge(torus);
```

This would result in `cuboid` being a `Mesh` that also has the cylinder
mesh and torus mesh. In this case, they would just be placed on top of
each other, but by utilizing #11454 we can transform the cylinder and
torus to get a result like this:


https://github.com/bevyengine/bevy/assets/57632562/557402c6-b896-4aba-bd95-312e7d1b5238

This is just a single entity and a single mesh.
2024-02-12 22:04:33 +00:00
Doonv
f84672b900
Fix Quad deprecation message mentioning a type that doesn't exist (#11798)
# Objective

The deprecation message of `bevy::render::mesh::shape::Quad` says that
you should use `bevy_math`'s `Quad` instead. But it doesn't exist.

## Solution

Mention the correct primitive: `Rectangle`
2024-02-09 20:52:30 +00:00
Joona Aalto
0166db33f7
Deprecate shapes in bevy_render::mesh::shape (#11773)
# Objective

#11431 and #11688 implemented meshing support for Bevy's new geometric
primitives. The next step is to deprecate the shapes in
`bevy_render::mesh::shape` and to later remove them completely for 0.14.

## Solution

Deprecate the shapes and reduce code duplication by utilizing the
primitive meshing API for the old shapes where possible.

Note that some shapes have behavior that can't be exactly reproduced
with the new primitives yet:

- `Box` is more of an AABB with min/max extents
- `Plane` supports a subdivision count
- `Quad` has a `flipped` property

These types have not been changed to utilize the new primitives yet.

---

## Changelog

- Deprecated all shapes in `bevy_render::mesh::shape`
- Changed all examples to use new primitives for meshing

## Migration Guide

Bevy has previously used rendering-specific types like `UVSphere` and
`Quad` for primitive mesh shapes. These have now been deprecated to use
the geometric primitives newly introduced in version 0.13.

Some examples:

```rust
let before = meshes.add(shape::Box::new(5.0, 0.15, 5.0));
let after = meshes.add(Cuboid::new(5.0, 0.15, 5.0));

let before = meshes.add(shape::Quad::default());
let after = meshes.add(Rectangle::default());

let before = meshes.add(shape::Plane::from_size(5.0));
// The surface normal can now also be specified when using `new`
let after = meshes.add(Plane3d::default().mesh().size(5.0, 5.0));

let before = meshes.add(
    Mesh::try_from(shape::Icosphere {
        radius: 0.5,
        subdivisions: 5,
    })
    .unwrap(),
);
let after = meshes.add(Sphere::new(0.5).mesh().ico(5).unwrap());
```
2024-02-08 18:01:34 +00:00
Lynn
4c86ad6aed
Mesh insert indices (#11745)
# Objective

- Fixes #11740 

## Solution

- Turned `Mesh::set_indices` into `Mesh::insert_indices` and added
related methods for completeness.

---

## Changelog

- Replaced `Mesh::set_indices(indices: Option<Indices>)` with
`Mesh::insert_indices(indices: Indices)`
- Replaced `Mesh::with_indices(indices: Option<Indices>)` with
`Mesh::with_inserted_indices(indices: Indices)` and
`Mesh::with_removed_indices()` mirroring the API for inserting /
removing attributes.
- Updated the examples and internal uses of the APIs described above.

## Migration Guide

- Use `Mesh::insert_indices` or `Mesh::with_inserted_indices` instead of
`Mesh::set_indices` / `Mesh::with_indices`.
- If you have passed `None` to `Mesh::set_indices` or
`Mesh::with_indices` you should use `Mesh::remove_indices` or
`Mesh::with_removed_indices` instead.

---------

Co-authored-by: François <mockersf@gmail.com>
2024-02-06 23:31:48 +00:00
Joona Aalto
cf15e6bba3
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 <alice.i.cecile@gmail.com>
2024-02-06 21:44:13 +00:00
Lynn
d4132f661a
Added remove_indices to Mesh (#11733)
# Objective

- Fixes #11727 

## Solution

- Added `Mesh::remove_indices(&mut self) -> Option<Indices>`
2024-02-06 07:41:01 +00:00
Isard
dd15890c6a
Added formats to MeshVertexAttribute constant's docstrings (#11705)
# Objective

Fixes #11653 

## Solution

- Just added the formats to the docstring, I played around with having
the format appear in the type somehow so that it didn't need to be
written manually in the docstring but it ended up being more trouble
than it was worth.

Co-authored-by: James Liu <contact@jamessliu.com>
2024-02-05 05:53:04 +00:00
Tristan Guichaoua
694c06f3d0
Inverse missing_docs logic (#11676)
# Objective

Currently the `missing_docs` lint is allowed-by-default and enabled at
crate level when their documentations is complete (see #3492).
This PR proposes to inverse this logic by making `missing_docs`
warn-by-default and mark crates with imcomplete docs allowed.

## Solution

Makes `missing_docs` warn at workspace level and allowed at crate level
when the docs is imcomplete.
2024-02-03 21:40:55 +00:00
Joona Aalto
9bad607df9
Implement meshing for Capsule2d (#11639)
# Objective

The `Capsule2d` primitive was added in #11585. It should support meshing
like the other 2D primitives.

## Solution

Implement meshing for `Capsule2d`.

It doesn't currently support "rings" like Bevy's `Capsule` shape (not
`Capsule3d`), but it does support resolution to control the number of
vertices used for one hemicircle. The total vertex count is two times
the resolution; if we allowed setting the full vertex count, odd numbers
would lead to uneven vertex counts for the top and bottom hemicircles
and produce potentially unwanted results.

The capsule looks like this (with UV visualization and wireframe) using
resolutions of 16, 8, and 3:

![Resolution
16](https://github.com/bevyengine/bevy/assets/57632562/feae22de-bdc5-438a-861f-848284b67a52)
![Resolution
8](https://github.com/bevyengine/bevy/assets/57632562/e95aab8e-793f-45ac-8a74-8be39f7626dd)
![Resolution of
3](https://github.com/bevyengine/bevy/assets/57632562/bcf01d23-1d8b-4cdb-966a-c9022a07c287)

The `2d_shapes` example now includes the capsule, so we also get one
more color of the rainbow 🌈

![New 2D shapes
example](https://github.com/bevyengine/bevy/assets/57632562/1c45b5f5-d26a-4e8c-8e8a-e106ab14d46e)
2024-02-03 18:03:43 +00:00
Chia-Hsiang Cheng
1352bf1df4
Add helpers for translate, rotate, and scale operations - Mesh (#11675)
# Objective

- Fixes #11594

## Solution

- Add helpers for translate, rotate, and scale operations.

---

## Changelog

- Added functions `translated_by`, `translate_by`, `rotated_by`,
`rotate_by`, `scaled_by`, and `scale_by`.
2024-02-03 16:36:43 +00:00
Brian Reavis
6b40b6749e
RenderAssetPersistencePolicy → RenderAssetUsages (#11399)
# Objective

Right now, all assets in the main world get extracted and prepared in
the render world (if the asset's using the RenderAssetPlugin). This is
unfortunate for two cases:

1. **TextureAtlas** / **FontAtlas**: This one's huge. The individual
`Image` assets that make up the atlas are cloned and prepared
individually when there's no reason for them to be. The atlas textures
are built on the CPU in the main world. *There can be hundreds of images
that get prepared for rendering only not to be used.*
2. If one loads an Image and needs to transform it in a system before
rendering it, kind of like the [decompression
example](https://github.com/bevyengine/bevy/blob/main/examples/asset/asset_decompression.rs#L120),
there's a price paid for extracting & preparing the asset that's not
intended to be rendered yet.

------

* References #10520
* References #1782

## Solution

This changes the `RenderAssetPersistencePolicy` enum to bitflags. I felt
that the objective with the parameter is so similar in nature to wgpu's
[`TextureUsages`](https://docs.rs/wgpu/latest/wgpu/struct.TextureUsages.html)
and
[`BufferUsages`](https://docs.rs/wgpu/latest/wgpu/struct.BufferUsages.html),
that it may as well be just like that.

```rust
// This asset only needs to be in the main world. Don't extract and prepare it.
RenderAssetUsages::MAIN_WORLD

// Keep this asset in the main world and  
RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD

// This asset is only needed in the render world. Remove it from the asset server once extracted.
RenderAssetUsages::RENDER_WORLD
```

### Alternate Solution

I considered introducing a third field to `RenderAssetPersistencePolicy`
enum:
```rust
enum RenderAssetPersistencePolicy {
    /// Keep the asset in the main world after extracting to the render world.
    Keep,
    /// Remove the asset from the main world after extracting to the render world.
    Unload,
    /// This doesn't need to be in the render world at all.
    NoExtract, // <-----
}
```
Functional, but this seemed like shoehorning. Another option is renaming
the enum to something like:
```rust
enum RenderAssetExtractionPolicy {
    /// Extract the asset and keep it in the main world.
    Extract,
    /// Remove the asset from the main world after extracting to the render world.
    ExtractAndUnload,
    /// This doesn't need to be in the render world at all.
    NoExtract,
}
```
I think this last one could be a good option if the bitflags are too
clunky.

## Migration Guide

* `RenderAssetPersistencePolicy::Keep` → `RenderAssetUsage::MAIN_WORLD |
RenderAssetUsage::RENDER_WORLD` (or `RenderAssetUsage::default()`)
* `RenderAssetPersistencePolicy::Unload` →
`RenderAssetUsage::RENDER_WORLD`
* For types implementing the `RenderAsset` trait, change `fn
persistence_policy(&self) -> RenderAssetPersistencePolicy` to `fn
asset_usage(&self) -> RenderAssetUsages`.
* Change any references to `cpu_persistent_access`
(`RenderAssetPersistencePolicy`) to `asset_usage` (`RenderAssetUsage`).
This applies to `Image`, `Mesh`, and a few other types.
2024-01-30 13:22:10 +00:00