Improve Mesh documentation (#9061)

# Objective

This PR continues https://github.com/bevyengine/bevy/pull/8885

It aims to improve the `Mesh` documentation in the following ways:
- Put everything at the "top level" instead of the "impl".
- Explain better what is a Mesh, how it can be created, and that it can
be edited.
- Explain it can be used with a `Material`, and mention
`StandardMaterial`, `PbrBundle`, `ColorMaterial`, and
`ColorMesh2dBundle` since those cover most cases
- Mention the glTF/Bevy vocabulary discrepancy for "Mesh"
- Add an image for the example
- Various nitpicky modifications

## Note

- The image I added is 90.3ko which I think is small enough?
- Since rustdoc doesn't allow cross-reference not in dependencies of a
subcrate [yet](https://github.com/rust-lang/rust/issues/74481), I have a
lot of backtick references that are not links :(
- Since rustdoc doesn't allow linking to code in the crate (?) I put
link to github directly.
- Since rustdoc doesn't allow embed images in doc
[yet](https://github.com/rust-lang/rust/issues/32104), maybe
[soon](https://github.com/rust-lang/rfcs/pull/3397), I had to put only a
link to the image. I don't think it's worth adding
[embed_doc_image](https://docs.rs/embed-doc-image/latest/embed_doc_image/)
as a dependency for this.
This commit is contained in:
Sélène Amanita 2023-07-31 19:55:42 +01:00 committed by GitHub
parent 3c6fad269b
commit cbe13f3aa5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 44 deletions

BIN
assets/docs/Mesh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

View file

@ -14,8 +14,8 @@ use std::path::Path;
/// A loader for an asset source. /// A loader for an asset source.
/// ///
/// Types implementing this trait are used by the asset server to load assets into their respective /// Types implementing this trait are used by the [`AssetServer`] to load assets
/// asset storages. /// into their respective asset storages.
pub trait AssetLoader: Send + Sync + 'static { pub trait AssetLoader: Send + Sync + 'static {
/// Processes the asset in an asynchronous closure. /// Processes the asset in an asynchronous closure.
fn load<'a>( fn load<'a>(

View file

@ -60,7 +60,8 @@ impl Plugin for GltfPlugin {
} }
} }
/// Representation of a loaded glTF file. /// Representation of a loaded glTF file
/// (file loaded via the `AssetServer` with the extension `.glb` or `.gltf`).
#[derive(Debug, TypeUuid, TypePath)] #[derive(Debug, TypeUuid, TypePath)]
#[uuid = "5c7d5f8a-f7b0-4e45-a09e-406c0372fea2"] #[uuid = "5c7d5f8a-f7b0-4e45-a09e-406c0372fea2"]
pub struct Gltf { pub struct Gltf {

View file

@ -26,28 +26,24 @@ use wgpu::{
pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0; pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0;
pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10; pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
// TODO: allow values to be unloaded after been submitting to the GPU to conserve memory /// A 3D object made out of vertices representing triangles, lines, or points,
#[derive(Debug, TypeUuid, TypePath, Clone)] /// with "attribute" values for each vertex.
#[uuid = "8ecbac0f-f545-4473-ad43-e1f4243af51e"]
pub struct Mesh {
primitive_topology: PrimitiveTopology,
/// `std::collections::BTreeMap` with all defined vertex attributes (Positions, Normals, ...)
/// for this mesh. Attribute ids to attribute values.
/// Uses a BTreeMap because, unlike HashMap, it has a defined iteration order,
/// which allows easy stable VertexBuffers (i.e. same buffer order)
attributes: BTreeMap<MeshVertexAttributeId, MeshAttributeData>,
indices: Option<Indices>,
morph_targets: Option<Handle<Image>>,
morph_target_names: Option<Vec<String>>,
}
/// Contains geometry in the form of a mesh.
/// ///
/// Often meshes are automatically generated by bevy's asset loaders or primitives, such as /// Meshes can be automatically generated by a bevy `AssetLoader` (generally by loading a `Gltf` file),
/// [`shape::Cube`](crate::mesh::shape::Cube) or [`shape::Box`](crate::mesh::shape::Box), but you can also construct /// or by converting a primitive [`shape`](crate::mesh::shape) using [`into`](std::convert::Into).
/// one yourself. /// It is also possible to create one manually.
/// They can be edited after creation.
/// ///
/// Example of constructing a mesh (to be rendered with a `StandardMaterial`): /// Meshes can be rendered with a `Material`, like `StandardMaterial` in `PbrBundle`
/// or `ColorMaterial` in `ColorMesh2dBundle`.
///
/// A [`Mesh`] in Bevy is equivalent to a "primitive" in the glTF format, for a
/// glTF Mesh representation, see `GltfMesh`.
///
/// ## Manual creation
///
/// The following function will construct a flat mesh, to be rendered with a
/// `StandardMaterial` or `ColorMaterial`:
/// ``` /// ```
/// # use bevy_render::mesh::{Mesh, Indices}; /// # use bevy_render::mesh::{Mesh, Indices};
/// # use bevy_render::render_resource::PrimitiveTopology; /// # use bevy_render::render_resource::PrimitiveTopology;
@ -78,50 +74,90 @@ pub struct Mesh {
/// 1, 3, 2 /// 1, 3, 2
/// ]))); /// ])));
/// mesh /// mesh
/// // For further visualization, explanation, and examples see the built-in Bevy examples
/// // and the implementation of the built-in shapes.
/// } /// }
/// ``` /// ```
/// Common points of confusion:
/// - UV maps in Bevy are "flipped", (0.0, 0.0) = Top-Left (not Bot-Left like `OpenGL`)
/// - It is normal for multiple vertices to have the same position
/// attribute - it's a common technique in 3D modelling for complex UV mapping or other calculations.
/// ///
/// To render correctly with `StandardMaterial` a mesh needs to have properly defined: /// You can see how it looks like [here](https://github.com/bevyengine/bevy/blob/main/assets/dovs/Mesh.png),
/// - [`UVs`](Mesh::ATTRIBUTE_UV_0): Bevy needs to know how to map a texture onto the mesh. /// used in a `PbrBundle` with a square bevy logo texture, with added axis, points,
/// - [`Normals`](Mesh::ATTRIBUTE_NORMAL): Bevy needs to know how light interacts with your mesh. ([0.0, 0.0, 1.0] is very /// lines and text for clarity.
/// common for simple meshes because simple meshes are smooth, and they don't require complex light calculations.)
/// - Vertex winding order -
/// the default behavior is with `StandardMaterial.cull_mode` = Some([`Face::Front`](crate::render_resource::Face::Front)) which means
/// that by default Bevy would *only* render the front of each triangle, and the front
/// is the side of the triangle in which the vertices appear in a *counter-clockwise* order.
/// ///
/// ## Other examples
///
/// For further visualization, explanation, and examples, see the built-in Bevy examples,
/// and the [implementation of the built-in shapes](https://github.com/bevyengine/bevy/tree/main/crates/bevy_render/src/mesh/shape).
/// In particular, [generate_custom_mesh](https://github.com/bevyengine/bevy/blob/main/examples/3d/generate_custom_mesh.rs)
/// teaches you to access modify a Mesh's attributes after creating it.
///
/// ## Common points of confusion
///
/// - UV maps in Bevy start at the top-left, see [`ATTRIBUTE_UV_0`](Mesh::ATTRIBUTE_UV_0),
/// other APIs can have other conventions, `OpenGL` starts at bottom-left.
/// - It is possible and sometimes useful for multiple vertices to have the same
/// [position attribute](Mesh::ATTRIBUTE_POSITION) value,
/// it's a common technique in 3D modelling for complex UV mapping or other calculations.
///
/// ## Use with `StandardMaterial`
///
/// To render correctly with `StandardMaterial`, a mesh needs to have properly defined:
/// - [`UVs`](Mesh::ATTRIBUTE_UV_0): Bevy needs to know how to map a texture onto the mesh
/// (also true for `ColorMaterial`).
/// - [`Normals`](Mesh::ATTRIBUTE_NORMAL): Bevy needs to know how light interacts with your mesh.
/// [0.0, 0.0, 1.0] is very common for simple flat meshes on the XY plane,
/// because simple meshes are smooth and they don't require complex light calculations.
/// - Vertex winding order: by default, `StandardMaterial.cull_mode` is [`Some(Face::Back)`](crate::render_resource::Face),
/// which means that Bevy would *only* render the "front" of each triangle, which
/// is the side of the triangle from where the vertices appear in a *counter-clockwise* order.
///
// TODO: allow values to be unloaded after been submitting to the GPU to conserve memory
#[derive(Debug, TypeUuid, TypePath, Clone)]
#[uuid = "8ecbac0f-f545-4473-ad43-e1f4243af51e"]
pub struct Mesh {
primitive_topology: PrimitiveTopology,
/// `std::collections::BTreeMap` with all defined vertex attributes (Positions, Normals, ...)
/// for this mesh. Attribute ids to attribute values.
/// Uses a BTreeMap because, unlike HashMap, it has a defined iteration order,
/// which allows easy stable VertexBuffers (i.e. same buffer order)
attributes: BTreeMap<MeshVertexAttributeId, MeshAttributeData>,
indices: Option<Indices>,
morph_targets: Option<Handle<Image>>,
morph_target_names: Option<Vec<String>>,
}
impl Mesh { impl Mesh {
/// Where the vertex is located in space. Use in conjunction with [`Mesh::insert_attribute`] /// Where the vertex is located in space. Use in conjunction with [`Mesh::insert_attribute`].
pub const ATTRIBUTE_POSITION: MeshVertexAttribute = pub const ATTRIBUTE_POSITION: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_Position", 0, VertexFormat::Float32x3); MeshVertexAttribute::new("Vertex_Position", 0, VertexFormat::Float32x3);
/// The direction the vertex normal is facing in. /// The direction the vertex normal is facing in.
/// Use in conjunction with [`Mesh::insert_attribute`] /// Use in conjunction with [`Mesh::insert_attribute`].
pub const ATTRIBUTE_NORMAL: MeshVertexAttribute = pub const ATTRIBUTE_NORMAL: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_Normal", 1, VertexFormat::Float32x3); MeshVertexAttribute::new("Vertex_Normal", 1, VertexFormat::Float32x3);
/// Texture coordinates for the vertex. Use in conjunction with [`Mesh::insert_attribute`] /// Texture coordinates for the vertex. Use in conjunction with [`Mesh::insert_attribute`].
///
/// Values are generally between 0. and 1., with `StandardMaterial` and `ColorMaterial`
/// `[0.,0.]` is the top left of the texture, and [1.,1.] the bottom-right.
/// You usually want to only use values in that range, values outside will be
/// clamped per pixel not for the vertex, "stretching" the borders of the texture.
/// This behavior can be useful in some cases, usually when the borders have only
/// one color, for example a logo, and you want to "extend" those borders.
pub const ATTRIBUTE_UV_0: MeshVertexAttribute = pub const ATTRIBUTE_UV_0: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_Uv", 2, VertexFormat::Float32x2); MeshVertexAttribute::new("Vertex_Uv", 2, VertexFormat::Float32x2);
/// The direction of the vertex tangent. Used for normal mapping /// The direction of the vertex tangent. Used for normal mapping.
/// Usually generated with [`generate_tangents`](Mesh::generate_tangents).
pub const ATTRIBUTE_TANGENT: MeshVertexAttribute = pub const ATTRIBUTE_TANGENT: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_Tangent", 3, VertexFormat::Float32x4); MeshVertexAttribute::new("Vertex_Tangent", 3, VertexFormat::Float32x4);
/// Per vertex coloring. Use in conjunction with [`Mesh::insert_attribute`] /// Per vertex coloring. Use in conjunction with [`Mesh::insert_attribute`].
pub const ATTRIBUTE_COLOR: MeshVertexAttribute = pub const ATTRIBUTE_COLOR: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_Color", 4, VertexFormat::Float32x4); MeshVertexAttribute::new("Vertex_Color", 4, VertexFormat::Float32x4);
/// Per vertex joint transform matrix weight. Use in conjunction with [`Mesh::insert_attribute`] /// Per vertex joint transform matrix weight. Use in conjunction with [`Mesh::insert_attribute`].
pub const ATTRIBUTE_JOINT_WEIGHT: MeshVertexAttribute = pub const ATTRIBUTE_JOINT_WEIGHT: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_JointWeight", 5, VertexFormat::Float32x4); MeshVertexAttribute::new("Vertex_JointWeight", 5, VertexFormat::Float32x4);
/// Per vertex joint transform matrix index. Use in conjunction with [`Mesh::insert_attribute`]
/// Per vertex joint transform matrix index. Use in conjunction with [`Mesh::insert_attribute`].
pub const ATTRIBUTE_JOINT_INDEX: MeshVertexAttribute = pub const ATTRIBUTE_JOINT_INDEX: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_JointIndex", 6, VertexFormat::Uint16x4); MeshVertexAttribute::new("Vertex_JointIndex", 6, VertexFormat::Uint16x4);