pub struct Mesh {
pub asset_usage: RenderAssetUsages,
/* 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 using into
.
It is also possible to create one manually. They can be edited after creation.
Meshes can be rendered with a Mesh2d
and MeshMaterial2d
or Mesh3d
and MeshMaterial3d
for 2D and 3D respectively.
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 using a triangle list topology, where each set of 3 vertices composes a triangle.
Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default())
// Add 4 vertices, each with its own position attribute (coordinate in
// 3D space), for each of the corners of the parallelogram.
.with_inserted_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.
.with_inserted_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)
.with_inserted_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.
.with_inserted_indices(Indices::U32(vec![
// First triangle
0, 3, 1,
// Second triangle
1, 3, 2
]))
}
You can see how it looks like here,
used in a Mesh3d
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 and modify the attributes of a Mesh
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 modeling for complex UV mapping or other calculations.
- Bevy performs frustum culling based on the
Aabb
of meshes, which is calculated and added automatically for new meshes only. If a mesh is modified, the entity’sAabb
needs to be updated manually or deleted so that it is re-calculated.
§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.
Fields§
§asset_usage: RenderAssetUsages
Implementations§
Source§impl Mesh
impl Mesh
Sourcepub const ATTRIBUTE_POSITION: MeshVertexAttribute
pub const ATTRIBUTE_POSITION: MeshVertexAttribute
Where the vertex is located in space. Use in conjunction with Mesh::insert_attribute
or Mesh::with_inserted_attribute
.
The format of this attribute is VertexFormat::Float32x3
.
Sourcepub const ATTRIBUTE_NORMAL: MeshVertexAttribute
pub const ATTRIBUTE_NORMAL: MeshVertexAttribute
The direction the vertex normal is facing in.
Use in conjunction with Mesh::insert_attribute
or Mesh::with_inserted_attribute
.
The format of this attribute is VertexFormat::Float32x3
.
Sourcepub const ATTRIBUTE_UV_0: MeshVertexAttribute
pub const ATTRIBUTE_UV_0: MeshVertexAttribute
Texture coordinates for the vertex. Use in conjunction with Mesh::insert_attribute
or Mesh::with_inserted_attribute
.
Generally [0.,0.]
is mapped to the top left of the texture, and [1.,1.]
to the bottom-right.
By default 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.
For different mapping outside of 0..=1
range,
see ImageAddressMode
.
The format of this attribute is VertexFormat::Float32x2
.
Sourcepub const ATTRIBUTE_UV_1: MeshVertexAttribute
pub const ATTRIBUTE_UV_1: MeshVertexAttribute
Alternate texture coordinates for the vertex. Use in conjunction with
Mesh::insert_attribute
or Mesh::with_inserted_attribute
.
Typically, these are used for lightmaps, textures that provide precomputed illumination.
The format of this attribute is VertexFormat::Float32x2
.
Sourcepub const ATTRIBUTE_TANGENT: MeshVertexAttribute
pub const ATTRIBUTE_TANGENT: MeshVertexAttribute
The direction of the vertex tangent. Used for normal mapping.
Usually generated with generate_tangents
or
with_generated_tangents
.
The format of this attribute is VertexFormat::Float32x4
.
Sourcepub const ATTRIBUTE_COLOR: MeshVertexAttribute
pub const ATTRIBUTE_COLOR: MeshVertexAttribute
Per vertex coloring. Use in conjunction with Mesh::insert_attribute
or Mesh::with_inserted_attribute
.
The format of this attribute is VertexFormat::Float32x4
.
Sourcepub const ATTRIBUTE_JOINT_WEIGHT: MeshVertexAttribute
pub const ATTRIBUTE_JOINT_WEIGHT: MeshVertexAttribute
Per vertex joint transform matrix weight. Use in conjunction with Mesh::insert_attribute
or Mesh::with_inserted_attribute
.
The format of this attribute is VertexFormat::Float32x4
.
Sourcepub const ATTRIBUTE_JOINT_INDEX: MeshVertexAttribute
pub const ATTRIBUTE_JOINT_INDEX: MeshVertexAttribute
Per vertex joint transform matrix index. Use in conjunction with Mesh::insert_attribute
or Mesh::with_inserted_attribute
.
The format of this attribute is VertexFormat::Uint16x4
.
Sourcepub fn new(
primitive_topology: PrimitiveTopology,
asset_usage: RenderAssetUsages,
) -> Mesh
pub fn new( primitive_topology: PrimitiveTopology, asset_usage: RenderAssetUsages, ) -> 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
.
Examples found in repository?
98 fn from(line: LineList) -> Self {
99 let vertices: Vec<_> = line.lines.into_iter().flat_map(|(a, b)| [a, b]).collect();
100
101 Mesh::new(
102 // This tells wgpu that the positions are list of lines
103 // where every pair is a start and end point
104 PrimitiveTopology::LineList,
105 RenderAssetUsages::RENDER_WORLD,
106 )
107 // Add the vertices positions as an attribute
108 .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
109 }
110}
111
112/// A list of points that will have a line drawn between each consecutive points
113#[derive(Debug, Clone)]
114struct LineStrip {
115 points: Vec<Vec3>,
116}
117
118impl From<LineStrip> for Mesh {
119 fn from(line: LineStrip) -> Self {
120 Mesh::new(
121 // This tells wgpu that the positions are a list of points
122 // where a line will be drawn between each consecutive point
123 PrimitiveTopology::LineStrip,
124 RenderAssetUsages::RENDER_WORLD,
125 )
126 // Add the point positions as an attribute
127 .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, line.points)
128 }
More examples
57fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
58 // Build a custom triangle mesh with colors
59 // We define a custom mesh because the examples only uses a limited
60 // set of vertex attributes for simplicity
61 let mesh = Mesh::new(
62 PrimitiveTopology::TriangleList,
63 RenderAssetUsages::default(),
64 )
65 .with_inserted_indices(Indices::U32(vec![0, 1, 2]))
66 .with_inserted_attribute(
67 Mesh::ATTRIBUTE_POSITION,
68 vec![
69 vec3(-0.5, -0.5, 0.0),
70 vec3(0.5, -0.5, 0.0),
71 vec3(0.0, 0.25, 0.0),
72 ],
73 )
74 .with_inserted_attribute(
75 Mesh::ATTRIBUTE_COLOR,
76 vec![
77 vec4(1.0, 0.0, 0.0, 1.0),
78 vec4(0.0, 1.0, 0.0, 1.0),
79 vec4(0.0, 0.0, 1.0, 1.0),
80 ],
81 );
82
83 // spawn 3 triangles to show that batching works
84 for (x, y) in [-0.5, 0.0, 0.5].into_iter().zip([-0.25, 0.5, -0.25]) {
85 // Spawn an entity with all the required components for it to be rendered with our custom pipeline
86 commands.spawn((
87 // We use a marker component to identify the mesh that will be rendered
88 // with our specialized pipeline
89 CustomRenderedEntity,
90 // We need to add the mesh handle to the entity
91 Mesh3d(meshes.add(mesh.clone())),
92 Transform::from_xyz(x, y, 0.0),
93 ));
94 }
95
96 // Spawn the camera.
97 commands.spawn((
98 Camera3d::default(),
99 // Move the camera back a bit to see all the triangles
100 Transform::from_xyz(0.0, 0.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y),
101 ));
102}
402 fn build(&self) -> Mesh {
403 let radius = self.heart.radius;
404 // The curved parts of each wing (half) of the heart have an angle of `PI * 1.25` or 225°
405 let wing_angle = PI * 1.25;
406
407 // We create buffers for the vertices, their normals and UVs, as well as the indices used to connect the vertices.
408 let mut vertices = Vec::with_capacity(2 * self.resolution);
409 let mut uvs = Vec::with_capacity(2 * self.resolution);
410 let mut indices = Vec::with_capacity(6 * self.resolution - 9);
411 // Since the heart is flat, we know all the normals are identical already.
412 let normals = vec![[0f32, 0f32, 1f32]; 2 * self.resolution];
413
414 // The point in the middle of the two curved parts of the heart
415 vertices.push([0.0; 3]);
416 uvs.push([0.5, 0.5]);
417
418 // The left wing of the heart, starting from the point in the middle.
419 for i in 1..self.resolution {
420 let angle = (i as f32 / self.resolution as f32) * wing_angle;
421 let (sin, cos) = ops::sin_cos(angle);
422 vertices.push([radius * (cos - 1.0), radius * sin, 0.0]);
423 uvs.push([0.5 - (cos - 1.0) / 4., 0.5 - sin / 2.]);
424 }
425
426 // The bottom tip of the heart
427 vertices.push([0.0, radius * (-1. - SQRT_2), 0.0]);
428 uvs.push([0.5, 1.]);
429
430 // The right wing of the heart, starting from the bottom most point and going towards the middle point.
431 for i in 0..self.resolution - 1 {
432 let angle = (i as f32 / self.resolution as f32) * wing_angle - PI / 4.;
433 let (sin, cos) = ops::sin_cos(angle);
434 vertices.push([radius * (cos + 1.0), radius * sin, 0.0]);
435 uvs.push([0.5 - (cos + 1.0) / 4., 0.5 - sin / 2.]);
436 }
437
438 // This is where we build all the triangles from the points created above.
439 // Each triangle has one corner on the middle point with the other two being adjacent points on the perimeter of the heart.
440 for i in 2..2 * self.resolution as u32 {
441 indices.extend_from_slice(&[i - 1, i, 0]);
442 }
443
444 // Here, the actual `Mesh` is created. We set the indices, vertices, normals and UVs created above and specify the topology of the mesh.
445 Mesh::new(
446 bevy::render::mesh::PrimitiveTopology::TriangleList,
447 RenderAssetUsages::default(),
448 )
449 .with_inserted_indices(bevy::render::mesh::Indices::U32(indices))
450 .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
451 .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
452 .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
453 }
48fn star(
49 mut commands: Commands,
50 // We will add a new Mesh for the star being created
51 mut meshes: ResMut<Assets<Mesh>>,
52) {
53 // Let's define the mesh for the object we want to draw: a nice star.
54 // We will specify here what kind of topology is used to define the mesh,
55 // that is, how triangles are built from the vertices. We will use a
56 // triangle list, meaning that each vertex of the triangle has to be
57 // specified. We set `RenderAssetUsages::RENDER_WORLD`, meaning this mesh
58 // will not be accessible in future frames from the `meshes` resource, in
59 // order to save on memory once it has been uploaded to the GPU.
60 let mut star = Mesh::new(
61 PrimitiveTopology::TriangleList,
62 RenderAssetUsages::RENDER_WORLD,
63 );
64
65 // Vertices need to have a position attribute. We will use the following
66 // vertices (I hope you can spot the star in the schema).
67 //
68 // 1
69 //
70 // 10 2
71 // 9 0 3
72 // 8 4
73 // 6
74 // 7 5
75 //
76 // These vertices are specified in 3D space.
77 let mut v_pos = vec![[0.0, 0.0, 0.0]];
78 for i in 0..10 {
79 // The angle between each vertex is 1/10 of a full rotation.
80 let a = i as f32 * PI / 5.0;
81 // The radius of inner vertices (even indices) is 100. For outer vertices (odd indices) it's 200.
82 let r = (1 - i % 2) as f32 * 100.0 + 100.0;
83 // Add the vertex position.
84 v_pos.push([r * ops::sin(a), r * ops::cos(a), 0.0]);
85 }
86 // Set the position attribute
87 star.insert_attribute(Mesh::ATTRIBUTE_POSITION, v_pos);
88 // And a RGB color attribute as well. A built-in `Mesh::ATTRIBUTE_COLOR` exists, but we
89 // use a custom vertex attribute here for demonstration purposes.
90 let mut v_color: Vec<u32> = vec![LinearRgba::BLACK.as_u32()];
91 v_color.extend_from_slice(&[LinearRgba::from(YELLOW).as_u32(); 10]);
92 star.insert_attribute(
93 MeshVertexAttribute::new("Vertex_Color", 1, VertexFormat::Uint32),
94 v_color,
95 );
96
97 // Now, we specify the indices of the vertex that are going to compose the
98 // triangles in our star. Vertices in triangles have to be specified in CCW
99 // winding (that will be the front face, colored). Since we are using
100 // triangle list, we will specify each triangle as 3 vertices
101 // First triangle: 0, 2, 1
102 // Second triangle: 0, 3, 2
103 // Third triangle: 0, 4, 3
104 // etc
105 // Last triangle: 0, 1, 10
106 let mut indices = vec![0, 1, 10];
107 for i in 2..=10 {
108 indices.extend_from_slice(&[0, i, i - 1]);
109 }
110 star.insert_indices(Indices::U32(indices));
111
112 // We can now spawn the entities for the star and the camera
113 commands.spawn((
114 // We use a marker component to identify the custom colored meshes
115 ColoredMesh2d,
116 // The `Handle<Mesh>` needs to be wrapped in a `Mesh2d` for 2D rendering
117 Mesh2d(meshes.add(star)),
118 ));
119
120 commands.spawn(Camera2d);
121}
39fn setup(
40 mut commands: Commands,
41 asset_server: Res<AssetServer>,
42 mut meshes: ResMut<Assets<Mesh>>,
43 mut materials: ResMut<Assets<StandardMaterial>>,
44 mut skinned_mesh_inverse_bindposes_assets: ResMut<Assets<SkinnedMeshInverseBindposes>>,
45) {
46 // Create a camera
47 commands.spawn((
48 Camera3d::default(),
49 Transform::from_xyz(2.5, 2.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
50 ));
51
52 // Create inverse bindpose matrices for a skeleton consists of 2 joints
53 let inverse_bindposes = skinned_mesh_inverse_bindposes_assets.add(vec![
54 Mat4::from_translation(Vec3::new(-0.5, -1.0, 0.0)),
55 Mat4::from_translation(Vec3::new(-0.5, -1.0, 0.0)),
56 ]);
57
58 // Create a mesh
59 let mesh = Mesh::new(
60 PrimitiveTopology::TriangleList,
61 RenderAssetUsages::RENDER_WORLD,
62 )
63 // Set mesh vertex positions
64 .with_inserted_attribute(
65 Mesh::ATTRIBUTE_POSITION,
66 vec![
67 [0.0, 0.0, 0.0],
68 [1.0, 0.0, 0.0],
69 [0.0, 0.5, 0.0],
70 [1.0, 0.5, 0.0],
71 [0.0, 1.0, 0.0],
72 [1.0, 1.0, 0.0],
73 [0.0, 1.5, 0.0],
74 [1.0, 1.5, 0.0],
75 [0.0, 2.0, 0.0],
76 [1.0, 2.0, 0.0],
77 ],
78 )
79 // Add UV coordinates that map the left half of the texture since its a 1 x
80 // 2 rectangle.
81 .with_inserted_attribute(
82 Mesh::ATTRIBUTE_UV_0,
83 vec![
84 [0.0, 0.00],
85 [0.5, 0.00],
86 [0.0, 0.25],
87 [0.5, 0.25],
88 [0.0, 0.50],
89 [0.5, 0.50],
90 [0.0, 0.75],
91 [0.5, 0.75],
92 [0.0, 1.00],
93 [0.5, 1.00],
94 ],
95 )
96 // Set mesh vertex normals
97 .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.0, 0.0, 1.0]; 10])
98 // Set mesh vertex joint indices for mesh skinning.
99 // Each vertex gets 4 indices used to address the `JointTransforms` array in the vertex shader
100 // as well as `SkinnedMeshJoint` array in the `SkinnedMesh` component.
101 // This means that a maximum of 4 joints can affect a single vertex.
102 .with_inserted_attribute(
103 Mesh::ATTRIBUTE_JOINT_INDEX,
104 // Need to be explicit here as [u16; 4] could be either Uint16x4 or Unorm16x4.
105 VertexAttributeValues::Uint16x4(vec![
106 [0, 0, 0, 0],
107 [0, 0, 0, 0],
108 [0, 1, 0, 0],
109 [0, 1, 0, 0],
110 [0, 1, 0, 0],
111 [0, 1, 0, 0],
112 [0, 1, 0, 0],
113 [0, 1, 0, 0],
114 [0, 1, 0, 0],
115 [0, 1, 0, 0],
116 ]),
117 )
118 // Set mesh vertex joint weights for mesh skinning.
119 // Each vertex gets 4 joint weights corresponding to the 4 joint indices assigned to it.
120 // The sum of these weights should equal to 1.
121 .with_inserted_attribute(
122 Mesh::ATTRIBUTE_JOINT_WEIGHT,
123 vec![
124 [1.00, 0.00, 0.0, 0.0],
125 [1.00, 0.00, 0.0, 0.0],
126 [0.75, 0.25, 0.0, 0.0],
127 [0.75, 0.25, 0.0, 0.0],
128 [0.50, 0.50, 0.0, 0.0],
129 [0.50, 0.50, 0.0, 0.0],
130 [0.25, 0.75, 0.0, 0.0],
131 [0.25, 0.75, 0.0, 0.0],
132 [0.00, 1.00, 0.0, 0.0],
133 [0.00, 1.00, 0.0, 0.0],
134 ],
135 )
136 // Tell bevy to construct triangles from a list of vertex indices,
137 // where each 3 vertex indices form a triangle.
138 .with_inserted_indices(Indices::U16(vec![
139 0, 1, 3, 0, 3, 2, 2, 3, 5, 2, 5, 4, 4, 5, 7, 4, 7, 6, 6, 7, 9, 6, 9, 8,
140 ]));
141
142 let mesh = meshes.add(mesh);
143
144 // We're seeding the PRNG here to make this example deterministic for testing purposes.
145 // This isn't strictly required in practical use unless you need your app to be deterministic.
146 let mut rng = ChaCha8Rng::seed_from_u64(42);
147
148 for i in -5..5 {
149 // Create joint entities
150 let joint_0 = commands
151 .spawn(Transform::from_xyz(
152 i as f32 * 1.5,
153 0.0,
154 // Move quads back a small amount to avoid Z-fighting and not
155 // obscure the transform gizmos.
156 -(i as f32 * 0.01).abs(),
157 ))
158 .id();
159 let joint_1 = commands.spawn((AnimatedJoint(i), Transform::IDENTITY)).id();
160
161 // Set joint_1 as a child of joint_0.
162 commands.entity(joint_0).add_children(&[joint_1]);
163
164 // Each joint in this vector corresponds to each inverse bindpose matrix in `SkinnedMeshInverseBindposes`.
165 let joint_entities = vec![joint_0, joint_1];
166
167 // Create skinned mesh renderer. Note that its transform doesn't affect the position of the mesh.
168 commands.spawn((
169 Mesh3d(mesh.clone()),
170 MeshMaterial3d(materials.add(StandardMaterial {
171 base_color: Color::srgb(
172 rng.gen_range(0.0..1.0),
173 rng.gen_range(0.0..1.0),
174 rng.gen_range(0.0..1.0),
175 ),
176 base_color_texture: Some(asset_server.load("textures/uv_checker_bw.png")),
177 ..default()
178 })),
179 SkinnedMesh {
180 inverse_bindposes: inverse_bindposes.clone(),
181 joints: joint_entities,
182 },
183 ));
184 }
185}
108fn create_cube_mesh() -> Mesh {
109 // Keep the mesh data accessible in future frames to be able to mutate it in toggle_texture.
110 Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD)
111 .with_inserted_attribute(
112 Mesh::ATTRIBUTE_POSITION,
113 // Each array is an [x, y, z] coordinate in local space.
114 // The camera coordinate space is right-handed x-right, y-up, z-back. This means "forward" is -Z.
115 // Meshes always rotate around their local [0, 0, 0] when a rotation is applied to their Transform.
116 // By centering our mesh around the origin, rotating the mesh preserves its center of mass.
117 vec![
118 // top (facing towards +y)
119 [-0.5, 0.5, -0.5], // vertex with index 0
120 [0.5, 0.5, -0.5], // vertex with index 1
121 [0.5, 0.5, 0.5], // etc. until 23
122 [-0.5, 0.5, 0.5],
123 // bottom (-y)
124 [-0.5, -0.5, -0.5],
125 [0.5, -0.5, -0.5],
126 [0.5, -0.5, 0.5],
127 [-0.5, -0.5, 0.5],
128 // right (+x)
129 [0.5, -0.5, -0.5],
130 [0.5, -0.5, 0.5],
131 [0.5, 0.5, 0.5], // This vertex is at the same position as vertex with index 2, but they'll have different UV and normal
132 [0.5, 0.5, -0.5],
133 // left (-x)
134 [-0.5, -0.5, -0.5],
135 [-0.5, -0.5, 0.5],
136 [-0.5, 0.5, 0.5],
137 [-0.5, 0.5, -0.5],
138 // back (+z)
139 [-0.5, -0.5, 0.5],
140 [-0.5, 0.5, 0.5],
141 [0.5, 0.5, 0.5],
142 [0.5, -0.5, 0.5],
143 // forward (-z)
144 [-0.5, -0.5, -0.5],
145 [-0.5, 0.5, -0.5],
146 [0.5, 0.5, -0.5],
147 [0.5, -0.5, -0.5],
148 ],
149 )
150 // Set-up UV coordinates to point to the upper (V < 0.5), "dirt+grass" part of the texture.
151 // Take a look at the custom image (assets/textures/array_texture.png)
152 // so the UV coords will make more sense
153 // Note: (0.0, 0.0) = Top-Left in UV mapping, (1.0, 1.0) = Bottom-Right in UV mapping
154 .with_inserted_attribute(
155 Mesh::ATTRIBUTE_UV_0,
156 vec![
157 // Assigning the UV coords for the top side.
158 [0.0, 0.2], [0.0, 0.0], [1.0, 0.0], [1.0, 0.2],
159 // Assigning the UV coords for the bottom side.
160 [0.0, 0.45], [0.0, 0.25], [1.0, 0.25], [1.0, 0.45],
161 // Assigning the UV coords for the right side.
162 [1.0, 0.45], [0.0, 0.45], [0.0, 0.2], [1.0, 0.2],
163 // Assigning the UV coords for the left side.
164 [1.0, 0.45], [0.0, 0.45], [0.0, 0.2], [1.0, 0.2],
165 // Assigning the UV coords for the back side.
166 [0.0, 0.45], [0.0, 0.2], [1.0, 0.2], [1.0, 0.45],
167 // Assigning the UV coords for the forward side.
168 [0.0, 0.45], [0.0, 0.2], [1.0, 0.2], [1.0, 0.45],
169 ],
170 )
171 // For meshes with flat shading, normals are orthogonal (pointing out) from the direction of
172 // the surface.
173 // Normals are required for correct lighting calculations.
174 // Each array represents a normalized vector, which length should be equal to 1.0.
175 .with_inserted_attribute(
176 Mesh::ATTRIBUTE_NORMAL,
177 vec![
178 // Normals for the top side (towards +y)
179 [0.0, 1.0, 0.0],
180 [0.0, 1.0, 0.0],
181 [0.0, 1.0, 0.0],
182 [0.0, 1.0, 0.0],
183 // Normals for the bottom side (towards -y)
184 [0.0, -1.0, 0.0],
185 [0.0, -1.0, 0.0],
186 [0.0, -1.0, 0.0],
187 [0.0, -1.0, 0.0],
188 // Normals for the right side (towards +x)
189 [1.0, 0.0, 0.0],
190 [1.0, 0.0, 0.0],
191 [1.0, 0.0, 0.0],
192 [1.0, 0.0, 0.0],
193 // Normals for the left side (towards -x)
194 [-1.0, 0.0, 0.0],
195 [-1.0, 0.0, 0.0],
196 [-1.0, 0.0, 0.0],
197 [-1.0, 0.0, 0.0],
198 // Normals for the back side (towards +z)
199 [0.0, 0.0, 1.0],
200 [0.0, 0.0, 1.0],
201 [0.0, 0.0, 1.0],
202 [0.0, 0.0, 1.0],
203 // Normals for the forward side (towards -z)
204 [0.0, 0.0, -1.0],
205 [0.0, 0.0, -1.0],
206 [0.0, 0.0, -1.0],
207 [0.0, 0.0, -1.0],
208 ],
209 )
210 // Create the triangles out of the 24 vertices we created.
211 // To construct a square, we need 2 triangles, therefore 12 triangles in total.
212 // To construct a triangle, we need the indices of its 3 defined vertices, adding them one
213 // by one, in a counter-clockwise order (relative to the position of the viewer, the order
214 // should appear counter-clockwise from the front of the triangle, in this case from outside the cube).
215 // Read more about how to correctly build a mesh manually in the Bevy documentation of a Mesh,
216 // further examples and the implementation of the built-in shapes.
217 //
218 // The first two defined triangles look like this (marked with the vertex indices,
219 // and the axis), when looking down at the top (+y) of the cube:
220 // -Z
221 // ^
222 // 0---1
223 // | /|
224 // | / | -> +X
225 // |/ |
226 // 3---2
227 //
228 // The right face's (+x) triangles look like this, seen from the outside of the cube.
229 // +Y
230 // ^
231 // 10--11
232 // | /|
233 // | / | -> -Z
234 // |/ |
235 // 9---8
236 //
237 // The back face's (+z) triangles look like this, seen from the outside of the cube.
238 // +Y
239 // ^
240 // 17--18
241 // |\ |
242 // | \ | -> +X
243 // | \|
244 // 16--19
245 .with_inserted_indices(Indices::U32(vec![
246 0,3,1 , 1,3,2, // triangles making up the top (+y) facing side.
247 4,5,7 , 5,6,7, // bottom (-y)
248 8,11,9 , 9,11,10, // right (+x)
249 12,13,15 , 13,14,15, // left (-x)
250 16,19,17 , 17,19,18, // back (+z)
251 20,21,23 , 21,22,23, // forward (-z)
252 ]))
253}
Sourcepub fn primitive_topology(&self) -> PrimitiveTopology
pub fn primitive_topology(&self) -> PrimitiveTopology
Returns the topology of the mesh.
Examples found in repository?
12fn setup(
13 mut commands: Commands,
14 asset_server: Res<AssetServer>,
15 meshes: Res<Assets<Mesh>>,
16 mut materials: ResMut<Assets<StandardMaterial>>,
17) {
18 // By default AssetServer will load assets from inside the "assets" folder.
19 // For example, the next line will load GltfAssetLabel::Primitive{mesh:0,primitive:0}.from_asset("ROOT/assets/models/cube/cube.gltf"),
20 // where "ROOT" is the directory of the Application.
21 //
22 // This can be overridden by setting [`AssetPlugin.file_path`].
23 let cube_handle = asset_server.load(
24 GltfAssetLabel::Primitive {
25 mesh: 0,
26 primitive: 0,
27 }
28 .from_asset("models/cube/cube.gltf"),
29 );
30 let sphere_handle = asset_server.load(
31 GltfAssetLabel::Primitive {
32 mesh: 0,
33 primitive: 0,
34 }
35 .from_asset("models/sphere/sphere.gltf"),
36 );
37
38 // All assets end up in their Assets<T> collection once they are done loading:
39 if let Some(sphere) = meshes.get(&sphere_handle) {
40 // You might notice that this doesn't run! This is because assets load in parallel without
41 // blocking. When an asset has loaded, it will appear in relevant Assets<T>
42 // collection.
43 info!("{:?}", sphere.primitive_topology());
44 } else {
45 info!("sphere hasn't loaded yet");
46 }
47
48 // You can load all assets in a folder like this. They will be loaded in parallel without
49 // blocking. The LoadedFolder asset holds handles to each asset in the folder. These are all
50 // dependencies of the LoadedFolder asset, meaning you can wait for the LoadedFolder asset to
51 // fire AssetEvent::LoadedWithDependencies if you want to wait for all assets in the folder
52 // to load.
53 // If you want to keep the assets in the folder alive, make sure you store the returned handle
54 // somewhere.
55 let _loaded_folder: Handle<LoadedFolder> = asset_server.load_folder("models/torus");
56
57 // If you want a handle to a specific asset in a loaded folder, the easiest way to get one is to call load.
58 // It will _not_ be loaded a second time.
59 // The LoadedFolder asset will ultimately also hold handles to the assets, but waiting for it to load
60 // and finding the right handle is more work!
61 let torus_handle = asset_server.load(
62 GltfAssetLabel::Primitive {
63 mesh: 0,
64 primitive: 0,
65 }
66 .from_asset("models/torus/torus.gltf"),
67 );
68
69 // You can also add assets directly to their Assets<T> storage:
70 let material_handle = materials.add(StandardMaterial {
71 base_color: Color::srgb(0.8, 0.7, 0.6),
72 ..default()
73 });
74
75 // torus
76 commands.spawn((
77 Mesh3d(torus_handle),
78 MeshMaterial3d(material_handle.clone()),
79 Transform::from_xyz(-3.0, 0.0, 0.0),
80 ));
81 // cube
82 commands.spawn((
83 Mesh3d(cube_handle),
84 MeshMaterial3d(material_handle.clone()),
85 Transform::from_xyz(0.0, 0.0, 0.0),
86 ));
87 // sphere
88 commands.spawn((
89 Mesh3d(sphere_handle),
90 MeshMaterial3d(material_handle),
91 Transform::from_xyz(3.0, 0.0, 0.0),
92 ));
93 // light
94 commands.spawn((PointLight::default(), Transform::from_xyz(4.0, 5.0, 4.0)));
95 // camera
96 commands.spawn((
97 Camera3d::default(),
98 Transform::from_xyz(0.0, 3.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
99 ));
100}
Sourcepub 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
.
Aabb
of entities with modified mesh are not updated automatically.
§Panics
Panics when the format of the values does not match the attribute’s format.
Examples found in repository?
13fn setup(
14 mut commands: Commands,
15 mut meshes: ResMut<Assets<Mesh>>,
16 mut materials: ResMut<Assets<ColorMaterial>>,
17 asset_server: Res<AssetServer>,
18) {
19 // Load the Bevy logo as a texture
20 let texture_handle = asset_server.load("branding/banner.png");
21 // Build a default quad mesh
22 let mut mesh = Mesh::from(Rectangle::default());
23 // Build vertex colors for the quad. One entry per vertex (the corners of the quad)
24 let vertex_colors: Vec<[f32; 4]> = vec![
25 LinearRgba::RED.to_f32_array(),
26 LinearRgba::GREEN.to_f32_array(),
27 LinearRgba::BLUE.to_f32_array(),
28 LinearRgba::WHITE.to_f32_array(),
29 ];
30 // Insert the vertex colors as an attribute
31 mesh.insert_attribute(Mesh::ATTRIBUTE_COLOR, vertex_colors);
32
33 let mesh_handle = meshes.add(mesh);
34
35 commands.spawn(Camera2d);
36
37 // Spawn the quad with vertex colors
38 commands.spawn((
39 Mesh2d(mesh_handle.clone()),
40 MeshMaterial2d(materials.add(ColorMaterial::default())),
41 Transform::from_translation(Vec3::new(-96., 0., 0.)).with_scale(Vec3::splat(128.)),
42 ));
43
44 // Spawning the quad with vertex colors and a texture results in tinting
45 commands.spawn((
46 Mesh2d(mesh_handle),
47 MeshMaterial2d(materials.add(texture_handle)),
48 Transform::from_translation(Vec3::new(96., 0., 0.)).with_scale(Vec3::splat(128.)),
49 ));
50}
More examples
13fn setup(
14 mut commands: Commands,
15 mut meshes: ResMut<Assets<Mesh>>,
16 mut materials: ResMut<Assets<StandardMaterial>>,
17) {
18 // plane
19 commands.spawn((
20 Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
21 MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
22 ));
23 // cube
24 // Assign vertex colors based on vertex positions
25 let mut colorful_cube = Mesh::from(Cuboid::default());
26 if let Some(VertexAttributeValues::Float32x3(positions)) =
27 colorful_cube.attribute(Mesh::ATTRIBUTE_POSITION)
28 {
29 let colors: Vec<[f32; 4]> = positions
30 .iter()
31 .map(|[r, g, b]| [(1. - *r) / 2., (1. - *g) / 2., (1. - *b) / 2., 1.])
32 .collect();
33 colorful_cube.insert_attribute(Mesh::ATTRIBUTE_COLOR, colors);
34 }
35 commands.spawn((
36 Mesh3d(meshes.add(colorful_cube)),
37 // This is the default color, but note that vertex colors are
38 // multiplied by the base color, so you'll likely want this to be
39 // white if using vertex colors.
40 MeshMaterial3d(materials.add(Color::srgb(1., 1., 1.))),
41 Transform::from_xyz(0.0, 0.5, 0.0),
42 ));
43
44 // Light
45 commands.spawn((
46 PointLight {
47 shadows_enabled: true,
48 ..default()
49 },
50 Transform::from_xyz(4.0, 5.0, 4.0).looking_at(Vec3::ZERO, Vec3::Y),
51 ));
52
53 // Camera
54 commands.spawn((
55 Camera3d::default(),
56 Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
57 ));
58}
53fn setup_scene(
54 asset_server: Res<AssetServer>,
55 mut images: ResMut<Assets<Image>>,
56 mut commands: Commands,
57 mut meshes: ResMut<Assets<Mesh>>,
58 mut materials: ResMut<Assets<StandardMaterial>>,
59) {
60 commands.insert_resource(AmbientLight {
61 color: Color::WHITE,
62 brightness: 300.0,
63 ..default()
64 });
65 commands.insert_resource(CameraMode::Chase);
66 commands.spawn((
67 DirectionalLight {
68 illuminance: 3_000.0,
69 shadows_enabled: true,
70 ..default()
71 },
72 Transform::default().looking_to(Vec3::new(-1.0, -0.7, -1.0), Vec3::X),
73 ));
74 // Sky
75 commands.spawn((
76 Mesh3d(meshes.add(Sphere::default())),
77 MeshMaterial3d(materials.add(StandardMaterial {
78 unlit: true,
79 base_color: Color::linear_rgb(0.1, 0.6, 1.0),
80 ..default()
81 })),
82 Transform::default().with_scale(Vec3::splat(-4000.0)),
83 ));
84 // Ground
85 let mut plane: Mesh = Plane3d::default().into();
86 let uv_size = 4000.0;
87 let uvs = vec![[uv_size, 0.0], [0.0, 0.0], [0.0, uv_size], [uv_size; 2]];
88 plane.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
89 commands.spawn((
90 Mesh3d(meshes.add(plane)),
91 MeshMaterial3d(materials.add(StandardMaterial {
92 base_color: Color::WHITE,
93 perceptual_roughness: 1.0,
94 base_color_texture: Some(images.add(uv_debug_texture())),
95 ..default()
96 })),
97 Transform::from_xyz(0.0, -0.65, 0.0).with_scale(Vec3::splat(80.)),
98 ));
99
100 spawn_cars(&asset_server, &mut meshes, &mut materials, &mut commands);
101 spawn_trees(&mut meshes, &mut materials, &mut commands);
102 spawn_barriers(&mut meshes, &mut materials, &mut commands);
103}
48fn star(
49 mut commands: Commands,
50 // We will add a new Mesh for the star being created
51 mut meshes: ResMut<Assets<Mesh>>,
52) {
53 // Let's define the mesh for the object we want to draw: a nice star.
54 // We will specify here what kind of topology is used to define the mesh,
55 // that is, how triangles are built from the vertices. We will use a
56 // triangle list, meaning that each vertex of the triangle has to be
57 // specified. We set `RenderAssetUsages::RENDER_WORLD`, meaning this mesh
58 // will not be accessible in future frames from the `meshes` resource, in
59 // order to save on memory once it has been uploaded to the GPU.
60 let mut star = Mesh::new(
61 PrimitiveTopology::TriangleList,
62 RenderAssetUsages::RENDER_WORLD,
63 );
64
65 // Vertices need to have a position attribute. We will use the following
66 // vertices (I hope you can spot the star in the schema).
67 //
68 // 1
69 //
70 // 10 2
71 // 9 0 3
72 // 8 4
73 // 6
74 // 7 5
75 //
76 // These vertices are specified in 3D space.
77 let mut v_pos = vec![[0.0, 0.0, 0.0]];
78 for i in 0..10 {
79 // The angle between each vertex is 1/10 of a full rotation.
80 let a = i as f32 * PI / 5.0;
81 // The radius of inner vertices (even indices) is 100. For outer vertices (odd indices) it's 200.
82 let r = (1 - i % 2) as f32 * 100.0 + 100.0;
83 // Add the vertex position.
84 v_pos.push([r * ops::sin(a), r * ops::cos(a), 0.0]);
85 }
86 // Set the position attribute
87 star.insert_attribute(Mesh::ATTRIBUTE_POSITION, v_pos);
88 // And a RGB color attribute as well. A built-in `Mesh::ATTRIBUTE_COLOR` exists, but we
89 // use a custom vertex attribute here for demonstration purposes.
90 let mut v_color: Vec<u32> = vec![LinearRgba::BLACK.as_u32()];
91 v_color.extend_from_slice(&[LinearRgba::from(YELLOW).as_u32(); 10]);
92 star.insert_attribute(
93 MeshVertexAttribute::new("Vertex_Color", 1, VertexFormat::Uint32),
94 v_color,
95 );
96
97 // Now, we specify the indices of the vertex that are going to compose the
98 // triangles in our star. Vertices in triangles have to be specified in CCW
99 // winding (that will be the front face, colored). Since we are using
100 // triangle list, we will specify each triangle as 3 vertices
101 // First triangle: 0, 2, 1
102 // Second triangle: 0, 3, 2
103 // Third triangle: 0, 4, 3
104 // etc
105 // Last triangle: 0, 1, 10
106 let mut indices = vec![0, 1, 10];
107 for i in 2..=10 {
108 indices.extend_from_slice(&[0, i, i - 1]);
109 }
110 star.insert_indices(Indices::U32(indices));
111
112 // We can now spawn the entities for the star and the camera
113 commands.spawn((
114 // We use a marker component to identify the custom colored meshes
115 ColoredMesh2d,
116 // The `Handle<Mesh>` needs to be wrapped in a `Mesh2d` for 2D rendering
117 Mesh2d(meshes.add(star)),
118 ));
119
120 commands.spawn(Camera2d);
121}
Sourcepub fn with_inserted_attribute(
self,
attribute: MeshVertexAttribute,
values: impl Into<VertexAttributeValues>,
) -> Mesh
pub fn with_inserted_attribute( self, attribute: MeshVertexAttribute, values: impl Into<VertexAttributeValues>, ) -> Mesh
Consumes the mesh and returns a mesh with data set for a vertex attribute (position, normal, etc.).
The name will often be one of the associated constants such as Mesh::ATTRIBUTE_POSITION
.
(Alternatively, you can use Mesh::insert_attribute
to mutate an existing mesh in-place)
Aabb
of entities with modified mesh are not updated automatically.
§Panics
Panics when the format of the values does not match the attribute’s format.
Examples found in repository?
98 fn from(line: LineList) -> Self {
99 let vertices: Vec<_> = line.lines.into_iter().flat_map(|(a, b)| [a, b]).collect();
100
101 Mesh::new(
102 // This tells wgpu that the positions are list of lines
103 // where every pair is a start and end point
104 PrimitiveTopology::LineList,
105 RenderAssetUsages::RENDER_WORLD,
106 )
107 // Add the vertices positions as an attribute
108 .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
109 }
110}
111
112/// A list of points that will have a line drawn between each consecutive points
113#[derive(Debug, Clone)]
114struct LineStrip {
115 points: Vec<Vec3>,
116}
117
118impl From<LineStrip> for Mesh {
119 fn from(line: LineStrip) -> Self {
120 Mesh::new(
121 // This tells wgpu that the positions are a list of points
122 // where a line will be drawn between each consecutive point
123 PrimitiveTopology::LineStrip,
124 RenderAssetUsages::RENDER_WORLD,
125 )
126 // Add the point positions as an attribute
127 .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, line.points)
128 }
More examples
32fn setup(
33 mut commands: Commands,
34 mut meshes: ResMut<Assets<Mesh>>,
35 mut materials: ResMut<Assets<CustomMaterial>>,
36) {
37 let mesh = Mesh::from(Cuboid::default())
38 // Sets the custom attribute
39 .with_inserted_attribute(
40 ATTRIBUTE_BLEND_COLOR,
41 // The cube mesh has 24 vertices (6 faces, 4 vertices per face), so we insert one BlendColor for each
42 vec![[1.0, 0.0, 0.0, 1.0]; 24],
43 );
44
45 // cube
46 commands.spawn((
47 Mesh3d(meshes.add(mesh)),
48 MeshMaterial3d(materials.add(CustomMaterial {
49 color: LinearRgba::WHITE,
50 })),
51 Transform::from_xyz(0.0, 0.5, 0.0),
52 ));
53
54 // camera
55 commands.spawn((
56 Camera3d::default(),
57 Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
58 ));
59}
57fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
58 // Build a custom triangle mesh with colors
59 // We define a custom mesh because the examples only uses a limited
60 // set of vertex attributes for simplicity
61 let mesh = Mesh::new(
62 PrimitiveTopology::TriangleList,
63 RenderAssetUsages::default(),
64 )
65 .with_inserted_indices(Indices::U32(vec![0, 1, 2]))
66 .with_inserted_attribute(
67 Mesh::ATTRIBUTE_POSITION,
68 vec![
69 vec3(-0.5, -0.5, 0.0),
70 vec3(0.5, -0.5, 0.0),
71 vec3(0.0, 0.25, 0.0),
72 ],
73 )
74 .with_inserted_attribute(
75 Mesh::ATTRIBUTE_COLOR,
76 vec![
77 vec4(1.0, 0.0, 0.0, 1.0),
78 vec4(0.0, 1.0, 0.0, 1.0),
79 vec4(0.0, 0.0, 1.0, 1.0),
80 ],
81 );
82
83 // spawn 3 triangles to show that batching works
84 for (x, y) in [-0.5, 0.0, 0.5].into_iter().zip([-0.25, 0.5, -0.25]) {
85 // Spawn an entity with all the required components for it to be rendered with our custom pipeline
86 commands.spawn((
87 // We use a marker component to identify the mesh that will be rendered
88 // with our specialized pipeline
89 CustomRenderedEntity,
90 // We need to add the mesh handle to the entity
91 Mesh3d(meshes.add(mesh.clone())),
92 Transform::from_xyz(x, y, 0.0),
93 ));
94 }
95
96 // Spawn the camera.
97 commands.spawn((
98 Camera3d::default(),
99 // Move the camera back a bit to see all the triangles
100 Transform::from_xyz(0.0, 0.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y),
101 ));
102}
402 fn build(&self) -> Mesh {
403 let radius = self.heart.radius;
404 // The curved parts of each wing (half) of the heart have an angle of `PI * 1.25` or 225°
405 let wing_angle = PI * 1.25;
406
407 // We create buffers for the vertices, their normals and UVs, as well as the indices used to connect the vertices.
408 let mut vertices = Vec::with_capacity(2 * self.resolution);
409 let mut uvs = Vec::with_capacity(2 * self.resolution);
410 let mut indices = Vec::with_capacity(6 * self.resolution - 9);
411 // Since the heart is flat, we know all the normals are identical already.
412 let normals = vec![[0f32, 0f32, 1f32]; 2 * self.resolution];
413
414 // The point in the middle of the two curved parts of the heart
415 vertices.push([0.0; 3]);
416 uvs.push([0.5, 0.5]);
417
418 // The left wing of the heart, starting from the point in the middle.
419 for i in 1..self.resolution {
420 let angle = (i as f32 / self.resolution as f32) * wing_angle;
421 let (sin, cos) = ops::sin_cos(angle);
422 vertices.push([radius * (cos - 1.0), radius * sin, 0.0]);
423 uvs.push([0.5 - (cos - 1.0) / 4., 0.5 - sin / 2.]);
424 }
425
426 // The bottom tip of the heart
427 vertices.push([0.0, radius * (-1. - SQRT_2), 0.0]);
428 uvs.push([0.5, 1.]);
429
430 // The right wing of the heart, starting from the bottom most point and going towards the middle point.
431 for i in 0..self.resolution - 1 {
432 let angle = (i as f32 / self.resolution as f32) * wing_angle - PI / 4.;
433 let (sin, cos) = ops::sin_cos(angle);
434 vertices.push([radius * (cos + 1.0), radius * sin, 0.0]);
435 uvs.push([0.5 - (cos + 1.0) / 4., 0.5 - sin / 2.]);
436 }
437
438 // This is where we build all the triangles from the points created above.
439 // Each triangle has one corner on the middle point with the other two being adjacent points on the perimeter of the heart.
440 for i in 2..2 * self.resolution as u32 {
441 indices.extend_from_slice(&[i - 1, i, 0]);
442 }
443
444 // Here, the actual `Mesh` is created. We set the indices, vertices, normals and UVs created above and specify the topology of the mesh.
445 Mesh::new(
446 bevy::render::mesh::PrimitiveTopology::TriangleList,
447 RenderAssetUsages::default(),
448 )
449 .with_inserted_indices(bevy::render::mesh::Indices::U32(indices))
450 .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
451 .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
452 .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
453 }
39fn setup(
40 mut commands: Commands,
41 asset_server: Res<AssetServer>,
42 mut meshes: ResMut<Assets<Mesh>>,
43 mut materials: ResMut<Assets<StandardMaterial>>,
44 mut skinned_mesh_inverse_bindposes_assets: ResMut<Assets<SkinnedMeshInverseBindposes>>,
45) {
46 // Create a camera
47 commands.spawn((
48 Camera3d::default(),
49 Transform::from_xyz(2.5, 2.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
50 ));
51
52 // Create inverse bindpose matrices for a skeleton consists of 2 joints
53 let inverse_bindposes = skinned_mesh_inverse_bindposes_assets.add(vec![
54 Mat4::from_translation(Vec3::new(-0.5, -1.0, 0.0)),
55 Mat4::from_translation(Vec3::new(-0.5, -1.0, 0.0)),
56 ]);
57
58 // Create a mesh
59 let mesh = Mesh::new(
60 PrimitiveTopology::TriangleList,
61 RenderAssetUsages::RENDER_WORLD,
62 )
63 // Set mesh vertex positions
64 .with_inserted_attribute(
65 Mesh::ATTRIBUTE_POSITION,
66 vec![
67 [0.0, 0.0, 0.0],
68 [1.0, 0.0, 0.0],
69 [0.0, 0.5, 0.0],
70 [1.0, 0.5, 0.0],
71 [0.0, 1.0, 0.0],
72 [1.0, 1.0, 0.0],
73 [0.0, 1.5, 0.0],
74 [1.0, 1.5, 0.0],
75 [0.0, 2.0, 0.0],
76 [1.0, 2.0, 0.0],
77 ],
78 )
79 // Add UV coordinates that map the left half of the texture since its a 1 x
80 // 2 rectangle.
81 .with_inserted_attribute(
82 Mesh::ATTRIBUTE_UV_0,
83 vec![
84 [0.0, 0.00],
85 [0.5, 0.00],
86 [0.0, 0.25],
87 [0.5, 0.25],
88 [0.0, 0.50],
89 [0.5, 0.50],
90 [0.0, 0.75],
91 [0.5, 0.75],
92 [0.0, 1.00],
93 [0.5, 1.00],
94 ],
95 )
96 // Set mesh vertex normals
97 .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.0, 0.0, 1.0]; 10])
98 // Set mesh vertex joint indices for mesh skinning.
99 // Each vertex gets 4 indices used to address the `JointTransforms` array in the vertex shader
100 // as well as `SkinnedMeshJoint` array in the `SkinnedMesh` component.
101 // This means that a maximum of 4 joints can affect a single vertex.
102 .with_inserted_attribute(
103 Mesh::ATTRIBUTE_JOINT_INDEX,
104 // Need to be explicit here as [u16; 4] could be either Uint16x4 or Unorm16x4.
105 VertexAttributeValues::Uint16x4(vec![
106 [0, 0, 0, 0],
107 [0, 0, 0, 0],
108 [0, 1, 0, 0],
109 [0, 1, 0, 0],
110 [0, 1, 0, 0],
111 [0, 1, 0, 0],
112 [0, 1, 0, 0],
113 [0, 1, 0, 0],
114 [0, 1, 0, 0],
115 [0, 1, 0, 0],
116 ]),
117 )
118 // Set mesh vertex joint weights for mesh skinning.
119 // Each vertex gets 4 joint weights corresponding to the 4 joint indices assigned to it.
120 // The sum of these weights should equal to 1.
121 .with_inserted_attribute(
122 Mesh::ATTRIBUTE_JOINT_WEIGHT,
123 vec![
124 [1.00, 0.00, 0.0, 0.0],
125 [1.00, 0.00, 0.0, 0.0],
126 [0.75, 0.25, 0.0, 0.0],
127 [0.75, 0.25, 0.0, 0.0],
128 [0.50, 0.50, 0.0, 0.0],
129 [0.50, 0.50, 0.0, 0.0],
130 [0.25, 0.75, 0.0, 0.0],
131 [0.25, 0.75, 0.0, 0.0],
132 [0.00, 1.00, 0.0, 0.0],
133 [0.00, 1.00, 0.0, 0.0],
134 ],
135 )
136 // Tell bevy to construct triangles from a list of vertex indices,
137 // where each 3 vertex indices form a triangle.
138 .with_inserted_indices(Indices::U16(vec![
139 0, 1, 3, 0, 3, 2, 2, 3, 5, 2, 5, 4, 4, 5, 7, 4, 7, 6, 6, 7, 9, 6, 9, 8,
140 ]));
141
142 let mesh = meshes.add(mesh);
143
144 // We're seeding the PRNG here to make this example deterministic for testing purposes.
145 // This isn't strictly required in practical use unless you need your app to be deterministic.
146 let mut rng = ChaCha8Rng::seed_from_u64(42);
147
148 for i in -5..5 {
149 // Create joint entities
150 let joint_0 = commands
151 .spawn(Transform::from_xyz(
152 i as f32 * 1.5,
153 0.0,
154 // Move quads back a small amount to avoid Z-fighting and not
155 // obscure the transform gizmos.
156 -(i as f32 * 0.01).abs(),
157 ))
158 .id();
159 let joint_1 = commands.spawn((AnimatedJoint(i), Transform::IDENTITY)).id();
160
161 // Set joint_1 as a child of joint_0.
162 commands.entity(joint_0).add_children(&[joint_1]);
163
164 // Each joint in this vector corresponds to each inverse bindpose matrix in `SkinnedMeshInverseBindposes`.
165 let joint_entities = vec![joint_0, joint_1];
166
167 // Create skinned mesh renderer. Note that its transform doesn't affect the position of the mesh.
168 commands.spawn((
169 Mesh3d(mesh.clone()),
170 MeshMaterial3d(materials.add(StandardMaterial {
171 base_color: Color::srgb(
172 rng.gen_range(0.0..1.0),
173 rng.gen_range(0.0..1.0),
174 rng.gen_range(0.0..1.0),
175 ),
176 base_color_texture: Some(asset_server.load("textures/uv_checker_bw.png")),
177 ..default()
178 })),
179 SkinnedMesh {
180 inverse_bindposes: inverse_bindposes.clone(),
181 joints: joint_entities,
182 },
183 ));
184 }
185}
108fn create_cube_mesh() -> Mesh {
109 // Keep the mesh data accessible in future frames to be able to mutate it in toggle_texture.
110 Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD)
111 .with_inserted_attribute(
112 Mesh::ATTRIBUTE_POSITION,
113 // Each array is an [x, y, z] coordinate in local space.
114 // The camera coordinate space is right-handed x-right, y-up, z-back. This means "forward" is -Z.
115 // Meshes always rotate around their local [0, 0, 0] when a rotation is applied to their Transform.
116 // By centering our mesh around the origin, rotating the mesh preserves its center of mass.
117 vec![
118 // top (facing towards +y)
119 [-0.5, 0.5, -0.5], // vertex with index 0
120 [0.5, 0.5, -0.5], // vertex with index 1
121 [0.5, 0.5, 0.5], // etc. until 23
122 [-0.5, 0.5, 0.5],
123 // bottom (-y)
124 [-0.5, -0.5, -0.5],
125 [0.5, -0.5, -0.5],
126 [0.5, -0.5, 0.5],
127 [-0.5, -0.5, 0.5],
128 // right (+x)
129 [0.5, -0.5, -0.5],
130 [0.5, -0.5, 0.5],
131 [0.5, 0.5, 0.5], // This vertex is at the same position as vertex with index 2, but they'll have different UV and normal
132 [0.5, 0.5, -0.5],
133 // left (-x)
134 [-0.5, -0.5, -0.5],
135 [-0.5, -0.5, 0.5],
136 [-0.5, 0.5, 0.5],
137 [-0.5, 0.5, -0.5],
138 // back (+z)
139 [-0.5, -0.5, 0.5],
140 [-0.5, 0.5, 0.5],
141 [0.5, 0.5, 0.5],
142 [0.5, -0.5, 0.5],
143 // forward (-z)
144 [-0.5, -0.5, -0.5],
145 [-0.5, 0.5, -0.5],
146 [0.5, 0.5, -0.5],
147 [0.5, -0.5, -0.5],
148 ],
149 )
150 // Set-up UV coordinates to point to the upper (V < 0.5), "dirt+grass" part of the texture.
151 // Take a look at the custom image (assets/textures/array_texture.png)
152 // so the UV coords will make more sense
153 // Note: (0.0, 0.0) = Top-Left in UV mapping, (1.0, 1.0) = Bottom-Right in UV mapping
154 .with_inserted_attribute(
155 Mesh::ATTRIBUTE_UV_0,
156 vec![
157 // Assigning the UV coords for the top side.
158 [0.0, 0.2], [0.0, 0.0], [1.0, 0.0], [1.0, 0.2],
159 // Assigning the UV coords for the bottom side.
160 [0.0, 0.45], [0.0, 0.25], [1.0, 0.25], [1.0, 0.45],
161 // Assigning the UV coords for the right side.
162 [1.0, 0.45], [0.0, 0.45], [0.0, 0.2], [1.0, 0.2],
163 // Assigning the UV coords for the left side.
164 [1.0, 0.45], [0.0, 0.45], [0.0, 0.2], [1.0, 0.2],
165 // Assigning the UV coords for the back side.
166 [0.0, 0.45], [0.0, 0.2], [1.0, 0.2], [1.0, 0.45],
167 // Assigning the UV coords for the forward side.
168 [0.0, 0.45], [0.0, 0.2], [1.0, 0.2], [1.0, 0.45],
169 ],
170 )
171 // For meshes with flat shading, normals are orthogonal (pointing out) from the direction of
172 // the surface.
173 // Normals are required for correct lighting calculations.
174 // Each array represents a normalized vector, which length should be equal to 1.0.
175 .with_inserted_attribute(
176 Mesh::ATTRIBUTE_NORMAL,
177 vec![
178 // Normals for the top side (towards +y)
179 [0.0, 1.0, 0.0],
180 [0.0, 1.0, 0.0],
181 [0.0, 1.0, 0.0],
182 [0.0, 1.0, 0.0],
183 // Normals for the bottom side (towards -y)
184 [0.0, -1.0, 0.0],
185 [0.0, -1.0, 0.0],
186 [0.0, -1.0, 0.0],
187 [0.0, -1.0, 0.0],
188 // Normals for the right side (towards +x)
189 [1.0, 0.0, 0.0],
190 [1.0, 0.0, 0.0],
191 [1.0, 0.0, 0.0],
192 [1.0, 0.0, 0.0],
193 // Normals for the left side (towards -x)
194 [-1.0, 0.0, 0.0],
195 [-1.0, 0.0, 0.0],
196 [-1.0, 0.0, 0.0],
197 [-1.0, 0.0, 0.0],
198 // Normals for the back side (towards +z)
199 [0.0, 0.0, 1.0],
200 [0.0, 0.0, 1.0],
201 [0.0, 0.0, 1.0],
202 [0.0, 0.0, 1.0],
203 // Normals for the forward side (towards -z)
204 [0.0, 0.0, -1.0],
205 [0.0, 0.0, -1.0],
206 [0.0, 0.0, -1.0],
207 [0.0, 0.0, -1.0],
208 ],
209 )
210 // Create the triangles out of the 24 vertices we created.
211 // To construct a square, we need 2 triangles, therefore 12 triangles in total.
212 // To construct a triangle, we need the indices of its 3 defined vertices, adding them one
213 // by one, in a counter-clockwise order (relative to the position of the viewer, the order
214 // should appear counter-clockwise from the front of the triangle, in this case from outside the cube).
215 // Read more about how to correctly build a mesh manually in the Bevy documentation of a Mesh,
216 // further examples and the implementation of the built-in shapes.
217 //
218 // The first two defined triangles look like this (marked with the vertex indices,
219 // and the axis), when looking down at the top (+y) of the cube:
220 // -Z
221 // ^
222 // 0---1
223 // | /|
224 // | / | -> +X
225 // |/ |
226 // 3---2
227 //
228 // The right face's (+x) triangles look like this, seen from the outside of the cube.
229 // +Y
230 // ^
231 // 10--11
232 // | /|
233 // | / | -> -Z
234 // |/ |
235 // 9---8
236 //
237 // The back face's (+z) triangles look like this, seen from the outside of the cube.
238 // +Y
239 // ^
240 // 17--18
241 // |\ |
242 // | \ | -> +X
243 // | \|
244 // 16--19
245 .with_inserted_indices(Indices::U32(vec![
246 0,3,1 , 1,3,2, // triangles making up the top (+y) facing side.
247 4,5,7 , 5,6,7, // bottom (-y)
248 8,11,9 , 9,11,10, // right (+x)
249 12,13,15 , 13,14,15, // left (-x)
250 16,19,17 , 17,19,18, // back (+z)
251 20,21,23 , 21,22,23, // forward (-z)
252 ]))
253}
Sourcepub 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
Sourcepub fn with_removed_attribute(
self,
attribute: impl Into<MeshVertexAttributeId>,
) -> Mesh
pub fn with_removed_attribute( self, attribute: impl Into<MeshVertexAttributeId>, ) -> Mesh
Consumes the mesh and returns a mesh without the data for a vertex attribute
(Alternatively, you can use Mesh::remove_attribute
to mutate an existing mesh in-place)
pub fn contains_attribute(&self, id: impl Into<MeshVertexAttributeId>) -> bool
Sourcepub 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 MeshVertexAttributeId
.
Examples found in repository?
13fn setup(
14 mut commands: Commands,
15 mut meshes: ResMut<Assets<Mesh>>,
16 mut materials: ResMut<Assets<StandardMaterial>>,
17) {
18 // plane
19 commands.spawn((
20 Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
21 MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
22 ));
23 // cube
24 // Assign vertex colors based on vertex positions
25 let mut colorful_cube = Mesh::from(Cuboid::default());
26 if let Some(VertexAttributeValues::Float32x3(positions)) =
27 colorful_cube.attribute(Mesh::ATTRIBUTE_POSITION)
28 {
29 let colors: Vec<[f32; 4]> = positions
30 .iter()
31 .map(|[r, g, b]| [(1. - *r) / 2., (1. - *g) / 2., (1. - *b) / 2., 1.])
32 .collect();
33 colorful_cube.insert_attribute(Mesh::ATTRIBUTE_COLOR, colors);
34 }
35 commands.spawn((
36 Mesh3d(meshes.add(colorful_cube)),
37 // This is the default color, but note that vertex colors are
38 // multiplied by the base color, so you'll likely want this to be
39 // white if using vertex colors.
40 MeshMaterial3d(materials.add(Color::srgb(1., 1., 1.))),
41 Transform::from_xyz(0.0, 0.5, 0.0),
42 ));
43
44 // Light
45 commands.spawn((
46 PointLight {
47 shadows_enabled: true,
48 ..default()
49 },
50 Transform::from_xyz(4.0, 5.0, 4.0).looking_at(Vec3::ZERO, Vec3::Y),
51 ));
52
53 // Camera
54 commands.spawn((
55 Camera3d::default(),
56 Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
57 ));
58}
More examples
284fn spawn_small_cubes(
285 commands: &mut Commands,
286 meshes: &mut Assets<Mesh>,
287 materials: &mut Assets<StandardMaterial>,
288) {
289 // Add the cube mesh.
290 let small_cube = meshes.add(Cuboid::new(
291 SMALL_CUBE_SIZE,
292 SMALL_CUBE_SIZE,
293 SMALL_CUBE_SIZE,
294 ));
295
296 // Add the cube material.
297 let small_cube_material = materials.add(StandardMaterial {
298 base_color: SILVER.into(),
299 ..default()
300 });
301
302 // Create the entity that the small cubes will be parented to. This is the
303 // entity that we rotate.
304 let sphere_parent = commands
305 .spawn(Transform::from_translation(Vec3::ZERO))
306 .insert(Visibility::default())
307 .insert(SphereParent)
308 .id();
309
310 // Now we have to figure out where to place the cubes. To do that, we create
311 // a sphere mesh, but we don't add it to the scene. Instead, we inspect the
312 // sphere mesh to find the positions of its vertices, and spawn a small cube
313 // at each one. That way, we end up with a bunch of cubes arranged in a
314 // spherical shape.
315
316 // Create the sphere mesh, and extract the positions of its vertices.
317 let sphere = Sphere::new(OUTER_RADIUS)
318 .mesh()
319 .ico(OUTER_SUBDIVISION_COUNT)
320 .unwrap();
321 let sphere_positions = sphere.attribute(Mesh::ATTRIBUTE_POSITION).unwrap();
322
323 // At each vertex, create a small cube.
324 for sphere_position in sphere_positions.as_float3().unwrap() {
325 let sphere_position = Vec3::from_slice(sphere_position);
326 let small_cube = commands
327 .spawn(Mesh3d(small_cube.clone()))
328 .insert(MeshMaterial3d(small_cube_material.clone()))
329 .insert(Transform::from_translation(sphere_position))
330 .id();
331 commands.entity(sphere_parent).add_child(small_cube);
332 }
333}
Sourcepub 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.
Examples found in repository?
256fn toggle_texture(mesh_to_change: &mut Mesh) {
257 // Get a mutable reference to the values of the UV attribute, so we can iterate over it.
258 let uv_attribute = mesh_to_change.attribute_mut(Mesh::ATTRIBUTE_UV_0).unwrap();
259 // The format of the UV coordinates should be Float32x2.
260 let VertexAttributeValues::Float32x2(uv_attribute) = uv_attribute else {
261 panic!("Unexpected vertex format, expected Float32x2.");
262 };
263
264 // Iterate over the UV coordinates, and change them as we want.
265 for uv_coord in uv_attribute.iter_mut() {
266 // If the UV coordinate points to the upper, "dirt+grass" part of the texture...
267 if (uv_coord[1] + 0.5) < 1.0 {
268 // ... point to the equivalent lower, "sand+water" part instead,
269 uv_coord[1] += 0.5;
270 } else {
271 // else, point back to the upper, "dirt+grass" part.
272 uv_coord[1] -= 0.5;
273 }
274 }
275}
More examples
16fn find_top_material_and_mesh(
17 mut materials: ResMut<Assets<StandardMaterial>>,
18 mut meshes: ResMut<Assets<Mesh>>,
19 time: Res<Time>,
20 mat_query: Query<(
21 &MeshMaterial3d<StandardMaterial>,
22 &Mesh3d,
23 &GltfMaterialName,
24 )>,
25) {
26 for (mat_handle, mesh_handle, name) in mat_query.iter() {
27 // locate a material by material name
28 if name.0 == "Top" {
29 if let Some(material) = materials.get_mut(mat_handle) {
30 if let Color::Hsla(ref mut hsla) = material.base_color {
31 *hsla = hsla.rotate_hue(time.delta_secs() * 100.0);
32 } else {
33 material.base_color = Color::from(Hsla::hsl(0.0, 0.9, 0.7));
34 }
35 }
36
37 if let Some(mesh) = meshes.get_mut(mesh_handle) {
38 if let Some(VertexAttributeValues::Float32x3(positions)) =
39 mesh.attribute_mut(Mesh::ATTRIBUTE_POSITION)
40 {
41 for position in positions {
42 *position = (
43 position[0],
44 1.5 + 0.5 * ops::sin(time.elapsed_secs() / 2.0),
45 position[2],
46 )
47 .into();
48 }
49 }
50 }
51 }
52 }
53}
173fn alter_mesh(
174 mut is_mesh_scaled: Local<bool>,
175 left_shape: Single<&Mesh3d, With<Left>>,
176 mut meshes: ResMut<Assets<Mesh>>,
177) {
178 // Obtain a mutable reference to the Mesh asset.
179 let Some(mesh) = meshes.get_mut(*left_shape) else {
180 return;
181 };
182
183 // Now we can directly manipulate vertices on the mesh. Here, we're just scaling in and out
184 // for demonstration purposes. This will affect all entities currently using the asset.
185 //
186 // To do this, we need to grab the stored attributes of each vertex. `Float32x3` just describes
187 // the format in which the attributes will be read: each position consists of an array of three
188 // f32 corresponding to x, y, and z.
189 //
190 // `ATTRIBUTE_POSITION` is a constant indicating that we want to know where the vertex is
191 // located in space (as opposed to which way its normal is facing, vertex color, or other
192 // details).
193 if let Some(VertexAttributeValues::Float32x3(positions)) =
194 mesh.attribute_mut(Mesh::ATTRIBUTE_POSITION)
195 {
196 // Check a Local value (which only this system can make use of) to determine if we're
197 // currently scaled up or not.
198 let scale_factor = if *is_mesh_scaled { 0.5 } else { 2.0 };
199
200 for position in positions.iter_mut() {
201 // Apply the scale factor to each of x, y, and z.
202 position[0] *= scale_factor;
203 position[1] *= scale_factor;
204 position[2] *= scale_factor;
205 }
206
207 // Flip the local value to reverse the behavior next time the key is pressed.
208 *is_mesh_scaled = !*is_mesh_scaled;
209 }
210}
Sourcepub fn attributes(
&self,
) -> impl Iterator<Item = (&MeshVertexAttribute, &VertexAttributeValues)>
pub fn attributes( &self, ) -> impl Iterator<Item = (&MeshVertexAttribute, &VertexAttributeValues)>
Returns an iterator that yields references to the data of each vertex attribute.
Sourcepub fn attributes_mut(
&mut self,
) -> impl Iterator<Item = (&MeshVertexAttribute, &mut VertexAttributeValues)>
pub fn attributes_mut( &mut self, ) -> impl Iterator<Item = (&MeshVertexAttribute, &mut VertexAttributeValues)>
Returns an iterator that yields mutable references to the data of each vertex attribute.
Sourcepub fn insert_indices(&mut self, indices: Indices)
pub fn insert_indices(&mut self, indices: 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.
Examples found in repository?
48fn star(
49 mut commands: Commands,
50 // We will add a new Mesh for the star being created
51 mut meshes: ResMut<Assets<Mesh>>,
52) {
53 // Let's define the mesh for the object we want to draw: a nice star.
54 // We will specify here what kind of topology is used to define the mesh,
55 // that is, how triangles are built from the vertices. We will use a
56 // triangle list, meaning that each vertex of the triangle has to be
57 // specified. We set `RenderAssetUsages::RENDER_WORLD`, meaning this mesh
58 // will not be accessible in future frames from the `meshes` resource, in
59 // order to save on memory once it has been uploaded to the GPU.
60 let mut star = Mesh::new(
61 PrimitiveTopology::TriangleList,
62 RenderAssetUsages::RENDER_WORLD,
63 );
64
65 // Vertices need to have a position attribute. We will use the following
66 // vertices (I hope you can spot the star in the schema).
67 //
68 // 1
69 //
70 // 10 2
71 // 9 0 3
72 // 8 4
73 // 6
74 // 7 5
75 //
76 // These vertices are specified in 3D space.
77 let mut v_pos = vec![[0.0, 0.0, 0.0]];
78 for i in 0..10 {
79 // The angle between each vertex is 1/10 of a full rotation.
80 let a = i as f32 * PI / 5.0;
81 // The radius of inner vertices (even indices) is 100. For outer vertices (odd indices) it's 200.
82 let r = (1 - i % 2) as f32 * 100.0 + 100.0;
83 // Add the vertex position.
84 v_pos.push([r * ops::sin(a), r * ops::cos(a), 0.0]);
85 }
86 // Set the position attribute
87 star.insert_attribute(Mesh::ATTRIBUTE_POSITION, v_pos);
88 // And a RGB color attribute as well. A built-in `Mesh::ATTRIBUTE_COLOR` exists, but we
89 // use a custom vertex attribute here for demonstration purposes.
90 let mut v_color: Vec<u32> = vec![LinearRgba::BLACK.as_u32()];
91 v_color.extend_from_slice(&[LinearRgba::from(YELLOW).as_u32(); 10]);
92 star.insert_attribute(
93 MeshVertexAttribute::new("Vertex_Color", 1, VertexFormat::Uint32),
94 v_color,
95 );
96
97 // Now, we specify the indices of the vertex that are going to compose the
98 // triangles in our star. Vertices in triangles have to be specified in CCW
99 // winding (that will be the front face, colored). Since we are using
100 // triangle list, we will specify each triangle as 3 vertices
101 // First triangle: 0, 2, 1
102 // Second triangle: 0, 3, 2
103 // Third triangle: 0, 4, 3
104 // etc
105 // Last triangle: 0, 1, 10
106 let mut indices = vec![0, 1, 10];
107 for i in 2..=10 {
108 indices.extend_from_slice(&[0, i, i - 1]);
109 }
110 star.insert_indices(Indices::U32(indices));
111
112 // We can now spawn the entities for the star and the camera
113 commands.spawn((
114 // We use a marker component to identify the custom colored meshes
115 ColoredMesh2d,
116 // The `Handle<Mesh>` needs to be wrapped in a `Mesh2d` for 2D rendering
117 Mesh2d(meshes.add(star)),
118 ));
119
120 commands.spawn(Camera2d);
121}
Sourcepub fn with_inserted_indices(self, indices: Indices) -> Mesh
pub fn with_inserted_indices(self, indices: Indices) -> Mesh
Consumes the mesh and returns a mesh with the given vertex indices. They describe how triangles
are constructed out of the vertex attributes and are therefore only useful for the
PrimitiveTopology
variants that use triangles.
(Alternatively, you can use Mesh::insert_indices
to mutate an existing mesh in-place)
Examples found in repository?
57fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
58 // Build a custom triangle mesh with colors
59 // We define a custom mesh because the examples only uses a limited
60 // set of vertex attributes for simplicity
61 let mesh = Mesh::new(
62 PrimitiveTopology::TriangleList,
63 RenderAssetUsages::default(),
64 )
65 .with_inserted_indices(Indices::U32(vec![0, 1, 2]))
66 .with_inserted_attribute(
67 Mesh::ATTRIBUTE_POSITION,
68 vec![
69 vec3(-0.5, -0.5, 0.0),
70 vec3(0.5, -0.5, 0.0),
71 vec3(0.0, 0.25, 0.0),
72 ],
73 )
74 .with_inserted_attribute(
75 Mesh::ATTRIBUTE_COLOR,
76 vec![
77 vec4(1.0, 0.0, 0.0, 1.0),
78 vec4(0.0, 1.0, 0.0, 1.0),
79 vec4(0.0, 0.0, 1.0, 1.0),
80 ],
81 );
82
83 // spawn 3 triangles to show that batching works
84 for (x, y) in [-0.5, 0.0, 0.5].into_iter().zip([-0.25, 0.5, -0.25]) {
85 // Spawn an entity with all the required components for it to be rendered with our custom pipeline
86 commands.spawn((
87 // We use a marker component to identify the mesh that will be rendered
88 // with our specialized pipeline
89 CustomRenderedEntity,
90 // We need to add the mesh handle to the entity
91 Mesh3d(meshes.add(mesh.clone())),
92 Transform::from_xyz(x, y, 0.0),
93 ));
94 }
95
96 // Spawn the camera.
97 commands.spawn((
98 Camera3d::default(),
99 // Move the camera back a bit to see all the triangles
100 Transform::from_xyz(0.0, 0.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y),
101 ));
102}
More examples
402 fn build(&self) -> Mesh {
403 let radius = self.heart.radius;
404 // The curved parts of each wing (half) of the heart have an angle of `PI * 1.25` or 225°
405 let wing_angle = PI * 1.25;
406
407 // We create buffers for the vertices, their normals and UVs, as well as the indices used to connect the vertices.
408 let mut vertices = Vec::with_capacity(2 * self.resolution);
409 let mut uvs = Vec::with_capacity(2 * self.resolution);
410 let mut indices = Vec::with_capacity(6 * self.resolution - 9);
411 // Since the heart is flat, we know all the normals are identical already.
412 let normals = vec![[0f32, 0f32, 1f32]; 2 * self.resolution];
413
414 // The point in the middle of the two curved parts of the heart
415 vertices.push([0.0; 3]);
416 uvs.push([0.5, 0.5]);
417
418 // The left wing of the heart, starting from the point in the middle.
419 for i in 1..self.resolution {
420 let angle = (i as f32 / self.resolution as f32) * wing_angle;
421 let (sin, cos) = ops::sin_cos(angle);
422 vertices.push([radius * (cos - 1.0), radius * sin, 0.0]);
423 uvs.push([0.5 - (cos - 1.0) / 4., 0.5 - sin / 2.]);
424 }
425
426 // The bottom tip of the heart
427 vertices.push([0.0, radius * (-1. - SQRT_2), 0.0]);
428 uvs.push([0.5, 1.]);
429
430 // The right wing of the heart, starting from the bottom most point and going towards the middle point.
431 for i in 0..self.resolution - 1 {
432 let angle = (i as f32 / self.resolution as f32) * wing_angle - PI / 4.;
433 let (sin, cos) = ops::sin_cos(angle);
434 vertices.push([radius * (cos + 1.0), radius * sin, 0.0]);
435 uvs.push([0.5 - (cos + 1.0) / 4., 0.5 - sin / 2.]);
436 }
437
438 // This is where we build all the triangles from the points created above.
439 // Each triangle has one corner on the middle point with the other two being adjacent points on the perimeter of the heart.
440 for i in 2..2 * self.resolution as u32 {
441 indices.extend_from_slice(&[i - 1, i, 0]);
442 }
443
444 // Here, the actual `Mesh` is created. We set the indices, vertices, normals and UVs created above and specify the topology of the mesh.
445 Mesh::new(
446 bevy::render::mesh::PrimitiveTopology::TriangleList,
447 RenderAssetUsages::default(),
448 )
449 .with_inserted_indices(bevy::render::mesh::Indices::U32(indices))
450 .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
451 .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
452 .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
453 }
39fn setup(
40 mut commands: Commands,
41 asset_server: Res<AssetServer>,
42 mut meshes: ResMut<Assets<Mesh>>,
43 mut materials: ResMut<Assets<StandardMaterial>>,
44 mut skinned_mesh_inverse_bindposes_assets: ResMut<Assets<SkinnedMeshInverseBindposes>>,
45) {
46 // Create a camera
47 commands.spawn((
48 Camera3d::default(),
49 Transform::from_xyz(2.5, 2.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
50 ));
51
52 // Create inverse bindpose matrices for a skeleton consists of 2 joints
53 let inverse_bindposes = skinned_mesh_inverse_bindposes_assets.add(vec![
54 Mat4::from_translation(Vec3::new(-0.5, -1.0, 0.0)),
55 Mat4::from_translation(Vec3::new(-0.5, -1.0, 0.0)),
56 ]);
57
58 // Create a mesh
59 let mesh = Mesh::new(
60 PrimitiveTopology::TriangleList,
61 RenderAssetUsages::RENDER_WORLD,
62 )
63 // Set mesh vertex positions
64 .with_inserted_attribute(
65 Mesh::ATTRIBUTE_POSITION,
66 vec![
67 [0.0, 0.0, 0.0],
68 [1.0, 0.0, 0.0],
69 [0.0, 0.5, 0.0],
70 [1.0, 0.5, 0.0],
71 [0.0, 1.0, 0.0],
72 [1.0, 1.0, 0.0],
73 [0.0, 1.5, 0.0],
74 [1.0, 1.5, 0.0],
75 [0.0, 2.0, 0.0],
76 [1.0, 2.0, 0.0],
77 ],
78 )
79 // Add UV coordinates that map the left half of the texture since its a 1 x
80 // 2 rectangle.
81 .with_inserted_attribute(
82 Mesh::ATTRIBUTE_UV_0,
83 vec![
84 [0.0, 0.00],
85 [0.5, 0.00],
86 [0.0, 0.25],
87 [0.5, 0.25],
88 [0.0, 0.50],
89 [0.5, 0.50],
90 [0.0, 0.75],
91 [0.5, 0.75],
92 [0.0, 1.00],
93 [0.5, 1.00],
94 ],
95 )
96 // Set mesh vertex normals
97 .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.0, 0.0, 1.0]; 10])
98 // Set mesh vertex joint indices for mesh skinning.
99 // Each vertex gets 4 indices used to address the `JointTransforms` array in the vertex shader
100 // as well as `SkinnedMeshJoint` array in the `SkinnedMesh` component.
101 // This means that a maximum of 4 joints can affect a single vertex.
102 .with_inserted_attribute(
103 Mesh::ATTRIBUTE_JOINT_INDEX,
104 // Need to be explicit here as [u16; 4] could be either Uint16x4 or Unorm16x4.
105 VertexAttributeValues::Uint16x4(vec![
106 [0, 0, 0, 0],
107 [0, 0, 0, 0],
108 [0, 1, 0, 0],
109 [0, 1, 0, 0],
110 [0, 1, 0, 0],
111 [0, 1, 0, 0],
112 [0, 1, 0, 0],
113 [0, 1, 0, 0],
114 [0, 1, 0, 0],
115 [0, 1, 0, 0],
116 ]),
117 )
118 // Set mesh vertex joint weights for mesh skinning.
119 // Each vertex gets 4 joint weights corresponding to the 4 joint indices assigned to it.
120 // The sum of these weights should equal to 1.
121 .with_inserted_attribute(
122 Mesh::ATTRIBUTE_JOINT_WEIGHT,
123 vec![
124 [1.00, 0.00, 0.0, 0.0],
125 [1.00, 0.00, 0.0, 0.0],
126 [0.75, 0.25, 0.0, 0.0],
127 [0.75, 0.25, 0.0, 0.0],
128 [0.50, 0.50, 0.0, 0.0],
129 [0.50, 0.50, 0.0, 0.0],
130 [0.25, 0.75, 0.0, 0.0],
131 [0.25, 0.75, 0.0, 0.0],
132 [0.00, 1.00, 0.0, 0.0],
133 [0.00, 1.00, 0.0, 0.0],
134 ],
135 )
136 // Tell bevy to construct triangles from a list of vertex indices,
137 // where each 3 vertex indices form a triangle.
138 .with_inserted_indices(Indices::U16(vec![
139 0, 1, 3, 0, 3, 2, 2, 3, 5, 2, 5, 4, 4, 5, 7, 4, 7, 6, 6, 7, 9, 6, 9, 8,
140 ]));
141
142 let mesh = meshes.add(mesh);
143
144 // We're seeding the PRNG here to make this example deterministic for testing purposes.
145 // This isn't strictly required in practical use unless you need your app to be deterministic.
146 let mut rng = ChaCha8Rng::seed_from_u64(42);
147
148 for i in -5..5 {
149 // Create joint entities
150 let joint_0 = commands
151 .spawn(Transform::from_xyz(
152 i as f32 * 1.5,
153 0.0,
154 // Move quads back a small amount to avoid Z-fighting and not
155 // obscure the transform gizmos.
156 -(i as f32 * 0.01).abs(),
157 ))
158 .id();
159 let joint_1 = commands.spawn((AnimatedJoint(i), Transform::IDENTITY)).id();
160
161 // Set joint_1 as a child of joint_0.
162 commands.entity(joint_0).add_children(&[joint_1]);
163
164 // Each joint in this vector corresponds to each inverse bindpose matrix in `SkinnedMeshInverseBindposes`.
165 let joint_entities = vec![joint_0, joint_1];
166
167 // Create skinned mesh renderer. Note that its transform doesn't affect the position of the mesh.
168 commands.spawn((
169 Mesh3d(mesh.clone()),
170 MeshMaterial3d(materials.add(StandardMaterial {
171 base_color: Color::srgb(
172 rng.gen_range(0.0..1.0),
173 rng.gen_range(0.0..1.0),
174 rng.gen_range(0.0..1.0),
175 ),
176 base_color_texture: Some(asset_server.load("textures/uv_checker_bw.png")),
177 ..default()
178 })),
179 SkinnedMesh {
180 inverse_bindposes: inverse_bindposes.clone(),
181 joints: joint_entities,
182 },
183 ));
184 }
185}
108fn create_cube_mesh() -> Mesh {
109 // Keep the mesh data accessible in future frames to be able to mutate it in toggle_texture.
110 Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD)
111 .with_inserted_attribute(
112 Mesh::ATTRIBUTE_POSITION,
113 // Each array is an [x, y, z] coordinate in local space.
114 // The camera coordinate space is right-handed x-right, y-up, z-back. This means "forward" is -Z.
115 // Meshes always rotate around their local [0, 0, 0] when a rotation is applied to their Transform.
116 // By centering our mesh around the origin, rotating the mesh preserves its center of mass.
117 vec![
118 // top (facing towards +y)
119 [-0.5, 0.5, -0.5], // vertex with index 0
120 [0.5, 0.5, -0.5], // vertex with index 1
121 [0.5, 0.5, 0.5], // etc. until 23
122 [-0.5, 0.5, 0.5],
123 // bottom (-y)
124 [-0.5, -0.5, -0.5],
125 [0.5, -0.5, -0.5],
126 [0.5, -0.5, 0.5],
127 [-0.5, -0.5, 0.5],
128 // right (+x)
129 [0.5, -0.5, -0.5],
130 [0.5, -0.5, 0.5],
131 [0.5, 0.5, 0.5], // This vertex is at the same position as vertex with index 2, but they'll have different UV and normal
132 [0.5, 0.5, -0.5],
133 // left (-x)
134 [-0.5, -0.5, -0.5],
135 [-0.5, -0.5, 0.5],
136 [-0.5, 0.5, 0.5],
137 [-0.5, 0.5, -0.5],
138 // back (+z)
139 [-0.5, -0.5, 0.5],
140 [-0.5, 0.5, 0.5],
141 [0.5, 0.5, 0.5],
142 [0.5, -0.5, 0.5],
143 // forward (-z)
144 [-0.5, -0.5, -0.5],
145 [-0.5, 0.5, -0.5],
146 [0.5, 0.5, -0.5],
147 [0.5, -0.5, -0.5],
148 ],
149 )
150 // Set-up UV coordinates to point to the upper (V < 0.5), "dirt+grass" part of the texture.
151 // Take a look at the custom image (assets/textures/array_texture.png)
152 // so the UV coords will make more sense
153 // Note: (0.0, 0.0) = Top-Left in UV mapping, (1.0, 1.0) = Bottom-Right in UV mapping
154 .with_inserted_attribute(
155 Mesh::ATTRIBUTE_UV_0,
156 vec![
157 // Assigning the UV coords for the top side.
158 [0.0, 0.2], [0.0, 0.0], [1.0, 0.0], [1.0, 0.2],
159 // Assigning the UV coords for the bottom side.
160 [0.0, 0.45], [0.0, 0.25], [1.0, 0.25], [1.0, 0.45],
161 // Assigning the UV coords for the right side.
162 [1.0, 0.45], [0.0, 0.45], [0.0, 0.2], [1.0, 0.2],
163 // Assigning the UV coords for the left side.
164 [1.0, 0.45], [0.0, 0.45], [0.0, 0.2], [1.0, 0.2],
165 // Assigning the UV coords for the back side.
166 [0.0, 0.45], [0.0, 0.2], [1.0, 0.2], [1.0, 0.45],
167 // Assigning the UV coords for the forward side.
168 [0.0, 0.45], [0.0, 0.2], [1.0, 0.2], [1.0, 0.45],
169 ],
170 )
171 // For meshes with flat shading, normals are orthogonal (pointing out) from the direction of
172 // the surface.
173 // Normals are required for correct lighting calculations.
174 // Each array represents a normalized vector, which length should be equal to 1.0.
175 .with_inserted_attribute(
176 Mesh::ATTRIBUTE_NORMAL,
177 vec![
178 // Normals for the top side (towards +y)
179 [0.0, 1.0, 0.0],
180 [0.0, 1.0, 0.0],
181 [0.0, 1.0, 0.0],
182 [0.0, 1.0, 0.0],
183 // Normals for the bottom side (towards -y)
184 [0.0, -1.0, 0.0],
185 [0.0, -1.0, 0.0],
186 [0.0, -1.0, 0.0],
187 [0.0, -1.0, 0.0],
188 // Normals for the right side (towards +x)
189 [1.0, 0.0, 0.0],
190 [1.0, 0.0, 0.0],
191 [1.0, 0.0, 0.0],
192 [1.0, 0.0, 0.0],
193 // Normals for the left side (towards -x)
194 [-1.0, 0.0, 0.0],
195 [-1.0, 0.0, 0.0],
196 [-1.0, 0.0, 0.0],
197 [-1.0, 0.0, 0.0],
198 // Normals for the back side (towards +z)
199 [0.0, 0.0, 1.0],
200 [0.0, 0.0, 1.0],
201 [0.0, 0.0, 1.0],
202 [0.0, 0.0, 1.0],
203 // Normals for the forward side (towards -z)
204 [0.0, 0.0, -1.0],
205 [0.0, 0.0, -1.0],
206 [0.0, 0.0, -1.0],
207 [0.0, 0.0, -1.0],
208 ],
209 )
210 // Create the triangles out of the 24 vertices we created.
211 // To construct a square, we need 2 triangles, therefore 12 triangles in total.
212 // To construct a triangle, we need the indices of its 3 defined vertices, adding them one
213 // by one, in a counter-clockwise order (relative to the position of the viewer, the order
214 // should appear counter-clockwise from the front of the triangle, in this case from outside the cube).
215 // Read more about how to correctly build a mesh manually in the Bevy documentation of a Mesh,
216 // further examples and the implementation of the built-in shapes.
217 //
218 // The first two defined triangles look like this (marked with the vertex indices,
219 // and the axis), when looking down at the top (+y) of the cube:
220 // -Z
221 // ^
222 // 0---1
223 // | /|
224 // | / | -> +X
225 // |/ |
226 // 3---2
227 //
228 // The right face's (+x) triangles look like this, seen from the outside of the cube.
229 // +Y
230 // ^
231 // 10--11
232 // | /|
233 // | / | -> -Z
234 // |/ |
235 // 9---8
236 //
237 // The back face's (+z) triangles look like this, seen from the outside of the cube.
238 // +Y
239 // ^
240 // 17--18
241 // |\ |
242 // | \ | -> +X
243 // | \|
244 // 16--19
245 .with_inserted_indices(Indices::U32(vec![
246 0,3,1 , 1,3,2, // triangles making up the top (+y) facing side.
247 4,5,7 , 5,6,7, // bottom (-y)
248 8,11,9 , 9,11,10, // right (+x)
249 12,13,15 , 13,14,15, // left (-x)
250 16,19,17 , 17,19,18, // back (+z)
251 20,21,23 , 21,22,23, // forward (-z)
252 ]))
253}
Sourcepub 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.
Sourcepub fn remove_indices(&mut self) -> Option<Indices>
pub fn remove_indices(&mut self) -> Option<Indices>
Removes the vertex indices
from the mesh and returns them.
Sourcepub fn with_removed_indices(self) -> Mesh
pub fn with_removed_indices(self) -> Mesh
Consumes the mesh and returns a mesh without the vertex indices
of the mesh.
(Alternatively, you can use Mesh::remove_indices
to mutate an existing mesh in-place)
Sourcepub fn get_vertex_size(&self) -> u64
pub fn get_vertex_size(&self) -> u64
Returns the size of a vertex in bytes.
Sourcepub fn get_vertex_buffer_size(&self) -> usize
pub fn get_vertex_buffer_size(&self) -> usize
Returns the size required for the vertex buffer in bytes.
Sourcepub 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.
Sourcepub fn get_mesh_vertex_buffer_layout(
&self,
mesh_vertex_buffer_layouts: &mut MeshVertexBufferLayouts,
) -> MeshVertexBufferLayoutRef
pub fn get_mesh_vertex_buffer_layout( &self, mesh_vertex_buffer_layouts: &mut MeshVertexBufferLayouts, ) -> MeshVertexBufferLayoutRef
Get this Mesh
’s MeshVertexBufferLayout
, used in SpecializedMeshPipeline
.
Sourcepub fn count_vertices(&self) -> usize
pub fn count_vertices(&self) -> usize
Counts all vertices of the mesh.
If the attributes have different vertex counts, the smallest is returned.
Sourcepub fn create_packed_vertex_buffer_data(&self) -> Vec<u8> ⓘ
pub fn create_packed_vertex_buffer_data(&self) -> Vec<u8> ⓘ
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.
If the vertex attributes have different lengths, they are all truncated to the length of the smallest.
This is a convenience method which allocates a Vec.
Prefer pre-allocating and using Mesh::write_packed_vertex_buffer_data
when possible.
Sourcepub fn write_packed_vertex_buffer_data(&self, slice: &mut [u8])
pub fn write_packed_vertex_buffer_data(&self, slice: &mut [u8])
Computes and write the vertex data of the mesh into a mutable byte slice.
The attributes are located in the order of their MeshVertexAttribute::id
.
This is used to transform the vertex data into a GPU friendly format.
If the vertex attributes have different lengths, they are all truncated to the length of the smallest.
Sourcepub 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.
Sourcepub fn with_duplicated_vertices(self) -> Mesh
pub fn with_duplicated_vertices(self) -> Mesh
Consumes the mesh and returns a mesh with no shared vertices.
This can dramatically increase the vertex count, so make sure this is what you want.
Does nothing if no Indices
are set.
(Alternatively, you can use Mesh::duplicate_vertices
to mutate an existing mesh in-place)
Sourcepub fn invert_winding(&mut self) -> Result<(), MeshWindingInvertError>
pub fn invert_winding(&mut self) -> Result<(), MeshWindingInvertError>
Sourcepub fn with_inverted_winding(self) -> Result<Mesh, MeshWindingInvertError>
pub fn with_inverted_winding(self) -> Result<Mesh, MeshWindingInvertError>
Consumes the mesh and returns a mesh with inverted winding of the indices such that all counter-clockwise triangles are now clockwise and vice versa.
Does nothing if no Indices
are set.
Sourcepub fn compute_normals(&mut self)
pub fn compute_normals(&mut self)
Calculates the Mesh::ATTRIBUTE_NORMAL
of a mesh.
If the mesh is indexed, this defaults to smooth normals. Otherwise, it defaults to flat
normals.
§Panics
Panics if Mesh::ATTRIBUTE_POSITION
is not of type float3
.
Panics if the mesh has any other topology than PrimitiveTopology::TriangleList
.
FIXME: This should handle more cases since this is called as a part of gltf mesh loading where we can’t really blame users for loading meshes that might not conform to the limitations here!
Sourcepub 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
.
Panics if the mesh has any other topology than PrimitiveTopology::TriangleList
.
Consider calling Mesh::duplicate_vertices
or exporting your mesh with normal
attributes.
FIXME: This should handle more cases since this is called as a part of gltf mesh loading where we can’t really blame users for loading meshes that might not conform to the limitations here!
Sourcepub fn compute_smooth_normals(&mut self)
pub fn compute_smooth_normals(&mut self)
Calculates the Mesh::ATTRIBUTE_NORMAL
of an indexed mesh, smoothing normals for shared
vertices.
§Panics
Panics if Mesh::ATTRIBUTE_POSITION
is not of type float3
.
Panics if the mesh has any other topology than PrimitiveTopology::TriangleList
.
Panics if the mesh does not have indices defined.
FIXME: This should handle more cases since this is called as a part of gltf mesh loading where we can’t really blame users for loading meshes that might not conform to the limitations here!
Sourcepub fn with_computed_normals(self) -> Mesh
pub fn with_computed_normals(self) -> Mesh
Consumes the mesh and returns a mesh with calculated Mesh::ATTRIBUTE_NORMAL
.
If the mesh is indexed, this defaults to smooth normals. Otherwise, it defaults to flat
normals.
(Alternatively, you can use Mesh::compute_normals
to mutate an existing mesh in-place)
§Panics
Panics if Mesh::ATTRIBUTE_POSITION
is not of type float3
.
Panics if the mesh has any other topology than PrimitiveTopology::TriangleList
.
Sourcepub fn with_computed_flat_normals(self) -> Mesh
pub fn with_computed_flat_normals(self) -> Mesh
Consumes the mesh and returns a mesh with calculated Mesh::ATTRIBUTE_NORMAL
.
(Alternatively, you can use Mesh::compute_flat_normals
to mutate an existing mesh in-place)
§Panics
Panics if Mesh::ATTRIBUTE_POSITION
is not of type float3
.
Panics if the mesh has any other topology than PrimitiveTopology::TriangleList
.
Panics if the mesh has indices defined
Sourcepub fn with_computed_smooth_normals(self) -> Mesh
pub fn with_computed_smooth_normals(self) -> Mesh
Consumes the mesh and returns a mesh with calculated Mesh::ATTRIBUTE_NORMAL
.
(Alternatively, you can use Mesh::compute_smooth_normals
to mutate an existing mesh in-place)
§Panics
Panics if Mesh::ATTRIBUTE_POSITION
is not of type float3
.
Panics if the mesh has any other topology than PrimitiveTopology::TriangleList
.
Panics if the mesh does not have indices defined.
Sourcepub 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.
Examples found in repository?
More examples
218fn setup_parallax(
219 mut commands: Commands,
220 mut materials: ResMut<Assets<StandardMaterial>>,
221 mut meshes: ResMut<Assets<Mesh>>,
222 asset_server: Res<AssetServer>,
223) {
224 // The normal map. Note that to generate it in the GIMP image editor, you should
225 // open the depth map, and do Filters → Generic → Normal Map
226 // You should enable the "flip X" checkbox.
227 let normal_handle = asset_server.load_with_settings(
228 "textures/parallax_example/cube_normal.png",
229 // The normal map texture is in linear color space. Lighting won't look correct
230 // if `is_srgb` is `true`, which is the default.
231 |settings: &mut ImageLoaderSettings| settings.is_srgb = false,
232 );
233
234 let mut cube = Mesh::from(Cuboid::new(0.15, 0.15, 0.15));
235
236 // NOTE: for normal maps and depth maps to work, the mesh
237 // needs tangents generated.
238 cube.generate_tangents().unwrap();
239
240 let parallax_material = materials.add(StandardMaterial {
241 perceptual_roughness: 0.4,
242 base_color_texture: Some(asset_server.load("textures/parallax_example/cube_color.png")),
243 normal_map_texture: Some(normal_handle),
244 // The depth map is a grayscale texture where black is the highest level and
245 // white the lowest.
246 depth_map: Some(asset_server.load("textures/parallax_example/cube_depth.png")),
247 parallax_depth_scale: 0.09,
248 parallax_mapping_method: ParallaxMappingMethod::Relief { max_steps: 4 },
249 max_parallax_layer_count: ops::exp2(5.0f32),
250 ..default()
251 });
252 commands.spawn((
253 Mesh3d(meshes.add(cube)),
254 MeshMaterial3d(parallax_material),
255 Transform::from_xyz(0.4, 0.2, -0.8),
256 Spin { speed: 0.3 },
257 ));
258}
67fn setup(
68 mut commands: Commands,
69 mut meshes: ResMut<Assets<Mesh>>,
70 mut materials: ResMut<Assets<StandardMaterial>>,
71) -> Result {
72 let mut seeded_rng = ChaCha8Rng::seed_from_u64(19878367467712);
73
74 // Make a plane for establishing space.
75 commands.spawn((
76 Mesh3d(meshes.add(Plane3d::default().mesh().size(12.0, 12.0))),
77 MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
78 Transform::from_xyz(0.0, -2.5, 0.0),
79 ));
80
81 // Spawn a light:
82 commands.spawn((
83 PointLight {
84 shadows_enabled: true,
85 ..default()
86 },
87 Transform::from_xyz(4.0, 8.0, 4.0),
88 ));
89
90 // Spawn a camera:
91 commands.spawn((
92 Camera3d::default(),
93 Transform::from_xyz(-2.0, 3.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
94 ));
95
96 // Create a new sphere mesh:
97 let mut sphere_mesh = Sphere::new(1.0).mesh().ico(7)?;
98 sphere_mesh.generate_tangents()?;
99
100 // Spawn the mesh into the scene:
101 let mut sphere = commands.spawn((
102 Mesh3d(meshes.add(sphere_mesh.clone())),
103 MeshMaterial3d(materials.add(StandardMaterial::default())),
104 Transform::from_xyz(-1.0, 1.0, 0.0),
105 ));
106
107 // Generate random sample points:
108 let triangles = sphere_mesh.triangles()?;
109 let distribution = UniformMeshSampler::try_new(triangles)?;
110
111 // Setup sample points:
112 let point_mesh = meshes.add(Sphere::new(0.01).mesh().ico(3)?);
113 let point_material = materials.add(StandardMaterial {
114 base_color: Srgba::RED.into(),
115 emissive: LinearRgba::rgb(1.0, 0.0, 0.0),
116 ..default()
117 });
118
119 // Add sample points as children of the sphere:
120 for point in distribution.sample_iter(&mut seeded_rng).take(10000) {
121 sphere.with_child((
122 Mesh3d(point_mesh.clone()),
123 MeshMaterial3d(point_material.clone()),
124 Transform::from_translation(point),
125 ));
126 }
127
128 // Indicate the system completed successfully:
129 Ok(())
130}
Sourcepub fn with_generated_tangents(self) -> Result<Mesh, GenerateTangentsError>
pub fn with_generated_tangents(self) -> Result<Mesh, GenerateTangentsError>
Consumes the mesh and returns a mesh with tangents generated using the mikktspace
algorithm.
The resulting mesh will have the Mesh::ATTRIBUTE_TANGENT
attribute if successful.
(Alternatively, you can use Mesh::generate_tangents
to mutate an existing mesh in-place)
Requires a PrimitiveTopology::TriangleList
topology and the Mesh::ATTRIBUTE_POSITION
, Mesh::ATTRIBUTE_NORMAL
and Mesh::ATTRIBUTE_UV_0
attributes set.
Examples found in repository?
100fn setup(mut commands: Commands, asset_server: Res<AssetServer>, app_status: Res<AppStatus>) {
101 commands.spawn((
102 Camera3d::default(),
103 Transform::from_translation(CAMERA_INITIAL_POSITION).looking_at(Vec3::ZERO, Vec3::Y),
104 ));
105
106 spawn_directional_light(&mut commands);
107
108 commands.spawn((
109 SceneRoot(asset_server.load("models/AnisotropyBarnLamp/AnisotropyBarnLamp.gltf#Scene0")),
110 Transform::from_xyz(0.0, 0.07, -0.13),
111 Scene::BarnLamp,
112 ));
113
114 commands.spawn((
115 Mesh3d(
116 asset_server.add(
117 Mesh::from(Sphere::new(0.1))
118 .with_generated_tangents()
119 .unwrap(),
120 ),
121 ),
122 MeshMaterial3d(asset_server.add(StandardMaterial {
123 base_color: palettes::tailwind::GRAY_300.into(),
124 anisotropy_rotation: 0.5,
125 anisotropy_strength: 1.,
126 ..default()
127 })),
128 Scene::Sphere,
129 Visibility::Hidden,
130 ));
131
132 spawn_text(&mut commands, &app_status);
133}
More examples
198fn setup(
199 mut commands: Commands,
200 mut materials: ResMut<Assets<StandardMaterial>>,
201 mut meshes: ResMut<Assets<Mesh>>,
202 asset_server: Res<AssetServer>,
203) {
204 // The normal map. Note that to generate it in the GIMP image editor, you should
205 // open the depth map, and do Filters → Generic → Normal Map
206 // You should enable the "flip X" checkbox.
207 let normal_handle = asset_server.load_with_settings(
208 "textures/parallax_example/cube_normal.png",
209 // The normal map texture is in linear color space. Lighting won't look correct
210 // if `is_srgb` is `true`, which is the default.
211 |settings: &mut ImageLoaderSettings| settings.is_srgb = false,
212 );
213
214 // Camera
215 commands.spawn((
216 Camera3d::default(),
217 Transform::from_xyz(1.5, 1.5, 1.5).looking_at(Vec3::ZERO, Vec3::Y),
218 CameraController,
219 ));
220
221 // light
222 commands
223 .spawn((
224 PointLight {
225 shadows_enabled: true,
226 ..default()
227 },
228 Transform::from_xyz(2.0, 1.0, -1.1),
229 ))
230 .with_children(|commands| {
231 // represent the light source as a sphere
232 let mesh = meshes.add(Sphere::new(0.05).mesh().ico(3).unwrap());
233 commands.spawn((Mesh3d(mesh), MeshMaterial3d(materials.add(Color::WHITE))));
234 });
235
236 // Plane
237 commands.spawn((
238 Mesh3d(meshes.add(Plane3d::default().mesh().size(10.0, 10.0))),
239 MeshMaterial3d(materials.add(StandardMaterial {
240 // standard material derived from dark green, but
241 // with roughness and reflectance set.
242 perceptual_roughness: 0.45,
243 reflectance: 0.18,
244 ..Color::srgb_u8(0, 80, 0).into()
245 })),
246 Transform::from_xyz(0.0, -1.0, 0.0),
247 ));
248
249 let parallax_depth_scale = TargetDepth::default().0;
250 let max_parallax_layer_count = ops::exp2(TargetLayers::default().0);
251 let parallax_mapping_method = CurrentMethod::default();
252 let parallax_material = materials.add(StandardMaterial {
253 perceptual_roughness: 0.4,
254 base_color_texture: Some(asset_server.load("textures/parallax_example/cube_color.png")),
255 normal_map_texture: Some(normal_handle),
256 // The depth map is a grayscale texture where black is the highest level and
257 // white the lowest.
258 depth_map: Some(asset_server.load("textures/parallax_example/cube_depth.png")),
259 parallax_depth_scale,
260 parallax_mapping_method: parallax_mapping_method.0,
261 max_parallax_layer_count,
262 ..default()
263 });
264 commands.spawn((
265 Mesh3d(
266 meshes.add(
267 // NOTE: for normal maps and depth maps to work, the mesh
268 // needs tangents generated.
269 Mesh::from(Cuboid::default())
270 .with_generated_tangents()
271 .unwrap(),
272 ),
273 ),
274 MeshMaterial3d(parallax_material.clone()),
275 Spin { speed: 0.3 },
276 ));
277
278 let background_cube = meshes.add(
279 Mesh::from(Cuboid::new(40.0, 40.0, 40.0))
280 .with_generated_tangents()
281 .unwrap(),
282 );
283
284 let background_cube_bundle = |translation| {
285 (
286 Mesh3d(background_cube.clone()),
287 MeshMaterial3d(parallax_material.clone()),
288 Transform::from_translation(translation),
289 Spin { speed: -0.1 },
290 )
291 };
292 commands.spawn(background_cube_bundle(Vec3::new(45., 0., 0.)));
293 commands.spawn(background_cube_bundle(Vec3::new(-45., 0., 0.)));
294 commands.spawn(background_cube_bundle(Vec3::new(0., 0., 45.)));
295 commands.spawn(background_cube_bundle(Vec3::new(0., 0., -45.)));
296
297 // example instructions
298 commands
299 .spawn((
300 Text::default(),
301 Node {
302 position_type: PositionType::Absolute,
303 top: Val::Px(12.0),
304 left: Val::Px(12.0),
305 ..default()
306 },
307 ))
308 .with_children(|p| {
309 p.spawn(TextSpan(format!(
310 "Parallax depth scale: {parallax_depth_scale:.5}\n"
311 )));
312 p.spawn(TextSpan(format!("Layers: {max_parallax_layer_count:.0}\n")));
313 p.spawn(TextSpan(format!("{parallax_mapping_method}\n")));
314 p.spawn(TextSpan::new("\n\n"));
315 p.spawn(TextSpan::new("Controls:\n"));
316 p.spawn(TextSpan::new("Left click - Change view angle\n"));
317 p.spawn(TextSpan::new(
318 "1/2 - Decrease/Increase parallax depth scale\n",
319 ));
320 p.spawn(TextSpan::new("3/4 - Decrease/Increase layer count\n"));
321 p.spawn(TextSpan::new("Space - Switch parallaxing algorithm\n"));
322 });
323}
Sourcepub fn merge(&mut self, other: &Mesh) -> Result<(), MergeMeshError>
pub fn merge(&mut self, other: &Mesh) -> Result<(), MergeMeshError>
Merges the Mesh
data of other
with self
. The attributes and indices of other
will be appended to self
.
Note that attributes of other
that don’t exist on self
will be ignored.
Aabb
of entities with modified mesh are not updated automatically.
§Errors
Returns Err(MergeMeshError)
if the vertex attribute values of other
are incompatible with self
.
For example, VertexAttributeValues::Float32
is incompatible with VertexAttributeValues::Float32x3
.
Sourcepub fn transformed_by(self, transform: Transform) -> Mesh
pub fn transformed_by(self, transform: Transform) -> Mesh
Transforms the vertex positions, normals, and tangents of the mesh by the given Transform
.
Aabb
of entities with modified mesh are not updated automatically.
Sourcepub fn transform_by(&mut self, transform: Transform)
pub fn transform_by(&mut self, transform: Transform)
Transforms the vertex positions, normals, and tangents of the mesh in place by the given Transform
.
Aabb
of entities with modified mesh are not updated automatically.
Sourcepub fn translated_by(self, translation: Vec3) -> Mesh
pub fn translated_by(self, translation: Vec3) -> Mesh
Translates the vertex positions of the mesh by the given Vec3
.
Aabb
of entities with modified mesh are not updated automatically.
Sourcepub fn translate_by(&mut self, translation: Vec3)
pub fn translate_by(&mut self, translation: Vec3)
Translates the vertex positions of the mesh in place by the given Vec3
.
Aabb
of entities with modified mesh are not updated automatically.
Sourcepub fn rotated_by(self, rotation: Quat) -> Mesh
pub fn rotated_by(self, rotation: Quat) -> Mesh
Rotates the vertex positions, normals, and tangents of the mesh by the given Quat
.
Aabb
of entities with modified mesh are not updated automatically.
Sourcepub fn rotate_by(&mut self, rotation: Quat)
pub fn rotate_by(&mut self, rotation: Quat)
Rotates the vertex positions, normals, and tangents of the mesh in place by the given Quat
.
Aabb
of entities with modified mesh are not updated automatically.
Sourcepub fn scaled_by(self, scale: Vec3) -> Mesh
pub fn scaled_by(self, scale: Vec3) -> Mesh
Scales the vertex positions, normals, and tangents of the mesh by the given Vec3
.
Aabb
of entities with modified mesh are not updated automatically.
Sourcepub fn scale_by(&mut self, scale: Vec3)
pub fn scale_by(&mut self, scale: Vec3)
Scales the vertex positions, normals, and tangents of the mesh in place by the given Vec3
.
Aabb
of entities with modified mesh are not updated automatically.
Sourcepub fn has_morph_targets(&self) -> bool
pub fn has_morph_targets(&self) -> bool
Whether this mesh has morph targets.
Sourcepub 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 morph_targets(&self) -> Option<&Handle<Image>>
Sourcepub fn with_morph_targets(self, morph_targets: Handle<Image>) -> Mesh
pub fn with_morph_targets(self, morph_targets: Handle<Image>) -> Mesh
Consumes the mesh and returns a mesh with the given morph targets.
This requires a “morph target image”. See MorphTargetImage
for info.
(Alternatively, you can use Mesh::set_morph_targets
to mutate an existing mesh in-place)
Sourcepub fn set_morph_target_names(&mut self, names: Vec<String>)
pub fn set_morph_target_names(&mut self, names: Vec<String>)
Sets the names of each morph target. This should correspond to the order of the morph targets in set_morph_targets
.
Sourcepub fn with_morph_target_names(self, names: Vec<String>) -> Mesh
pub fn with_morph_target_names(self, names: Vec<String>) -> Mesh
Consumes the mesh and returns a mesh with morph target names.
Names should correspond to the order of the morph targets in set_morph_targets
.
(Alternatively, you can use Mesh::set_morph_target_names
to mutate an existing mesh in-place)
Sourcepub 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.
Examples found in repository?
91fn name_morphs(
92 mut has_printed: Local<bool>,
93 morph_data: Res<MorphData>,
94 meshes: Res<Assets<Mesh>>,
95) {
96 if *has_printed {
97 return;
98 }
99
100 let Some(mesh) = meshes.get(&morph_data.mesh) else {
101 return;
102 };
103 let Some(names) = mesh.morph_target_names() else {
104 return;
105 };
106
107 info!("Target names:");
108 for name in names {
109 info!(" {name}");
110 }
111 *has_printed = true;
112}
Sourcepub fn normalize_joint_weights(&mut self)
pub fn normalize_joint_weights(&mut self)
Normalize joint weights so they sum to 1.
Sourcepub fn triangles(
&self,
) -> Result<impl Iterator<Item = Triangle3d>, MeshTrianglesError>
pub fn triangles( &self, ) -> Result<impl Iterator<Item = Triangle3d>, MeshTrianglesError>
Get a list of this Mesh’s triangles as an iterator if possible.
Returns an error if any of the following conditions are met (see MeshTrianglesError
):
- The Mesh’s primitive topology is not
TriangleList
orTriangleStrip
. - The Mesh is missing position or index data.
- The Mesh’s position data has the wrong format (not
Float32x3
).
Examples found in repository?
67fn setup(
68 mut commands: Commands,
69 mut meshes: ResMut<Assets<Mesh>>,
70 mut materials: ResMut<Assets<StandardMaterial>>,
71) -> Result {
72 let mut seeded_rng = ChaCha8Rng::seed_from_u64(19878367467712);
73
74 // Make a plane for establishing space.
75 commands.spawn((
76 Mesh3d(meshes.add(Plane3d::default().mesh().size(12.0, 12.0))),
77 MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
78 Transform::from_xyz(0.0, -2.5, 0.0),
79 ));
80
81 // Spawn a light:
82 commands.spawn((
83 PointLight {
84 shadows_enabled: true,
85 ..default()
86 },
87 Transform::from_xyz(4.0, 8.0, 4.0),
88 ));
89
90 // Spawn a camera:
91 commands.spawn((
92 Camera3d::default(),
93 Transform::from_xyz(-2.0, 3.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
94 ));
95
96 // Create a new sphere mesh:
97 let mut sphere_mesh = Sphere::new(1.0).mesh().ico(7)?;
98 sphere_mesh.generate_tangents()?;
99
100 // Spawn the mesh into the scene:
101 let mut sphere = commands.spawn((
102 Mesh3d(meshes.add(sphere_mesh.clone())),
103 MeshMaterial3d(materials.add(StandardMaterial::default())),
104 Transform::from_xyz(-1.0, 1.0, 0.0),
105 ));
106
107 // Generate random sample points:
108 let triangles = sphere_mesh.triangles()?;
109 let distribution = UniformMeshSampler::try_new(triangles)?;
110
111 // Setup sample points:
112 let point_mesh = meshes.add(Sphere::new(0.01).mesh().ico(3)?);
113 let point_material = materials.add(StandardMaterial {
114 base_color: Srgba::RED.into(),
115 emissive: LinearRgba::rgb(1.0, 0.0, 0.0),
116 ..default()
117 });
118
119 // Add sample points as children of the sphere:
120 for point in distribution.sample_iter(&mut seeded_rng).take(10000) {
121 sphere.with_child((
122 Mesh3d(point_mesh.clone()),
123 MeshMaterial3d(point_material.clone()),
124 Transform::from_translation(point),
125 ));
126 }
127
128 // Indicate the system completed successfully:
129 Ok(())
130}
Trait Implementations§
Source§impl From<CircularSector> for Mesh
impl From<CircularSector> for Mesh
Source§fn from(sector: CircularSector) -> Mesh
fn from(sector: CircularSector) -> Mesh
Converts this sector into a Mesh
using a default CircularSectorMeshBuilder
.
See the documentation of CircularSectorMeshBuilder
for more details.
Source§impl From<CircularSegment> for Mesh
impl From<CircularSegment> for Mesh
Source§fn from(segment: CircularSegment) -> Mesh
fn from(segment: CircularSegment) -> Mesh
Converts this sector into a Mesh
using a default CircularSegmentMeshBuilder
.
See the documentation of CircularSegmentMeshBuilder
for more details.
Source§impl From<ConicalFrustum> for Mesh
impl From<ConicalFrustum> for Mesh
Source§fn from(frustum: ConicalFrustum) -> Mesh
fn from(frustum: ConicalFrustum) -> Mesh
Source§impl<const N: usize> From<ConvexPolygon<N>> for Mesh
impl<const N: usize> From<ConvexPolygon<N>> for Mesh
Source§fn from(polygon: ConvexPolygon<N>) -> Mesh
fn from(polygon: ConvexPolygon<N>) -> Mesh
Source§impl From<RegularPolygon> for Mesh
impl From<RegularPolygon> for Mesh
Source§fn from(polygon: RegularPolygon) -> Mesh
fn from(polygon: RegularPolygon) -> Mesh
Source§impl<T> From<T> for Meshwhere
T: MeshBuilder,
impl<T> From<T> for Meshwhere
T: MeshBuilder,
Source§impl From<Tetrahedron> for Mesh
impl From<Tetrahedron> for Mesh
Source§fn from(tetrahedron: Tetrahedron) -> Mesh
fn from(tetrahedron: Tetrahedron) -> Mesh
Source§impl From<Triangle2d> for Mesh
impl From<Triangle2d> for Mesh
Source§fn from(triangle: Triangle2d) -> Mesh
fn from(triangle: Triangle2d) -> Mesh
Source§impl From<Triangle3d> for Mesh
impl From<Triangle3d> for Mesh
Source§fn from(triangle: Triangle3d) -> Mesh
fn from(triangle: Triangle3d) -> Mesh
Source§impl FromArg for &'static Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl FromArg for &'static Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§impl FromArg for &'static mut Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl FromArg for &'static mut Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§impl FromArg for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl FromArg for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§impl FromReflect for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl FromReflect for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§fn from_reflect(reflect: &(dyn PartialReflect + 'static)) -> Option<Mesh>
fn from_reflect(reflect: &(dyn PartialReflect + 'static)) -> Option<Mesh>
Self
from a reflected value.Source§fn take_from_reflect(
reflect: Box<dyn PartialReflect>,
) -> Result<Self, Box<dyn PartialReflect>>
fn take_from_reflect( reflect: Box<dyn PartialReflect>, ) -> Result<Self, Box<dyn PartialReflect>>
Self
using,
constructing the value using from_reflect
if that fails. Read moreSource§impl GetOwnership for &Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl GetOwnership for &Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§impl GetOwnership for &mut Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl GetOwnership for &mut Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§impl GetOwnership for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl GetOwnership for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§impl GetTypeRegistration for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl GetTypeRegistration for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§fn get_type_registration() -> TypeRegistration
fn get_type_registration() -> TypeRegistration
TypeRegistration
for this type.Source§fn register_type_dependencies(registry: &mut TypeRegistry)
fn register_type_dependencies(registry: &mut TypeRegistry)
Source§impl IntoReturn for &Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl IntoReturn for &Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§impl IntoReturn for &mut Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl IntoReturn for &mut Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§impl IntoReturn for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl IntoReturn for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§impl PartialReflect for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl PartialReflect for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
Source§fn try_apply(
&mut self,
value: &(dyn PartialReflect + 'static),
) -> Result<(), ApplyError>
fn try_apply( &mut self, value: &(dyn PartialReflect + 'static), ) -> Result<(), ApplyError>
Source§fn reflect_kind(&self) -> ReflectKind
fn reflect_kind(&self) -> ReflectKind
Source§fn reflect_ref(&self) -> ReflectRef<'_>
fn reflect_ref(&self) -> ReflectRef<'_>
Source§fn reflect_mut(&mut self) -> ReflectMut<'_>
fn reflect_mut(&mut self) -> ReflectMut<'_>
Source§fn reflect_owned(self: Box<Mesh>) -> ReflectOwned
fn reflect_owned(self: Box<Mesh>) -> ReflectOwned
Source§fn try_into_reflect(
self: Box<Mesh>,
) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
fn try_into_reflect( self: Box<Mesh>, ) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
Source§fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>
fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>
Source§fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>
fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>
Source§fn into_partial_reflect(self: Box<Mesh>) -> Box<dyn PartialReflect>
fn into_partial_reflect(self: Box<Mesh>) -> Box<dyn PartialReflect>
Source§fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)
fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)
Source§fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)
fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)
Source§fn reflect_partial_eq(
&self,
value: &(dyn PartialReflect + 'static),
) -> Option<bool>
fn reflect_partial_eq( &self, value: &(dyn PartialReflect + 'static), ) -> Option<bool>
Source§fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>
Self
using reflection. Read moreSource§fn apply(&mut self, value: &(dyn PartialReflect + 'static))
fn apply(&mut self, value: &(dyn PartialReflect + 'static))
Source§fn clone_value(&self) -> Box<dyn PartialReflect>
fn clone_value(&self) -> Box<dyn PartialReflect>
reflect_clone
. To convert reflected values to dynamic ones, use to_dynamic
.Self
into its dynamic representation. Read moreSource§fn to_dynamic(&self) -> Box<dyn PartialReflect>
fn to_dynamic(&self) -> Box<dyn PartialReflect>
Source§fn reflect_hash(&self) -> Option<u64>
fn reflect_hash(&self) -> Option<u64>
Source§fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
Source§fn is_dynamic(&self) -> bool
fn is_dynamic(&self) -> bool
Source§impl Reflect for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl Reflect for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut dyn Any
. Read moreSource§fn into_reflect(self: Box<Mesh>) -> Box<dyn Reflect>
fn into_reflect(self: Box<Mesh>) -> Box<dyn Reflect>
Source§fn as_reflect(&self) -> &(dyn Reflect + 'static)
fn as_reflect(&self) -> &(dyn Reflect + 'static)
Source§fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
Source§impl Struct for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl Struct for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>
fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>
name
as a &dyn PartialReflect
.Source§fn field_mut(
&mut self,
name: &str,
) -> Option<&mut (dyn PartialReflect + 'static)>
fn field_mut( &mut self, name: &str, ) -> Option<&mut (dyn PartialReflect + 'static)>
name
as a
&mut dyn PartialReflect
.Source§fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>
fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>
index
as a
&dyn PartialReflect
.Source§fn field_at_mut(
&mut self,
index: usize,
) -> Option<&mut (dyn PartialReflect + 'static)>
fn field_at_mut( &mut self, index: usize, ) -> Option<&mut (dyn PartialReflect + 'static)>
index
as a &mut dyn PartialReflect
.Source§fn name_at(&self, index: usize) -> Option<&str>
fn name_at(&self, index: usize) -> Option<&str>
index
.Source§fn iter_fields(&self) -> FieldIter<'_> ⓘ
fn iter_fields(&self) -> FieldIter<'_> ⓘ
fn to_dynamic_struct(&self) -> DynamicStruct
Source§fn clone_dynamic(&self) -> DynamicStruct
fn clone_dynamic(&self) -> DynamicStruct
to_dynamic_struct
insteadDynamicStruct
.Source§fn get_represented_struct_info(&self) -> Option<&'static StructInfo>
fn get_represented_struct_info(&self) -> Option<&'static StructInfo>
None
if TypeInfo
is not available.Source§impl TypePath for Mesh
impl TypePath for Mesh
Source§fn type_path() -> &'static str
fn type_path() -> &'static str
Source§fn short_type_path() -> &'static str
fn short_type_path() -> &'static str
Source§fn type_ident() -> Option<&'static str>
fn type_ident() -> Option<&'static str>
Source§fn crate_name() -> Option<&'static str>
fn crate_name() -> Option<&'static str>
Source§impl Typed for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
impl Typed for Meshwhere
Mesh: Any + Send + Sync,
Option<Indices>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Handle<Image>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Option<Vec<String>>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
RenderAssetUsages: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
Source§impl VisitAssetDependencies for Mesh
impl VisitAssetDependencies for Mesh
fn visit_dependencies(&self, visit: &mut impl FnMut(UntypedAssetId))
impl Asset for Mesh
Auto Trait Implementations§
impl Freeze for Mesh
impl !RefUnwindSafe for Mesh
impl Send for Mesh
impl Sync for Mesh
impl Unpin for Mesh
impl !UnwindSafe for Mesh
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.Source§impl<A> AssetContainer for Awhere
A: Asset,
impl<A> AssetContainer for Awhere
A: Asset,
fn insert(self: Box<A>, id: UntypedAssetId, world: &mut World)
fn asset_type_name(&self) -> &'static str
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
, which can then be
downcast
into Box<dyn ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
, which can then be further
downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§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.Source§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.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§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.Source§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.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> DynamicTypePath for Twhere
T: TypePath,
impl<T> DynamicTypePath for Twhere
T: TypePath,
Source§fn reflect_type_path(&self) -> &str
fn reflect_type_path(&self) -> &str
TypePath::type_path
.Source§fn reflect_short_type_path(&self) -> &str
fn reflect_short_type_path(&self) -> &str
Source§fn reflect_type_ident(&self) -> Option<&str>
fn reflect_type_ident(&self) -> Option<&str>
TypePath::type_ident
.Source§fn reflect_crate_name(&self) -> Option<&str>
fn reflect_crate_name(&self) -> Option<&str>
TypePath::crate_name
.Source§fn reflect_module_path(&self) -> Option<&str>
fn reflect_module_path(&self) -> Option<&str>
Source§impl<T> DynamicTyped for Twhere
T: Typed,
impl<T> DynamicTyped for Twhere
T: Typed,
Source§fn reflect_type_info(&self) -> &'static TypeInfo
fn reflect_type_info(&self) -> &'static TypeInfo
Typed::type_info
.Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<S> GetField for Swhere
S: Struct,
impl<S> GetField for Swhere
S: Struct,
Source§impl<T> GetPath for T
impl<T> GetPath for T
Source§fn reflect_path<'p>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>
fn reflect_path<'p>( &self, path: impl ReflectPath<'p>, ) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>
path
. Read moreSource§fn reflect_path_mut<'p>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>
fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>
path
. Read moreSource§fn path<'p, T>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
fn path<'p, T>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
path
. Read moreSource§fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
path
. Read moreSource§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.