Search code examples
rustbevy

How can I manually create meshes in bevy with vertices?


What do I have to do to to create a mesh for bevy with the following vertices:

let mut vertices : Vec<[f32; 3]> = Vec::new();

    vertices.push([0.0, 0.0, 0.0]);
    vertices.push([1.0, 2.0, 1.0]);
    vertices.push([2.0, 0.0, 0.0]);

I then want to spawn a MeshBundle like so

commands
    .spawn(MeshBundle {
        mesh: mesh,
        transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
        ..Default::default()
    });

Solution

  • This answer has been updated for the latest bevy = "0.11" and uses the default shaders.

    The code below demonstrates how to:

    1. Define vertex positions for a bevy::render::pipeline::PrimitiveTopology::TriangleList
    2. Assign vertex normals and uv coordinates to the vertices
    3. Create a triangle using the 3 vertices we defined

    It is based on the built in shapes in bevy, which can be found here.

    use bevy::prelude::*;
    use bevy::render::mesh::{self, PrimitiveTopology};
    
    fn main() {
        App::new()
            .insert_resource(Msaa::Sample4)
            .add_plugins(DefaultPlugins)
            .add_systems(Startup, setup)
            .run();
    }
    
    fn setup(
        mut commands: Commands,
        mut meshes: ResMut<Assets<Mesh>>,
        mut materials: ResMut<Assets<StandardMaterial>>,
    ) {
        let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
    
        // Positions of the vertices
        // See https://bevy-cheatbook.github.io/features/coords.html
        mesh.insert_attribute(
            Mesh::ATTRIBUTE_POSITION,
            vec![[0., 0., 0.], [1., 2., 1.], [2., 0., 0.]],
        );
    
        // In this example, normals and UVs don't matter,
        // so we just use the same value for all of them
        mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0., 1., 0.]; 3]);
        mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0., 0.]; 3]);
    
        // A triangle using vertices 0, 2, and 1.
        // Note: order matters. [0, 1, 2] will be flipped upside down, and you won't see it from behind!
        mesh.set_indices(Some(mesh::Indices::U32(vec![0, 2, 1])));
    
        commands.spawn(PbrBundle {
            mesh: meshes.add(mesh),
            material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
            ..default()
        });
    
        commands.spawn(PointLightBundle {
            point_light: PointLight {
                intensity: 1500.0,
                shadows_enabled: true,
                ..default()
            },
            transform: Transform::from_xyz(4.0, 8.0, 4.0),
            ..default()
        });
    
        commands.spawn(Camera3dBundle {
            transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
            ..default()
        });
    }
    

    You will have to define your own positions, uvs and normals according to your use case. Some shaders won't need all of these mesh attributes.