Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Page about working with GLTF in Bevy #2

Closed
inodentry opened this issue Feb 24, 2021 · 5 comments
Closed

Page about working with GLTF in Bevy #2

inodentry opened this issue Feb 24, 2021 · 5 comments
Labels
C-enhancement New content that isn't covered already S-cookbook Content in the Cookbook section

Comments

@inodentry
Copy link
Contributor

Add a section describing how to work with asset labels to address sub-assets in GLTF files.

It should cover how to get individual meshes, scenes, textures, etc. that were loaded from a GLTF file.

It should cover both bevy-generated labels (Scene0, Primitive0, ...) and custom labels (when a GLTF file was exported with labels included in the file).

@inodentry inodentry added S-cookbook Content in the Cookbook section C-enhancement New content that isn't covered already labels Feb 24, 2021
@inodentry inodentry changed the title GLTF asset labels Page about working with GLTF in Bevy Apr 2, 2021
@inodentry
Copy link
Contributor Author

Some of this information is mentioned on the new Assets page in the new 0.5 book.

However, that is not enough. I am leaving this issue open, for a proper page about GLTF in Bevy.

@allsey87
Copy link

I am working on this. I am trying to manually do what the spawn_scene command does with the flight helmet in this example using PbrBundle, Mesh, StandardMaterial etc. I will try to provide some code soon.

@allsey87
Copy link

allsey87 commented May 24, 2021

So I have some pretty ugly code/first draft that works, at least for the flight helmet GLTF, so let me know what you think, @jamadazi.

fn main() {
    App::build()
        .insert_resource(AmbientLight {
            color: Color::WHITE,
            brightness: 1.0 / 5.0f32,
        })
        .insert_resource(Msaa { samples: 4 })
        .add_plugins(DefaultPlugins)
        .add_startup_system(setup.system())
        .add_system(late_setup.system())
        .run();
}

struct Model(Handle<Gltf>);

fn setup(mut commands: Commands,
         asset_server: Res<AssetServer>) {
    
    let handle : Handle<Gltf> = asset_server.load("models/FlightHelmet/FlightHelmet.gltf");
    commands.insert_resource(Model(handle));
    
    commands.spawn_bundle(PerspectiveCameraBundle {
        transform: Transform::from_xyz(0.7, 0.7, 1.0).looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y),
        ..Default::default()
    });
    commands.spawn_bundle(LightBundle {
        transform: Transform::from_xyz(3.0, 5.0, 3.0),
        ..Default::default()
    });
}

fn late_setup(mut commands: Commands, 
              handle: Res<Model>,
              mut done: Local<bool>,
              gltfs: Res<Assets<Gltf>>,
              gltf_nodes: Res<Assets<GltfNode>>,
              gltf_meshes: Res<Assets<GltfMesh>>) {
    if !*done {
        if let Some(gltf) = gltfs.get(&handle.0) {
            let nodes = gltf.nodes.iter().filter_map(|node| gltf_nodes.get(node));
            commands.spawn()
                .with_children(|parent| create_gltf_entities(parent, &gltf_meshes, nodes));
            *done = true;
        }
    }
}

fn create_gltf_entities<'n>(builder: &mut ChildBuilder,
                            meshes: &Res<Assets<GltfMesh>>,
                            nodes: impl IntoIterator<Item = &'n GltfNode>) {
    for node in nodes {
        let mut entity = builder.spawn_bundle((node.transform.clone(),));
        entity.with_children(|parent| create_gltf_entities(parent, meshes, &node.children));
        /* grab the first primitve for this node */
        let primitive = node.mesh.as_ref()
            .and_then(|mesh| meshes.get(mesh))
            .and_then(|mesh| mesh.primitives.first());
        if let Some(primitive) = primitive {
            if let Some(material) = primitive.material.as_ref() {
                entity.insert_bundle(PbrBundle {
                    mesh: primitive.mesh.clone(),
                    material: material.clone(),
                    ..Default::default()
                });
            }
        }
    }
}

I need to test the create_gltf_entities on more models, since I am not sure if the transforms are set up correctly. It works well for the FlightHelmet since, I believe, all the transforms are just zero and all nodes are just root nodes (note that this means the recursive aspect of this function hasn't been tested).

@allsey87
Copy link

By the way, when I try to load the materials by what I am pretty sure are the exported names, I get an error and nothing shows up in the Bevy window.

This works:

commands.spawn().with_children(|parent| {
        parent.spawn_bundle(PbrBundle {
            mesh: asset_server.load("models/FlightHelmet/FlightHelmet.gltf#Mesh0/Primitive0"),
            material: asset_server.load("models/FlightHelmet/FlightHelmet.gltf#Material0"),
            ..Default::default()
        });
});

This doesn't:

commands.spawn().with_children(|parent| {
        parent.spawn_bundle(PbrBundle {
            mesh: asset_server.load("models/FlightHelmet/FlightHelmet.gltf#Mesh0/Primitive0"),
            material: asset_server.load("models/FlightHelmet/FlightHelmet.gltf#HoseMat"),
            ..Default::default()
        });
});

The message from bevy_log is:

DEBUG bevy_render::render_graph::nodes::pass_node: Could not draw indexed because the pipeline layout wasn't fully set for pipeline: Some(WeakHandle<PipelineDescriptor>(Id(ebfc1d11-a2a4-44cb-8f12-c49cc631146c, 13909840682157579068)))

Looking closer at bevy_gltf's loader.rs, I am not convinced that the loader is currently making these sub-assets available by their provided names. The names are exported to the Gltf object under named_nodes, named_meshes, named_materials etc, but I don't think these names can be currently used via an asset server.

Checking all the calls to set_labeled_asset inside the GLTF loader gives me this list of available (sub)assets:

May 24 16:43:27.925 DEBUG bevy_gltf::loader: labeled asset = Material0
May 24 16:43:27.926 DEBUG bevy_gltf::loader: labeled asset = Material1
May 24 16:43:27.926 DEBUG bevy_gltf::loader: labeled asset = Material2
May 24 16:43:27.926 DEBUG bevy_gltf::loader: labeled asset = Material3
May 24 16:43:27.927 DEBUG bevy_gltf::loader: labeled asset = Material4
May 24 16:43:27.927 DEBUG bevy_gltf::loader: labeled asset = Material5
May 24 16:43:27.984 DEBUG bevy_gltf::loader: labeled asset = Mesh0/Primitive0
May 24 16:43:27.985 DEBUG bevy_gltf::loader: labeled asset = Mesh0
May 24 16:43:28.050 DEBUG bevy_gltf::loader: labeled asset = Mesh1/Primitive0
May 24 16:43:28.050 DEBUG bevy_gltf::loader: labeled asset = Mesh1
May 24 16:43:28.069 DEBUG bevy_gltf::loader: labeled asset = Mesh2/Primitive0
May 24 16:43:28.069 DEBUG bevy_gltf::loader: labeled asset = Mesh2
May 24 16:43:28.126 DEBUG bevy_gltf::loader: labeled asset = Mesh3/Primitive0
May 24 16:43:28.126 DEBUG bevy_gltf::loader: labeled asset = Mesh3
May 24 16:43:28.174 DEBUG bevy_gltf::loader: labeled asset = Mesh4/Primitive0
May 24 16:43:28.174 DEBUG bevy_gltf::loader: labeled asset = Mesh4
May 24 16:43:28.176 DEBUG bevy_gltf::loader: labeled asset = Mesh5/Primitive0
May 24 16:43:28.176 DEBUG bevy_gltf::loader: labeled asset = Mesh5
May 24 16:43:28.177 DEBUG bevy_gltf::loader: labeled asset = Node0
May 24 16:43:28.177 DEBUG bevy_gltf::loader: labeled asset = Node1
May 24 16:43:28.177 DEBUG bevy_gltf::loader: labeled asset = Node2
May 24 16:43:28.177 DEBUG bevy_gltf::loader: labeled asset = Node3
May 24 16:43:28.177 DEBUG bevy_gltf::loader: labeled asset = Node4
May 24 16:43:28.177 DEBUG bevy_gltf::loader: labeled asset = Node5
May 24 16:43:31.216 DEBUG bevy_gltf::loader: labeled asset = Texture0
May 24 16:43:31.216 DEBUG bevy_gltf::loader: labeled asset = Texture1
May 24 16:43:31.216 DEBUG bevy_gltf::loader: labeled asset = Texture2
May 24 16:43:31.216 DEBUG bevy_gltf::loader: labeled asset = Texture3
May 24 16:43:31.216 DEBUG bevy_gltf::loader: labeled asset = Texture4
May 24 16:43:31.216 DEBUG bevy_gltf::loader: labeled asset = Texture5
May 24 16:43:31.216 DEBUG bevy_gltf::loader: labeled asset = Texture6
May 24 16:43:31.216 DEBUG bevy_gltf::loader: labeled asset = Texture7
May 24 16:43:31.216 DEBUG bevy_gltf::loader: labeled asset = Texture8
May 24 16:43:31.216 DEBUG bevy_gltf::loader: labeled asset = Texture9
May 24 16:43:31.217 DEBUG bevy_gltf::loader: labeled asset = Texture10
May 24 16:43:31.217 DEBUG bevy_gltf::loader: labeled asset = Texture11
May 24 16:43:31.217 DEBUG bevy_gltf::loader: labeled asset = Texture12
May 24 16:43:31.217 DEBUG bevy_gltf::loader: labeled asset = Texture13
May 24 16:43:31.217 DEBUG bevy_gltf::loader: labeled asset = Texture14
May 24 16:43:31.218 DEBUG bevy_gltf::loader: labeled asset = Scene0

@inodentry
Copy link
Contributor Author

Page on Bevy GLTF exists now and (I believe) covers all the common use cases pretty well.

If there is more to be desired, comment or file issues! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement New content that isn't covered already S-cookbook Content in the Cookbook section
Projects
None yet
Development

No branches or pull requests

2 participants