GLTF extension support (#11138)

# Objective
Adds support for accessing raw extension data of loaded GLTF assets

## Solution
Via the GLTF loader settings, you can specify whether or not to include
the GLTF source. While not the ideal way of solving this problem,
modeling all of GLTF within Bevy just for extensions adds a lot of
complexity to the way Bevy handles GLTF currently. See the example GLTF
meta file and code
```
(
    meta_format_version: "1.0",
    asset: Load(
        loader: "bevy_gltf::loader::GltfLoader",
        settings: (
            load_meshes: true,
            load_cameras: true,
            load_lights: true,
            include_source: true,
        ),
    ),
)
```
```rs
pub fn load_gltf(mut commands: Commands, assets: Res<AssetServer>) {
    let my_gltf = assets.load("test_platform.gltf");

    commands.insert_resource(MyAssetPack {
        spawned: false,
        handle: my_gltf,
    });
}

#[derive(Resource)]
pub struct MyAssetPack {
    pub spawned: bool,
    pub handle: Handle<Gltf>,
}

pub fn spawn_gltf_objects(
    mut commands: Commands,
    mut my: ResMut<MyAssetPack>,
    assets_gltf: Res<Assets<Gltf>>,
) {
    // This flag is used to because this system has to be run until the asset is loaded.
    // If there's a better way of going about this I am unaware of it.
    if my.spawned {
        return;
    }

    if let Some(gltf) = assets_gltf.get(&my.handle) {
        info!("spawn");
        my.spawned = true;
        // spawn the first scene in the file
        commands.spawn(SceneBundle {
            scene: gltf.scenes[0].clone(),
            ..Default::default()
        });

        let source = gltf.source.as_ref().unwrap();
        info!("materials count {}", &source.materials().size_hint().0);
        info!(
            "materials ext is some {}",
            &source.materials().next().unwrap().extensions().is_some()
        );
    }
}
```

---

## Changelog
Added support for GLTF extensions through including raw GLTF source via
loader flag `GltfLoaderSettings::include_source == true`, stored in
`Gltf::source: Option<gltf::Gltf>`

## Migration Guide
This will have issues with "asset migrations", as there is currently no
way for .meta files to be migrated. Attempting to migrate .meta files
without the new flag will yield the following error:
```
bevy_asset::server: Failed to deserialize meta for asset test_platform.gltf: Failed to deserialize asset meta: SpannedError { code: MissingStructField { field: "include_source", outer: Some("GltfLoaderSettings") }, position: Position { line: 9, col: 9 } }
```
This means users who want to migrate their .meta files will have to add
the `include_source: true,` setting to their meta files by hand.
This commit is contained in:
Cornelius 2024-01-15 09:38:01 -06:00 committed by GitHub
parent c29a9729a4
commit a7b99f0500
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 12 additions and 1 deletions

View file

@ -35,7 +35,7 @@ bevy_tasks = { path = "../bevy_tasks", version = "0.12.0" }
bevy_utils = { path = "../bevy_utils", version = "0.12.0" }
# other
gltf = { version = "1.3.0", default-features = false, features = [
gltf = { version = "1.4.0", default-features = false, features = [
"KHR_lights_punctual",
"KHR_materials_transmission",
"KHR_materials_ior",
@ -43,6 +43,7 @@ gltf = { version = "1.3.0", default-features = false, features = [
"KHR_materials_unlit",
"KHR_materials_emissive_strength",
"extras",
"extensions",
"names",
"utils",
] }

View file

@ -98,6 +98,8 @@ pub struct Gltf {
/// Named animations loaded from the glTF file.
#[cfg(feature = "bevy_animation")]
pub named_animations: HashMap<String, Handle<AnimationClip>>,
/// The gltf root of the gltf asset, see <https://docs.rs/gltf/latest/gltf/struct.Gltf.html>. Only has a value when `GltfLoaderSettings::include_source` is true.
pub source: Option<gltf::Gltf>,
}
/// A glTF node with all of its child nodes, its [`GltfMesh`],

View file

@ -131,6 +131,8 @@ pub struct GltfLoaderSettings {
pub load_cameras: bool,
/// If true, the loader will spawn lights for gltf light nodes.
pub load_lights: bool,
/// If true, the loader will include the root of the gltf root node.
pub include_source: bool,
}
impl Default for GltfLoaderSettings {
@ -139,6 +141,7 @@ impl Default for GltfLoaderSettings {
load_meshes: true,
load_cameras: true,
load_lights: true,
include_source: false,
}
}
}
@ -673,6 +676,11 @@ async fn load_gltf<'a, 'b, 'c>(
animations,
#[cfg(feature = "bevy_animation")]
named_animations,
source: if settings.include_source {
Some(gltf)
} else {
None
},
})
}