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

add handling of all missing gltf extras: scene, mesh & materials #13453

Merged
merged 12 commits into from
Jun 3, 2024
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,17 @@ description = "Loads and renders a glTF file as a scene"
category = "3D Rendering"
wasm = true

[[example]]
name = "load_gltf_extras"
path = "examples/3d/load_gltf_extras.rs"
doc-scrape-examples = true

[package.metadata.example.load_gltf_extras]
name = "Load glTF extras"
description = "Loads and renders a glTF file as a scene, and all the gltf extras"
kaosat-dev marked this conversation as resolved.
Show resolved Hide resolved
category = "3D Rendering"
wasm = true

[[example]]
name = "motion_blur"
path = "examples/3d/motion_blur.rs"
Expand Down
Binary file added assets/models/extras/gltf_extras.glb
Binary file not shown.
35 changes: 34 additions & 1 deletion crates/bevy_gltf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ impl GltfPlugin {
impl Plugin for GltfPlugin {
fn build(&self, app: &mut App) {
app.register_type::<GltfExtras>()
.register_type::<GltfSceneExtras>()
.register_type::<GltfMeshExtras>()
.register_type::<GltfMaterialExtras>()
.init_asset::<Gltf>()
.init_asset::<GltfNode>()
.init_asset::<GltfPrimitive>()
Expand Down Expand Up @@ -148,7 +151,7 @@ pub struct GltfPrimitive {
pub material_extras: Option<GltfExtras>,
}

/// Additional untyped data that can be present on most glTF types.
/// Additional untyped data that can be present on most glTF types at the primitive level.
///
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-extras).
#[derive(Clone, Debug, Reflect, Default, Component)]
Expand All @@ -157,3 +160,33 @@ pub struct GltfExtras {
/// Content of the extra data.
pub value: String,
}

/// Additional untyped data that can be present on most glTF types at the scene level.
///
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-extras).
#[derive(Clone, Debug, Reflect, Default, Component)]
#[reflect(Component)]
pub struct GltfSceneExtras {
/// Content of the extra data.
pub value: String,
}

/// Additional untyped data that can be present on most glTF types at the mesh level.
///
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-extras).
#[derive(Clone, Debug, Reflect, Default, Component)]
#[reflect(Component)]
pub struct GltfMeshExtras {
/// Content of the extra data.
pub value: String,
}

/// Additional untyped data that can be present on most glTF types at the material level.
///
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-extras).
#[derive(Clone, Debug, Reflect, Default, Component)]
#[reflect(Component)]
pub struct GltfMaterialExtras {
/// Content of the extra data.
pub value: String,
}
30 changes: 28 additions & 2 deletions crates/bevy_gltf/src/loader.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{vertex_attributes::convert_attribute, Gltf, GltfExtras, GltfNode};
use crate::{
vertex_attributes::convert_attribute, Gltf, GltfExtras, GltfMaterialExtras, GltfMeshExtras,
GltfNode, GltfSceneExtras,
};
#[cfg(feature = "bevy_animation")]
use bevy_animation::{AnimationTarget, AnimationTargetId};
use bevy_asset::{
Expand Down Expand Up @@ -622,7 +625,8 @@ async fn load_gltf<'a, 'b, 'c>(
let mut node_index_to_entity_map = HashMap::new();
let mut entity_to_skin_index_map = EntityHashMap::default();
let mut scene_load_context = load_context.begin_labeled_asset();
world

let world_root_id = world
.spawn(SpatialBundle::INHERITED_IDENTITY)
.with_children(|parent| {
for node in scene.nodes() {
Expand All @@ -647,7 +651,15 @@ async fn load_gltf<'a, 'b, 'c>(
return;
}
}
})
.id();

if let Some(extras) = scene.extras().as_ref() {
world.entity_mut(world_root_id).insert(GltfSceneExtras {
value: extras.get().to_string(),
});
}

if let Some(Err(err)) = err {
return Err(err);
}
Expand Down Expand Up @@ -1256,6 +1268,7 @@ fn load_node(
material: load_context.get_label_handle(&material_label),
..Default::default()
});

let target_count = primitive.morph_targets().len();
if target_count != 0 {
let weights = match mesh.weights() {
Expand Down Expand Up @@ -1286,6 +1299,19 @@ fn load_node(
});
}

// Add gltf extras to the mesh entity
kaosat-dev marked this conversation as resolved.
Show resolved Hide resolved
if let Some(extras) = mesh.extras() {
mesh_entity.insert(GltfMeshExtras {
value: extras.get().to_string(),
});
}

if let Some(extras) = material.extras() {
mesh_entity.insert(GltfMaterialExtras {
value: extras.get().to_string(),
});
}

mesh_entity.insert(Name::new(primitive_name(&mesh, &primitive)));
// Mark for adding skinned mesh
if let Some(skin) = gltf_node.skin() {
Expand Down
75 changes: 75 additions & 0 deletions examples/3d/load_gltf_extras.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//! Loads and renders a glTF file as a scene, and list all the different `gltf_extras`.

use bevy::{
gltf::{GltfExtras, GltfMaterialExtras, GltfMeshExtras, GltfSceneExtras},
prelude::*,
};

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, check_for_gltf_extras)
.run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.7, 0.7, 1.0).looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y),
..default()
});
kaosat-dev marked this conversation as resolved.
Show resolved Hide resolved

commands.spawn(DirectionalLightBundle {
directional_light: DirectionalLight {
shadows_enabled: true,
..default()
},
..default()
});
// a barebones scene containing one of each gltf_extra type
commands.spawn(SceneBundle {
scene: asset_server.load("models/extras/gltf_extras.glb#Scene0"),
..default()
});
}

fn check_for_gltf_extras(
gltf_extras_query: Query<(Entity, Option<&Name>, &GltfExtras), Added<GltfExtras>>,
gltf_scene_extras_query: Query<
(Entity, Option<&Name>, &GltfSceneExtras),
Added<GltfSceneExtras>,
>,
gltf_mesh_extras_query: Query<(Entity, Option<&Name>, &GltfMeshExtras), Added<GltfMeshExtras>>,
gltf_material_extras_query: Query<
(Entity, Option<&Name>, &GltfMaterialExtras),
Added<GltfMaterialExtras>,
>,
kaosat-dev marked this conversation as resolved.
Show resolved Hide resolved
) {
for extra in gltf_extras_query.iter() {
info!(
"primitive extra for {:?} : {:?} (id: {})",
extra.1, extra.2, extra.0
);
}
kaosat-dev marked this conversation as resolved.
Show resolved Hide resolved

for extra in gltf_scene_extras_query.iter() {
info!(
"scene extra for {:?} : {:?} (id: {})",
extra.1, extra.2, extra.0
);
}

for extra in gltf_mesh_extras_query.iter() {
info!(
"mesh extra for {:?} : {:?} (id: {})",
extra.1, extra.2, extra.0
);
}

for extra in gltf_material_extras_query.iter() {
info!(
"material extra for {:?} : {:?} (id: {})",
extra.1, extra.2, extra.0
);
}
}
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ Example | Description
[Lightmaps](../examples/3d/lightmaps.rs) | Rendering a scene with baked lightmaps
[Lines](../examples/3d/lines.rs) | Create a custom material to draw 3d lines
[Load glTF](../examples/3d/load_gltf.rs) | Loads and renders a glTF file as a scene
[Load glTF extras](../examples/3d/load_gltf_extras.rs) | Loads and renders a glTF file as a scene, and all the gltf extras
kaosat-dev marked this conversation as resolved.
Show resolved Hide resolved
[Meshlet](../examples/3d/meshlet.rs) | Meshlet rendering for dense high-poly scenes (experimental)
[Motion Blur](../examples/3d/motion_blur.rs) | Demonstrates per-pixel motion blur
[Orthographic View](../examples/3d/orthographic.rs) | Shows how to create a 3D orthographic view (for isometric-look in games or CAD applications)
Expand Down