Skip to main content

Mesh

Struct Mesh 

Source
pub struct Mesh {
    pub asset_usage: RenderAssetUsages,
    pub enable_raytracing: bool,
    pub final_aabb: Option<Aabb3d>,
    /* 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’s Aabb 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 for ColorMaterial).
  • 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 is Some(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.

§Remote Inspection

To transmit a Mesh between two running Bevy apps, e.g. through BRP, use SerializedMesh. This type is only meant for short-term transmission between same versions and should not be stored anywhere.

Fields§

§asset_usage: RenderAssetUsages§enable_raytracing: bool

Whether or not to build a BLAS for use with bevy_solari raytracing.

Note that this is not whether the mesh is compatible with bevy_solari raytracing. This field just controls whether or not a BLAS gets built for this mesh, assuming that the mesh is compatible.

The use case for this field is using lower-resolution proxy meshes for raytracing (to save on BLAS memory usage), while using higher-resolution meshes for raster. You can set this field to true for the lower-resolution proxy mesh, and to false for the high-resolution raster mesh.

Alternatively, you can use the same mesh for both raster and raytracing, with this field set to true.

Does nothing if not used with bevy_solari, or if the mesh is not compatible with bevy_solari (see bevy_solari’s docs).

§final_aabb: Option<Aabb3d>

Precomputed min and max extents of the mesh position data. Used mainly for constructing Aabbs for frustum culling. This data will be set if/when a mesh is extracted to the GPU

Implementations§

Source§

impl Mesh

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub const FIRST_AVAILABLE_CUSTOM_ATTRIBUTE: u64 = 8

The first index that can be used for custom vertex attributes. Only the attributes with an index below this are used by Bevy.

Source

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?
examples/3d/lines.rs (lines 88-93)
85    fn from(line: LineList) -> Self {
86        let vertices: Vec<_> = line.lines.into_iter().flat_map(|(a, b)| [a, b]).collect();
87
88        Mesh::new(
89            // This tells wgpu that the positions are list of lines
90            // where every pair is a start and end point
91            PrimitiveTopology::LineList,
92            RenderAssetUsages::RENDER_WORLD,
93        )
94        // Add the vertices positions as an attribute
95        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
96    }
97}
98
99/// A list of points that will have a line drawn between each consecutive points
100#[derive(Debug, Clone)]
101struct LineStrip {
102    points: Vec<Vec3>,
103    indices: Indices,
104}
105
106impl From<LineStrip> for Mesh {
107    fn from(line: LineStrip) -> Self {
108        Mesh::new(
109            // This tells wgpu that the positions are a list of points
110            // where a line will be drawn between each consecutive point
111            PrimitiveTopology::LineStrip,
112            RenderAssetUsages::RENDER_WORLD,
113        )
114        // Add the point positions as an attribute
115        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, line.points)
116        .with_inserted_indices(line.indices)
117    }
More examples
Hide additional examples
examples/shader_advanced/specialized_mesh_pipeline.rs (lines 58-61)
54fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
55    // Build a custom triangle mesh with colors
56    // We define a custom mesh because the examples only uses a limited
57    // set of vertex attributes for simplicity
58    let mesh = Mesh::new(
59        PrimitiveTopology::TriangleList,
60        RenderAssetUsages::default(),
61    )
62    .with_inserted_indices(Indices::U32(vec![0, 1, 2]))
63    .with_inserted_attribute(
64        Mesh::ATTRIBUTE_POSITION,
65        vec![
66            vec3(-0.5, -0.5, 0.0),
67            vec3(0.5, -0.5, 0.0),
68            vec3(0.0, 0.25, 0.0),
69        ],
70    )
71    .with_inserted_attribute(
72        Mesh::ATTRIBUTE_COLOR,
73        vec![
74            vec4(1.0, 0.0, 0.0, 1.0),
75            vec4(0.0, 1.0, 0.0, 1.0),
76            vec4(0.0, 0.0, 1.0, 1.0),
77        ],
78    );
79
80    // spawn 3 triangles to show that batching works
81    for (x, y) in [-0.5, 0.0, 0.5].into_iter().zip([-0.25, 0.5, -0.25]) {
82        // Spawn an entity with all the required components for it to be rendered with our custom pipeline
83        commands.spawn((
84            // We use a marker component to identify the mesh that will be rendered
85            // with our specialized pipeline
86            CustomRenderedEntity,
87            // We need to add the mesh handle to the entity
88            Mesh3d(meshes.add(mesh.clone())),
89            Transform::from_xyz(x, y, 0.0),
90        ));
91    }
92
93    // Spawn the camera.
94    commands.spawn((
95        Camera3d::default(),
96        // Move the camera back a bit to see all the triangles
97        Transform::from_xyz(0.0, 0.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y),
98    ));
99}
examples/math/custom_primitives.rs (lines 557-560)
514    fn build(&self) -> Mesh {
515        let radius = self.heart.radius;
516        // The curved parts of each wing (half) of the heart have an angle of `PI * 1.25` or 225°
517        let wing_angle = PI * 1.25;
518
519        // We create buffers for the vertices, their normals and UVs, as well as the indices used to connect the vertices.
520        let mut vertices = Vec::with_capacity(2 * self.resolution);
521        let mut uvs = Vec::with_capacity(2 * self.resolution);
522        let mut indices = Vec::with_capacity(6 * self.resolution - 9);
523        // Since the heart is flat, we know all the normals are identical already.
524        let normals = vec![[0f32, 0f32, 1f32]; 2 * self.resolution];
525
526        // The point in the middle of the two curved parts of the heart
527        vertices.push([0.0; 3]);
528        uvs.push([0.5, 0.5]);
529
530        // The left wing of the heart, starting from the point in the middle.
531        for i in 1..self.resolution {
532            let angle = (i as f32 / self.resolution as f32) * wing_angle;
533            let (sin, cos) = ops::sin_cos(angle);
534            vertices.push([radius * (cos - 1.0), radius * sin, 0.0]);
535            uvs.push([0.5 - (cos - 1.0) / 4., 0.5 - sin / 2.]);
536        }
537
538        // The bottom tip of the heart
539        vertices.push([0.0, radius * (-1. - SQRT_2), 0.0]);
540        uvs.push([0.5, 1.]);
541
542        // The right wing of the heart, starting from the bottom most point and going towards the middle point.
543        for i in 0..self.resolution - 1 {
544            let angle = (i as f32 / self.resolution as f32) * wing_angle - PI / 4.;
545            let (sin, cos) = ops::sin_cos(angle);
546            vertices.push([radius * (cos + 1.0), radius * sin, 0.0]);
547            uvs.push([0.5 - (cos + 1.0) / 4., 0.5 - sin / 2.]);
548        }
549
550        // This is where we build all the triangles from the points created above.
551        // Each triangle has one corner on the middle point with the other two being adjacent points on the perimeter of the heart.
552        for i in 2..2 * self.resolution as u32 {
553            indices.extend_from_slice(&[i - 1, i, 0]);
554        }
555
556        // Here, the actual `Mesh` is created. We set the indices, vertices, normals and UVs created above and specify the topology of the mesh.
557        Mesh::new(
558            bevy::mesh::PrimitiveTopology::TriangleList,
559            RenderAssetUsages::default(),
560        )
561        .with_inserted_indices(bevy::mesh::Indices::U32(indices))
562        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
563        .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
564        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
565    }
examples/shader_advanced/compute_mesh.rs (lines 102-105)
82fn setup(
83    mut commands: Commands,
84    mut meshes: ResMut<Assets<Mesh>>,
85    mut materials: ResMut<Assets<StandardMaterial>>,
86) {
87    // a truly empty mesh will error if used in Mesh3d
88    // so we set up the data to be what we want the compute shader to output
89    // We're using 36 indices and 24 vertices which is directly taken from
90    // the Bevy Cuboid mesh implementation.
91    //
92    // We allocate 50 spots for each attribute here because
93    // it is *very important* that the amount of data allocated here is
94    // *bigger* than (or exactly equal to) the amount of data we intend to
95    // write from the compute shader. This amount of data defines how big
96    // the buffer we get from the mesh_allocator will be, which in turn
97    // defines how big the buffer is when we're in the compute shader.
98    //
99    // If it turns out you don't need all of the space when the compute shader
100    // is writing data, you can write NaN to the rest of the data.
101    let empty_mesh = {
102        let mut mesh = Mesh::new(
103            PrimitiveTopology::TriangleList,
104            RenderAssetUsages::RENDER_WORLD,
105        )
106        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vec![[0.; 3]; 50])
107        .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.; 3]; 50])
108        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.; 2]; 50])
109        .with_inserted_indices(Indices::U32(vec![0; 50]));
110
111        mesh.asset_usage = RenderAssetUsages::RENDER_WORLD;
112        mesh
113    };
114
115    let handle = meshes.add(empty_mesh);
116
117    // we spawn two "users" of the mesh handle,
118    // but only insert `GenerateMesh` on one of them
119    // to show that the mesh handle works as usual
120    commands.spawn((
121        GenerateMesh(handle.clone()),
122        Mesh3d(handle.clone()),
123        MeshMaterial3d(materials.add(StandardMaterial {
124            base_color: RED_400.into(),
125            ..default()
126        })),
127        Transform::from_xyz(-2.5, 1.5, 0.),
128    ));
129
130    commands.spawn((
131        Mesh3d(handle),
132        MeshMaterial3d(materials.add(StandardMaterial {
133            base_color: SKY_400.into(),
134            ..default()
135        })),
136        Transform::from_xyz(2.5, 1.5, 0.),
137    ));
138
139    // some additional scene elements.
140    // This mesh specifically is here so that we don't assume
141    // mesh_allocator offsets that would only work if we had
142    // one mesh in the scene.
143    commands.spawn((
144        Mesh3d(meshes.add(Circle::new(4.0))),
145        MeshMaterial3d(materials.add(Color::WHITE)),
146        Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
147    ));
148    commands.spawn((
149        PointLight {
150            shadow_maps_enabled: true,
151            ..default()
152        },
153        Transform::from_xyz(4.0, 8.0, 4.0),
154    ));
155    // camera
156    commands.spawn((
157        Camera3d::default(),
158        Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
159    ));
160}
examples/2d/mesh2d_manual.rs (lines 61-64)
49fn star(
50    mut commands: Commands,
51    // We will add a new Mesh for the star being created
52    mut meshes: ResMut<Assets<Mesh>>,
53) {
54    // Let's define the mesh for the object we want to draw: a nice star.
55    // We will specify here what kind of topology is used to define the mesh,
56    // that is, how triangles are built from the vertices. We will use a
57    // triangle list, meaning that each vertex of the triangle has to be
58    // specified. We set `RenderAssetUsages::RENDER_WORLD`, meaning this mesh
59    // will not be accessible in future frames from the `meshes` resource, in
60    // order to save on memory once it has been uploaded to the GPU.
61    let mut star = Mesh::new(
62        PrimitiveTopology::TriangleList,
63        RenderAssetUsages::RENDER_WORLD,
64    );
65
66    // Vertices need to have a position attribute. We will use the following
67    // vertices (I hope you can spot the star in the schema).
68    //
69    //        1
70    //
71    //     10   2
72    // 9      0      3
73    //     8     4
74    //        6
75    //   7        5
76    //
77    // These vertices are specified in 3D space.
78    let mut v_pos = vec![[0.0, 0.0, 0.0]];
79    for i in 0..10 {
80        // The angle between each vertex is 1/10 of a full rotation.
81        let a = i as f32 * PI / 5.0;
82        // The radius of inner vertices (even indices) is 100. For outer vertices (odd indices) it's 200.
83        let r = (1 - i % 2) as f32 * 100.0 + 100.0;
84        // Add the vertex position.
85        v_pos.push([r * ops::sin(a), r * ops::cos(a), 0.0]);
86    }
87    // Set the position attribute
88    star.insert_attribute(Mesh::ATTRIBUTE_POSITION, v_pos);
89    // And a RGB color attribute as well. A built-in `Mesh::ATTRIBUTE_COLOR` exists, but we
90    // use a custom vertex attribute here for demonstration purposes.
91    let mut v_color: Vec<u32> = vec![LinearRgba::BLACK.as_u32()];
92    v_color.extend_from_slice(&[LinearRgba::from(YELLOW).as_u32(); 10]);
93    star.insert_attribute(
94        MeshVertexAttribute::new("Vertex_Color", 1, VertexFormat::Uint32),
95        v_color,
96    );
97
98    // Now, we specify the indices of the vertex that are going to compose the
99    // triangles in our star. Vertices in triangles have to be specified in CCW
100    // winding (that will be the front face, colored). Since we are using
101    // triangle list, we will specify each triangle as 3 vertices
102    //   First triangle: 0, 2, 1
103    //   Second triangle: 0, 3, 2
104    //   Third triangle: 0, 4, 3
105    //   etc
106    //   Last triangle: 0, 1, 10
107    let mut indices = vec![0, 1, 10];
108    for i in 2..=10 {
109        indices.extend_from_slice(&[0, i, i - 1]);
110    }
111    star.insert_indices(Indices::U32(indices));
112
113    // We can now spawn the entities for the star and the camera
114    commands.spawn((
115        // We use a marker component to identify the custom colored meshes
116        ColoredMesh2d,
117        // The `Handle<Mesh>` needs to be wrapped in a `Mesh2d` for 2D rendering
118        Mesh2d(meshes.add(star)),
119    ));
120
121    commands.spawn(Camera2d);
122}
tests/3d/test_invalid_skinned_mesh.rs (lines 99-102)
92fn setup_meshes(
93    mut commands: Commands,
94    mut mesh_assets: ResMut<Assets<Mesh>>,
95    mut material_assets: ResMut<Assets<StandardMaterial>>,
96    mut inverse_bindposes_assets: ResMut<Assets<SkinnedMeshInverseBindposes>>,
97) {
98    // Create a mesh with two rectangles.
99    let unskinned_mesh = Mesh::new(
100        PrimitiveTopology::TriangleList,
101        RenderAssetUsages::default(),
102    )
103    .with_inserted_attribute(
104        Mesh::ATTRIBUTE_POSITION,
105        vec![
106            [-0.3, -0.3, 0.0],
107            [0.3, -0.3, 0.0],
108            [-0.3, 0.3, 0.0],
109            [0.3, 0.3, 0.0],
110            [-0.4, 0.8, 0.0],
111            [0.4, 0.8, 0.0],
112            [-0.4, 1.8, 0.0],
113            [0.4, 1.8, 0.0],
114        ],
115    )
116    .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.0, 0.0, 1.0]; 8])
117    .with_inserted_indices(Indices::U16(vec![0, 1, 3, 0, 3, 2, 4, 5, 7, 4, 7, 6]));
118
119    // Copy the mesh and add skinning attributes that bind each rectangle to a joint.
120    let skinned_mesh = unskinned_mesh
121        .clone()
122        .with_inserted_attribute(
123            Mesh::ATTRIBUTE_JOINT_INDEX,
124            VertexAttributeValues::Uint16x4(vec![
125                [0, 0, 0, 0],
126                [0, 0, 0, 0],
127                [0, 0, 0, 0],
128                [0, 0, 0, 0],
129                [1, 0, 0, 0],
130                [1, 0, 0, 0],
131                [1, 0, 0, 0],
132                [1, 0, 0, 0],
133            ]),
134        )
135        .with_inserted_attribute(
136            Mesh::ATTRIBUTE_JOINT_WEIGHT,
137            vec![[1.00, 0.00, 0.0, 0.0]; 8],
138        );
139
140    let unskinned_mesh_handle = mesh_assets.add(unskinned_mesh);
141    let skinned_mesh_handle = mesh_assets.add(skinned_mesh);
142
143    let inverse_bindposes_handle = inverse_bindposes_assets.add(vec![
144        Mat4::IDENTITY,
145        Mat4::from_translation(Vec3::new(0.0, -1.3, 0.0)),
146    ]);
147
148    let mesh_material_handle = material_assets.add(StandardMaterial::default());
149
150    let background_material_handle = material_assets.add(StandardMaterial {
151        base_color: Color::srgb(0.05, 0.15, 0.05),
152        reflectance: 0.2,
153        ..default()
154    });
155
156    #[derive(PartialEq)]
157    enum Variation {
158        Normal,
159        MissingMeshAttributes,
160        MissingJointEntity,
161        MissingSkinnedMeshComponent,
162    }
163
164    for (index, variation) in [
165        Variation::Normal,
166        Variation::MissingMeshAttributes,
167        Variation::MissingJointEntity,
168        Variation::MissingSkinnedMeshComponent,
169    ]
170    .into_iter()
171    .enumerate()
172    {
173        // Skip variations that are currently broken. See https://github.com/bevyengine/bevy/issues/16929,
174        // https://github.com/bevyengine/bevy/pull/18074.
175        if (variation == Variation::MissingSkinnedMeshComponent)
176            || (variation == Variation::MissingMeshAttributes)
177        {
178            continue;
179        }
180
181        let transform = Transform::from_xyz(((index as f32) - 1.5) * 4.5, 0.0, 0.0);
182
183        let joint_0 = commands.spawn(transform).id();
184
185        let joint_1 = commands
186            .spawn((ChildOf(joint_0), AnimatedJoint, Transform::IDENTITY))
187            .id();
188
189        if variation == Variation::MissingJointEntity {
190            commands.entity(joint_1).despawn();
191        }
192
193        let mesh_handle = match variation {
194            Variation::MissingMeshAttributes => &unskinned_mesh_handle,
195            _ => &skinned_mesh_handle,
196        };
197
198        let mut entity_commands = commands.spawn((
199            Mesh3d(mesh_handle.clone()),
200            MeshMaterial3d(mesh_material_handle.clone()),
201            transform,
202        ));
203
204        if variation != Variation::MissingSkinnedMeshComponent {
205            entity_commands.insert(SkinnedMesh {
206                inverse_bindposes: inverse_bindposes_handle.clone(),
207                joints: vec![joint_0, joint_1],
208            });
209        }
210
211        // Add a square behind the mesh to distinguish it from the other meshes.
212        commands.spawn((
213            Transform::from_xyz(transform.translation.x, transform.translation.y, -0.8),
214            Mesh3d(mesh_assets.add(Plane3d::default().mesh().size(4.3, 4.3).normal(Dir3::Z))),
215            MeshMaterial3d(background_material_handle.clone()),
216        ));
217    }
218}
Source

pub fn primitive_topology(&self) -> PrimitiveTopology

Returns the topology of the mesh.

Examples found in repository?
examples/asset/asset_loading.rs (line 43)
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}
Source

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. Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_insert_attribute

Examples found in repository?
examples/2d/mesh2d_vertex_color_texture.rs (line 31)
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
Hide additional examples
examples/3d/vertex_colors.rs (line 33)
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            shadow_maps_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}
examples/3d/motion_blur.rs (line 88)
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(GlobalAmbientLight {
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            shadow_maps_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}
examples/2d/mesh2d_manual.rs (line 88)
49fn star(
50    mut commands: Commands,
51    // We will add a new Mesh for the star being created
52    mut meshes: ResMut<Assets<Mesh>>,
53) {
54    // Let's define the mesh for the object we want to draw: a nice star.
55    // We will specify here what kind of topology is used to define the mesh,
56    // that is, how triangles are built from the vertices. We will use a
57    // triangle list, meaning that each vertex of the triangle has to be
58    // specified. We set `RenderAssetUsages::RENDER_WORLD`, meaning this mesh
59    // will not be accessible in future frames from the `meshes` resource, in
60    // order to save on memory once it has been uploaded to the GPU.
61    let mut star = Mesh::new(
62        PrimitiveTopology::TriangleList,
63        RenderAssetUsages::RENDER_WORLD,
64    );
65
66    // Vertices need to have a position attribute. We will use the following
67    // vertices (I hope you can spot the star in the schema).
68    //
69    //        1
70    //
71    //     10   2
72    // 9      0      3
73    //     8     4
74    //        6
75    //   7        5
76    //
77    // These vertices are specified in 3D space.
78    let mut v_pos = vec![[0.0, 0.0, 0.0]];
79    for i in 0..10 {
80        // The angle between each vertex is 1/10 of a full rotation.
81        let a = i as f32 * PI / 5.0;
82        // The radius of inner vertices (even indices) is 100. For outer vertices (odd indices) it's 200.
83        let r = (1 - i % 2) as f32 * 100.0 + 100.0;
84        // Add the vertex position.
85        v_pos.push([r * ops::sin(a), r * ops::cos(a), 0.0]);
86    }
87    // Set the position attribute
88    star.insert_attribute(Mesh::ATTRIBUTE_POSITION, v_pos);
89    // And a RGB color attribute as well. A built-in `Mesh::ATTRIBUTE_COLOR` exists, but we
90    // use a custom vertex attribute here for demonstration purposes.
91    let mut v_color: Vec<u32> = vec![LinearRgba::BLACK.as_u32()];
92    v_color.extend_from_slice(&[LinearRgba::from(YELLOW).as_u32(); 10]);
93    star.insert_attribute(
94        MeshVertexAttribute::new("Vertex_Color", 1, VertexFormat::Uint32),
95        v_color,
96    );
97
98    // Now, we specify the indices of the vertex that are going to compose the
99    // triangles in our star. Vertices in triangles have to be specified in CCW
100    // winding (that will be the front face, colored). Since we are using
101    // triangle list, we will specify each triangle as 3 vertices
102    //   First triangle: 0, 2, 1
103    //   Second triangle: 0, 3, 2
104    //   Third triangle: 0, 4, 3
105    //   etc
106    //   Last triangle: 0, 1, 10
107    let mut indices = vec![0, 1, 10];
108    for i in 2..=10 {
109        indices.extend_from_slice(&[0, i, i - 1]);
110    }
111    star.insert_indices(Indices::U32(indices));
112
113    // We can now spawn the entities for the star and the camera
114    commands.spawn((
115        // We use a marker component to identify the custom colored meshes
116        ColoredMesh2d,
117        // The `Handle<Mesh>` needs to be wrapped in a `Mesh2d` for 2D rendering
118        Mesh2d(meshes.add(star)),
119    ));
120
121    commands.spawn(Camera2d);
122}
examples/3d/solari.rs (line 400)
374fn add_raytracing_meshes_on_scene_load(
375    scene_ready: On<WorldInstanceReady>,
376    children: Query<&Children>,
377    mesh_query: Query<(
378        &Mesh3d,
379        &MeshMaterial3d<StandardMaterial>,
380        Option<&GltfMaterialName>,
381    )>,
382    mut meshes: ResMut<Assets<Mesh>>,
383    mut materials: ResMut<Assets<StandardMaterial>>,
384    mut commands: Commands,
385    args: Res<Args>,
386) {
387    for descendant in children.iter_descendants(scene_ready.entity) {
388        if let Ok((Mesh3d(mesh_handle), MeshMaterial3d(material_handle), material_name)) =
389            mesh_query.get(descendant)
390        {
391            // Add raytracing mesh component
392            commands
393                .entity(descendant)
394                .insert(RaytracingMesh3d(mesh_handle.clone()));
395
396            // Ensure meshes are Solari compatible
397            let mut mesh = meshes.get_mut(mesh_handle).unwrap();
398            if !mesh.contains_attribute(Mesh::ATTRIBUTE_UV_0) {
399                let vertex_count = mesh.count_vertices();
400                mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.0, 0.0]; vertex_count]);
401                mesh.insert_attribute(
402                    Mesh::ATTRIBUTE_TANGENT,
403                    vec![[0.0, 0.0, 0.0, 0.0]; vertex_count],
404                );
405            }
406            if !mesh.contains_attribute(Mesh::ATTRIBUTE_TANGENT) {
407                mesh.generate_tangents().unwrap();
408            }
409            if mesh.contains_attribute(Mesh::ATTRIBUTE_UV_1) {
410                mesh.remove_attribute(Mesh::ATTRIBUTE_UV_1);
411            }
412            if let Some(indices) = mesh.indices_mut()
413                && let Indices::U16(_) = indices
414            {
415                *indices = Indices::U32(indices.iter().map(|i| i as u32).collect());
416            }
417
418            // Prevent rasterization if using pathtracer
419            if args.pathtracer == Some(true) {
420                commands.entity(descendant).remove::<Mesh3d>();
421            }
422
423            // Adjust scene materials to better demo Solari features
424            if material_name.map(|s| s.0.as_str()) == Some("material") {
425                let mut material = materials.get_mut(material_handle).unwrap();
426                material.emissive = LinearRgba::BLACK;
427            }
428            if material_name.map(|s| s.0.as_str()) == Some("Lights") {
429                let mut material = materials.get_mut(material_handle).unwrap();
430                material.emissive =
431                    LinearRgba::from(Color::srgb(0.941, 0.714, 0.043)) * 1_000_000.0;
432                material.alpha_mode = AlphaMode::Opaque;
433                material.specular_transmission = 0.0;
434
435                commands.insert_resource(RobotLightMaterial(material_handle.clone()));
436            }
437            if material_name.map(|s| s.0.as_str()) == Some("Glass_Dark_01") {
438                let mut material = materials.get_mut(material_handle).unwrap();
439                material.alpha_mode = AlphaMode::Opaque;
440                material.specular_transmission = 0.0;
441            }
442        }
443    }
444}
Source

pub fn try_insert_attribute( &mut self, attribute: MeshVertexAttribute, values: impl Into<VertexAttributeValues>, ) -> Result<(), MeshAccessError>

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.

Returns an error if the mesh data has been extracted to RenderWorld.

§Panics

Panics when the format of the values does not match the attribute’s format.

Source

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. Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_with_inserted_attribute

Examples found in repository?
examples/3d/lines.rs (line 95)
85    fn from(line: LineList) -> Self {
86        let vertices: Vec<_> = line.lines.into_iter().flat_map(|(a, b)| [a, b]).collect();
87
88        Mesh::new(
89            // This tells wgpu that the positions are list of lines
90            // where every pair is a start and end point
91            PrimitiveTopology::LineList,
92            RenderAssetUsages::RENDER_WORLD,
93        )
94        // Add the vertices positions as an attribute
95        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
96    }
97}
98
99/// A list of points that will have a line drawn between each consecutive points
100#[derive(Debug, Clone)]
101struct LineStrip {
102    points: Vec<Vec3>,
103    indices: Indices,
104}
105
106impl From<LineStrip> for Mesh {
107    fn from(line: LineStrip) -> Self {
108        Mesh::new(
109            // This tells wgpu that the positions are a list of points
110            // where a line will be drawn between each consecutive point
111            PrimitiveTopology::LineStrip,
112            RenderAssetUsages::RENDER_WORLD,
113        )
114        // Add the point positions as an attribute
115        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, line.points)
116        .with_inserted_indices(line.indices)
117    }
More examples
Hide additional examples
examples/shader_advanced/custom_vertex_attribute.rs (lines 37-41)
30fn setup(
31    mut commands: Commands,
32    mut meshes: ResMut<Assets<Mesh>>,
33    mut materials: ResMut<Assets<CustomMaterial>>,
34) {
35    let mesh = Mesh::from(Cuboid::default())
36        // Sets the custom attribute
37        .with_inserted_attribute(
38            ATTRIBUTE_BLEND_COLOR,
39            // The cube mesh has 24 vertices (6 faces, 4 vertices per face), so we insert one BlendColor for each
40            vec![[1.0, 0.0, 0.0, 1.0]; 24],
41        );
42
43    // cube
44    commands.spawn((
45        Mesh3d(meshes.add(mesh)),
46        MeshMaterial3d(materials.add(CustomMaterial {
47            color: LinearRgba::WHITE,
48        })),
49        Transform::from_xyz(0.0, 0.5, 0.0),
50    ));
51
52    // camera
53    commands.spawn((
54        Camera3d::default(),
55        Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
56    ));
57}
examples/shader_advanced/specialized_mesh_pipeline.rs (lines 63-70)
54fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
55    // Build a custom triangle mesh with colors
56    // We define a custom mesh because the examples only uses a limited
57    // set of vertex attributes for simplicity
58    let mesh = Mesh::new(
59        PrimitiveTopology::TriangleList,
60        RenderAssetUsages::default(),
61    )
62    .with_inserted_indices(Indices::U32(vec![0, 1, 2]))
63    .with_inserted_attribute(
64        Mesh::ATTRIBUTE_POSITION,
65        vec![
66            vec3(-0.5, -0.5, 0.0),
67            vec3(0.5, -0.5, 0.0),
68            vec3(0.0, 0.25, 0.0),
69        ],
70    )
71    .with_inserted_attribute(
72        Mesh::ATTRIBUTE_COLOR,
73        vec![
74            vec4(1.0, 0.0, 0.0, 1.0),
75            vec4(0.0, 1.0, 0.0, 1.0),
76            vec4(0.0, 0.0, 1.0, 1.0),
77        ],
78    );
79
80    // spawn 3 triangles to show that batching works
81    for (x, y) in [-0.5, 0.0, 0.5].into_iter().zip([-0.25, 0.5, -0.25]) {
82        // Spawn an entity with all the required components for it to be rendered with our custom pipeline
83        commands.spawn((
84            // We use a marker component to identify the mesh that will be rendered
85            // with our specialized pipeline
86            CustomRenderedEntity,
87            // We need to add the mesh handle to the entity
88            Mesh3d(meshes.add(mesh.clone())),
89            Transform::from_xyz(x, y, 0.0),
90        ));
91    }
92
93    // Spawn the camera.
94    commands.spawn((
95        Camera3d::default(),
96        // Move the camera back a bit to see all the triangles
97        Transform::from_xyz(0.0, 0.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y),
98    ));
99}
examples/math/custom_primitives.rs (line 562)
514    fn build(&self) -> Mesh {
515        let radius = self.heart.radius;
516        // The curved parts of each wing (half) of the heart have an angle of `PI * 1.25` or 225°
517        let wing_angle = PI * 1.25;
518
519        // We create buffers for the vertices, their normals and UVs, as well as the indices used to connect the vertices.
520        let mut vertices = Vec::with_capacity(2 * self.resolution);
521        let mut uvs = Vec::with_capacity(2 * self.resolution);
522        let mut indices = Vec::with_capacity(6 * self.resolution - 9);
523        // Since the heart is flat, we know all the normals are identical already.
524        let normals = vec![[0f32, 0f32, 1f32]; 2 * self.resolution];
525
526        // The point in the middle of the two curved parts of the heart
527        vertices.push([0.0; 3]);
528        uvs.push([0.5, 0.5]);
529
530        // The left wing of the heart, starting from the point in the middle.
531        for i in 1..self.resolution {
532            let angle = (i as f32 / self.resolution as f32) * wing_angle;
533            let (sin, cos) = ops::sin_cos(angle);
534            vertices.push([radius * (cos - 1.0), radius * sin, 0.0]);
535            uvs.push([0.5 - (cos - 1.0) / 4., 0.5 - sin / 2.]);
536        }
537
538        // The bottom tip of the heart
539        vertices.push([0.0, radius * (-1. - SQRT_2), 0.0]);
540        uvs.push([0.5, 1.]);
541
542        // The right wing of the heart, starting from the bottom most point and going towards the middle point.
543        for i in 0..self.resolution - 1 {
544            let angle = (i as f32 / self.resolution as f32) * wing_angle - PI / 4.;
545            let (sin, cos) = ops::sin_cos(angle);
546            vertices.push([radius * (cos + 1.0), radius * sin, 0.0]);
547            uvs.push([0.5 - (cos + 1.0) / 4., 0.5 - sin / 2.]);
548        }
549
550        // This is where we build all the triangles from the points created above.
551        // Each triangle has one corner on the middle point with the other two being adjacent points on the perimeter of the heart.
552        for i in 2..2 * self.resolution as u32 {
553            indices.extend_from_slice(&[i - 1, i, 0]);
554        }
555
556        // Here, the actual `Mesh` is created. We set the indices, vertices, normals and UVs created above and specify the topology of the mesh.
557        Mesh::new(
558            bevy::mesh::PrimitiveTopology::TriangleList,
559            RenderAssetUsages::default(),
560        )
561        .with_inserted_indices(bevy::mesh::Indices::U32(indices))
562        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
563        .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
564        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
565    }
examples/shader_advanced/compute_mesh.rs (line 106)
82fn setup(
83    mut commands: Commands,
84    mut meshes: ResMut<Assets<Mesh>>,
85    mut materials: ResMut<Assets<StandardMaterial>>,
86) {
87    // a truly empty mesh will error if used in Mesh3d
88    // so we set up the data to be what we want the compute shader to output
89    // We're using 36 indices and 24 vertices which is directly taken from
90    // the Bevy Cuboid mesh implementation.
91    //
92    // We allocate 50 spots for each attribute here because
93    // it is *very important* that the amount of data allocated here is
94    // *bigger* than (or exactly equal to) the amount of data we intend to
95    // write from the compute shader. This amount of data defines how big
96    // the buffer we get from the mesh_allocator will be, which in turn
97    // defines how big the buffer is when we're in the compute shader.
98    //
99    // If it turns out you don't need all of the space when the compute shader
100    // is writing data, you can write NaN to the rest of the data.
101    let empty_mesh = {
102        let mut mesh = Mesh::new(
103            PrimitiveTopology::TriangleList,
104            RenderAssetUsages::RENDER_WORLD,
105        )
106        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vec![[0.; 3]; 50])
107        .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.; 3]; 50])
108        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.; 2]; 50])
109        .with_inserted_indices(Indices::U32(vec![0; 50]));
110
111        mesh.asset_usage = RenderAssetUsages::RENDER_WORLD;
112        mesh
113    };
114
115    let handle = meshes.add(empty_mesh);
116
117    // we spawn two "users" of the mesh handle,
118    // but only insert `GenerateMesh` on one of them
119    // to show that the mesh handle works as usual
120    commands.spawn((
121        GenerateMesh(handle.clone()),
122        Mesh3d(handle.clone()),
123        MeshMaterial3d(materials.add(StandardMaterial {
124            base_color: RED_400.into(),
125            ..default()
126        })),
127        Transform::from_xyz(-2.5, 1.5, 0.),
128    ));
129
130    commands.spawn((
131        Mesh3d(handle),
132        MeshMaterial3d(materials.add(StandardMaterial {
133            base_color: SKY_400.into(),
134            ..default()
135        })),
136        Transform::from_xyz(2.5, 1.5, 0.),
137    ));
138
139    // some additional scene elements.
140    // This mesh specifically is here so that we don't assume
141    // mesh_allocator offsets that would only work if we had
142    // one mesh in the scene.
143    commands.spawn((
144        Mesh3d(meshes.add(Circle::new(4.0))),
145        MeshMaterial3d(materials.add(Color::WHITE)),
146        Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
147    ));
148    commands.spawn((
149        PointLight {
150            shadow_maps_enabled: true,
151            ..default()
152        },
153        Transform::from_xyz(4.0, 8.0, 4.0),
154    ));
155    // camera
156    commands.spawn((
157        Camera3d::default(),
158        Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
159    ));
160}
tests/3d/test_invalid_skinned_mesh.rs (lines 103-115)
92fn setup_meshes(
93    mut commands: Commands,
94    mut mesh_assets: ResMut<Assets<Mesh>>,
95    mut material_assets: ResMut<Assets<StandardMaterial>>,
96    mut inverse_bindposes_assets: ResMut<Assets<SkinnedMeshInverseBindposes>>,
97) {
98    // Create a mesh with two rectangles.
99    let unskinned_mesh = Mesh::new(
100        PrimitiveTopology::TriangleList,
101        RenderAssetUsages::default(),
102    )
103    .with_inserted_attribute(
104        Mesh::ATTRIBUTE_POSITION,
105        vec![
106            [-0.3, -0.3, 0.0],
107            [0.3, -0.3, 0.0],
108            [-0.3, 0.3, 0.0],
109            [0.3, 0.3, 0.0],
110            [-0.4, 0.8, 0.0],
111            [0.4, 0.8, 0.0],
112            [-0.4, 1.8, 0.0],
113            [0.4, 1.8, 0.0],
114        ],
115    )
116    .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.0, 0.0, 1.0]; 8])
117    .with_inserted_indices(Indices::U16(vec![0, 1, 3, 0, 3, 2, 4, 5, 7, 4, 7, 6]));
118
119    // Copy the mesh and add skinning attributes that bind each rectangle to a joint.
120    let skinned_mesh = unskinned_mesh
121        .clone()
122        .with_inserted_attribute(
123            Mesh::ATTRIBUTE_JOINT_INDEX,
124            VertexAttributeValues::Uint16x4(vec![
125                [0, 0, 0, 0],
126                [0, 0, 0, 0],
127                [0, 0, 0, 0],
128                [0, 0, 0, 0],
129                [1, 0, 0, 0],
130                [1, 0, 0, 0],
131                [1, 0, 0, 0],
132                [1, 0, 0, 0],
133            ]),
134        )
135        .with_inserted_attribute(
136            Mesh::ATTRIBUTE_JOINT_WEIGHT,
137            vec![[1.00, 0.00, 0.0, 0.0]; 8],
138        );
139
140    let unskinned_mesh_handle = mesh_assets.add(unskinned_mesh);
141    let skinned_mesh_handle = mesh_assets.add(skinned_mesh);
142
143    let inverse_bindposes_handle = inverse_bindposes_assets.add(vec![
144        Mat4::IDENTITY,
145        Mat4::from_translation(Vec3::new(0.0, -1.3, 0.0)),
146    ]);
147
148    let mesh_material_handle = material_assets.add(StandardMaterial::default());
149
150    let background_material_handle = material_assets.add(StandardMaterial {
151        base_color: Color::srgb(0.05, 0.15, 0.05),
152        reflectance: 0.2,
153        ..default()
154    });
155
156    #[derive(PartialEq)]
157    enum Variation {
158        Normal,
159        MissingMeshAttributes,
160        MissingJointEntity,
161        MissingSkinnedMeshComponent,
162    }
163
164    for (index, variation) in [
165        Variation::Normal,
166        Variation::MissingMeshAttributes,
167        Variation::MissingJointEntity,
168        Variation::MissingSkinnedMeshComponent,
169    ]
170    .into_iter()
171    .enumerate()
172    {
173        // Skip variations that are currently broken. See https://github.com/bevyengine/bevy/issues/16929,
174        // https://github.com/bevyengine/bevy/pull/18074.
175        if (variation == Variation::MissingSkinnedMeshComponent)
176            || (variation == Variation::MissingMeshAttributes)
177        {
178            continue;
179        }
180
181        let transform = Transform::from_xyz(((index as f32) - 1.5) * 4.5, 0.0, 0.0);
182
183        let joint_0 = commands.spawn(transform).id();
184
185        let joint_1 = commands
186            .spawn((ChildOf(joint_0), AnimatedJoint, Transform::IDENTITY))
187            .id();
188
189        if variation == Variation::MissingJointEntity {
190            commands.entity(joint_1).despawn();
191        }
192
193        let mesh_handle = match variation {
194            Variation::MissingMeshAttributes => &unskinned_mesh_handle,
195            _ => &skinned_mesh_handle,
196        };
197
198        let mut entity_commands = commands.spawn((
199            Mesh3d(mesh_handle.clone()),
200            MeshMaterial3d(mesh_material_handle.clone()),
201            transform,
202        ));
203
204        if variation != Variation::MissingSkinnedMeshComponent {
205            entity_commands.insert(SkinnedMesh {
206                inverse_bindposes: inverse_bindposes_handle.clone(),
207                joints: vec![joint_0, joint_1],
208            });
209        }
210
211        // Add a square behind the mesh to distinguish it from the other meshes.
212        commands.spawn((
213            Transform::from_xyz(transform.translation.x, transform.translation.y, -0.8),
214            Mesh3d(mesh_assets.add(Plane3d::default().mesh().size(4.3, 4.3).normal(Dir3::Z))),
215            MeshMaterial3d(background_material_handle.clone()),
216        ));
217    }
218}
Source

pub fn try_with_inserted_attribute( self, attribute: MeshVertexAttribute, values: impl Into<VertexAttributeValues>, ) -> Result<Mesh, MeshAccessError>

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.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn remove_attribute( &mut self, attribute: impl Into<MeshVertexAttributeId>, ) -> Option<VertexAttributeValues>

Removes the data for a vertex attribute

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_remove_attribute

Examples found in repository?
examples/3d/solari.rs (line 410)
374fn add_raytracing_meshes_on_scene_load(
375    scene_ready: On<WorldInstanceReady>,
376    children: Query<&Children>,
377    mesh_query: Query<(
378        &Mesh3d,
379        &MeshMaterial3d<StandardMaterial>,
380        Option<&GltfMaterialName>,
381    )>,
382    mut meshes: ResMut<Assets<Mesh>>,
383    mut materials: ResMut<Assets<StandardMaterial>>,
384    mut commands: Commands,
385    args: Res<Args>,
386) {
387    for descendant in children.iter_descendants(scene_ready.entity) {
388        if let Ok((Mesh3d(mesh_handle), MeshMaterial3d(material_handle), material_name)) =
389            mesh_query.get(descendant)
390        {
391            // Add raytracing mesh component
392            commands
393                .entity(descendant)
394                .insert(RaytracingMesh3d(mesh_handle.clone()));
395
396            // Ensure meshes are Solari compatible
397            let mut mesh = meshes.get_mut(mesh_handle).unwrap();
398            if !mesh.contains_attribute(Mesh::ATTRIBUTE_UV_0) {
399                let vertex_count = mesh.count_vertices();
400                mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.0, 0.0]; vertex_count]);
401                mesh.insert_attribute(
402                    Mesh::ATTRIBUTE_TANGENT,
403                    vec![[0.0, 0.0, 0.0, 0.0]; vertex_count],
404                );
405            }
406            if !mesh.contains_attribute(Mesh::ATTRIBUTE_TANGENT) {
407                mesh.generate_tangents().unwrap();
408            }
409            if mesh.contains_attribute(Mesh::ATTRIBUTE_UV_1) {
410                mesh.remove_attribute(Mesh::ATTRIBUTE_UV_1);
411            }
412            if let Some(indices) = mesh.indices_mut()
413                && let Indices::U16(_) = indices
414            {
415                *indices = Indices::U32(indices.iter().map(|i| i as u32).collect());
416            }
417
418            // Prevent rasterization if using pathtracer
419            if args.pathtracer == Some(true) {
420                commands.entity(descendant).remove::<Mesh3d>();
421            }
422
423            // Adjust scene materials to better demo Solari features
424            if material_name.map(|s| s.0.as_str()) == Some("material") {
425                let mut material = materials.get_mut(material_handle).unwrap();
426                material.emissive = LinearRgba::BLACK;
427            }
428            if material_name.map(|s| s.0.as_str()) == Some("Lights") {
429                let mut material = materials.get_mut(material_handle).unwrap();
430                material.emissive =
431                    LinearRgba::from(Color::srgb(0.941, 0.714, 0.043)) * 1_000_000.0;
432                material.alpha_mode = AlphaMode::Opaque;
433                material.specular_transmission = 0.0;
434
435                commands.insert_resource(RobotLightMaterial(material_handle.clone()));
436            }
437            if material_name.map(|s| s.0.as_str()) == Some("Glass_Dark_01") {
438                let mut material = materials.get_mut(material_handle).unwrap();
439                material.alpha_mode = AlphaMode::Opaque;
440                material.specular_transmission = 0.0;
441            }
442        }
443    }
444}
Source

pub fn try_remove_attribute( &mut self, attribute: impl Into<MeshVertexAttributeId>, ) -> Result<VertexAttributeValues, MeshAccessError>

Removes the data for a vertex attribute Returns an error if the mesh data has been extracted to RenderWorldor if the attribute does not exist.

Source

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)

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_with_removed_attribute

Source

pub fn try_with_removed_attribute( self, attribute: impl Into<MeshVertexAttributeId>, ) -> Result<Mesh, MeshAccessError>

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)

Returns an error if the mesh data has been extracted to RenderWorldor if the attribute does not exist.

Source

pub fn contains_attribute(&self, id: impl Into<MeshVertexAttributeId>) -> bool

Returns a bool indicating if the attribute is present in this mesh’s vertex data.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_contains_attribute

Examples found in repository?
examples/3d/solari.rs (line 398)
374fn add_raytracing_meshes_on_scene_load(
375    scene_ready: On<WorldInstanceReady>,
376    children: Query<&Children>,
377    mesh_query: Query<(
378        &Mesh3d,
379        &MeshMaterial3d<StandardMaterial>,
380        Option<&GltfMaterialName>,
381    )>,
382    mut meshes: ResMut<Assets<Mesh>>,
383    mut materials: ResMut<Assets<StandardMaterial>>,
384    mut commands: Commands,
385    args: Res<Args>,
386) {
387    for descendant in children.iter_descendants(scene_ready.entity) {
388        if let Ok((Mesh3d(mesh_handle), MeshMaterial3d(material_handle), material_name)) =
389            mesh_query.get(descendant)
390        {
391            // Add raytracing mesh component
392            commands
393                .entity(descendant)
394                .insert(RaytracingMesh3d(mesh_handle.clone()));
395
396            // Ensure meshes are Solari compatible
397            let mut mesh = meshes.get_mut(mesh_handle).unwrap();
398            if !mesh.contains_attribute(Mesh::ATTRIBUTE_UV_0) {
399                let vertex_count = mesh.count_vertices();
400                mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.0, 0.0]; vertex_count]);
401                mesh.insert_attribute(
402                    Mesh::ATTRIBUTE_TANGENT,
403                    vec![[0.0, 0.0, 0.0, 0.0]; vertex_count],
404                );
405            }
406            if !mesh.contains_attribute(Mesh::ATTRIBUTE_TANGENT) {
407                mesh.generate_tangents().unwrap();
408            }
409            if mesh.contains_attribute(Mesh::ATTRIBUTE_UV_1) {
410                mesh.remove_attribute(Mesh::ATTRIBUTE_UV_1);
411            }
412            if let Some(indices) = mesh.indices_mut()
413                && let Indices::U16(_) = indices
414            {
415                *indices = Indices::U32(indices.iter().map(|i| i as u32).collect());
416            }
417
418            // Prevent rasterization if using pathtracer
419            if args.pathtracer == Some(true) {
420                commands.entity(descendant).remove::<Mesh3d>();
421            }
422
423            // Adjust scene materials to better demo Solari features
424            if material_name.map(|s| s.0.as_str()) == Some("material") {
425                let mut material = materials.get_mut(material_handle).unwrap();
426                material.emissive = LinearRgba::BLACK;
427            }
428            if material_name.map(|s| s.0.as_str()) == Some("Lights") {
429                let mut material = materials.get_mut(material_handle).unwrap();
430                material.emissive =
431                    LinearRgba::from(Color::srgb(0.941, 0.714, 0.043)) * 1_000_000.0;
432                material.alpha_mode = AlphaMode::Opaque;
433                material.specular_transmission = 0.0;
434
435                commands.insert_resource(RobotLightMaterial(material_handle.clone()));
436            }
437            if material_name.map(|s| s.0.as_str()) == Some("Glass_Dark_01") {
438                let mut material = materials.get_mut(material_handle).unwrap();
439                material.alpha_mode = AlphaMode::Opaque;
440                material.specular_transmission = 0.0;
441            }
442        }
443    }
444}
Source

pub fn try_contains_attribute( &self, id: impl Into<MeshVertexAttributeId>, ) -> Result<bool, MeshAccessError>

Returns a bool indicating if the attribute is present in this mesh’s vertex data.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn attribute( &self, id: impl Into<MeshVertexAttributeId>, ) -> Option<&VertexAttributeValues>

Retrieves the data currently set to the vertex attribute with the specified MeshVertexAttributeId.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_attribute or Mesh::try_attribute_option

Examples found in repository?
examples/3d/vertex_colors.rs (line 27)
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            shadow_maps_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
Hide additional examples
examples/3d/occlusion_culling.rs (line 291)
254fn spawn_small_cubes(
255    commands: &mut Commands,
256    meshes: &mut Assets<Mesh>,
257    materials: &mut Assets<StandardMaterial>,
258) {
259    // Add the cube mesh.
260    let small_cube = meshes.add(Cuboid::new(
261        SMALL_CUBE_SIZE,
262        SMALL_CUBE_SIZE,
263        SMALL_CUBE_SIZE,
264    ));
265
266    // Add the cube material.
267    let small_cube_material = materials.add(StandardMaterial {
268        base_color: SILVER.into(),
269        ..default()
270    });
271
272    // Create the entity that the small cubes will be parented to. This is the
273    // entity that we rotate.
274    let sphere_parent = commands
275        .spawn(Transform::from_translation(Vec3::ZERO))
276        .insert(Visibility::default())
277        .insert(SphereParent)
278        .id();
279
280    // Now we have to figure out where to place the cubes. To do that, we create
281    // a sphere mesh, but we don't add it to the scene. Instead, we inspect the
282    // sphere mesh to find the positions of its vertices, and spawn a small cube
283    // at each one. That way, we end up with a bunch of cubes arranged in a
284    // spherical shape.
285
286    // Create the sphere mesh, and extract the positions of its vertices.
287    let sphere = Sphere::new(OUTER_RADIUS)
288        .mesh()
289        .ico(OUTER_SUBDIVISION_COUNT)
290        .unwrap();
291    let sphere_positions = sphere.attribute(Mesh::ATTRIBUTE_POSITION).unwrap();
292
293    // At each vertex, create a small cube.
294    for sphere_position in sphere_positions.as_float3().unwrap() {
295        let sphere_position = Vec3::from_slice(sphere_position);
296        let small_cube = commands
297            .spawn(Mesh3d(small_cube.clone()))
298            .insert(MeshMaterial3d(small_cube_material.clone()))
299            .insert(Transform::from_translation(sphere_position))
300            .id();
301        commands.entity(sphere_parent).add_child(small_cube);
302    }
303}
Source

pub fn try_attribute( &self, id: impl Into<MeshVertexAttributeId>, ) -> Result<&VertexAttributeValues, MeshAccessError>

Retrieves the data currently set to the vertex attribute with the specified MeshVertexAttributeId.

Returns an error if the mesh data has been extracted to RenderWorldor if the attribute does not exist.

Source

pub fn try_attribute_option( &self, id: impl Into<MeshVertexAttributeId>, ) -> Result<Option<&VertexAttributeValues>, MeshAccessError>

Retrieves the data currently set to the vertex attribute with the specified MeshVertexAttributeId.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_attribute_mut

Examples found in repository?
examples/3d/generate_custom_mesh.rs (line 256)
254fn toggle_texture(mesh_to_change: &mut Mesh) {
255    // Get a mutable reference to the values of the UV attribute, so we can iterate over it.
256    let uv_attribute = mesh_to_change.attribute_mut(Mesh::ATTRIBUTE_UV_0).unwrap();
257    // The format of the UV coordinates should be Float32x2.
258    let VertexAttributeValues::Float32x2(uv_attribute) = uv_attribute else {
259        panic!("Unexpected vertex format, expected Float32x2.");
260    };
261
262    // Iterate over the UV coordinates, and change them as we want.
263    for uv_coord in uv_attribute.iter_mut() {
264        // If the UV coordinate points to the upper, "dirt+grass" part of the texture...
265        if (uv_coord[1] + 0.5) < 1.0 {
266            // ... point to the equivalent lower, "sand+water" part instead,
267            uv_coord[1] += 0.5;
268        } else {
269            // else, point back to the upper, "dirt+grass" part.
270            uv_coord[1] -= 0.5;
271        }
272    }
273}
More examples
Hide additional examples
examples/gltf/query_gltf_primitives.rs (line 39)
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(mut 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(mut mesh) = meshes.get_mut(mesh_handle)
38                && 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}
examples/asset/alter_mesh.rs (line 196)
175fn alter_mesh(
176    mut is_mesh_scaled: Local<bool>,
177    left_shape: Single<&Mesh3d, With<Left>>,
178    mut meshes: ResMut<Assets<Mesh>>,
179) {
180    // Obtain a mutable reference to the Mesh asset.
181    let Some(mut mesh) = meshes.get_mut(*left_shape) else {
182        return;
183    };
184
185    // Now we can directly manipulate vertices on the mesh. Here, we're just scaling in and out
186    // for demonstration purposes. This will affect all entities currently using the asset.
187    //
188    // To do this, we need to grab the stored attributes of each vertex. `Float32x3` just describes
189    // the format in which the attributes will be read: each position consists of an array of three
190    // f32 corresponding to x, y, and z.
191    //
192    // `ATTRIBUTE_POSITION` is a constant indicating that we want to know where the vertex is
193    // located in space (as opposed to which way its normal is facing, vertex color, or other
194    // details).
195    if let Some(VertexAttributeValues::Float32x3(positions)) =
196        mesh.attribute_mut(Mesh::ATTRIBUTE_POSITION)
197    {
198        // Check a Local value (which only this system can make use of) to determine if we're
199        // currently scaled up or not.
200        let scale_factor = if *is_mesh_scaled { 0.5 } else { 2.0 };
201
202        for position in positions.iter_mut() {
203            // Apply the scale factor to each of x, y, and z.
204            position[0] *= scale_factor;
205            position[1] *= scale_factor;
206            position[2] *= scale_factor;
207        }
208
209        // Flip the local value to reverse the behavior next time the key is pressed.
210        *is_mesh_scaled = !*is_mesh_scaled;
211    }
212}
examples/3d/solari.rs (line 218)
200fn setup_many_lights(
201    mut commands: Commands,
202    asset_server: Res<AssetServer>,
203    mut meshes: ResMut<Assets<Mesh>>,
204    mut materials: ResMut<Assets<StandardMaterial>>,
205    args: Res<Args>,
206    #[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))] dlss_rr_supported: Option<
207        Res<DlssRayReconstructionSupported>,
208    >,
209) {
210    let mut rng = ChaCha8Rng::seed_from_u64(42);
211
212    let mut plane_mesh = Plane3d::default()
213        .mesh()
214        .size(400.0, 400.0)
215        .build()
216        .with_generated_tangents()
217        .unwrap();
218    match plane_mesh.attribute_mut(Mesh::ATTRIBUTE_UV_0).unwrap() {
219        VertexAttributeValues::Float32x2(items) => {
220            items.iter_mut().flatten().for_each(|x| *x *= 3.0);
221        }
222        _ => unreachable!(),
223    }
224    let plane_mesh = meshes.add(plane_mesh);
225    let cube_mesh = meshes.add(
226        Cuboid::default()
227            .mesh()
228            .build()
229            .with_generated_tangents()
230            .unwrap(),
231    );
232    let sphere_mesh = meshes.add(
233        Sphere::new(1.0)
234            .mesh()
235            .build()
236            .with_generated_tangents()
237            .unwrap(),
238    );
239
240    commands
241        .spawn((
242            RaytracingMesh3d(plane_mesh.clone()),
243            MeshMaterial3d(
244                materials.add(StandardMaterial {
245                    base_color_texture: Some(
246                        asset_server
247                            .load_builder()
248                            .with_settings::<ImageLoaderSettings>(|settings| {
249                                settings
250                                    .sampler
251                                    .get_or_init_descriptor()
252                                    .set_address_mode(ImageAddressMode::Repeat);
253                            })
254                            .load("textures/uv_checker_bw.png"),
255                    ),
256                    perceptual_roughness: 0.0,
257                    ..default()
258                }),
259            ),
260        ))
261        .insert_if(Mesh3d(plane_mesh), || args.pathtracer != Some(true));
262
263    for _ in 0..8000 {
264        commands
265            .spawn((
266                RaytracingMesh3d(cube_mesh.clone()),
267                MeshMaterial3d(materials.add(StandardMaterial {
268                    base_color: Color::srgb(rng.random(), rng.random(), rng.random()),
269                    perceptual_roughness: rng.random(),
270                    ..default()
271                })),
272                Transform::default()
273                    .with_scale(Vec3 {
274                        x: rng.random_range(0.2..=2.0),
275                        y: rng.random_range(0.2..=2.0),
276                        z: rng.random_range(0.2..=2.0),
277                    })
278                    .with_translation(Vec3::new(
279                        rng.random_range(-180.0..=180.0),
280                        0.2,
281                        rng.random_range(-180.0..=180.0),
282                    )),
283            ))
284            .insert_if(Mesh3d(cube_mesh.clone()), || args.pathtracer != Some(true));
285    }
286
287    for x in -10..=10 {
288        for y in -10..=10 {
289            commands
290                .spawn((
291                    RaytracingMesh3d(sphere_mesh.clone()),
292                    MeshMaterial3d(
293                        materials.add(StandardMaterial {
294                            emissive: Color::linear_rgb(
295                                rng.random::<f32>() * 60000.0,
296                                rng.random::<f32>() * 60000.0,
297                                rng.random::<f32>() * 60000.0,
298                            )
299                            .into(),
300                            ..default()
301                        }),
302                    ),
303                    Transform::default().with_translation(Vec3::new(
304                        (x * 20) as f32,
305                        7.0,
306                        (y * 20) as f32,
307                    )),
308                ))
309                .insert_if(Mesh3d(sphere_mesh.clone()), || {
310                    args.pathtracer != Some(true)
311                });
312        }
313    }
314
315    let mut camera = commands.spawn((
316        Camera3d::default(),
317        Camera {
318            clear_color: ClearColorConfig::Custom(Color::BLACK),
319            ..default()
320        },
321        FreeCamera {
322            walk_speed: 3.0,
323            run_speed: 10.0,
324            ..Default::default()
325        },
326        Transform::from_translation(Vec3::new(6.11329, 166.74896, 451.8226)).with_rotation(
327            Quat::from_xyzw(-0.183938, 0.009093744, 0.0017017953, 0.9828943),
328        ),
329        // Msaa::Off and CameraMainTextureUsages with STORAGE_BINDING are required for Solari
330        CameraMainTextureUsages::default().with(TextureUsages::STORAGE_BINDING),
331        Msaa::Off,
332        Bloom {
333            intensity: 0.1,
334            ..Bloom::NATURAL
335        },
336    ));
337
338    if args.pathtracer == Some(true) {
339        camera.insert(Pathtracer::default());
340    } else {
341        camera.insert(SolariLighting::default());
342    }
343
344    // Using DLSS Ray Reconstruction for denoising (and cheaper rendering via upscaling) is _highly_ recommended when using Solari
345    #[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
346    if dlss_rr_supported.is_some() {
347        camera.insert(Dlss::<DlssRayReconstructionFeature> {
348            perf_quality_mode: Default::default(),
349            reset: Default::default(),
350            _phantom_data: Default::default(),
351        });
352    }
353
354    commands.spawn((
355        Node {
356            position_type: PositionType::Absolute,
357            right: px(0.0),
358            padding: px(4.0).all(),
359            border_radius: BorderRadius::bottom_left(px(4.0)),
360            ..default()
361        },
362        BackgroundColor(Color::srgba(0.10, 0.10, 0.10, 0.8)),
363        children![(
364            PerformanceText,
365            Text::default(),
366            TextFont {
367                font_size: FontSize::Px(8.0),
368                ..default()
369            },
370        )],
371    ));
372}
Source

pub fn try_attribute_mut( &mut self, id: impl Into<MeshVertexAttributeId>, ) -> Result<&mut VertexAttributeValues, MeshAccessError>

Retrieves the data currently set to the vertex attribute with the specified name mutably.

Returns an error if the mesh data has been extracted to RenderWorldor if the attribute does not exist.

Source

pub fn try_attribute_mut_option( &mut self, id: impl Into<MeshVertexAttributeId>, ) -> Result<Option<&mut VertexAttributeValues>, MeshAccessError>

Retrieves the data currently set to the vertex attribute with the specified name mutably.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn attributes( &self, ) -> impl Iterator<Item = (&MeshVertexAttribute, &VertexAttributeValues)>

Returns an iterator that yields references to the data of each vertex attribute.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_attributes

Source

pub fn try_attributes( &self, ) -> Result<impl Iterator<Item = (&MeshVertexAttribute, &VertexAttributeValues)>, MeshAccessError>

Returns an iterator that yields references to the data of each vertex attribute. Returns an error if data has been extracted to RenderWorld

Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_attributes_mut

Source

pub fn try_attributes_mut( &mut self, ) -> Result<impl Iterator<Item = (&MeshVertexAttribute, &mut VertexAttributeValues)>, MeshAccessError>

Returns an iterator that yields mutable references to the data of each vertex attribute.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_insert_indices

Examples found in repository?
examples/2d/mesh2d_manual.rs (line 111)
49fn star(
50    mut commands: Commands,
51    // We will add a new Mesh for the star being created
52    mut meshes: ResMut<Assets<Mesh>>,
53) {
54    // Let's define the mesh for the object we want to draw: a nice star.
55    // We will specify here what kind of topology is used to define the mesh,
56    // that is, how triangles are built from the vertices. We will use a
57    // triangle list, meaning that each vertex of the triangle has to be
58    // specified. We set `RenderAssetUsages::RENDER_WORLD`, meaning this mesh
59    // will not be accessible in future frames from the `meshes` resource, in
60    // order to save on memory once it has been uploaded to the GPU.
61    let mut star = Mesh::new(
62        PrimitiveTopology::TriangleList,
63        RenderAssetUsages::RENDER_WORLD,
64    );
65
66    // Vertices need to have a position attribute. We will use the following
67    // vertices (I hope you can spot the star in the schema).
68    //
69    //        1
70    //
71    //     10   2
72    // 9      0      3
73    //     8     4
74    //        6
75    //   7        5
76    //
77    // These vertices are specified in 3D space.
78    let mut v_pos = vec![[0.0, 0.0, 0.0]];
79    for i in 0..10 {
80        // The angle between each vertex is 1/10 of a full rotation.
81        let a = i as f32 * PI / 5.0;
82        // The radius of inner vertices (even indices) is 100. For outer vertices (odd indices) it's 200.
83        let r = (1 - i % 2) as f32 * 100.0 + 100.0;
84        // Add the vertex position.
85        v_pos.push([r * ops::sin(a), r * ops::cos(a), 0.0]);
86    }
87    // Set the position attribute
88    star.insert_attribute(Mesh::ATTRIBUTE_POSITION, v_pos);
89    // And a RGB color attribute as well. A built-in `Mesh::ATTRIBUTE_COLOR` exists, but we
90    // use a custom vertex attribute here for demonstration purposes.
91    let mut v_color: Vec<u32> = vec![LinearRgba::BLACK.as_u32()];
92    v_color.extend_from_slice(&[LinearRgba::from(YELLOW).as_u32(); 10]);
93    star.insert_attribute(
94        MeshVertexAttribute::new("Vertex_Color", 1, VertexFormat::Uint32),
95        v_color,
96    );
97
98    // Now, we specify the indices of the vertex that are going to compose the
99    // triangles in our star. Vertices in triangles have to be specified in CCW
100    // winding (that will be the front face, colored). Since we are using
101    // triangle list, we will specify each triangle as 3 vertices
102    //   First triangle: 0, 2, 1
103    //   Second triangle: 0, 3, 2
104    //   Third triangle: 0, 4, 3
105    //   etc
106    //   Last triangle: 0, 1, 10
107    let mut indices = vec![0, 1, 10];
108    for i in 2..=10 {
109        indices.extend_from_slice(&[0, i, i - 1]);
110    }
111    star.insert_indices(Indices::U32(indices));
112
113    // We can now spawn the entities for the star and the camera
114    commands.spawn((
115        // We use a marker component to identify the custom colored meshes
116        ColoredMesh2d,
117        // The `Handle<Mesh>` needs to be wrapped in a `Mesh2d` for 2D rendering
118        Mesh2d(meshes.add(star)),
119    ));
120
121    commands.spawn(Camera2d);
122}
Source

pub fn try_insert_indices( &mut self, indices: Indices, ) -> Result<(), MeshAccessError>

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.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

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)

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_with_inserted_indices

Examples found in repository?
examples/3d/lines.rs (line 116)
107    fn from(line: LineStrip) -> Self {
108        Mesh::new(
109            // This tells wgpu that the positions are a list of points
110            // where a line will be drawn between each consecutive point
111            PrimitiveTopology::LineStrip,
112            RenderAssetUsages::RENDER_WORLD,
113        )
114        // Add the point positions as an attribute
115        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, line.points)
116        .with_inserted_indices(line.indices)
117    }
More examples
Hide additional examples
examples/shader_advanced/specialized_mesh_pipeline.rs (line 62)
54fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
55    // Build a custom triangle mesh with colors
56    // We define a custom mesh because the examples only uses a limited
57    // set of vertex attributes for simplicity
58    let mesh = Mesh::new(
59        PrimitiveTopology::TriangleList,
60        RenderAssetUsages::default(),
61    )
62    .with_inserted_indices(Indices::U32(vec![0, 1, 2]))
63    .with_inserted_attribute(
64        Mesh::ATTRIBUTE_POSITION,
65        vec![
66            vec3(-0.5, -0.5, 0.0),
67            vec3(0.5, -0.5, 0.0),
68            vec3(0.0, 0.25, 0.0),
69        ],
70    )
71    .with_inserted_attribute(
72        Mesh::ATTRIBUTE_COLOR,
73        vec![
74            vec4(1.0, 0.0, 0.0, 1.0),
75            vec4(0.0, 1.0, 0.0, 1.0),
76            vec4(0.0, 0.0, 1.0, 1.0),
77        ],
78    );
79
80    // spawn 3 triangles to show that batching works
81    for (x, y) in [-0.5, 0.0, 0.5].into_iter().zip([-0.25, 0.5, -0.25]) {
82        // Spawn an entity with all the required components for it to be rendered with our custom pipeline
83        commands.spawn((
84            // We use a marker component to identify the mesh that will be rendered
85            // with our specialized pipeline
86            CustomRenderedEntity,
87            // We need to add the mesh handle to the entity
88            Mesh3d(meshes.add(mesh.clone())),
89            Transform::from_xyz(x, y, 0.0),
90        ));
91    }
92
93    // Spawn the camera.
94    commands.spawn((
95        Camera3d::default(),
96        // Move the camera back a bit to see all the triangles
97        Transform::from_xyz(0.0, 0.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y),
98    ));
99}
examples/math/custom_primitives.rs (line 561)
514    fn build(&self) -> Mesh {
515        let radius = self.heart.radius;
516        // The curved parts of each wing (half) of the heart have an angle of `PI * 1.25` or 225°
517        let wing_angle = PI * 1.25;
518
519        // We create buffers for the vertices, their normals and UVs, as well as the indices used to connect the vertices.
520        let mut vertices = Vec::with_capacity(2 * self.resolution);
521        let mut uvs = Vec::with_capacity(2 * self.resolution);
522        let mut indices = Vec::with_capacity(6 * self.resolution - 9);
523        // Since the heart is flat, we know all the normals are identical already.
524        let normals = vec![[0f32, 0f32, 1f32]; 2 * self.resolution];
525
526        // The point in the middle of the two curved parts of the heart
527        vertices.push([0.0; 3]);
528        uvs.push([0.5, 0.5]);
529
530        // The left wing of the heart, starting from the point in the middle.
531        for i in 1..self.resolution {
532            let angle = (i as f32 / self.resolution as f32) * wing_angle;
533            let (sin, cos) = ops::sin_cos(angle);
534            vertices.push([radius * (cos - 1.0), radius * sin, 0.0]);
535            uvs.push([0.5 - (cos - 1.0) / 4., 0.5 - sin / 2.]);
536        }
537
538        // The bottom tip of the heart
539        vertices.push([0.0, radius * (-1. - SQRT_2), 0.0]);
540        uvs.push([0.5, 1.]);
541
542        // The right wing of the heart, starting from the bottom most point and going towards the middle point.
543        for i in 0..self.resolution - 1 {
544            let angle = (i as f32 / self.resolution as f32) * wing_angle - PI / 4.;
545            let (sin, cos) = ops::sin_cos(angle);
546            vertices.push([radius * (cos + 1.0), radius * sin, 0.0]);
547            uvs.push([0.5 - (cos + 1.0) / 4., 0.5 - sin / 2.]);
548        }
549
550        // This is where we build all the triangles from the points created above.
551        // Each triangle has one corner on the middle point with the other two being adjacent points on the perimeter of the heart.
552        for i in 2..2 * self.resolution as u32 {
553            indices.extend_from_slice(&[i - 1, i, 0]);
554        }
555
556        // Here, the actual `Mesh` is created. We set the indices, vertices, normals and UVs created above and specify the topology of the mesh.
557        Mesh::new(
558            bevy::mesh::PrimitiveTopology::TriangleList,
559            RenderAssetUsages::default(),
560        )
561        .with_inserted_indices(bevy::mesh::Indices::U32(indices))
562        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
563        .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
564        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
565    }
examples/shader_advanced/compute_mesh.rs (line 109)
82fn setup(
83    mut commands: Commands,
84    mut meshes: ResMut<Assets<Mesh>>,
85    mut materials: ResMut<Assets<StandardMaterial>>,
86) {
87    // a truly empty mesh will error if used in Mesh3d
88    // so we set up the data to be what we want the compute shader to output
89    // We're using 36 indices and 24 vertices which is directly taken from
90    // the Bevy Cuboid mesh implementation.
91    //
92    // We allocate 50 spots for each attribute here because
93    // it is *very important* that the amount of data allocated here is
94    // *bigger* than (or exactly equal to) the amount of data we intend to
95    // write from the compute shader. This amount of data defines how big
96    // the buffer we get from the mesh_allocator will be, which in turn
97    // defines how big the buffer is when we're in the compute shader.
98    //
99    // If it turns out you don't need all of the space when the compute shader
100    // is writing data, you can write NaN to the rest of the data.
101    let empty_mesh = {
102        let mut mesh = Mesh::new(
103            PrimitiveTopology::TriangleList,
104            RenderAssetUsages::RENDER_WORLD,
105        )
106        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vec![[0.; 3]; 50])
107        .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.; 3]; 50])
108        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.; 2]; 50])
109        .with_inserted_indices(Indices::U32(vec![0; 50]));
110
111        mesh.asset_usage = RenderAssetUsages::RENDER_WORLD;
112        mesh
113    };
114
115    let handle = meshes.add(empty_mesh);
116
117    // we spawn two "users" of the mesh handle,
118    // but only insert `GenerateMesh` on one of them
119    // to show that the mesh handle works as usual
120    commands.spawn((
121        GenerateMesh(handle.clone()),
122        Mesh3d(handle.clone()),
123        MeshMaterial3d(materials.add(StandardMaterial {
124            base_color: RED_400.into(),
125            ..default()
126        })),
127        Transform::from_xyz(-2.5, 1.5, 0.),
128    ));
129
130    commands.spawn((
131        Mesh3d(handle),
132        MeshMaterial3d(materials.add(StandardMaterial {
133            base_color: SKY_400.into(),
134            ..default()
135        })),
136        Transform::from_xyz(2.5, 1.5, 0.),
137    ));
138
139    // some additional scene elements.
140    // This mesh specifically is here so that we don't assume
141    // mesh_allocator offsets that would only work if we had
142    // one mesh in the scene.
143    commands.spawn((
144        Mesh3d(meshes.add(Circle::new(4.0))),
145        MeshMaterial3d(materials.add(Color::WHITE)),
146        Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
147    ));
148    commands.spawn((
149        PointLight {
150            shadow_maps_enabled: true,
151            ..default()
152        },
153        Transform::from_xyz(4.0, 8.0, 4.0),
154    ));
155    // camera
156    commands.spawn((
157        Camera3d::default(),
158        Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
159    ));
160}
tests/3d/test_invalid_skinned_mesh.rs (line 117)
92fn setup_meshes(
93    mut commands: Commands,
94    mut mesh_assets: ResMut<Assets<Mesh>>,
95    mut material_assets: ResMut<Assets<StandardMaterial>>,
96    mut inverse_bindposes_assets: ResMut<Assets<SkinnedMeshInverseBindposes>>,
97) {
98    // Create a mesh with two rectangles.
99    let unskinned_mesh = Mesh::new(
100        PrimitiveTopology::TriangleList,
101        RenderAssetUsages::default(),
102    )
103    .with_inserted_attribute(
104        Mesh::ATTRIBUTE_POSITION,
105        vec![
106            [-0.3, -0.3, 0.0],
107            [0.3, -0.3, 0.0],
108            [-0.3, 0.3, 0.0],
109            [0.3, 0.3, 0.0],
110            [-0.4, 0.8, 0.0],
111            [0.4, 0.8, 0.0],
112            [-0.4, 1.8, 0.0],
113            [0.4, 1.8, 0.0],
114        ],
115    )
116    .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.0, 0.0, 1.0]; 8])
117    .with_inserted_indices(Indices::U16(vec![0, 1, 3, 0, 3, 2, 4, 5, 7, 4, 7, 6]));
118
119    // Copy the mesh and add skinning attributes that bind each rectangle to a joint.
120    let skinned_mesh = unskinned_mesh
121        .clone()
122        .with_inserted_attribute(
123            Mesh::ATTRIBUTE_JOINT_INDEX,
124            VertexAttributeValues::Uint16x4(vec![
125                [0, 0, 0, 0],
126                [0, 0, 0, 0],
127                [0, 0, 0, 0],
128                [0, 0, 0, 0],
129                [1, 0, 0, 0],
130                [1, 0, 0, 0],
131                [1, 0, 0, 0],
132                [1, 0, 0, 0],
133            ]),
134        )
135        .with_inserted_attribute(
136            Mesh::ATTRIBUTE_JOINT_WEIGHT,
137            vec![[1.00, 0.00, 0.0, 0.0]; 8],
138        );
139
140    let unskinned_mesh_handle = mesh_assets.add(unskinned_mesh);
141    let skinned_mesh_handle = mesh_assets.add(skinned_mesh);
142
143    let inverse_bindposes_handle = inverse_bindposes_assets.add(vec![
144        Mat4::IDENTITY,
145        Mat4::from_translation(Vec3::new(0.0, -1.3, 0.0)),
146    ]);
147
148    let mesh_material_handle = material_assets.add(StandardMaterial::default());
149
150    let background_material_handle = material_assets.add(StandardMaterial {
151        base_color: Color::srgb(0.05, 0.15, 0.05),
152        reflectance: 0.2,
153        ..default()
154    });
155
156    #[derive(PartialEq)]
157    enum Variation {
158        Normal,
159        MissingMeshAttributes,
160        MissingJointEntity,
161        MissingSkinnedMeshComponent,
162    }
163
164    for (index, variation) in [
165        Variation::Normal,
166        Variation::MissingMeshAttributes,
167        Variation::MissingJointEntity,
168        Variation::MissingSkinnedMeshComponent,
169    ]
170    .into_iter()
171    .enumerate()
172    {
173        // Skip variations that are currently broken. See https://github.com/bevyengine/bevy/issues/16929,
174        // https://github.com/bevyengine/bevy/pull/18074.
175        if (variation == Variation::MissingSkinnedMeshComponent)
176            || (variation == Variation::MissingMeshAttributes)
177        {
178            continue;
179        }
180
181        let transform = Transform::from_xyz(((index as f32) - 1.5) * 4.5, 0.0, 0.0);
182
183        let joint_0 = commands.spawn(transform).id();
184
185        let joint_1 = commands
186            .spawn((ChildOf(joint_0), AnimatedJoint, Transform::IDENTITY))
187            .id();
188
189        if variation == Variation::MissingJointEntity {
190            commands.entity(joint_1).despawn();
191        }
192
193        let mesh_handle = match variation {
194            Variation::MissingMeshAttributes => &unskinned_mesh_handle,
195            _ => &skinned_mesh_handle,
196        };
197
198        let mut entity_commands = commands.spawn((
199            Mesh3d(mesh_handle.clone()),
200            MeshMaterial3d(mesh_material_handle.clone()),
201            transform,
202        ));
203
204        if variation != Variation::MissingSkinnedMeshComponent {
205            entity_commands.insert(SkinnedMesh {
206                inverse_bindposes: inverse_bindposes_handle.clone(),
207                joints: vec![joint_0, joint_1],
208            });
209        }
210
211        // Add a square behind the mesh to distinguish it from the other meshes.
212        commands.spawn((
213            Transform::from_xyz(transform.translation.x, transform.translation.y, -0.8),
214            Mesh3d(mesh_assets.add(Plane3d::default().mesh().size(4.3, 4.3).normal(Dir3::Z))),
215            MeshMaterial3d(background_material_handle.clone()),
216        ));
217    }
218}
examples/animation/custom_skinned_mesh.rs (lines 137-139)
38fn setup(
39    mut commands: Commands,
40    asset_server: Res<AssetServer>,
41    mut meshes: ResMut<Assets<Mesh>>,
42    mut materials: ResMut<Assets<StandardMaterial>>,
43    mut skinned_mesh_inverse_bindposes_assets: ResMut<Assets<SkinnedMeshInverseBindposes>>,
44) {
45    // Create a camera
46    commands.spawn((
47        Camera3d::default(),
48        Transform::from_xyz(2.5, 2.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
49    ));
50
51    // Create inverse bindpose matrices for a skeleton consists of 2 joints
52    let inverse_bindposes = skinned_mesh_inverse_bindposes_assets.add(vec![
53        Mat4::from_translation(Vec3::new(-0.5, -1.0, 0.0)),
54        Mat4::from_translation(Vec3::new(-0.5, -1.0, 0.0)),
55    ]);
56
57    // Create a mesh
58    let mesh = Mesh::new(
59        PrimitiveTopology::TriangleList,
60        RenderAssetUsages::RENDER_WORLD,
61    )
62    // Set mesh vertex positions
63    .with_inserted_attribute(
64        Mesh::ATTRIBUTE_POSITION,
65        vec![
66            [0.0, 0.0, 0.0],
67            [1.0, 0.0, 0.0],
68            [0.0, 0.5, 0.0],
69            [1.0, 0.5, 0.0],
70            [0.0, 1.0, 0.0],
71            [1.0, 1.0, 0.0],
72            [0.0, 1.5, 0.0],
73            [1.0, 1.5, 0.0],
74            [0.0, 2.0, 0.0],
75            [1.0, 2.0, 0.0],
76        ],
77    )
78    // Add UV coordinates that map the left half of the texture since its a 1 x
79    // 2 rectangle.
80    .with_inserted_attribute(
81        Mesh::ATTRIBUTE_UV_0,
82        vec![
83            [0.0, 0.00],
84            [0.5, 0.00],
85            [0.0, 0.25],
86            [0.5, 0.25],
87            [0.0, 0.50],
88            [0.5, 0.50],
89            [0.0, 0.75],
90            [0.5, 0.75],
91            [0.0, 1.00],
92            [0.5, 1.00],
93        ],
94    )
95    // Set mesh vertex normals
96    .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.0, 0.0, 1.0]; 10])
97    // Set mesh vertex joint indices for mesh skinning.
98    // Each vertex gets 4 indices used to address the `JointTransforms` array in the vertex shader
99    //  as well as `SkinnedMeshJoint` array in the `SkinnedMesh` component.
100    // This means that a maximum of 4 joints can affect a single vertex.
101    .with_inserted_attribute(
102        Mesh::ATTRIBUTE_JOINT_INDEX,
103        // Need to be explicit here as [u16; 4] could be either Uint16x4 or Unorm16x4.
104        VertexAttributeValues::Uint16x4(vec![
105            [0, 0, 0, 0],
106            [0, 0, 0, 0],
107            [0, 1, 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        ]),
116    )
117    // Set mesh vertex joint weights for mesh skinning.
118    // Each vertex gets 4 joint weights corresponding to the 4 joint indices assigned to it.
119    // The sum of these weights should equal to 1.
120    .with_inserted_attribute(
121        Mesh::ATTRIBUTE_JOINT_WEIGHT,
122        vec![
123            [1.00, 0.00, 0.0, 0.0],
124            [1.00, 0.00, 0.0, 0.0],
125            [0.75, 0.25, 0.0, 0.0],
126            [0.75, 0.25, 0.0, 0.0],
127            [0.50, 0.50, 0.0, 0.0],
128            [0.50, 0.50, 0.0, 0.0],
129            [0.25, 0.75, 0.0, 0.0],
130            [0.25, 0.75, 0.0, 0.0],
131            [0.00, 1.00, 0.0, 0.0],
132            [0.00, 1.00, 0.0, 0.0],
133        ],
134    )
135    // Tell bevy to construct triangles from a list of vertex indices,
136    // where each 3 vertex indices form a triangle.
137    .with_inserted_indices(Indices::U16(vec![
138        0, 1, 3, 0, 3, 2, 2, 3, 5, 2, 5, 4, 4, 5, 7, 4, 7, 6, 6, 7, 9, 6, 9, 8,
139    ]))
140    // Create skinned mesh bounds. Together with the `DynamicSkinnedMeshBounds`
141    // component, this will ensure the mesh is correctly frustum culled.
142    .with_generated_skinned_mesh_bounds()
143    .unwrap();
144
145    let mesh = meshes.add(mesh);
146
147    // We're seeding the PRNG here to make this example deterministic for testing purposes.
148    // This isn't strictly required in practical use unless you need your app to be deterministic.
149    let mut rng = ChaCha8Rng::seed_from_u64(42);
150
151    for i in -5..5 {
152        // Create joint entities
153        let joint_0 = commands
154            .spawn(Transform::from_xyz(
155                i as f32 * 1.5,
156                0.0,
157                // Move quads back a small amount to avoid Z-fighting and not
158                // obscure the transform gizmos.
159                -(i as f32 * 0.01).abs(),
160            ))
161            .id();
162        let joint_1 = commands.spawn((AnimatedJoint(i), Transform::IDENTITY)).id();
163
164        // Set joint_1 as a child of joint_0.
165        commands.entity(joint_0).add_children(&[joint_1]);
166
167        // Each joint in this vector corresponds to each inverse bindpose matrix in `SkinnedMeshInverseBindposes`.
168        let joint_entities = vec![joint_0, joint_1];
169
170        // Create skinned mesh renderer. Note that its transform doesn't affect the position of the mesh.
171        commands.spawn((
172            Mesh3d(mesh.clone()),
173            MeshMaterial3d(materials.add(StandardMaterial {
174                base_color: Color::srgb(
175                    rng.random_range(0.0..1.0),
176                    rng.random_range(0.0..1.0),
177                    rng.random_range(0.0..1.0),
178                ),
179                base_color_texture: Some(asset_server.load("textures/uv_checker_bw.png")),
180                ..default()
181            })),
182            SkinnedMesh {
183                inverse_bindposes: inverse_bindposes.clone(),
184                joints: joint_entities,
185            },
186            DynamicSkinnedMeshBounds,
187        ));
188    }
189}
Source

pub fn try_with_inserted_indices( self, indices: Indices, ) -> Result<Mesh, MeshAccessError>

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::try_insert_indices to mutate an existing mesh in-place)

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn indices(&self) -> Option<&Indices>

Retrieves the vertex indices of the mesh, returns None if not found.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_indices

Source

pub fn try_indices(&self) -> Result<&Indices, MeshAccessError>

Retrieves the vertex indices of the mesh.

Returns an error if the mesh data has been extracted to RenderWorldor if the attribute does not exist.

Source

pub fn try_indices_option(&self) -> Result<Option<&Indices>, MeshAccessError>

Retrieves the vertex indices of the mesh, returns None if not found.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn indices_mut(&mut self) -> Option<&mut Indices>

Retrieves the vertex indices of the mesh mutably.

Examples found in repository?
examples/3d/solari.rs (line 412)
374fn add_raytracing_meshes_on_scene_load(
375    scene_ready: On<WorldInstanceReady>,
376    children: Query<&Children>,
377    mesh_query: Query<(
378        &Mesh3d,
379        &MeshMaterial3d<StandardMaterial>,
380        Option<&GltfMaterialName>,
381    )>,
382    mut meshes: ResMut<Assets<Mesh>>,
383    mut materials: ResMut<Assets<StandardMaterial>>,
384    mut commands: Commands,
385    args: Res<Args>,
386) {
387    for descendant in children.iter_descendants(scene_ready.entity) {
388        if let Ok((Mesh3d(mesh_handle), MeshMaterial3d(material_handle), material_name)) =
389            mesh_query.get(descendant)
390        {
391            // Add raytracing mesh component
392            commands
393                .entity(descendant)
394                .insert(RaytracingMesh3d(mesh_handle.clone()));
395
396            // Ensure meshes are Solari compatible
397            let mut mesh = meshes.get_mut(mesh_handle).unwrap();
398            if !mesh.contains_attribute(Mesh::ATTRIBUTE_UV_0) {
399                let vertex_count = mesh.count_vertices();
400                mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.0, 0.0]; vertex_count]);
401                mesh.insert_attribute(
402                    Mesh::ATTRIBUTE_TANGENT,
403                    vec![[0.0, 0.0, 0.0, 0.0]; vertex_count],
404                );
405            }
406            if !mesh.contains_attribute(Mesh::ATTRIBUTE_TANGENT) {
407                mesh.generate_tangents().unwrap();
408            }
409            if mesh.contains_attribute(Mesh::ATTRIBUTE_UV_1) {
410                mesh.remove_attribute(Mesh::ATTRIBUTE_UV_1);
411            }
412            if let Some(indices) = mesh.indices_mut()
413                && let Indices::U16(_) = indices
414            {
415                *indices = Indices::U32(indices.iter().map(|i| i as u32).collect());
416            }
417
418            // Prevent rasterization if using pathtracer
419            if args.pathtracer == Some(true) {
420                commands.entity(descendant).remove::<Mesh3d>();
421            }
422
423            // Adjust scene materials to better demo Solari features
424            if material_name.map(|s| s.0.as_str()) == Some("material") {
425                let mut material = materials.get_mut(material_handle).unwrap();
426                material.emissive = LinearRgba::BLACK;
427            }
428            if material_name.map(|s| s.0.as_str()) == Some("Lights") {
429                let mut material = materials.get_mut(material_handle).unwrap();
430                material.emissive =
431                    LinearRgba::from(Color::srgb(0.941, 0.714, 0.043)) * 1_000_000.0;
432                material.alpha_mode = AlphaMode::Opaque;
433                material.specular_transmission = 0.0;
434
435                commands.insert_resource(RobotLightMaterial(material_handle.clone()));
436            }
437            if material_name.map(|s| s.0.as_str()) == Some("Glass_Dark_01") {
438                let mut material = materials.get_mut(material_handle).unwrap();
439                material.alpha_mode = AlphaMode::Opaque;
440                material.specular_transmission = 0.0;
441            }
442        }
443    }
444}
Source

pub fn try_indices_mut(&mut self) -> Result<&mut Indices, MeshAccessError>

Retrieves the vertex indices of the mesh mutably.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn try_indices_mut_option( &mut self, ) -> Result<Option<&mut Indices>, MeshAccessError>

Retrieves the vertex indices of the mesh mutably.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn remove_indices(&mut self) -> Option<Indices>

Removes the vertex indices from the mesh and returns them.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_remove_indices

Source

pub fn try_remove_indices(&mut self) -> Result<Option<Indices>, MeshAccessError>

Removes the vertex indices from the mesh and returns them.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

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)

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_with_removed_indices

Source

pub fn try_with_removed_indices(self) -> Result<Mesh, MeshAccessError>

Consumes the mesh and returns a mesh without the vertex indices of the mesh.

(Alternatively, you can use Mesh::try_remove_indices to mutate an existing mesh in-place)

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn get_vertex_size(&self) -> u64

Returns the size of a vertex in bytes.

§Panics

Panics when the mesh data has already been extracted to RenderWorld.

Source

pub fn get_vertex_buffer_size(&self) -> usize

Returns the size required for the vertex buffer in bytes.

§Panics

Panics when the mesh data has already been extracted to RenderWorld.

Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld.

Source

pub fn get_morph_targets(&self) -> Option<&[MorphAttributes]>

Available on crate feature morph only.

If any morph displacements are present, returns them as a MorphAttributes array.

§Panics

Panics when the mesh data has already been extracted to the render world.

Source

pub fn get_mesh_vertex_buffer_layout( &self, mesh_vertex_buffer_layouts: &mut MeshVertexBufferLayouts, ) -> MeshVertexBufferLayoutRef

Get this Mesh’s MeshVertexBufferLayout, used in SpecializedMeshPipeline.

§Panics

Panics when the mesh data has already been extracted to RenderWorld.

Source

pub fn count_vertices(&self) -> usize

Counts all vertices of the mesh.

If the attributes have different vertex counts, the smallest is returned.

§Panics

Panics when the mesh data has already been extracted to RenderWorld.

Examples found in repository?
examples/3d/solari.rs (line 399)
374fn add_raytracing_meshes_on_scene_load(
375    scene_ready: On<WorldInstanceReady>,
376    children: Query<&Children>,
377    mesh_query: Query<(
378        &Mesh3d,
379        &MeshMaterial3d<StandardMaterial>,
380        Option<&GltfMaterialName>,
381    )>,
382    mut meshes: ResMut<Assets<Mesh>>,
383    mut materials: ResMut<Assets<StandardMaterial>>,
384    mut commands: Commands,
385    args: Res<Args>,
386) {
387    for descendant in children.iter_descendants(scene_ready.entity) {
388        if let Ok((Mesh3d(mesh_handle), MeshMaterial3d(material_handle), material_name)) =
389            mesh_query.get(descendant)
390        {
391            // Add raytracing mesh component
392            commands
393                .entity(descendant)
394                .insert(RaytracingMesh3d(mesh_handle.clone()));
395
396            // Ensure meshes are Solari compatible
397            let mut mesh = meshes.get_mut(mesh_handle).unwrap();
398            if !mesh.contains_attribute(Mesh::ATTRIBUTE_UV_0) {
399                let vertex_count = mesh.count_vertices();
400                mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.0, 0.0]; vertex_count]);
401                mesh.insert_attribute(
402                    Mesh::ATTRIBUTE_TANGENT,
403                    vec![[0.0, 0.0, 0.0, 0.0]; vertex_count],
404                );
405            }
406            if !mesh.contains_attribute(Mesh::ATTRIBUTE_TANGENT) {
407                mesh.generate_tangents().unwrap();
408            }
409            if mesh.contains_attribute(Mesh::ATTRIBUTE_UV_1) {
410                mesh.remove_attribute(Mesh::ATTRIBUTE_UV_1);
411            }
412            if let Some(indices) = mesh.indices_mut()
413                && let Indices::U16(_) = indices
414            {
415                *indices = Indices::U32(indices.iter().map(|i| i as u32).collect());
416            }
417
418            // Prevent rasterization if using pathtracer
419            if args.pathtracer == Some(true) {
420                commands.entity(descendant).remove::<Mesh3d>();
421            }
422
423            // Adjust scene materials to better demo Solari features
424            if material_name.map(|s| s.0.as_str()) == Some("material") {
425                let mut material = materials.get_mut(material_handle).unwrap();
426                material.emissive = LinearRgba::BLACK;
427            }
428            if material_name.map(|s| s.0.as_str()) == Some("Lights") {
429                let mut material = materials.get_mut(material_handle).unwrap();
430                material.emissive =
431                    LinearRgba::from(Color::srgb(0.941, 0.714, 0.043)) * 1_000_000.0;
432                material.alpha_mode = AlphaMode::Opaque;
433                material.specular_transmission = 0.0;
434
435                commands.insert_resource(RobotLightMaterial(material_handle.clone()));
436            }
437            if material_name.map(|s| s.0.as_str()) == Some("Glass_Dark_01") {
438                let mut material = materials.get_mut(material_handle).unwrap();
439                material.alpha_mode = AlphaMode::Opaque;
440                material.specular_transmission = 0.0;
441            }
442        }
443    }
444}
Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld.

Source

pub fn write_packed_vertex_buffer_data(&self, slice: WriteOnly<'_, [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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld.

Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_duplicate_vertices

Source

pub fn try_duplicate_vertices(&mut self) -> Result<(), MeshAccessError>

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.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

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)

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_with_duplicated_vertices

Examples found in repository?
examples/3d/light_probe_blending.rs (line 302)
289fn spawn_reflective_prism(
290    commands: &mut Commands,
291    meshes: &mut Assets<Mesh>,
292    material: Handle<StandardMaterial>,
293) {
294    // Create a mesh.
295    let cube = meshes.add(
296        Cuboid {
297            half_size: vec3(2.0, 1.0, 10.0),
298        }
299        .mesh()
300        .build()
301        // We use flat normals so that the surface appears flat, not curved.
302        .with_duplicated_vertices()
303        .with_computed_flat_normals(),
304    );
305
306    // Spawn the cube.
307    commands.spawn((
308        Mesh3d(cube),
309        MeshMaterial3d(material),
310        Transform::from_xyz(0.0, -4.0, -5.5),
311        ReflectivePrism,
312        Visibility::Hidden,
313    ));
314}
More examples
Hide additional examples
examples/3d/pccm.rs (line 115)
104fn spawn_inner_cube(
105    commands: &mut Commands,
106    meshes: &mut Assets<Mesh>,
107    materials: &mut Assets<StandardMaterial>,
108) {
109    let cube_mesh = meshes.add(
110        Cuboid {
111            half_size: Vec3::new(5.0, 1.0, 2.0),
112        }
113        .mesh()
114        .build()
115        .with_duplicated_vertices()
116        .with_computed_flat_normals(),
117    );
118    let cube_material = materials.add(StandardMaterial {
119        base_color: Color::WHITE,
120        metallic: 1.0,
121        reflectance: 1.0,
122        perceptual_roughness: 0.0,
123        ..default()
124    });
125
126    commands.spawn((
127        Mesh3d(cube_mesh),
128        MeshMaterial3d(cube_material),
129        Transform::from_xyz(0.0, -4.0, -2.5),
130        InnerCube,
131    ));
132}
examples/3d/clustered_decal_maps.rs (line 201)
184fn spawn_plane_mesh(
185    commands: &mut Commands,
186    asset_server: &AssetServer,
187    meshes: &mut Assets<Mesh>,
188    materials: &mut Assets<StandardMaterial>,
189) {
190    // Create a plane onto which we project decals.
191    //
192    // As the plane has a normal map, we must generate tangents for the
193    // vertices.
194    let plane_mesh = meshes.add(
195        Plane3d {
196            normal: Dir3::NEG_Z,
197            half_size: Vec2::splat(PLANE_HALF_SIZE),
198        }
199        .mesh()
200        .build()
201        .with_duplicated_vertices()
202        .with_computed_flat_normals()
203        .with_generated_tangents()
204        .unwrap(),
205    );
206
207    // Give the plane some texture.
208    //
209    // Note that, as this is a normal map, we must disable sRGB when loading.
210    let normal_map_texture = asset_server
211        .load_builder()
212        .with_settings(|settings: &mut ImageLoaderSettings| settings.is_srgb = false)
213        .load("textures/ScratchedGold-Normal.png");
214
215    // Actually spawn the plane.
216    commands.spawn((
217        Mesh3d(plane_mesh),
218        MeshMaterial3d(materials.add(StandardMaterial {
219            base_color: Color::from(CRIMSON),
220            normal_map_texture: Some(normal_map_texture),
221            ..StandardMaterial::default()
222        })),
223        Transform::IDENTITY,
224    ));
225}
Source

pub fn try_with_duplicated_vertices(self) -> Result<Mesh, MeshAccessError>

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::try_duplicate_vertices to mutate an existing mesh in-place)

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn merge_duplicate_vertices( &mut self, ) -> Result<(), MeshMergeDuplicateVerticesError>

Remove duplicate vertices and create the index pointing to the unique vertices.

Returns an error if the mesh data has been extracted to RenderWorld. Returns an error if the mesh already has Indices set, even if there are duplicate vertices. If deduplication is needed with indices already set, consider calling Mesh::duplicate_vertices and then this function.

Source

pub fn with_merge_duplicate_vertices( self, ) -> Result<Mesh, MeshMergeDuplicateVerticesError>

Consumes the mesh and returns a mesh with merged vertices.

(Alternatively, you can use Mesh::merge_duplicate_vertices to mutate an existing mesh in-place)

Returns an error if the mesh data has been extracted to RenderWorld. Returns an error if the mesh already has Indices set, even if there are duplicate vertices. If deduplication is needed with indices already set, consider calling Mesh::duplicate_vertices and then this function.

Source

pub fn invert_winding(&mut self) -> Result<(), MeshWindingInvertError>

Inverts the winding of the indices such that all counter-clockwise triangles are now clockwise and vice versa. For lines, their start and end indices are flipped.

Does nothing if no Indices are set. If this operation succeeded, an Ok result is returned.

Source

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.

Source

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.= Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_compute_normals

Source

pub fn try_compute_normals(&mut self) -> Result<(), MeshAccessError>

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.=

Source

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. Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_compute_flat_normals

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!

Source

pub fn try_compute_flat_normals(&mut self) -> Result<(), MeshAccessError>

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!

Source

pub fn compute_smooth_normals(&mut self)

Calculates the Mesh::ATTRIBUTE_NORMAL of an indexed mesh, smoothing normals for shared vertices.

This method weights normals by the angles of the corners of connected triangles, thus eliminating triangle area and count as factors in the final normal. This does make it somewhat slower than Mesh::compute_area_weighted_normals which does not need to greedily normalize each triangle’s normal or calculate corner angles.

If you would rather have the computed normals be weighted by triangle area, see Mesh::compute_area_weighted_normals instead. If you need to weight them in some other way, see Mesh::compute_custom_smooth_normals.

§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. Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_compute_smooth_normals

Source

pub fn try_compute_smooth_normals(&mut self) -> Result<(), MeshAccessError>

Calculates the Mesh::ATTRIBUTE_NORMAL of an indexed mesh, smoothing normals for shared vertices.

This method weights normals by the angles of the corners of connected triangles, thus eliminating triangle area and count as factors in the final normal. This does make it somewhat slower than Mesh::compute_area_weighted_normals which does not need to greedily normalize each triangle’s normal or calculate corner angles.

If you would rather have the computed normals be weighted by triangle area, see Mesh::compute_area_weighted_normals instead. If you need to weight them in some other way, see Mesh::compute_custom_smooth_normals.

§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.

Source

pub fn compute_area_weighted_normals(&mut self)

Calculates the Mesh::ATTRIBUTE_NORMAL of an indexed mesh, smoothing normals for shared vertices.

This method weights normals by the area of each triangle containing the vertex. Thus, larger triangles will skew the normals of their vertices towards their own normal more than smaller triangles will.

This method is actually somewhat faster than Mesh::compute_smooth_normals because an intermediate result of triangle normal calculation is already scaled by the triangle’s area.

If you would rather have the computed normals be influenced only by the angles of connected edges, see Mesh::compute_smooth_normals instead. If you need to weight them in some other way, see Mesh::compute_custom_smooth_normals.

§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. Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_compute_area_weighted_normals

Source

pub fn try_compute_area_weighted_normals( &mut self, ) -> Result<(), MeshAccessError>

Calculates the Mesh::ATTRIBUTE_NORMAL of an indexed mesh, smoothing normals for shared vertices.

This method weights normals by the area of each triangle containing the vertex. Thus, larger triangles will skew the normals of their vertices towards their own normal more than smaller triangles will.

This method is actually somewhat faster than Mesh::compute_smooth_normals because an intermediate result of triangle normal calculation is already scaled by the triangle’s area.

If you would rather have the computed normals be influenced only by the angles of connected edges, see Mesh::compute_smooth_normals instead. If you need to weight them in some other way, see Mesh::compute_custom_smooth_normals.

§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.

Source

pub fn compute_custom_smooth_normals( &mut self, per_triangle: impl FnMut([usize; 3], &[[f32; 3]], &mut [Vec3]), )

Calculates the Mesh::ATTRIBUTE_NORMAL of an indexed mesh, smoothing normals for shared vertices.

This method allows you to customize how normals are weighted via the per_triangle parameter, which must be a function or closure that accepts 3 parameters:

  • The indices of the three vertices of the triangle as a [usize; 3].
  • A reference to the values of the Mesh::ATTRIBUTE_POSITION of the mesh (&[[f32; 3]]).
  • A mutable reference to the sums of all normals so far.

See also the standard methods included in Bevy for calculating smooth normals:

An example that would weight each connected triangle’s normal equally, thus skewing normals towards the planes divided into the most triangles:

mesh.compute_custom_smooth_normals(|[a, b, c], positions, normals| {
    let normal = Vec3::from(bevy_mesh::triangle_normal(positions[a], positions[b], positions[c]));
    for idx in [a, b, c] {
        normals[idx] += normal;
    }
});
§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. Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_compute_custom_smooth_normals

Source

pub fn try_compute_custom_smooth_normals( &mut self, per_triangle: impl FnMut([usize; 3], &[[f32; 3]], &mut [Vec3]), ) -> Result<(), MeshAccessError>

Calculates the Mesh::ATTRIBUTE_NORMAL of an indexed mesh, smoothing normals for shared vertices.

This method allows you to customize how normals are weighted via the per_triangle parameter, which must be a function or closure that accepts 3 parameters:

  • The indices of the three vertices of the triangle as a [usize; 3].
  • A reference to the values of the Mesh::ATTRIBUTE_POSITION of the mesh (&[[f32; 3]]).
  • A mutable reference to the sums of all normals so far.

See also the standard methods included in Bevy for calculating smooth normals:

An example that would weight each connected triangle’s normal equally, thus skewing normals towards the planes divided into the most triangles:

mesh.compute_custom_smooth_normals(|[a, b, c], positions, normals| {
    let normal = Vec3::from(bevy_mesh::triangle_normal(positions[a], positions[b], positions[c]));
    for idx in [a, b, c] {
        normals[idx] += normal;
    }
});
§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.

Source

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. Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_with_computed_normals

Source

pub fn try_with_computed_normals(self) -> Result<Mesh, MeshAccessError>

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.

Source

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 Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_with_computed_flat_normals

Examples found in repository?
examples/3d/light_probe_blending.rs (line 303)
289fn spawn_reflective_prism(
290    commands: &mut Commands,
291    meshes: &mut Assets<Mesh>,
292    material: Handle<StandardMaterial>,
293) {
294    // Create a mesh.
295    let cube = meshes.add(
296        Cuboid {
297            half_size: vec3(2.0, 1.0, 10.0),
298        }
299        .mesh()
300        .build()
301        // We use flat normals so that the surface appears flat, not curved.
302        .with_duplicated_vertices()
303        .with_computed_flat_normals(),
304    );
305
306    // Spawn the cube.
307    commands.spawn((
308        Mesh3d(cube),
309        MeshMaterial3d(material),
310        Transform::from_xyz(0.0, -4.0, -5.5),
311        ReflectivePrism,
312        Visibility::Hidden,
313    ));
314}
More examples
Hide additional examples
examples/3d/pccm.rs (line 116)
104fn spawn_inner_cube(
105    commands: &mut Commands,
106    meshes: &mut Assets<Mesh>,
107    materials: &mut Assets<StandardMaterial>,
108) {
109    let cube_mesh = meshes.add(
110        Cuboid {
111            half_size: Vec3::new(5.0, 1.0, 2.0),
112        }
113        .mesh()
114        .build()
115        .with_duplicated_vertices()
116        .with_computed_flat_normals(),
117    );
118    let cube_material = materials.add(StandardMaterial {
119        base_color: Color::WHITE,
120        metallic: 1.0,
121        reflectance: 1.0,
122        perceptual_roughness: 0.0,
123        ..default()
124    });
125
126    commands.spawn((
127        Mesh3d(cube_mesh),
128        MeshMaterial3d(cube_material),
129        Transform::from_xyz(0.0, -4.0, -2.5),
130        InnerCube,
131    ));
132}
examples/3d/clustered_decal_maps.rs (line 202)
184fn spawn_plane_mesh(
185    commands: &mut Commands,
186    asset_server: &AssetServer,
187    meshes: &mut Assets<Mesh>,
188    materials: &mut Assets<StandardMaterial>,
189) {
190    // Create a plane onto which we project decals.
191    //
192    // As the plane has a normal map, we must generate tangents for the
193    // vertices.
194    let plane_mesh = meshes.add(
195        Plane3d {
196            normal: Dir3::NEG_Z,
197            half_size: Vec2::splat(PLANE_HALF_SIZE),
198        }
199        .mesh()
200        .build()
201        .with_duplicated_vertices()
202        .with_computed_flat_normals()
203        .with_generated_tangents()
204        .unwrap(),
205    );
206
207    // Give the plane some texture.
208    //
209    // Note that, as this is a normal map, we must disable sRGB when loading.
210    let normal_map_texture = asset_server
211        .load_builder()
212        .with_settings(|settings: &mut ImageLoaderSettings| settings.is_srgb = false)
213        .load("textures/ScratchedGold-Normal.png");
214
215    // Actually spawn the plane.
216    commands.spawn((
217        Mesh3d(plane_mesh),
218        MeshMaterial3d(materials.add(StandardMaterial {
219            base_color: Color::from(CRIMSON),
220            normal_map_texture: Some(normal_map_texture),
221            ..StandardMaterial::default()
222        })),
223        Transform::IDENTITY,
224    ));
225}
Source

pub fn try_with_computed_flat_normals(self) -> Result<Mesh, MeshAccessError>

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

Source

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)

This method weights normals by the angles of triangle corners connected to each vertex. If you would rather have the computed normals be weighted by triangle area, see Mesh::with_computed_area_weighted_normals instead.

§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. Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_with_computed_smooth_normals

Source

pub fn try_with_computed_smooth_normals(self) -> Result<Mesh, MeshAccessError>

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)

This method weights normals by the angles of triangle corners connected to each vertex. If you would rather have the computed normals be weighted by triangle area, see Mesh::with_computed_area_weighted_normals instead.

§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.

Source

pub fn with_computed_area_weighted_normals(self) -> Mesh

Consumes the mesh and returns a mesh with calculated Mesh::ATTRIBUTE_NORMAL.

(Alternatively, you can use Mesh::compute_area_weighted_normals to mutate an existing mesh in-place)

This method weights normals by the area of each triangle containing the vertex. Thus, larger triangles will skew the normals of their vertices towards their own normal more than smaller triangles will. If you would rather have the computed normals be influenced only by the angles of connected edges, see Mesh::with_computed_smooth_normals instead.

§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. Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_with_computed_area_weighted_normals

Source

pub fn try_with_computed_area_weighted_normals( self, ) -> Result<Mesh, MeshAccessError>

Consumes the mesh and returns a mesh with calculated Mesh::ATTRIBUTE_NORMAL.

(Alternatively, you can use Mesh::compute_area_weighted_normals to mutate an existing mesh in-place)

This method weights normals by the area of each triangle containing the vertex. Thus, larger triangles will skew the normals of their vertices towards their own normal more than smaller triangles will. If you would rather have the computed normals be influenced only by the angles of connected edges, see Mesh::with_computed_smooth_normals instead.

§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.

Source

pub fn generate_tangents(&mut self) -> Result<(), GenerateTangentsError>

Available on crate feature bevy_mikktspace only.

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?
examples/3d/clearcoat.rs (line 88)
82fn create_sphere_mesh(meshes: &mut Assets<Mesh>) -> Handle<Mesh> {
83    // We're going to use normal maps, so make sure we've generated tangents, or
84    // else the normal maps won't show up.
85
86    let mut sphere_mesh = Sphere::new(1.0).mesh().build();
87    sphere_mesh
88        .generate_tangents()
89        .expect("Failed to generate tangents");
90    meshes.add(sphere_mesh)
91}
More examples
Hide additional examples
examples/3d/rotate_environment_map.rs (line 56)
50fn create_sphere_mesh(meshes: &mut Assets<Mesh>) -> Handle<Mesh> {
51    // We're going to use normal maps, so make sure we've generated tangents, or
52    // else the normal maps won't show up.
53
54    let mut sphere_mesh = Sphere::new(1.0).mesh().build();
55    sphere_mesh
56        .generate_tangents()
57        .expect("Failed to generate tangents");
58    meshes.add(sphere_mesh)
59}
examples/3d/deferred_rendering.rs (line 234)
212fn setup_parallax(
213    mut commands: Commands,
214    mut materials: ResMut<Assets<StandardMaterial>>,
215    mut meshes: ResMut<Assets<Mesh>>,
216    asset_server: Res<AssetServer>,
217) {
218    // The normal map. Note that to generate it in the GIMP image editor, you should
219    // open the depth map, and do Filters → Generic → Normal Map
220    // You should enable the "flip X" checkbox.
221    let normal_handle = asset_server
222        .load_builder()
223        .with_settings(
224            // The normal map texture is in linear color space. Lighting won't look correct
225            // if `is_srgb` is `true`, which is the default.
226            |settings: &mut ImageLoaderSettings| settings.is_srgb = false,
227        )
228        .load("textures/parallax_example/cube_normal.png");
229
230    let mut cube = Mesh::from(Cuboid::new(0.15, 0.15, 0.15));
231
232    // NOTE: for normal maps and depth maps to work, the mesh
233    // needs tangents generated.
234    cube.generate_tangents().unwrap();
235
236    let parallax_material = materials.add(StandardMaterial {
237        perceptual_roughness: 0.4,
238        base_color_texture: Some(asset_server.load("textures/parallax_example/cube_color.png")),
239        normal_map_texture: Some(normal_handle),
240        // The depth map is a grayscale texture where black is the highest level and
241        // white the lowest.
242        depth_map: Some(asset_server.load("textures/parallax_example/cube_depth.png")),
243        parallax_depth_scale: 0.09,
244        parallax_mapping_method: ParallaxMappingMethod::Relief { max_steps: 4 },
245        max_parallax_layer_count: ops::exp2(5.0f32),
246        ..default()
247    });
248    commands.spawn((
249        Mesh3d(meshes.add(cube)),
250        MeshMaterial3d(parallax_material),
251        Transform::from_xyz(0.4, 0.2, -0.8),
252        Spin { speed: 0.3 },
253    ));
254}
examples/ecs/error_handling.rs (line 91)
60fn setup(
61    mut commands: Commands,
62    mut meshes: ResMut<Assets<Mesh>>,
63    mut materials: ResMut<Assets<StandardMaterial>>,
64) -> Result {
65    let mut seeded_rng = ChaCha8Rng::seed_from_u64(19878367467712);
66
67    // Make a plane for establishing space.
68    commands.spawn((
69        Mesh3d(meshes.add(Plane3d::default().mesh().size(12.0, 12.0))),
70        MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
71        Transform::from_xyz(0.0, -2.5, 0.0),
72    ));
73
74    // Spawn a light:
75    commands.spawn((
76        PointLight {
77            shadow_maps_enabled: true,
78            ..default()
79        },
80        Transform::from_xyz(4.0, 8.0, 4.0),
81    ));
82
83    // Spawn a camera:
84    commands.spawn((
85        Camera3d::default(),
86        Transform::from_xyz(-2.0, 3.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
87    ));
88
89    // Create a new sphere mesh:
90    let mut sphere_mesh = Sphere::new(1.0).mesh().ico(7)?;
91    sphere_mesh.generate_tangents()?;
92
93    // Spawn the mesh into the scene:
94    let mut sphere = commands.spawn((
95        Mesh3d(meshes.add(sphere_mesh.clone())),
96        MeshMaterial3d(materials.add(StandardMaterial::default())),
97        Transform::from_xyz(-1.0, 1.0, 0.0),
98    ));
99
100    // Generate random sample points:
101    let triangles = sphere_mesh.triangles()?;
102    let distribution = UniformMeshSampler::try_new(triangles)?;
103
104    // Setup sample points:
105    let point_mesh = meshes.add(Sphere::new(0.01).mesh().ico(3)?);
106    let point_material = materials.add(StandardMaterial {
107        base_color: Srgba::RED.into(),
108        emissive: LinearRgba::rgb(1.0, 0.0, 0.0),
109        ..default()
110    });
111
112    // Add sample points as children of the sphere:
113    for point in distribution.sample_iter(&mut seeded_rng).take(10000) {
114        sphere.with_child((
115            Mesh3d(point_mesh.clone()),
116            MeshMaterial3d(point_material.clone()),
117            Transform::from_translation(point),
118        ));
119    }
120
121    // Indicate the system completed successfully:
122    Ok(())
123}
examples/3d/solari.rs (line 407)
374fn add_raytracing_meshes_on_scene_load(
375    scene_ready: On<WorldInstanceReady>,
376    children: Query<&Children>,
377    mesh_query: Query<(
378        &Mesh3d,
379        &MeshMaterial3d<StandardMaterial>,
380        Option<&GltfMaterialName>,
381    )>,
382    mut meshes: ResMut<Assets<Mesh>>,
383    mut materials: ResMut<Assets<StandardMaterial>>,
384    mut commands: Commands,
385    args: Res<Args>,
386) {
387    for descendant in children.iter_descendants(scene_ready.entity) {
388        if let Ok((Mesh3d(mesh_handle), MeshMaterial3d(material_handle), material_name)) =
389            mesh_query.get(descendant)
390        {
391            // Add raytracing mesh component
392            commands
393                .entity(descendant)
394                .insert(RaytracingMesh3d(mesh_handle.clone()));
395
396            // Ensure meshes are Solari compatible
397            let mut mesh = meshes.get_mut(mesh_handle).unwrap();
398            if !mesh.contains_attribute(Mesh::ATTRIBUTE_UV_0) {
399                let vertex_count = mesh.count_vertices();
400                mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.0, 0.0]; vertex_count]);
401                mesh.insert_attribute(
402                    Mesh::ATTRIBUTE_TANGENT,
403                    vec![[0.0, 0.0, 0.0, 0.0]; vertex_count],
404                );
405            }
406            if !mesh.contains_attribute(Mesh::ATTRIBUTE_TANGENT) {
407                mesh.generate_tangents().unwrap();
408            }
409            if mesh.contains_attribute(Mesh::ATTRIBUTE_UV_1) {
410                mesh.remove_attribute(Mesh::ATTRIBUTE_UV_1);
411            }
412            if let Some(indices) = mesh.indices_mut()
413                && let Indices::U16(_) = indices
414            {
415                *indices = Indices::U32(indices.iter().map(|i| i as u32).collect());
416            }
417
418            // Prevent rasterization if using pathtracer
419            if args.pathtracer == Some(true) {
420                commands.entity(descendant).remove::<Mesh3d>();
421            }
422
423            // Adjust scene materials to better demo Solari features
424            if material_name.map(|s| s.0.as_str()) == Some("material") {
425                let mut material = materials.get_mut(material_handle).unwrap();
426                material.emissive = LinearRgba::BLACK;
427            }
428            if material_name.map(|s| s.0.as_str()) == Some("Lights") {
429                let mut material = materials.get_mut(material_handle).unwrap();
430                material.emissive =
431                    LinearRgba::from(Color::srgb(0.941, 0.714, 0.043)) * 1_000_000.0;
432                material.alpha_mode = AlphaMode::Opaque;
433                material.specular_transmission = 0.0;
434
435                commands.insert_resource(RobotLightMaterial(material_handle.clone()));
436            }
437            if material_name.map(|s| s.0.as_str()) == Some("Glass_Dark_01") {
438                let mut material = materials.get_mut(material_handle).unwrap();
439                material.alpha_mode = AlphaMode::Opaque;
440                material.specular_transmission = 0.0;
441            }
442        }
443    }
444}
Source

pub fn with_generated_tangents(self) -> Result<Mesh, GenerateTangentsError>

Available on crate feature bevy_mikktspace only.

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?
examples/3d/anisotropy.rs (line 120)
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        WorldAssetRoot(
110            asset_server.load("models/AnisotropyBarnLamp/AnisotropyBarnLamp.gltf#Scene0"),
111        ),
112        Transform::from_xyz(0.0, 0.07, -0.13),
113        Scene::BarnLamp,
114    ));
115
116    commands.spawn((
117        Mesh3d(
118            asset_server.add(
119                Mesh::from(Sphere::new(0.1))
120                    .with_generated_tangents()
121                    .unwrap(),
122            ),
123        ),
124        MeshMaterial3d(asset_server.add(StandardMaterial {
125            base_color: palettes::tailwind::GRAY_300.into(),
126            anisotropy_rotation: 0.5,
127            anisotropy_strength: 1.,
128            ..default()
129        })),
130        Scene::Sphere,
131        Visibility::Hidden,
132    ));
133
134    spawn_text(&mut commands, &app_status);
135}
More examples
Hide additional examples
examples/3d/clustered_decal_maps.rs (line 203)
184fn spawn_plane_mesh(
185    commands: &mut Commands,
186    asset_server: &AssetServer,
187    meshes: &mut Assets<Mesh>,
188    materials: &mut Assets<StandardMaterial>,
189) {
190    // Create a plane onto which we project decals.
191    //
192    // As the plane has a normal map, we must generate tangents for the
193    // vertices.
194    let plane_mesh = meshes.add(
195        Plane3d {
196            normal: Dir3::NEG_Z,
197            half_size: Vec2::splat(PLANE_HALF_SIZE),
198        }
199        .mesh()
200        .build()
201        .with_duplicated_vertices()
202        .with_computed_flat_normals()
203        .with_generated_tangents()
204        .unwrap(),
205    );
206
207    // Give the plane some texture.
208    //
209    // Note that, as this is a normal map, we must disable sRGB when loading.
210    let normal_map_texture = asset_server
211        .load_builder()
212        .with_settings(|settings: &mut ImageLoaderSettings| settings.is_srgb = false)
213        .load("textures/ScratchedGold-Normal.png");
214
215    // Actually spawn the plane.
216    commands.spawn((
217        Mesh3d(plane_mesh),
218        MeshMaterial3d(materials.add(StandardMaterial {
219            base_color: Color::from(CRIMSON),
220            normal_map_texture: Some(normal_map_texture),
221            ..StandardMaterial::default()
222        })),
223        Transform::IDENTITY,
224    ));
225}
examples/3d/parallax_mapping.rs (line 272)
200fn setup(
201    mut commands: Commands,
202    mut materials: ResMut<Assets<StandardMaterial>>,
203    mut meshes: ResMut<Assets<Mesh>>,
204    asset_server: Res<AssetServer>,
205) {
206    // The normal map. Note that to generate it in the GIMP image editor, you should
207    // open the depth map, and do Filters → Generic → Normal Map
208    // You should enable the "flip X" checkbox.
209    let normal_handle = asset_server
210        .load_builder()
211        .with_settings(
212            // The normal map texture is in linear color space. Lighting won't look correct
213            // if `is_srgb` is `true`, which is the default.
214            |settings: &mut ImageLoaderSettings| settings.is_srgb = false,
215        )
216        .load("textures/parallax_example/cube_normal.png");
217
218    // Camera
219    commands.spawn((
220        Camera3d::default(),
221        Transform::from_xyz(1.5, 1.5, 1.5).looking_at(Vec3::ZERO, Vec3::Y),
222        FreeCameraController,
223    ));
224
225    // represent the light source as a sphere
226    let mesh = meshes.add(Sphere::new(0.05).mesh().ico(3).unwrap());
227
228    // light
229    commands.spawn((
230        PointLight {
231            shadow_maps_enabled: true,
232            ..default()
233        },
234        Transform::from_xyz(2.0, 1.0, -1.1),
235        children![(Mesh3d(mesh), MeshMaterial3d(materials.add(Color::WHITE)))],
236    ));
237
238    // Plane
239    commands.spawn((
240        Mesh3d(meshes.add(Plane3d::default().mesh().size(10.0, 10.0))),
241        MeshMaterial3d(materials.add(StandardMaterial {
242            // standard material derived from dark green, but
243            // with roughness and reflectance set.
244            perceptual_roughness: 0.45,
245            reflectance: 0.18,
246            ..Color::srgb_u8(0, 80, 0).into()
247        })),
248        Transform::from_xyz(0.0, -1.0, 0.0),
249    ));
250
251    let parallax_depth_scale = TargetDepth::default().0;
252    let max_parallax_layer_count = ops::exp2(TargetLayers::default().0);
253    let parallax_mapping_method = CurrentMethod::default();
254    let parallax_material = materials.add(StandardMaterial {
255        perceptual_roughness: 0.4,
256        base_color_texture: Some(asset_server.load("textures/parallax_example/cube_color.png")),
257        normal_map_texture: Some(normal_handle),
258        // The depth map is a grayscale texture where black is the highest level and
259        // white the lowest.
260        depth_map: Some(asset_server.load("textures/parallax_example/cube_depth.png")),
261        parallax_depth_scale,
262        parallax_mapping_method: parallax_mapping_method.0,
263        max_parallax_layer_count,
264        ..default()
265    });
266    commands.spawn((
267        Mesh3d(
268            meshes.add(
269                // NOTE: for normal maps and depth maps to work, the mesh
270                // needs tangents generated.
271                Mesh::from(Cuboid::default())
272                    .with_generated_tangents()
273                    .unwrap(),
274            ),
275        ),
276        MeshMaterial3d(parallax_material.clone()),
277        Spin { speed: 0.3 },
278    ));
279
280    let background_cube = meshes.add(
281        Mesh::from(Cuboid::new(40.0, 40.0, 40.0))
282            .with_generated_tangents()
283            .unwrap(),
284    );
285
286    let background_cube_bundle = |translation| {
287        (
288            Mesh3d(background_cube.clone()),
289            MeshMaterial3d(parallax_material.clone()),
290            Transform::from_translation(translation),
291            Spin { speed: -0.1 },
292        )
293    };
294    commands.spawn(background_cube_bundle(Vec3::new(45., 0., 0.)));
295    commands.spawn(background_cube_bundle(Vec3::new(-45., 0., 0.)));
296    commands.spawn(background_cube_bundle(Vec3::new(0., 0., 45.)));
297    commands.spawn(background_cube_bundle(Vec3::new(0., 0., -45.)));
298
299    // example instructions
300    commands.spawn((
301        Text::default(),
302        Node {
303            position_type: PositionType::Absolute,
304            top: px(12),
305            left: px(12),
306            ..default()
307        },
308        children![
309            (TextSpan(format!("Parallax depth scale: {parallax_depth_scale:.5}\n"))),
310            (TextSpan(format!("Layers: {max_parallax_layer_count:.0}\n"))),
311            (TextSpan(format!("{parallax_mapping_method}\n"))),
312            (TextSpan::new("\n\n")),
313            (TextSpan::new("Controls:\n")),
314            (TextSpan::new("Left click - Change view angle\n")),
315            (TextSpan::new("1/2 - Decrease/Increase parallax depth scale\n",)),
316            (TextSpan::new("3/4 - Decrease/Increase layer count\n")),
317            (TextSpan::new("Space - Switch parallaxing algorithm\n")),
318        ],
319    ));
320}
examples/3d/solari.rs (line 216)
200fn setup_many_lights(
201    mut commands: Commands,
202    asset_server: Res<AssetServer>,
203    mut meshes: ResMut<Assets<Mesh>>,
204    mut materials: ResMut<Assets<StandardMaterial>>,
205    args: Res<Args>,
206    #[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))] dlss_rr_supported: Option<
207        Res<DlssRayReconstructionSupported>,
208    >,
209) {
210    let mut rng = ChaCha8Rng::seed_from_u64(42);
211
212    let mut plane_mesh = Plane3d::default()
213        .mesh()
214        .size(400.0, 400.0)
215        .build()
216        .with_generated_tangents()
217        .unwrap();
218    match plane_mesh.attribute_mut(Mesh::ATTRIBUTE_UV_0).unwrap() {
219        VertexAttributeValues::Float32x2(items) => {
220            items.iter_mut().flatten().for_each(|x| *x *= 3.0);
221        }
222        _ => unreachable!(),
223    }
224    let plane_mesh = meshes.add(plane_mesh);
225    let cube_mesh = meshes.add(
226        Cuboid::default()
227            .mesh()
228            .build()
229            .with_generated_tangents()
230            .unwrap(),
231    );
232    let sphere_mesh = meshes.add(
233        Sphere::new(1.0)
234            .mesh()
235            .build()
236            .with_generated_tangents()
237            .unwrap(),
238    );
239
240    commands
241        .spawn((
242            RaytracingMesh3d(plane_mesh.clone()),
243            MeshMaterial3d(
244                materials.add(StandardMaterial {
245                    base_color_texture: Some(
246                        asset_server
247                            .load_builder()
248                            .with_settings::<ImageLoaderSettings>(|settings| {
249                                settings
250                                    .sampler
251                                    .get_or_init_descriptor()
252                                    .set_address_mode(ImageAddressMode::Repeat);
253                            })
254                            .load("textures/uv_checker_bw.png"),
255                    ),
256                    perceptual_roughness: 0.0,
257                    ..default()
258                }),
259            ),
260        ))
261        .insert_if(Mesh3d(plane_mesh), || args.pathtracer != Some(true));
262
263    for _ in 0..8000 {
264        commands
265            .spawn((
266                RaytracingMesh3d(cube_mesh.clone()),
267                MeshMaterial3d(materials.add(StandardMaterial {
268                    base_color: Color::srgb(rng.random(), rng.random(), rng.random()),
269                    perceptual_roughness: rng.random(),
270                    ..default()
271                })),
272                Transform::default()
273                    .with_scale(Vec3 {
274                        x: rng.random_range(0.2..=2.0),
275                        y: rng.random_range(0.2..=2.0),
276                        z: rng.random_range(0.2..=2.0),
277                    })
278                    .with_translation(Vec3::new(
279                        rng.random_range(-180.0..=180.0),
280                        0.2,
281                        rng.random_range(-180.0..=180.0),
282                    )),
283            ))
284            .insert_if(Mesh3d(cube_mesh.clone()), || args.pathtracer != Some(true));
285    }
286
287    for x in -10..=10 {
288        for y in -10..=10 {
289            commands
290                .spawn((
291                    RaytracingMesh3d(sphere_mesh.clone()),
292                    MeshMaterial3d(
293                        materials.add(StandardMaterial {
294                            emissive: Color::linear_rgb(
295                                rng.random::<f32>() * 60000.0,
296                                rng.random::<f32>() * 60000.0,
297                                rng.random::<f32>() * 60000.0,
298                            )
299                            .into(),
300                            ..default()
301                        }),
302                    ),
303                    Transform::default().with_translation(Vec3::new(
304                        (x * 20) as f32,
305                        7.0,
306                        (y * 20) as f32,
307                    )),
308                ))
309                .insert_if(Mesh3d(sphere_mesh.clone()), || {
310                    args.pathtracer != Some(true)
311                });
312        }
313    }
314
315    let mut camera = commands.spawn((
316        Camera3d::default(),
317        Camera {
318            clear_color: ClearColorConfig::Custom(Color::BLACK),
319            ..default()
320        },
321        FreeCamera {
322            walk_speed: 3.0,
323            run_speed: 10.0,
324            ..Default::default()
325        },
326        Transform::from_translation(Vec3::new(6.11329, 166.74896, 451.8226)).with_rotation(
327            Quat::from_xyzw(-0.183938, 0.009093744, 0.0017017953, 0.9828943),
328        ),
329        // Msaa::Off and CameraMainTextureUsages with STORAGE_BINDING are required for Solari
330        CameraMainTextureUsages::default().with(TextureUsages::STORAGE_BINDING),
331        Msaa::Off,
332        Bloom {
333            intensity: 0.1,
334            ..Bloom::NATURAL
335        },
336    ));
337
338    if args.pathtracer == Some(true) {
339        camera.insert(Pathtracer::default());
340    } else {
341        camera.insert(SolariLighting::default());
342    }
343
344    // Using DLSS Ray Reconstruction for denoising (and cheaper rendering via upscaling) is _highly_ recommended when using Solari
345    #[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
346    if dlss_rr_supported.is_some() {
347        camera.insert(Dlss::<DlssRayReconstructionFeature> {
348            perf_quality_mode: Default::default(),
349            reset: Default::default(),
350            _phantom_data: Default::default(),
351        });
352    }
353
354    commands.spawn((
355        Node {
356            position_type: PositionType::Absolute,
357            right: px(0.0),
358            padding: px(4.0).all(),
359            border_radius: BorderRadius::bottom_left(px(4.0)),
360            ..default()
361        },
362        BackgroundColor(Color::srgba(0.10, 0.10, 0.10, 0.8)),
363        children![(
364            PerformanceText,
365            Text::default(),
366            TextFont {
367                font_size: FontSize::Px(8.0),
368                ..default()
369            },
370        )],
371    ));
372}
Source

pub fn merge(&mut self, other: &Mesh) -> Result<(), MeshMergeError>

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

If any of the following conditions are not met, this function errors:

  • All of the vertex attributes that have the same attribute id, must also have the same attribute type. For example two attributes with the same id, but where one is a VertexAttributeValues::Float32 and the other is a VertexAttributeValues::Float32x3, would be invalid.
  • Both meshes must have the same primitive topology.
Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_transformed_by

Source

pub fn try_transformed_by( self, transform: Transform, ) -> Result<Mesh, MeshAccessError>

Transforms the vertex positions, normals, and tangents of the mesh by the given Transform.

Aabb of entities with modified mesh are not updated automatically.

Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_transform_by

Source

pub fn try_transform_by( &mut self, transform: Transform, ) -> Result<(), MeshAccessError>

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.

Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_translated_by

Source

pub fn try_translated_by( self, translation: Vec3, ) -> Result<Mesh, MeshAccessError>

Translates the vertex positions of the mesh by the given Vec3.

Aabb of entities with modified mesh are not updated automatically.

Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_translate_by

Source

pub fn try_translate_by( &mut self, translation: Vec3, ) -> Result<(), MeshAccessError>

Translates the vertex positions of the mesh in place by the given Vec3.

Aabb of entities with modified mesh are not updated automatically.

Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_rotated_by

Source

pub fn try_rotated_by(self, rotation: Quat) -> Result<Mesh, MeshAccessError>

Rotates the vertex positions, normals, and tangents of the mesh by the given Quat.

Aabb of entities with modified mesh are not updated automatically.

Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_rotate_by

Source

pub fn try_rotate_by(&mut self, rotation: Quat) -> Result<(), MeshAccessError>

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.

Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_scaled_by

Source

pub fn try_scaled_by(self, scale: Vec3) -> Result<Mesh, MeshAccessError>

Scales the vertex positions, normals, and tangents of the mesh by the given Vec3.

Aabb of entities with modified mesh are not updated automatically.

Source

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.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_scale_by

Source

pub fn try_scale_by(&mut self, scale: Vec3) -> Result<(), MeshAccessError>

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.

Source

pub fn normalize_joint_weights(&mut self)

Normalize joint weights so they sum to 1.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_normalize_joint_weights

Source

pub fn try_normalize_joint_weights(&mut self) -> Result<(), MeshAccessError>

Normalize joint weights so they sum to 1.

Source

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 or TriangleStrip.
  • The Mesh is missing position or index data.
  • The Mesh’s position data has the wrong format (not Float32x3).
Examples found in repository?
examples/ecs/error_handling.rs (line 101)
60fn setup(
61    mut commands: Commands,
62    mut meshes: ResMut<Assets<Mesh>>,
63    mut materials: ResMut<Assets<StandardMaterial>>,
64) -> Result {
65    let mut seeded_rng = ChaCha8Rng::seed_from_u64(19878367467712);
66
67    // Make a plane for establishing space.
68    commands.spawn((
69        Mesh3d(meshes.add(Plane3d::default().mesh().size(12.0, 12.0))),
70        MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
71        Transform::from_xyz(0.0, -2.5, 0.0),
72    ));
73
74    // Spawn a light:
75    commands.spawn((
76        PointLight {
77            shadow_maps_enabled: true,
78            ..default()
79        },
80        Transform::from_xyz(4.0, 8.0, 4.0),
81    ));
82
83    // Spawn a camera:
84    commands.spawn((
85        Camera3d::default(),
86        Transform::from_xyz(-2.0, 3.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
87    ));
88
89    // Create a new sphere mesh:
90    let mut sphere_mesh = Sphere::new(1.0).mesh().ico(7)?;
91    sphere_mesh.generate_tangents()?;
92
93    // Spawn the mesh into the scene:
94    let mut sphere = commands.spawn((
95        Mesh3d(meshes.add(sphere_mesh.clone())),
96        MeshMaterial3d(materials.add(StandardMaterial::default())),
97        Transform::from_xyz(-1.0, 1.0, 0.0),
98    ));
99
100    // Generate random sample points:
101    let triangles = sphere_mesh.triangles()?;
102    let distribution = UniformMeshSampler::try_new(triangles)?;
103
104    // Setup sample points:
105    let point_mesh = meshes.add(Sphere::new(0.01).mesh().ico(3)?);
106    let point_material = materials.add(StandardMaterial {
107        base_color: Srgba::RED.into(),
108        emissive: LinearRgba::rgb(1.0, 0.0, 0.0),
109        ..default()
110    });
111
112    // Add sample points as children of the sphere:
113    for point in distribution.sample_iter(&mut seeded_rng).take(10000) {
114        sphere.with_child((
115            Mesh3d(point_mesh.clone()),
116            MeshMaterial3d(point_material.clone()),
117            Transform::from_translation(point),
118        ));
119    }
120
121    // Indicate the system completed successfully:
122    Ok(())
123}
Source

pub fn take_gpu_data(&mut self) -> Result<Mesh, MeshAccessError>

Extracts the mesh vertex, index and morph target data for GPU upload. This function is called internally in render world extraction, it is unlikely to be useful outside of that context.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn skinned_mesh_bounds(&self) -> Option<&SkinnedMeshBounds>

Get this mesh’s SkinnedMeshBounds.

Source

pub fn set_skinned_mesh_bounds( &mut self, skinned_mesh_bounds: Option<SkinnedMeshBounds>, )

Set this mesh’s SkinnedMeshBounds.

Source

pub fn with_skinned_mesh_bounds( self, skinned_mesh_bounds: Option<SkinnedMeshBounds>, ) -> Mesh

Consumes the mesh and returns a mesh with the given SkinnedMeshBounds.

Source

pub fn generate_skinned_mesh_bounds( &mut self, ) -> Result<(), SkinnedMeshBoundsError>

Generate SkinnedMeshBounds for this mesh.

Source

pub fn with_generated_skinned_mesh_bounds( self, ) -> Result<Mesh, SkinnedMeshBoundsError>

Consumes the mesh and returns a mesh with generated SkinnedMeshBounds.

Examples found in repository?
tests/3d/test_skinned_mesh_bounds.rs (line 183)
124fn spawn_custom_meshes(
125    mut commands: Commands,
126    mut mesh_assets: ResMut<Assets<Mesh>>,
127    mut material_assets: ResMut<Assets<StandardMaterial>>,
128    mut inverse_bindposes_assets: ResMut<Assets<SkinnedMeshInverseBindposes>>,
129) {
130    let mesh_handle = mesh_assets.add(
131        Mesh::new(
132            PrimitiveTopology::TriangleStrip,
133            // Test that skinned mesh bounds work even if the mesh is render
134            // world only.
135            RenderAssetUsages::RENDER_WORLD,
136        )
137        .with_inserted_attribute(
138            Mesh::ATTRIBUTE_POSITION,
139            vec![
140                [-0.5, 0.0, 0.0],
141                [0.5, 0.0, 0.0],
142                [-0.5, 0.5, 0.0],
143                [0.5, 0.5, 0.0],
144                [-0.5, 1.0, 0.0],
145                [0.5, 1.0, 0.0],
146                [-0.5, 1.5, 0.0],
147                [0.5, 1.5, 0.0],
148                [-0.5, 2.0, 0.0],
149                [0.5, 2.0, 0.0],
150            ],
151        )
152        .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.0, 0.0, 1.0]; 10])
153        .with_inserted_attribute(
154            Mesh::ATTRIBUTE_JOINT_INDEX,
155            VertexAttributeValues::Uint16x4(vec![
156                [1, 0, 0, 0],
157                [1, 0, 0, 0],
158                [1, 2, 0, 0],
159                [1, 2, 0, 0],
160                [1, 2, 0, 0],
161                [1, 2, 0, 0],
162                [2, 1, 0, 0],
163                [2, 1, 0, 0],
164                [2, 0, 0, 0],
165                [2, 0, 0, 0],
166            ]),
167        )
168        .with_inserted_attribute(
169            Mesh::ATTRIBUTE_JOINT_WEIGHT,
170            vec![
171                [1.00, 0.00, 0.0, 0.0],
172                [1.00, 0.00, 0.0, 0.0],
173                [0.75, 0.25, 0.0, 0.0],
174                [0.75, 0.25, 0.0, 0.0],
175                [0.50, 0.50, 0.0, 0.0],
176                [0.50, 0.50, 0.0, 0.0],
177                [0.75, 0.25, 0.0, 0.0],
178                [0.75, 0.25, 0.0, 0.0],
179                [1.00, 0.00, 0.0, 0.0],
180                [1.00, 0.00, 0.0, 0.0],
181            ],
182        )
183        .with_generated_skinned_mesh_bounds()
184        .unwrap(),
185    );
186
187    let inverse_bindposes_handle = inverse_bindposes_assets.add(vec![
188        Mat4::from_translation(Vec3::new(0.0, 0.0, 0.0)),
189        Mat4::from_translation(Vec3::new(0.0, 0.0, 0.0)),
190        Mat4::from_translation(Vec3::new(0.0, -1.0, 0.0)),
191    ]);
192
193    struct MeshInstance {
194        animations: [CustomAnimationId; 2],
195    }
196
197    let mesh_instances = [
198        // Simple cases. First joint is still, second joint is all rotation/translation/scale variations.
199        MeshInstance { animations: [0, 1] },
200        MeshInstance { animations: [0, 2] },
201        MeshInstance { animations: [0, 3] },
202        MeshInstance { animations: [0, 4] },
203        MeshInstance { animations: [0, 5] },
204        MeshInstance { animations: [0, 6] },
205        MeshInstance { animations: [0, 7] },
206        MeshInstance { animations: [0, 8] },
207        // Skewed cases. First joint is non-uniform scaling, second joint is rotation/translation variations.
208        MeshInstance { animations: [9, 1] },
209        MeshInstance { animations: [9, 2] },
210        MeshInstance { animations: [9, 3] },
211        MeshInstance { animations: [9, 4] },
212        MeshInstance { animations: [9, 5] },
213    ];
214
215    for (i, mesh_instance) in mesh_instances.iter().enumerate() {
216        let x = ((i as f32) * 2.0) - ((mesh_instances.len() - 1) as f32);
217
218        let base_entity = commands
219            .spawn((Transform::from_xyz(x, 0.0, 0.0), Visibility::default()))
220            .id();
221
222        let joints = vec![
223            commands.spawn((Transform::IDENTITY,)).id(),
224            commands
225                .spawn((
226                    CustomAnimation(mesh_instance.animations[0]),
227                    Transform::IDENTITY,
228                ))
229                .id(),
230            commands
231                .spawn((
232                    CustomAnimation(mesh_instance.animations[1]),
233                    Transform::IDENTITY,
234                ))
235                .id(),
236        ];
237
238        commands.entity(joints[0]).insert(ChildOf(base_entity));
239
240        commands.entity(joints[1]).insert(ChildOf(joints[0]));
241        commands.entity(joints[2]).insert(ChildOf(joints[1]));
242
243        let mesh_entity = commands
244            .spawn((
245                Transform::IDENTITY,
246                Mesh3d(mesh_handle.clone()),
247                MeshMaterial3d(material_assets.add(StandardMaterial {
248                    base_color: Color::WHITE,
249                    cull_mode: None,
250                    ..default()
251                })),
252                SkinnedMesh {
253                    inverse_bindposes: inverse_bindposes_handle.clone(),
254                    joints: joints.clone(),
255                },
256                DynamicSkinnedMeshBounds,
257            ))
258            .id();
259
260        commands.entity(mesh_entity).insert(ChildOf(base_entity));
261    }
262}
More examples
Hide additional examples
examples/animation/custom_skinned_mesh.rs (line 142)
38fn setup(
39    mut commands: Commands,
40    asset_server: Res<AssetServer>,
41    mut meshes: ResMut<Assets<Mesh>>,
42    mut materials: ResMut<Assets<StandardMaterial>>,
43    mut skinned_mesh_inverse_bindposes_assets: ResMut<Assets<SkinnedMeshInverseBindposes>>,
44) {
45    // Create a camera
46    commands.spawn((
47        Camera3d::default(),
48        Transform::from_xyz(2.5, 2.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
49    ));
50
51    // Create inverse bindpose matrices for a skeleton consists of 2 joints
52    let inverse_bindposes = skinned_mesh_inverse_bindposes_assets.add(vec![
53        Mat4::from_translation(Vec3::new(-0.5, -1.0, 0.0)),
54        Mat4::from_translation(Vec3::new(-0.5, -1.0, 0.0)),
55    ]);
56
57    // Create a mesh
58    let mesh = Mesh::new(
59        PrimitiveTopology::TriangleList,
60        RenderAssetUsages::RENDER_WORLD,
61    )
62    // Set mesh vertex positions
63    .with_inserted_attribute(
64        Mesh::ATTRIBUTE_POSITION,
65        vec![
66            [0.0, 0.0, 0.0],
67            [1.0, 0.0, 0.0],
68            [0.0, 0.5, 0.0],
69            [1.0, 0.5, 0.0],
70            [0.0, 1.0, 0.0],
71            [1.0, 1.0, 0.0],
72            [0.0, 1.5, 0.0],
73            [1.0, 1.5, 0.0],
74            [0.0, 2.0, 0.0],
75            [1.0, 2.0, 0.0],
76        ],
77    )
78    // Add UV coordinates that map the left half of the texture since its a 1 x
79    // 2 rectangle.
80    .with_inserted_attribute(
81        Mesh::ATTRIBUTE_UV_0,
82        vec![
83            [0.0, 0.00],
84            [0.5, 0.00],
85            [0.0, 0.25],
86            [0.5, 0.25],
87            [0.0, 0.50],
88            [0.5, 0.50],
89            [0.0, 0.75],
90            [0.5, 0.75],
91            [0.0, 1.00],
92            [0.5, 1.00],
93        ],
94    )
95    // Set mesh vertex normals
96    .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.0, 0.0, 1.0]; 10])
97    // Set mesh vertex joint indices for mesh skinning.
98    // Each vertex gets 4 indices used to address the `JointTransforms` array in the vertex shader
99    //  as well as `SkinnedMeshJoint` array in the `SkinnedMesh` component.
100    // This means that a maximum of 4 joints can affect a single vertex.
101    .with_inserted_attribute(
102        Mesh::ATTRIBUTE_JOINT_INDEX,
103        // Need to be explicit here as [u16; 4] could be either Uint16x4 or Unorm16x4.
104        VertexAttributeValues::Uint16x4(vec![
105            [0, 0, 0, 0],
106            [0, 0, 0, 0],
107            [0, 1, 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        ]),
116    )
117    // Set mesh vertex joint weights for mesh skinning.
118    // Each vertex gets 4 joint weights corresponding to the 4 joint indices assigned to it.
119    // The sum of these weights should equal to 1.
120    .with_inserted_attribute(
121        Mesh::ATTRIBUTE_JOINT_WEIGHT,
122        vec![
123            [1.00, 0.00, 0.0, 0.0],
124            [1.00, 0.00, 0.0, 0.0],
125            [0.75, 0.25, 0.0, 0.0],
126            [0.75, 0.25, 0.0, 0.0],
127            [0.50, 0.50, 0.0, 0.0],
128            [0.50, 0.50, 0.0, 0.0],
129            [0.25, 0.75, 0.0, 0.0],
130            [0.25, 0.75, 0.0, 0.0],
131            [0.00, 1.00, 0.0, 0.0],
132            [0.00, 1.00, 0.0, 0.0],
133        ],
134    )
135    // Tell bevy to construct triangles from a list of vertex indices,
136    // where each 3 vertex indices form a triangle.
137    .with_inserted_indices(Indices::U16(vec![
138        0, 1, 3, 0, 3, 2, 2, 3, 5, 2, 5, 4, 4, 5, 7, 4, 7, 6, 6, 7, 9, 6, 9, 8,
139    ]))
140    // Create skinned mesh bounds. Together with the `DynamicSkinnedMeshBounds`
141    // component, this will ensure the mesh is correctly frustum culled.
142    .with_generated_skinned_mesh_bounds()
143    .unwrap();
144
145    let mesh = meshes.add(mesh);
146
147    // We're seeding the PRNG here to make this example deterministic for testing purposes.
148    // This isn't strictly required in practical use unless you need your app to be deterministic.
149    let mut rng = ChaCha8Rng::seed_from_u64(42);
150
151    for i in -5..5 {
152        // Create joint entities
153        let joint_0 = commands
154            .spawn(Transform::from_xyz(
155                i as f32 * 1.5,
156                0.0,
157                // Move quads back a small amount to avoid Z-fighting and not
158                // obscure the transform gizmos.
159                -(i as f32 * 0.01).abs(),
160            ))
161            .id();
162        let joint_1 = commands.spawn((AnimatedJoint(i), Transform::IDENTITY)).id();
163
164        // Set joint_1 as a child of joint_0.
165        commands.entity(joint_0).add_children(&[joint_1]);
166
167        // Each joint in this vector corresponds to each inverse bindpose matrix in `SkinnedMeshInverseBindposes`.
168        let joint_entities = vec![joint_0, joint_1];
169
170        // Create skinned mesh renderer. Note that its transform doesn't affect the position of the mesh.
171        commands.spawn((
172            Mesh3d(mesh.clone()),
173            MeshMaterial3d(materials.add(StandardMaterial {
174                base_color: Color::srgb(
175                    rng.random_range(0.0..1.0),
176                    rng.random_range(0.0..1.0),
177                    rng.random_range(0.0..1.0),
178                ),
179                base_color_texture: Some(asset_server.load("textures/uv_checker_bw.png")),
180                ..default()
181            })),
182            SkinnedMesh {
183                inverse_bindposes: inverse_bindposes.clone(),
184                joints: joint_entities,
185            },
186            DynamicSkinnedMeshBounds,
187        ));
188    }
189}
Source§

impl Mesh

Source

pub fn has_morph_targets(&self) -> bool

Available on crate feature morph only.

Whether this mesh has morph targets.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_has_morph_targets

Source

pub fn try_has_morph_targets(&self) -> Result<bool, MeshAccessError>

Available on crate feature morph only.

Whether this mesh has morph targets.

Source

pub fn set_morph_targets(&mut self, morph_targets: Vec<MorphAttributes>)

Available on crate feature morph only.

Set the morph target displacements for this mesh.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_set_morph_targets

Source

pub fn try_set_morph_targets( &mut self, morph_targets: Vec<MorphAttributes>, ) -> Result<(), MeshAccessError>

Available on crate feature morph only.

Set the [morph target] displacements for this mesh.

Source

pub fn morph_targets(&self) -> Option<&Vec<MorphAttributes>>

Available on crate feature morph only.

Retrieve the morph target displacements for this mesh, or None if there are no morph targets.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_morph_targets

Source

pub fn try_morph_targets( &self, ) -> Result<&Vec<MorphAttributes>, MeshAccessError>

Available on crate feature morph only.

Retrieve the morph displacements for this mesh, or None if there are no morph targets.

Returns an error if the mesh data has been extracted to RenderWorldor if the morph targets do not exist.

Source

pub fn with_morph_targets(self, morph_targets: Vec<MorphAttributes>) -> Mesh

Available on crate feature morph only.

Consumes the mesh and returns a mesh with the given morph target displacements.

(Alternatively, you can use Mesh::set_morph_targets to mutate an existing mesh in-place)

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_with_morph_targets

Source

pub fn try_with_morph_targets( self, morph_targets: Vec<MorphAttributes>, ) -> Result<Mesh, MeshAccessError>

Available on crate feature morph only.

Consumes the mesh and returns a mesh with the given morph targets.

(Alternatively, you can use Mesh::set_morph_targets to mutate an existing mesh in-place)

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn set_morph_target_names(&mut self, names: Vec<String>)

Available on crate feature morph only.

Sets the names of each morph target. This should correspond to the order of the morph targets in set_morph_targets.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_set_morph_target_names

Source

pub fn try_set_morph_target_names( &mut self, names: Vec<String>, ) -> Result<(), MeshAccessError>

Available on crate feature morph only.

Sets the names of each morph target. This should correspond to the order of the morph targets in set_morph_targets.

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn with_morph_target_names(self, names: Vec<String>) -> Mesh

Available on crate feature morph only.

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)

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_set_morph_target_names

Source

pub fn try_with_morph_target_names( self, names: Vec<String>, ) -> Result<Mesh, MeshAccessError>

Available on crate feature morph only.

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)

Returns an error if the mesh data has been extracted to RenderWorld.

Source

pub fn morph_target_names(&self) -> Option<&[String]>

Available on crate feature morph only.

Gets a list of all morph target names, if they exist.

§Panics

Panics when the mesh data has already been extracted to RenderWorld. To handle this as an error use Mesh::try_morph_target_names

Examples found in repository?
examples/animation/morph_targets.rs (line 89)
80fn name_morphs(
81    asset_server: Res<AssetServer>,
82    mut events: MessageReader<AssetEvent<Mesh>>,
83    meshes: Res<Assets<Mesh>>,
84) {
85    for event in events.read() {
86        if let AssetEvent::<Mesh>::Added { id } = event
87            && let Some(path) = asset_server.get_path(*id)
88            && let Some(mesh) = meshes.get(*id)
89            && let Some(names) = mesh.morph_target_names()
90        {
91            info!("Morph target names for {path:?}:");
92
93            for name in names {
94                info!("  {name}");
95            }
96        }
97    }
98}
Source

pub fn try_morph_target_names( &self, ) -> Result<Option<&[String]>, MeshAccessError>

Available on crate feature morph only.

Gets a list of all morph target names, if they exist.

Returns an error if the mesh data has been extracted to RenderWorldor if the morph targets do not exist.

Trait Implementations§

Source§

impl Asset for Mesh

Source§

impl Clone for Mesh

Source§

fn clone(&self) -> Mesh

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Mesh

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl From<Annulus> for Mesh

Source§

fn from(annulus: Annulus) -> Mesh

Converts to this type from the input type.
Source§

impl From<Capsule2d> for Mesh

Source§

fn from(capsule: Capsule2d) -> Mesh

Converts to this type from the input type.
Source§

impl From<Capsule3d> for Mesh

Source§

fn from(capsule: Capsule3d) -> Mesh

Converts to this type from the input type.
Source§

impl From<Circle> for Mesh

Source§

fn from(circle: Circle) -> Mesh

Converts to this type from the input type.
Source§

impl From<CircularSector> for Mesh

Source§

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

Source§

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<Cone> for Mesh

Source§

fn from(cone: Cone) -> Mesh

Converts to this type from the input type.
Source§

impl From<ConicalFrustum> for Mesh

Source§

fn from(frustum: ConicalFrustum) -> Mesh

Converts to this type from the input type.
Source§

impl From<ConvexPolygon> for Mesh

Source§

fn from(polygon: ConvexPolygon) -> Mesh

Converts to this type from the input type.
Source§

impl From<Cuboid> for Mesh

Source§

fn from(cuboid: Cuboid) -> Mesh

Converts to this type from the input type.
Source§

impl From<Cylinder> for Mesh

Source§

fn from(cylinder: Cylinder) -> Mesh

Converts to this type from the input type.
Source§

impl From<Ellipse> for Mesh

Source§

fn from(ellipse: Ellipse) -> Mesh

Converts to this type from the input type.
Source§

impl<P> From<Extrusion<P>> for Mesh

Source§

fn from(value: Extrusion<P>) -> Mesh

Converts to this type from the input type.
Source§

impl From<Plane3d> for Mesh

Source§

fn from(plane: Plane3d) -> Mesh

Converts to this type from the input type.
Source§

impl From<Polyline2d> for Mesh

Source§

fn from(polyline: Polyline2d) -> Mesh

Converts to this type from the input type.
Source§

impl From<Polyline3d> for Mesh

Source§

fn from(polyline: Polyline3d) -> Mesh

Converts to this type from the input type.
Source§

impl From<Rectangle> for Mesh

Source§

fn from(rectangle: Rectangle) -> Mesh

Converts to this type from the input type.
Source§

impl From<RegularPolygon> for Mesh

Source§

fn from(polygon: RegularPolygon) -> Mesh

Converts to this type from the input type.
Source§

impl From<Rhombus> for Mesh

Source§

fn from(rhombus: Rhombus) -> Mesh

Converts to this type from the input type.
Source§

impl<P> From<Ring<P>> for Mesh
where P: Primitive2d + Meshable,

Source§

fn from(ring: Ring<P>) -> Mesh

Converts to this type from the input type.
Source§

impl From<Segment2d> for Mesh

Source§

fn from(segment: Segment2d) -> Mesh

Converts this segment into a Mesh using a default Segment2dMeshBuilder.

Source§

impl From<Segment3d> for Mesh

Source§

fn from(segment: Segment3d) -> Mesh

Converts to this type from the input type.
Source§

impl From<Sphere> for Mesh

Source§

fn from(sphere: Sphere) -> Mesh

Converts to this type from the input type.
Source§

impl<T> From<T> for Mesh
where T: MeshBuilder,

Source§

fn from(builder: T) -> Mesh

Converts to this type from the input type.
Source§

impl From<Tetrahedron> for Mesh

Source§

fn from(tetrahedron: Tetrahedron) -> Mesh

Converts to this type from the input type.
Source§

impl From<Torus> for Mesh

Source§

fn from(torus: Torus) -> Mesh

Converts to this type from the input type.
Source§

impl From<Triangle2d> for Mesh

Source§

fn from(triangle: Triangle2d) -> Mesh

Converts to this type from the input type.
Source§

impl From<Triangle3d> for Mesh

Source§

fn from(triangle: Triangle3d) -> Mesh

Converts to this type from the input type.
Source§

impl FromArg for Mesh

Source§

type This<'from_arg> = Mesh

The type to convert into. Read more
Source§

fn from_arg(arg: Arg<'_>) -> Result<<Mesh as FromArg>::This<'_>, ArgError>

Creates an item from an argument. Read more
Source§

impl FromReflect for Mesh

Source§

fn from_reflect(reflect: &(dyn PartialReflect + 'static)) -> Option<Mesh>

Constructs a concrete instance of Self from a reflected value.
Source§

fn take_from_reflect( reflect: Box<dyn PartialReflect>, ) -> Result<Self, Box<dyn PartialReflect>>

Attempts to downcast the given value to Self using, constructing the value using from_reflect if that fails. Read more
Source§

impl GetOwnership for Mesh

Source§

fn ownership() -> Ownership

Returns the ownership of Self.
Source§

impl GetTypeRegistration for Mesh

Source§

fn get_type_registration() -> TypeRegistration

Returns the default TypeRegistration for this type.
Source§

fn register_type_dependencies(registry: &mut TypeRegistry)

Registers other types needed by this type. Read more
Source§

impl IntoReturn for Mesh

Source§

fn into_return<'into_return>(self) -> Return<'into_return>
where Mesh: 'into_return,

Converts Self into a Return value.
Source§

impl MeshAabb for Mesh

Source§

fn compute_aabb(&self) -> Option<Aabb>

Compute the Axis-Aligned Bounding Box of the mesh vertices in model space Read more
Source§

impl Mul<Mesh> for Transform

Source§

type Output = Mesh

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Mesh) -> <Transform as Mul<Mesh>>::Output

Performs the * operation. Read more
Source§

impl PartialEq for Mesh

Source§

fn eq(&self, other: &Mesh) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialReflect for Mesh

Source§

fn get_represented_type_info(&self) -> Option<&'static TypeInfo>

Returns the TypeInfo of the type represented by this value. Read more
Source§

fn try_apply( &mut self, value: &(dyn PartialReflect + 'static), ) -> Result<(), ApplyError>

Tries to apply a reflected value to this value. Read more
Source§

fn reflect_kind(&self) -> ReflectKind

Returns a zero-sized enumeration of “kinds” of type. Read more
Source§

fn reflect_ref(&self) -> ReflectRef<'_>

Returns an immutable enumeration of “kinds” of type. Read more
Source§

fn reflect_mut(&mut self) -> ReflectMut<'_>

Returns a mutable enumeration of “kinds” of type. Read more
Source§

fn reflect_owned(self: Box<Mesh>) -> ReflectOwned

Returns an owned enumeration of “kinds” of type. Read more
Source§

fn try_into_reflect( self: Box<Mesh>, ) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>

Attempts to cast this type to a boxed, fully-reflected value.
Source§

fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>

Attempts to cast this type to a fully-reflected value.
Source§

fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>

Attempts to cast this type to a mutable, fully-reflected value.
Source§

fn into_partial_reflect(self: Box<Mesh>) -> Box<dyn PartialReflect>

Casts this type to a boxed, reflected value. Read more
Source§

fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)

Casts this type to a reflected value. Read more
Source§

fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)

Casts this type to a mutable, reflected value. Read more
Source§

fn reflect_partial_eq( &self, value: &(dyn PartialReflect + 'static), ) -> Option<bool>

Returns a “partial equality” comparison result. Read more
Source§

fn reflect_partial_cmp( &self, value: &(dyn PartialReflect + 'static), ) -> Option<Ordering>

Returns a “partial comparison” result. Read more
Source§

fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>

Attempts to clone Self using reflection. Read more
Source§

fn apply(&mut self, value: &(dyn PartialReflect + 'static))

Applies a reflected value to this value. Read more
Source§

fn to_dynamic(&self) -> Box<dyn PartialReflect>

Converts this reflected value into its dynamic representation based on its kind. Read more
Source§

fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
where T: 'static, Self: Sized + TypePath,

For a type implementing PartialReflect, combines reflect_clone and take in a useful fashion, automatically constructing an appropriate ReflectCloneError if the downcast fails.
Source§

fn reflect_hash(&self) -> Option<u64>

Returns a hash of the value (which includes the type). Read more
Source§

fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Debug formatter for the value. Read more
Source§

fn is_dynamic(&self) -> bool

Indicates whether or not this type is a dynamic type. Read more
Source§

impl Reflect for Mesh

Source§

fn into_any(self: Box<Mesh>) -> Box<dyn Any>

Returns the value as a Box<dyn Any>. Read more
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Returns the value as a &dyn Any. Read more
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Returns the value as a &mut dyn Any. Read more
Source§

fn into_reflect(self: Box<Mesh>) -> Box<dyn Reflect>

Casts this type to a boxed, fully-reflected value.
Source§

fn as_reflect(&self) -> &(dyn Reflect + 'static)

Casts this type to a fully-reflected value.
Source§

fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)

Casts this type to a mutable, fully-reflected value.
Source§

fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>

Performs a type-checked assignment of a reflected value to this value. Read more
Source§

impl Struct for Mesh

Source§

fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>

Gets a reference to the value of the field named name as a &dyn PartialReflect.
Source§

fn field_mut( &mut self, name: &str, ) -> Option<&mut (dyn PartialReflect + 'static)>

Gets a mutable reference to the value of the field named name as a &mut dyn PartialReflect.
Source§

fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>

Gets a reference to the value of the field with index index as a &dyn PartialReflect.
Source§

fn field_at_mut( &mut self, index: usize, ) -> Option<&mut (dyn PartialReflect + 'static)>

Gets a mutable reference to the value of the field with index index as a &mut dyn PartialReflect.
Source§

fn name_at(&self, index: usize) -> Option<&str>

Gets the name of the field with index index.
Source§

fn index_of_name(&self, name: &str) -> Option<usize>

Gets the index of the field with the given name.
Source§

fn field_len(&self) -> usize

Returns the number of fields in the struct.
Source§

fn iter_fields(&self) -> FieldIter<'_>

Returns an iterator over the values of the reflectable fields for this struct.
Source§

fn to_dynamic_struct(&self) -> DynamicStruct

Creates a new DynamicStruct from this struct.
Source§

fn get_represented_struct_info(&self) -> Option<&'static StructInfo>

Will return None if TypeInfo is not available.
Source§

impl StructuralPartialEq for Mesh

Source§

impl TypePath for Mesh

Source§

fn type_path() -> &'static str

Returns the fully qualified path of the underlying type. Read more
Source§

fn short_type_path() -> &'static str

Returns a short, pretty-print enabled path to the type. Read more
Source§

fn type_ident() -> Option<&'static str>

Returns the name of the type, or None if it is anonymous. Read more
Source§

fn crate_name() -> Option<&'static str>

Returns the name of the crate the type is in, or None if it is anonymous. Read more
Source§

fn module_path() -> Option<&'static str>

Returns the path to the module the type is in, or None if it is anonymous. Read more
Source§

impl Typed for Mesh

Source§

fn type_info() -> &'static TypeInfo

Returns the compile-time info for the underlying type.
Source§

impl VisitAssetDependencies for Mesh

Source§

fn visit_dependencies(&self, visit: &mut impl FnMut(UntypedAssetId))

Auto Trait Implementations§

§

impl Freeze for Mesh

§

impl RefUnwindSafe for Mesh

§

impl Send for Mesh

§

impl Sync for Mesh

§

impl Unpin for Mesh

§

impl UnsafeUnpin for Mesh

§

impl UnwindSafe for Mesh

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, U> AsBindGroupShaderType<U> for T
where U: ShaderType, &'a T: for<'a> Into<U>,

Source§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> ConditionalSend for T
where T: Send,

Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts 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>

Converts 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)

Converts &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)

Converts &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 T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert 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>

Convert 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)

Convert &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)

Convert &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
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> DynamicTypePath for T
where T: TypePath,

Source§

impl<T> DynamicTyped for T
where T: Typed,

Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<S> GetField for S
where S: Struct,

Source§

fn get_field<T>(&self, name: &str) -> Option<&T>
where T: Reflect,

Gets a reference to the value of the field named name, downcast to T.
Source§

fn get_field_mut<T>(&mut self, name: &str) -> Option<&mut T>
where T: Reflect,

Gets a mutable reference to the value of the field named name, downcast to T.
Source§

impl<T> GetPath for T
where T: Reflect + ?Sized,

Source§

fn reflect_path<'p>( &self, path: impl ReflectPath<'p>, ) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>

Returns a reference to the value specified by path. Read more
Source§

fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>

Returns a mutable reference to the value specified by path. Read more
Source§

fn path<'p, T>( &self, path: impl ReflectPath<'p>, ) -> Result<&T, ReflectPathError<'p>>
where T: Reflect,

Returns a statically typed reference to the value specified by path. Read more
Source§

fn path_mut<'p, T>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut T, ReflectPathError<'p>>
where T: Reflect,

Returns a statically typed mutable reference to the value specified by path. Read more
Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

impl<T> HitDataExtra for T
where T: Send + Sync + Debug + Any + 'static,

Source§

impl<T> Identity for T
where T: ?Sized,

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
Source§

impl<T> InitializeFromFunction<T> for T

Source§

fn initialize_from_function(f: fn() -> T) -> T

Create an instance of this type from an initialization function
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> IntoResult<T> for T

Source§

fn into_result(self) -> Result<T, RunSystemError>

Converts this type into the system output type.
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<A> Is for A
where A: Any,

Source§

fn is<T>() -> bool
where T: Any,

Checks if the current type “is” another type, using a TypeId equality comparison. This is most useful in the context of generic logic. Read more
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows 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
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows 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
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Reflectable for T

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Settings for T
where T: 'static + Send + Sync,

Source§

impl<Ret> SpawnIfAsync<(), Ret> for Ret

Source§

fn spawn(self) -> Ret

Spawn the value into the dioxus runtime if it is an async block
Source§

impl<T, O> SuperFrom<T> for O
where O: From<T>,

Source§

fn super_from(input: T) -> O

Convert from a type to another type.
Source§

impl<T, O, M> SuperInto<O, M> for T
where O: SuperFrom<T, M>,

Source§

fn super_into(self) -> O

Convert from a type to another type.
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .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
where Self: BorrowMut<B>, B: ?Sized,

Calls .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
where Self: AsRef<R>, R: ?Sized,

Calls .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
where Self: AsMut<R>, R: ?Sized,

Calls .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
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> TypeData for T
where T: 'static + Send + Sync + Clone,

Source§

fn clone_type_data(&self) -> Box<dyn TypeData>

Creates a type-erased clone of this value.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more