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