Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_gltf/src/assets.rs
6595 views
1
//! Representation of assets present in a glTF file
2
3
use core::ops::Deref;
4
5
#[cfg(feature = "bevy_animation")]
6
use bevy_animation::AnimationClip;
7
use bevy_asset::{Asset, Handle};
8
use bevy_ecs::{component::Component, reflect::ReflectComponent};
9
use bevy_mesh::{skinning::SkinnedMeshInverseBindposes, Mesh};
10
use bevy_pbr::StandardMaterial;
11
use bevy_platform::collections::HashMap;
12
use bevy_reflect::{prelude::ReflectDefault, Reflect, TypePath};
13
use bevy_scene::Scene;
14
15
use crate::GltfAssetLabel;
16
17
/// Representation of a loaded glTF file.
18
#[derive(Asset, Debug, TypePath)]
19
pub struct Gltf {
20
/// All scenes loaded from the glTF file.
21
pub scenes: Vec<Handle<Scene>>,
22
/// Named scenes loaded from the glTF file.
23
pub named_scenes: HashMap<Box<str>, Handle<Scene>>,
24
/// All meshes loaded from the glTF file.
25
pub meshes: Vec<Handle<GltfMesh>>,
26
/// Named meshes loaded from the glTF file.
27
pub named_meshes: HashMap<Box<str>, Handle<GltfMesh>>,
28
/// All materials loaded from the glTF file.
29
pub materials: Vec<Handle<StandardMaterial>>,
30
/// Named materials loaded from the glTF file.
31
pub named_materials: HashMap<Box<str>, Handle<StandardMaterial>>,
32
/// All nodes loaded from the glTF file.
33
pub nodes: Vec<Handle<GltfNode>>,
34
/// Named nodes loaded from the glTF file.
35
pub named_nodes: HashMap<Box<str>, Handle<GltfNode>>,
36
/// All skins loaded from the glTF file.
37
pub skins: Vec<Handle<GltfSkin>>,
38
/// Named skins loaded from the glTF file.
39
pub named_skins: HashMap<Box<str>, Handle<GltfSkin>>,
40
/// Default scene to be displayed.
41
pub default_scene: Option<Handle<Scene>>,
42
/// All animations loaded from the glTF file.
43
#[cfg(feature = "bevy_animation")]
44
pub animations: Vec<Handle<AnimationClip>>,
45
/// Named animations loaded from the glTF file.
46
#[cfg(feature = "bevy_animation")]
47
pub named_animations: HashMap<Box<str>, Handle<AnimationClip>>,
48
/// 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.
49
pub source: Option<gltf::Gltf>,
50
}
51
52
/// A glTF mesh, which may consist of multiple [`GltfPrimitives`](GltfPrimitive)
53
/// and an optional [`GltfExtras`].
54
///
55
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-mesh).
56
#[derive(Asset, Debug, Clone, TypePath)]
57
pub struct GltfMesh {
58
/// Index of the mesh inside the scene
59
pub index: usize,
60
/// Computed name for a mesh - either a user defined mesh name from gLTF or a generated name from index
61
pub name: String,
62
/// Primitives of the glTF mesh.
63
pub primitives: Vec<GltfPrimitive>,
64
/// Additional data.
65
pub extras: Option<GltfExtras>,
66
}
67
68
impl GltfMesh {
69
/// Create a mesh extracting name and index from glTF def
70
pub fn new(
71
mesh: &gltf::Mesh,
72
primitives: Vec<GltfPrimitive>,
73
extras: Option<GltfExtras>,
74
) -> Self {
75
Self {
76
index: mesh.index(),
77
name: if let Some(name) = mesh.name() {
78
name.to_string()
79
} else {
80
format!("GltfMesh{}", mesh.index())
81
},
82
primitives,
83
extras,
84
}
85
}
86
87
/// Subasset label for this mesh within the gLTF parent asset.
88
pub fn asset_label(&self) -> GltfAssetLabel {
89
GltfAssetLabel::Mesh(self.index)
90
}
91
}
92
93
/// A glTF node with all of its child nodes, its [`GltfMesh`],
94
/// [`Transform`](bevy_transform::prelude::Transform), its optional [`GltfSkin`]
95
/// and an optional [`GltfExtras`].
96
///
97
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-node).
98
#[derive(Asset, Debug, Clone, TypePath)]
99
pub struct GltfNode {
100
/// Index of the node inside the scene
101
pub index: usize,
102
/// Computed name for a node - either a user defined node name from gLTF or a generated name from index
103
pub name: String,
104
/// Direct children of the node.
105
pub children: Vec<Handle<GltfNode>>,
106
/// Mesh of the node.
107
pub mesh: Option<Handle<GltfMesh>>,
108
/// Skin of the node.
109
pub skin: Option<Handle<GltfSkin>>,
110
/// Local transform.
111
pub transform: bevy_transform::prelude::Transform,
112
/// Is this node used as an animation root
113
#[cfg(feature = "bevy_animation")]
114
pub is_animation_root: bool,
115
/// Additional data.
116
pub extras: Option<GltfExtras>,
117
}
118
119
impl GltfNode {
120
/// Create a node extracting name and index from glTF def
121
pub fn new(
122
node: &gltf::Node,
123
children: Vec<Handle<GltfNode>>,
124
mesh: Option<Handle<GltfMesh>>,
125
transform: bevy_transform::prelude::Transform,
126
skin: Option<Handle<GltfSkin>>,
127
extras: Option<GltfExtras>,
128
) -> Self {
129
Self {
130
index: node.index(),
131
name: if let Some(name) = node.name() {
132
name.to_string()
133
} else {
134
format!("GltfNode{}", node.index())
135
},
136
children,
137
mesh,
138
transform,
139
skin,
140
#[cfg(feature = "bevy_animation")]
141
is_animation_root: false,
142
extras,
143
}
144
}
145
146
/// Create a node with animation root mark
147
#[cfg(feature = "bevy_animation")]
148
pub fn with_animation_root(self, is_animation_root: bool) -> Self {
149
Self {
150
is_animation_root,
151
..self
152
}
153
}
154
155
/// Subasset label for this node within the gLTF parent asset.
156
pub fn asset_label(&self) -> GltfAssetLabel {
157
GltfAssetLabel::Node(self.index)
158
}
159
}
160
161
/// Part of a [`GltfMesh`] that consists of a [`Mesh`], an optional [`StandardMaterial`] and [`GltfExtras`].
162
///
163
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-mesh-primitive).
164
#[derive(Asset, Debug, Clone, TypePath)]
165
pub struct GltfPrimitive {
166
/// Index of the primitive inside the mesh
167
pub index: usize,
168
/// Index of the parent [`GltfMesh`] of this primitive
169
pub parent_mesh_index: usize,
170
/// Computed name for a primitive - either a user defined primitive name from gLTF or a generated name from index
171
pub name: String,
172
/// Topology to be rendered.
173
pub mesh: Handle<Mesh>,
174
/// Material to apply to the `mesh`.
175
pub material: Option<Handle<StandardMaterial>>,
176
/// Additional data.
177
pub extras: Option<GltfExtras>,
178
/// Additional data of the `material`.
179
pub material_extras: Option<GltfExtras>,
180
}
181
182
impl GltfPrimitive {
183
/// Create a primitive extracting name and index from glTF def
184
pub fn new(
185
gltf_mesh: &gltf::Mesh,
186
gltf_primitive: &gltf::Primitive,
187
mesh: Handle<Mesh>,
188
material: Option<Handle<StandardMaterial>>,
189
extras: Option<GltfExtras>,
190
material_extras: Option<GltfExtras>,
191
) -> Self {
192
GltfPrimitive {
193
index: gltf_primitive.index(),
194
parent_mesh_index: gltf_mesh.index(),
195
name: {
196
let mesh_name = gltf_mesh.name().unwrap_or("Mesh");
197
if gltf_mesh.primitives().len() > 1 {
198
format!("{}.{}", mesh_name, gltf_primitive.index())
199
} else {
200
mesh_name.to_string()
201
}
202
},
203
mesh,
204
material,
205
extras,
206
material_extras,
207
}
208
}
209
210
/// Subasset label for this primitive within its parent [`GltfMesh`] within the gLTF parent asset.
211
pub fn asset_label(&self) -> GltfAssetLabel {
212
GltfAssetLabel::Primitive {
213
mesh: self.parent_mesh_index,
214
primitive: self.index,
215
}
216
}
217
}
218
219
/// A glTF skin with all of its joint nodes, [`SkinnedMeshInversiveBindposes`](bevy_mesh::skinning::SkinnedMeshInverseBindposes)
220
/// and an optional [`GltfExtras`].
221
///
222
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-skin).
223
#[derive(Asset, Debug, Clone, TypePath)]
224
pub struct GltfSkin {
225
/// Index of the skin inside the scene
226
pub index: usize,
227
/// Computed name for a skin - either a user defined skin name from gLTF or a generated name from index
228
pub name: String,
229
/// All the nodes that form this skin.
230
pub joints: Vec<Handle<GltfNode>>,
231
/// Inverse-bind matrices of this skin.
232
pub inverse_bind_matrices: Handle<SkinnedMeshInverseBindposes>,
233
/// Additional data.
234
pub extras: Option<GltfExtras>,
235
}
236
237
impl GltfSkin {
238
/// Create a skin extracting name and index from glTF def
239
pub fn new(
240
skin: &gltf::Skin,
241
joints: Vec<Handle<GltfNode>>,
242
inverse_bind_matrices: Handle<SkinnedMeshInverseBindposes>,
243
extras: Option<GltfExtras>,
244
) -> Self {
245
Self {
246
index: skin.index(),
247
name: if let Some(name) = skin.name() {
248
name.to_string()
249
} else {
250
format!("GltfSkin{}", skin.index())
251
},
252
joints,
253
inverse_bind_matrices,
254
extras,
255
}
256
}
257
258
/// Subasset label for this skin within the gLTF parent asset.
259
pub fn asset_label(&self) -> GltfAssetLabel {
260
GltfAssetLabel::Skin(self.index)
261
}
262
}
263
264
/// Additional untyped data that can be present on most glTF types at the primitive level.
265
///
266
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-extras).
267
#[derive(Clone, Debug, Reflect, Default, Component)]
268
#[reflect(Component, Clone, Default, Debug)]
269
pub struct GltfExtras {
270
/// Content of the extra data.
271
pub value: String,
272
}
273
274
impl From<&serde_json::value::RawValue> for GltfExtras {
275
fn from(value: &serde_json::value::RawValue) -> Self {
276
GltfExtras {
277
value: value.get().to_string(),
278
}
279
}
280
}
281
282
/// Additional untyped data that can be present on most glTF types at the scene level.
283
///
284
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-extras).
285
#[derive(Clone, Debug, Reflect, Default, Component)]
286
#[reflect(Component, Clone, Default, Debug)]
287
pub struct GltfSceneExtras {
288
/// Content of the extra data.
289
pub value: String,
290
}
291
292
/// Additional untyped data that can be present on most glTF types at the mesh level.
293
///
294
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-extras).
295
#[derive(Clone, Debug, Reflect, Default, Component)]
296
#[reflect(Component, Clone, Default, Debug)]
297
pub struct GltfMeshExtras {
298
/// Content of the extra data.
299
pub value: String,
300
}
301
302
/// The mesh name of a glTF primitive.
303
///
304
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-mesh).
305
#[derive(Clone, Debug, Reflect, Default, Component)]
306
#[reflect(Component, Clone)]
307
pub struct GltfMeshName(pub String);
308
309
impl Deref for GltfMeshName {
310
type Target = str;
311
312
fn deref(&self) -> &Self::Target {
313
self.0.as_ref()
314
}
315
}
316
317
/// Additional untyped data that can be present on most glTF types at the material level.
318
///
319
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-extras).
320
#[derive(Clone, Debug, Reflect, Default, Component)]
321
#[reflect(Component, Clone, Default, Debug)]
322
pub struct GltfMaterialExtras {
323
/// Content of the extra data.
324
pub value: String,
325
}
326
327
/// The material name of a glTF primitive.
328
///
329
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-material).
330
#[derive(Clone, Debug, Reflect, Default, Component)]
331
#[reflect(Component, Clone)]
332
pub struct GltfMaterialName(pub String);
333
334
impl Deref for GltfMaterialName {
335
type Target = str;
336
337
fn deref(&self) -> &Self::Target {
338
self.0.as_ref()
339
}
340
}
341
342