Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Mesh documentation #9061

Merged
merged 6 commits into from
Jul 31, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/docs/Mesh.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/bevy_asset/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use std::path::Path;

/// A loader for an asset source.
///
/// Types implementing this trait are used by the asset server to load assets into their respective
/// asset storages.
/// Types implementing this trait are used by the [`AssetServer`] to load assets
/// into their respective asset storages.
pub trait AssetLoader: Send + Sync + 'static {
/// Processes the asset in an asynchronous closure.
fn load<'a>(
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_gltf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,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)]
#[uuid = "5c7d5f8a-f7b0-4e45-a09e-406c0372fea2"]
pub struct Gltf {
Expand Down
110 changes: 69 additions & 41 deletions crates/bevy_render/src/mesh/mesh/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,24 @@ use wgpu::{
pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0;
pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;

// 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>>,
}

/// Contains geometry in the form of a mesh.
/// A 3D object made out of vertices representing triangles, lines, or points,
/// with special "attribute" values for each vertex.
///
/// Often meshes are automatically generated by bevy's asset loaders or primitives, such as
/// [`shape::Cube`](crate::mesh::shape::Cube) or [`shape::Box`](crate::mesh::shape::Box), but you can also construct
/// one yourself.
/// Meshes can be automatically generated by a bevy `AssetLoader` (generally by loading a `Gltf` file),
/// or by converting a primitive [`shape`](crate::mesh::shape) using [`into`](std::convert::Into).
/// 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::render_resource::PrimitiveTopology;
Expand Down Expand Up @@ -78,50 +74,82 @@ pub struct Mesh {
/// 1, 3, 2
/// ])));
/// 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:
/// - [`UVs`](Mesh::ATTRIBUTE_UV_0): Bevy needs to know how to map a texture onto the mesh.
/// - [`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 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.
/// You can see how it looks like [here](https://github.com/bevyengine/bevy/blob/main/assets/dovs/Mesh.png),
/// used in a `PbrBundle` with a square bevy logo texture, with added axis, points,
/// lines and text for clarity.
///
/// For further visualization, explanation, and examples see the built-in Bevy examples,
/// in particular [generate_custom_mesh](https://github.com/bevyengine/bevy/blob/main/examples/3d/generate_custom_mesh.rs),
/// and the [implementation of the built-in shapes](https://github.com/bevyengine/bevy/tree/main/crates/bevy_render/src/mesh/shape).
///
/// ## Common points of confusion
///
/// - UV maps in Bevy are "flipped", `[0.0, 0.0]` = Top-Left (not Bot-Left like `OpenGL`).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's only flipped compared to OpenGL, to me this implies bevy is doing something non-standard here. As far as I know, top-left is part of the gltf spec

In other words, I agree it's worth pointing out, but it should be clearer that it's flipped compared to opengl.

Something like

Suggested change
/// - UV maps in Bevy are "flipped", `[0.0, 0.0]` = Top-Left (not Bot-Left like `OpenGL`).
/// - UV maps in bevy start at the top-left unlike opengl which starts at the bottom-left

/// - It is normal for multiple vertices to have the same [position attribute](Mesh::ATTRIBUTE_POSITION) value,
Copy link
Contributor

@IceSentry IceSentry Jul 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe try to rephrase this to not use the word normal? I generally wouldn't mind, but in the context of meshes it might be worth avoiding the potential confusion with vertex normal.

/// 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::Front)`](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 {
/// 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 =
MeshVertexAttribute::new("Vertex_Position", 0, VertexFormat::Float32x3);

/// 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 =
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., `[0.,0.]` being the top left of the texture,
/// and [1.,1.] the bottom-right. Values outside this range will generate visual artifacts with
/// `StandardMaterial` and `ColorMaterial`.
pub const ATTRIBUTE_UV_0: MeshVertexAttribute =
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 =
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 =
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 =
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 =
MeshVertexAttribute::new("Vertex_JointIndex", 6, VertexFormat::Uint16x4);

Expand Down