Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/3d/edit_material_on_gltf.rs
6592 views
1
//! Showcases how to change the material of a `Scene` spawned from a Gltf
2
3
use bevy::{
4
audio::AudioPlugin, color::palettes, gltf::GltfMaterialName, prelude::*,
5
scene::SceneInstanceReady,
6
};
7
8
fn main() {
9
App::new()
10
.add_plugins(DefaultPlugins.build().disable::<AudioPlugin>())
11
.add_systems(Startup, setup_scene)
12
.add_observer(change_material)
13
.run();
14
}
15
16
/// This is added to a [`SceneRoot`] and will cause the [`StandardMaterial::base_color`]
17
/// of all materials to be overwritten
18
#[derive(Component)]
19
struct ColorOverride(Color);
20
21
fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
22
commands.spawn((
23
Camera3d::default(),
24
Transform::from_xyz(0., 1., 2.5).looking_at(Vec3::new(0., 0.25, 0.), Dir3::Y),
25
));
26
27
commands.spawn((
28
DirectionalLight::default(),
29
Transform::from_xyz(0., 1., 0.25).looking_at(Vec3::ZERO, Dir3::Y),
30
));
31
32
// FlightHelmet handle
33
let flight_helmet = asset_server
34
.load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf"));
35
// This model will keep its original materials
36
commands.spawn(SceneRoot(flight_helmet.clone()));
37
// This model will be tinted red
38
commands.spawn((
39
SceneRoot(flight_helmet.clone()),
40
Transform::from_xyz(-1.25, 0., 0.),
41
ColorOverride(palettes::tailwind::RED_300.into()),
42
));
43
// This model will be tinted green
44
commands.spawn((
45
SceneRoot(flight_helmet),
46
Transform::from_xyz(1.25, 0., 0.),
47
ColorOverride(palettes::tailwind::GREEN_300.into()),
48
));
49
}
50
51
fn change_material(
52
event: On<SceneInstanceReady>,
53
mut commands: Commands,
54
children: Query<&Children>,
55
color_override: Query<&ColorOverride>,
56
mesh_materials: Query<(&MeshMaterial3d<StandardMaterial>, &GltfMaterialName)>,
57
mut asset_materials: ResMut<Assets<StandardMaterial>>,
58
) {
59
info!("processing Scene Entity: {}", event.entity());
60
// Iterate over all children recursively
61
for descendant in children.iter_descendants(event.entity()) {
62
// Get the material id and name which were created from the glTF file information
63
let Ok((id, material_name)) = mesh_materials.get(descendant) else {
64
continue;
65
};
66
// Get the material of the descendant
67
let Some(material) = asset_materials.get_mut(id.id()) else {
68
continue;
69
};
70
71
// match on the material name, modifying the materials as necessary
72
match material_name.0.as_str() {
73
"LeatherPartsMat" => {
74
info!("editing LeatherPartsMat to use ColorOverride tint");
75
// Get the `ColorOverride` of the entity, if it does not have a color override, skip
76
let Ok(color_override) = color_override.get(event.entity()) else {
77
continue;
78
};
79
// Create a copy of the material and override base color
80
// If you intend on creating multiple models with the same tint, it
81
// is best to cache the handle somewhere, as having multiple materials
82
// that are identical is expensive
83
let mut new_material = material.clone();
84
new_material.base_color = color_override.0;
85
86
// Override `MeshMaterial3d` with new material
87
commands
88
.entity(descendant)
89
.insert(MeshMaterial3d(asset_materials.add(new_material)));
90
}
91
name => {
92
info!("not replacing: {name}");
93
}
94
}
95
}
96
}
97
98