pub struct Mesh { /* private fields */ }
Expand description
A 3D object made out of vertices representing triangles, lines, or points, with “attribute” values for each vertex.
Meshes can be automatically generated by a bevy AssetLoader
(generally by loading a Gltf
file),
or by converting a primitive shape
using into
.
It is also possible to create one manually.
They can be edited after creation.
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
:
fn create_simple_parallelogram() -> Mesh {
// Create a new mesh, add 4 vertices, each with its own position attribute (coordinate in
// 3D space), for each of the corners of the parallelogram.
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
mesh.insert_attribute(
Mesh::ATTRIBUTE_POSITION,
vec![[0.0, 0.0, 0.0], [1.0, 2.0, 0.0], [2.0, 2.0, 0.0], [1.0, 0.0, 0.0]]
);
// Assign a UV coordinate to each vertex.
mesh.insert_attribute(
Mesh::ATTRIBUTE_UV_0,
vec![[0.0, 1.0], [0.5, 0.0], [1.0, 0.0], [0.5, 1.0]]
);
// Assign normals (everything points outwards)
mesh.insert_attribute(
Mesh::ATTRIBUTE_NORMAL,
vec![[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]]
);
// After defining all the vertices and their attributes, build each triangle using the
// indices of the vertices that make it up in a counter-clockwise order.
mesh.set_indices(Some(Indices::U32(vec![
// First triangle
0, 3, 1,
// Second triangle
1, 3, 2
])));
mesh
}
You can see how it looks like here,
used in a PbrBundle
with a square bevy logo texture, with added axis, points,
lines and text for clarity.
Other examples
For further visualization, explanation, and examples, see the built-in Bevy examples, and the implementation of the built-in shapes. In particular, generate_custom_mesh 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
, 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 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
: Bevy needs to know how to map a texture onto the mesh (also true forColorMaterial
).Normals
: 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
isSome(Face::Back)
, 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.
Implementations§
§impl Mesh
impl Mesh
pub const ATTRIBUTE_POSITION: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_Position", 0, VertexFormat::Float32x3)
pub const ATTRIBUTE_POSITION: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_Position", 0, VertexFormat::Float32x3)
Where the vertex is located in space. Use in conjunction with Mesh::insert_attribute
.
pub const ATTRIBUTE_NORMAL: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_Normal", 1, VertexFormat::Float32x3)
pub const ATTRIBUTE_NORMAL: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_Normal", 1, VertexFormat::Float32x3)
The direction the vertex normal is facing in.
Use in conjunction with Mesh::insert_attribute
.
pub const ATTRIBUTE_UV_0: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_Uv", 2, VertexFormat::Float32x2)
pub const ATTRIBUTE_UV_0: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_Uv", 2, VertexFormat::Float32x2)
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_TANGENT: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_Tangent", 3, VertexFormat::Float32x4)
pub const ATTRIBUTE_TANGENT: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_Tangent", 3, VertexFormat::Float32x4)
The direction of the vertex tangent. Used for normal mapping.
Usually generated with generate_tangents
.
pub const ATTRIBUTE_COLOR: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_Color", 4, VertexFormat::Float32x4)
pub const ATTRIBUTE_COLOR: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_Color", 4, VertexFormat::Float32x4)
Per vertex coloring. Use in conjunction with Mesh::insert_attribute
.
pub const ATTRIBUTE_JOINT_WEIGHT: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_JointWeight", 5, VertexFormat::Float32x4)
pub const ATTRIBUTE_JOINT_WEIGHT: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_JointWeight", 5, VertexFormat::Float32x4)
Per vertex joint transform matrix weight. Use in conjunction with Mesh::insert_attribute
.
pub const ATTRIBUTE_JOINT_INDEX: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_JointIndex", 6, VertexFormat::Uint16x4)
pub const ATTRIBUTE_JOINT_INDEX: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_JointIndex", 6, VertexFormat::Uint16x4)
Per vertex joint transform matrix index. Use in conjunction with Mesh::insert_attribute
.
pub fn new(primitive_topology: PrimitiveTopology) -> Mesh
pub fn new(primitive_topology: PrimitiveTopology) -> Mesh
Construct a new mesh. You need to provide a PrimitiveTopology
so that the
renderer knows how to treat the vertex data. Most of the time this will be
PrimitiveTopology::TriangleList
.
pub fn primitive_topology(&self) -> PrimitiveTopology
pub fn primitive_topology(&self) -> PrimitiveTopology
Returns the topology of the mesh.
pub fn insert_attribute(
&mut self,
attribute: MeshVertexAttribute,
values: impl Into<VertexAttributeValues>
)
pub fn insert_attribute( &mut self, attribute: MeshVertexAttribute, values: impl Into<VertexAttributeValues> )
Sets the data for a vertex attribute (position, normal etc.). The name will
often be one of the associated constants such as Mesh::ATTRIBUTE_POSITION
.
Panics
Panics when the format of the values does not match the attribute’s format.
pub fn remove_attribute(
&mut self,
attribute: impl Into<MeshVertexAttributeId>
) -> Option<VertexAttributeValues>
pub fn remove_attribute( &mut self, attribute: impl Into<MeshVertexAttributeId> ) -> Option<VertexAttributeValues>
Removes the data for a vertex attribute
pub fn contains_attribute(&self, id: impl Into<MeshVertexAttributeId>) -> bool
pub fn attribute(
&self,
id: impl Into<MeshVertexAttributeId>
) -> Option<&VertexAttributeValues>
pub fn attribute( &self, id: impl Into<MeshVertexAttributeId> ) -> Option<&VertexAttributeValues>
Retrieves the data currently set to the vertex attribute with the specified name
.
pub fn attribute_mut(
&mut self,
id: impl Into<MeshVertexAttributeId>
) -> Option<&mut VertexAttributeValues>
pub fn attribute_mut( &mut self, id: impl Into<MeshVertexAttributeId> ) -> Option<&mut VertexAttributeValues>
Retrieves the data currently set to the vertex attribute with the specified name
mutably.
pub fn attributes(
&self
) -> impl Iterator<Item = (MeshVertexAttributeId, &VertexAttributeValues)>
pub fn attributes( &self ) -> impl Iterator<Item = (MeshVertexAttributeId, &VertexAttributeValues)>
Returns an iterator that yields references to the data of each vertex attribute.
pub fn attributes_mut(
&mut self
) -> impl Iterator<Item = (MeshVertexAttributeId, &mut VertexAttributeValues)>
pub fn attributes_mut( &mut self ) -> impl Iterator<Item = (MeshVertexAttributeId, &mut VertexAttributeValues)>
Returns an iterator that yields mutable references to the data of each vertex attribute.
pub fn set_indices(&mut self, indices: Option<Indices>)
pub fn set_indices(&mut self, indices: Option<Indices>)
Sets the vertex indices of the mesh. They describe how triangles are constructed out of the
vertex attributes and are therefore only useful for the PrimitiveTopology
variants
that use triangles.
pub fn indices_mut(&mut self) -> Option<&mut Indices>
pub fn indices_mut(&mut self) -> Option<&mut Indices>
Retrieves the vertex indices
of the mesh mutably.
pub fn get_index_buffer_bytes(&self) -> Option<&[u8]>
pub fn get_index_buffer_bytes(&self) -> Option<&[u8]>
Computes and returns the index data of the mesh as bytes. This is used to transform the index data into a GPU friendly format.
pub fn get_mesh_vertex_buffer_layout(
&self
) -> Hashed<InnerMeshVertexBufferLayout, FixedState>
pub fn get_mesh_vertex_buffer_layout( &self ) -> Hashed<InnerMeshVertexBufferLayout, FixedState>
Get this Mesh
’s MeshVertexBufferLayout
, used in SpecializedMeshPipeline
.
pub fn count_vertices(&self) -> usize
pub fn count_vertices(&self) -> usize
pub fn get_vertex_buffer_data(&self) -> Vec<u8, Global> ⓘ
pub fn get_vertex_buffer_data(&self) -> Vec<u8, Global> ⓘ
Computes and returns the vertex data of the mesh as bytes.
Therefore the attributes are located in the order of their MeshVertexAttribute::id
.
This is used to transform the vertex data into a GPU friendly format.
Panics
Panics if the attributes have different vertex counts.
pub fn duplicate_vertices(&mut self)
pub fn duplicate_vertices(&mut self)
Duplicates the vertex attributes so that no vertices are shared.
This can dramatically increase the vertex count, so make sure this is what you want. Does nothing if no Indices are set.
pub fn compute_flat_normals(&mut self)
pub fn compute_flat_normals(&mut self)
Calculates the Mesh::ATTRIBUTE_NORMAL
of a mesh.
Panics
Panics if Indices
are set or Mesh::ATTRIBUTE_POSITION
is not of type float3
or
if the mesh has any other topology than PrimitiveTopology::TriangleList
.
Consider calling Mesh::duplicate_vertices
or export your mesh with normal attributes.
pub fn generate_tangents(&mut self) -> Result<(), GenerateTangentsError>
pub fn generate_tangents(&mut self) -> Result<(), GenerateTangentsError>
Generate tangents for the mesh using the mikktspace
algorithm.
Sets the Mesh::ATTRIBUTE_TANGENT
attribute if successful.
Requires a PrimitiveTopology::TriangleList
topology and the Mesh::ATTRIBUTE_POSITION
, Mesh::ATTRIBUTE_NORMAL
and Mesh::ATTRIBUTE_UV_0
attributes set.
pub fn compute_aabb(&self) -> Option<Aabb>
pub fn compute_aabb(&self) -> Option<Aabb>
Compute the Axis-Aligned Bounding Box of the mesh vertices in model space
pub fn has_morph_targets(&self) -> bool
pub fn has_morph_targets(&self) -> bool
Whether this mesh has morph targets.
pub fn set_morph_targets(&mut self, morph_targets: Handle<Image>)
pub fn set_morph_targets(&mut self, morph_targets: Handle<Image>)
Set morph targets image for this mesh. This requires a “morph target image”. See MorphTargetImage
for info.
pub fn set_morph_target_names(&mut self, names: Vec<String, Global>)
pub fn set_morph_target_names(&mut self, names: Vec<String, Global>)
Sets the names of each morph target. This should correspond to the order of the morph targets in set_morph_targets
.
pub fn morph_target_names(&self) -> Option<&[String]>
pub fn morph_target_names(&self) -> Option<&[String]>
Gets a list of all morph target names, if they exist.
Trait Implementations§
§impl From<RegularPolygon> for Mesh
impl From<RegularPolygon> for Mesh
§fn from(polygon: RegularPolygon) -> Mesh
fn from(polygon: RegularPolygon) -> Mesh
§impl RenderAsset for Mesh
impl RenderAsset for Mesh
§fn extract_asset(&self) -> <Mesh as RenderAsset>::ExtractedAsset
fn extract_asset(&self) -> <Mesh as RenderAsset>::ExtractedAsset
Clones the mesh.
§fn prepare_asset(
mesh: <Mesh as RenderAsset>::ExtractedAsset,
_: &mut <<Mesh as RenderAsset>::Param as SystemParam>::Item<'_, '_>
) -> Result<<Mesh as RenderAsset>::PreparedAsset, PrepareAssetError<<Mesh as RenderAsset>::ExtractedAsset>>
fn prepare_asset( mesh: <Mesh as RenderAsset>::ExtractedAsset, _: &mut <<Mesh as RenderAsset>::Param as SystemParam>::Item<'_, '_> ) -> Result<<Mesh as RenderAsset>::PreparedAsset, PrepareAssetError<<Mesh as RenderAsset>::ExtractedAsset>>
Converts the extracted mesh a into GpuMesh
.
§type ExtractedAsset = Mesh
type ExtractedAsset = Mesh
§type PreparedAsset = GpuMesh
type PreparedAsset = GpuMesh
§type Param = (Res<'static, RenderDevice>, Res<'static, RenderAssets<Image>>)
type Param = (Res<'static, RenderDevice>, Res<'static, RenderAssets<Image>>)
RenderAsset::prepare_asset
.
For convenience use the lifetimeless
SystemParam
.§impl TypePath for Mesh
impl TypePath for Mesh
§fn short_type_path() -> &'static str
fn short_type_path() -> &'static str
§fn type_ident() -> Option<&'static str>
fn type_ident() -> Option<&'static str>
§fn crate_name() -> Option<&'static str>
fn crate_name() -> Option<&'static str>
Auto Trait Implementations§
impl RefUnwindSafe for Mesh
impl Send for Mesh
impl Sync for Mesh
impl Unpin for Mesh
impl UnwindSafe for Mesh
Blanket Implementations§
§impl<T, U> AsBindGroupShaderType<U> for Twhere
U: ShaderType,
&'a T: for<'a> Into<U>,
impl<T, U> AsBindGroupShaderType<U> for Twhere U: ShaderType, &'a T: for<'a> Into<U>,
§fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere T: Any,
§fn into_any(self: Box<T, Global>) -> Box<dyn Any, Global>
fn into_any(self: Box<T, Global>) -> Box<dyn Any, Global>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.§fn into_any_rc(self: Rc<T, Global>) -> Rc<dyn Any, Global>
fn into_any_rc(self: Rc<T, Global>) -> Rc<dyn Any, Global>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.§impl<T> DynamicTypePath for Twhere
T: TypePath,
impl<T> DynamicTypePath for Twhere T: TypePath,
§fn reflect_type_path(&self) -> &str
fn reflect_type_path(&self) -> &str
TypePath::type_path
.§fn reflect_short_type_path(&self) -> &str
fn reflect_short_type_path(&self) -> &str
§fn reflect_type_ident(&self) -> Option<&str>
fn reflect_type_ident(&self) -> Option<&str>
TypePath::type_ident
.§fn reflect_crate_name(&self) -> Option<&str>
fn reflect_crate_name(&self) -> Option<&str>
TypePath::crate_name
.