Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/gltf/gltf_document.cpp
20778 views
1
/**************************************************************************/
2
/* gltf_document.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "gltf_document.h"
32
33
#include "extensions/gltf_document_extension_convert_importer_mesh.h"
34
#include "extensions/gltf_spec_gloss.h"
35
#include "gltf_state.h"
36
#include "gltf_template_convert.h"
37
#include "skin_tool.h"
38
39
#include "core/config/project_settings.h"
40
#include "core/crypto/crypto_core.h"
41
#include "core/io/config_file.h"
42
#include "core/io/dir_access.h"
43
#include "core/io/file_access.h"
44
#include "core/io/file_access_memory.h"
45
#include "core/io/json.h"
46
#include "core/io/stream_peer.h"
47
#include "core/object/object_id.h"
48
#include "core/version.h"
49
#include "scene/2d/node_2d.h"
50
#include "scene/3d/bone_attachment_3d.h"
51
#include "scene/3d/camera_3d.h"
52
#include "scene/3d/importer_mesh_instance_3d.h"
53
#include "scene/3d/light_3d.h"
54
#include "scene/3d/mesh_instance_3d.h"
55
#include "scene/3d/multimesh_instance_3d.h"
56
#include "scene/animation/animation_player.h"
57
#include "scene/resources/3d/skin.h"
58
#include "scene/resources/image_texture.h"
59
#include "scene/resources/portable_compressed_texture.h"
60
#include "scene/resources/surface_tool.h"
61
62
#ifdef TOOLS_ENABLED
63
#include "editor/file_system/editor_file_system.h"
64
#endif
65
66
#include "modules/modules_enabled.gen.h" // For csg, gridmap.
67
68
#ifdef MODULE_CSG_ENABLED
69
#include "modules/csg/csg_shape.h"
70
#endif
71
#ifdef MODULE_GRIDMAP_ENABLED
72
#include "modules/gridmap/grid_map.h"
73
#endif
74
75
// FIXME: Hardcoded to avoid editor dependency.
76
#define GLTF_IMPORT_GENERATE_TANGENT_ARRAYS 8
77
#define GLTF_IMPORT_USE_NAMED_SKIN_BINDS 16
78
#define GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS 32
79
#define GLTF_IMPORT_FORCE_DISABLE_MESH_COMPRESSION 64
80
81
#include <cstdio>
82
#include <cstdlib>
83
84
static void _attach_extras_to_meta(const Dictionary &p_extras, Ref<Resource> p_node) {
85
if (!p_extras.is_empty()) {
86
p_node->set_meta("extras", p_extras);
87
}
88
}
89
90
static void _attach_meta_to_extras(Ref<Resource> p_node, Dictionary &p_json) {
91
if (p_node->has_meta("extras")) {
92
Dictionary node_extras = p_node->get_meta("extras");
93
if (p_json.has("extras")) {
94
Dictionary extras = p_json["extras"];
95
extras.merge(node_extras);
96
} else {
97
p_json["extras"] = node_extras;
98
}
99
}
100
}
101
102
Error GLTFDocument::_serialize(Ref<GLTFState> p_state) {
103
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
104
ERR_CONTINUE(ext.is_null());
105
Error err = ext->export_preserialize(p_state);
106
ERR_CONTINUE(err != OK);
107
}
108
109
/* STEP CONVERT MESH INSTANCES */
110
_convert_mesh_instances(p_state);
111
112
/* STEP SERIALIZE CAMERAS */
113
Error err = _serialize_cameras(p_state);
114
if (err != OK) {
115
return Error::FAILED;
116
}
117
118
/* STEP 3 CREATE SKINS */
119
err = _serialize_skins(p_state);
120
if (err != OK) {
121
return Error::FAILED;
122
}
123
124
/* STEP SERIALIZE MESHES (we have enough info now) */
125
err = _serialize_meshes(p_state);
126
if (err != OK) {
127
return Error::FAILED;
128
}
129
130
/* STEP SERIALIZE TEXTURES */
131
err = _serialize_materials(p_state);
132
if (err != OK) {
133
return Error::FAILED;
134
}
135
136
/* STEP SERIALIZE TEXTURE SAMPLERS */
137
err = _serialize_texture_samplers(p_state);
138
if (err != OK) {
139
return Error::FAILED;
140
}
141
142
/* STEP SERIALIZE ANIMATIONS */
143
err = _serialize_animations(p_state);
144
if (err != OK) {
145
return Error::FAILED;
146
}
147
148
/* STEP SERIALIZE IMAGES */
149
err = _serialize_images(p_state);
150
if (err != OK) {
151
return Error::FAILED;
152
}
153
154
/* STEP SERIALIZE TEXTURES */
155
err = _serialize_textures(p_state);
156
if (err != OK) {
157
return Error::FAILED;
158
}
159
160
/* STEP SERIALIZE NODES */
161
err = _serialize_nodes(p_state);
162
if (err != OK) {
163
return Error::FAILED;
164
}
165
166
/* STEP SERIALIZE SCENE */
167
err = _serialize_scenes(p_state);
168
if (err != OK) {
169
return Error::FAILED;
170
}
171
172
/* STEP SERIALIZE LIGHTS */
173
err = _serialize_lights(p_state);
174
if (err != OK) {
175
return Error::FAILED;
176
}
177
178
/* STEP SERIALIZE EXTENSIONS */
179
err = _serialize_gltf_extensions(p_state);
180
if (err != OK) {
181
return Error::FAILED;
182
}
183
184
/* STEP SERIALIZE VERSION */
185
err = _serialize_asset_header(p_state);
186
if (err != OK) {
187
return Error::FAILED;
188
}
189
190
/* STEP SERIALIZE ACCESSORS */
191
err = _encode_accessors(p_state);
192
if (err != OK) {
193
return Error::FAILED;
194
}
195
196
/* STEP SERIALIZE BUFFER VIEWS */
197
err = _encode_buffer_views(p_state);
198
if (err != OK) {
199
return Error::FAILED;
200
}
201
202
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
203
ERR_CONTINUE(ext.is_null());
204
err = ext->export_post(p_state);
205
ERR_FAIL_COND_V(err != OK, err);
206
}
207
208
return OK;
209
}
210
211
Error GLTFDocument::_serialize_gltf_extensions(Ref<GLTFState> p_state) const {
212
Vector<String> extensions_used = p_state->extensions_used;
213
Vector<String> extensions_required = p_state->extensions_required;
214
if (!p_state->lights.is_empty()) {
215
extensions_used.push_back("KHR_lights_punctual");
216
}
217
if (p_state->use_khr_texture_transform) {
218
extensions_used.push_back("KHR_texture_transform");
219
extensions_required.push_back("KHR_texture_transform");
220
}
221
if (!extensions_used.is_empty()) {
222
extensions_used.sort();
223
p_state->json["extensionsUsed"] = extensions_used;
224
}
225
if (!extensions_required.is_empty()) {
226
extensions_required.sort();
227
p_state->json["extensionsRequired"] = extensions_required;
228
}
229
return OK;
230
}
231
232
Error GLTFDocument::_serialize_scenes(Ref<GLTFState> p_state) {
233
// Godot only supports one scene per glTF file.
234
Array scenes;
235
Dictionary scene_dict;
236
scenes.append(scene_dict);
237
p_state->json["scenes"] = scenes;
238
p_state->json["scene"] = 0;
239
// Add nodes to the scene dict.
240
if (!p_state->root_nodes.is_empty()) {
241
scene_dict["nodes"] = p_state->root_nodes;
242
}
243
if (!p_state->scene_name.is_empty()) {
244
scene_dict["name"] = p_state->scene_name;
245
}
246
return OK;
247
}
248
249
Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> p_state) {
250
Error err;
251
Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ, &err);
252
if (file.is_null()) {
253
return err;
254
}
255
256
Vector<uint8_t> array;
257
array.resize(file->get_length());
258
file->get_buffer(array.ptrw(), array.size());
259
String text = String::utf8((const char *)array.ptr(), array.size());
260
261
JSON json;
262
err = json.parse(text);
263
if (err != OK) {
264
_err_print_error("", p_path.utf8().get_data(), json.get_error_line(), json.get_error_message().utf8().get_data(), false, ERR_HANDLER_SCRIPT);
265
return err;
266
}
267
p_state->json = json.get_data();
268
269
return OK;
270
}
271
272
Error GLTFDocument::_parse_glb(Ref<FileAccess> p_file, Ref<GLTFState> p_state) {
273
ERR_FAIL_COND_V(p_file.is_null(), ERR_INVALID_PARAMETER);
274
ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER);
275
ERR_FAIL_COND_V(p_file->get_position() != 0, ERR_FILE_CANT_READ);
276
uint32_t magic = p_file->get_32();
277
ERR_FAIL_COND_V(magic != 0x46546C67, ERR_FILE_UNRECOGNIZED); //glTF
278
p_file->get_32(); // version
279
p_file->get_32(); // length
280
uint32_t chunk_length = p_file->get_32();
281
uint32_t chunk_type = p_file->get_32();
282
283
ERR_FAIL_COND_V(chunk_type != 0x4E4F534A, ERR_PARSE_ERROR); //JSON
284
Vector<uint8_t> json_data;
285
json_data.resize(chunk_length);
286
uint32_t len = p_file->get_buffer(json_data.ptrw(), chunk_length);
287
ERR_FAIL_COND_V(len != chunk_length, ERR_FILE_CORRUPT);
288
289
String text = String::utf8((const char *)json_data.ptr(), json_data.size());
290
291
JSON json;
292
Error err = json.parse(text);
293
ERR_FAIL_COND_V_MSG(err != OK, err, "glTF Binary: Error parsing .glb file's JSON data: " + json.get_error_message() + " at line: " + itos(json.get_error_line()));
294
295
p_state->json = json.get_data();
296
297
//data?
298
299
chunk_length = p_file->get_32();
300
chunk_type = p_file->get_32();
301
302
if (p_file->eof_reached()) {
303
return OK; //all good
304
}
305
306
ERR_FAIL_COND_V(chunk_type != 0x004E4942, ERR_PARSE_ERROR); //BIN
307
308
p_state->glb_data.resize(chunk_length);
309
len = p_file->get_buffer(p_state->glb_data.ptrw(), chunk_length);
310
ERR_FAIL_COND_V(len != chunk_length, ERR_FILE_CORRUPT);
311
312
return OK;
313
}
314
315
static Array _vec3_to_arr(const Vector3 &p_vec3) {
316
Array array;
317
array.resize(3);
318
array[0] = p_vec3.x;
319
array[1] = p_vec3.y;
320
array[2] = p_vec3.z;
321
return array;
322
}
323
324
static Vector3 _arr_to_vec3(const Array &p_array) {
325
ERR_FAIL_COND_V(p_array.size() != 3, Vector3());
326
return Vector3(p_array[0], p_array[1], p_array[2]);
327
}
328
329
static Array _quaternion_to_array(const Quaternion &p_quaternion) {
330
Array array;
331
array.resize(4);
332
array[0] = p_quaternion.x;
333
array[1] = p_quaternion.y;
334
array[2] = p_quaternion.z;
335
array[3] = p_quaternion.w;
336
return array;
337
}
338
339
static Quaternion _arr_to_quaternion(const Array &p_array) {
340
ERR_FAIL_COND_V(p_array.size() != 4, Quaternion());
341
return Quaternion(p_array[0], p_array[1], p_array[2], p_array[3]);
342
}
343
344
static Transform3D _arr_to_xform(const Array &p_array) {
345
ERR_FAIL_COND_V(p_array.size() != 16, Transform3D());
346
347
Transform3D xform;
348
xform.basis.set_column(Vector3::AXIS_X, Vector3(p_array[0], p_array[1], p_array[2]));
349
xform.basis.set_column(Vector3::AXIS_Y, Vector3(p_array[4], p_array[5], p_array[6]));
350
xform.basis.set_column(Vector3::AXIS_Z, Vector3(p_array[8], p_array[9], p_array[10]));
351
xform.set_origin(Vector3(p_array[12], p_array[13], p_array[14]));
352
353
return xform;
354
}
355
356
static Vector<real_t> _xform_to_array(const Transform3D p_transform) {
357
Vector<real_t> array;
358
array.resize(16);
359
Vector3 axis_x = p_transform.get_basis().get_column(Vector3::AXIS_X);
360
array.write[0] = axis_x.x;
361
array.write[1] = axis_x.y;
362
array.write[2] = axis_x.z;
363
array.write[3] = 0.0f;
364
Vector3 axis_y = p_transform.get_basis().get_column(Vector3::AXIS_Y);
365
array.write[4] = axis_y.x;
366
array.write[5] = axis_y.y;
367
array.write[6] = axis_y.z;
368
array.write[7] = 0.0f;
369
Vector3 axis_z = p_transform.get_basis().get_column(Vector3::AXIS_Z);
370
array.write[8] = axis_z.x;
371
array.write[9] = axis_z.y;
372
array.write[10] = axis_z.z;
373
array.write[11] = 0.0f;
374
Vector3 origin = p_transform.get_origin();
375
array.write[12] = origin.x;
376
array.write[13] = origin.y;
377
array.write[14] = origin.z;
378
array.write[15] = 1.0f;
379
return array;
380
}
381
382
Error GLTFDocument::_serialize_nodes(Ref<GLTFState> p_state) {
383
Array nodes;
384
for (int i = 0; i < p_state->nodes.size(); i++) {
385
Dictionary node;
386
Ref<GLTFNode> gltf_node = p_state->nodes[i];
387
Dictionary extensions;
388
node["extensions"] = extensions;
389
if (!gltf_node->get_name().is_empty()) {
390
node["name"] = gltf_node->get_name();
391
}
392
if (gltf_node->camera != -1) {
393
node["camera"] = gltf_node->camera;
394
}
395
if (gltf_node->light != -1) {
396
Dictionary lights_punctual;
397
extensions["KHR_lights_punctual"] = lights_punctual;
398
lights_punctual["light"] = gltf_node->light;
399
}
400
if (!gltf_node->visible) {
401
Dictionary khr_node_visibility;
402
extensions["KHR_node_visibility"] = khr_node_visibility;
403
khr_node_visibility["visible"] = gltf_node->visible;
404
if (!p_state->extensions_used.has("KHR_node_visibility")) {
405
p_state->extensions_used.push_back("KHR_node_visibility");
406
if (_visibility_mode == VISIBILITY_MODE_INCLUDE_REQUIRED) {
407
p_state->extensions_required.push_back("KHR_node_visibility");
408
}
409
}
410
}
411
if (gltf_node->mesh != -1) {
412
node["mesh"] = gltf_node->mesh;
413
}
414
if (gltf_node->skin != -1) {
415
node["skin"] = gltf_node->skin;
416
}
417
if (gltf_node->skeleton != -1 && gltf_node->skin < 0) {
418
}
419
if (gltf_node->transform.basis.is_orthogonal()) {
420
// An orthogonal transform is decomposable into TRS, so prefer that.
421
const Vector3 position = gltf_node->get_position();
422
if (!position.is_zero_approx()) {
423
node["translation"] = _vec3_to_arr(position);
424
}
425
const Quaternion rotation = gltf_node->get_rotation();
426
if (!rotation.is_equal_approx(Quaternion())) {
427
node["rotation"] = _quaternion_to_array(rotation);
428
}
429
const Vector3 scale = gltf_node->get_scale();
430
if (!scale.is_equal_approx(Vector3(1.0f, 1.0f, 1.0f))) {
431
node["scale"] = _vec3_to_arr(scale);
432
}
433
} else {
434
node["matrix"] = _xform_to_array(gltf_node->transform);
435
}
436
if (gltf_node->children.size()) {
437
Array children;
438
for (int j = 0; j < gltf_node->children.size(); j++) {
439
children.push_back(gltf_node->children[j]);
440
}
441
node["children"] = children;
442
}
443
444
Node *scene_node = nullptr;
445
if (i < (int)p_state->scene_nodes.size()) {
446
scene_node = p_state->scene_nodes[i];
447
}
448
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
449
ERR_CONTINUE(ext.is_null());
450
Error err = ext->export_node(p_state, gltf_node, node, scene_node);
451
ERR_CONTINUE(err != OK);
452
}
453
454
if (extensions.is_empty()) {
455
node.erase("extensions");
456
}
457
_attach_meta_to_extras(gltf_node, node);
458
nodes.push_back(node);
459
}
460
if (!nodes.is_empty()) {
461
p_state->json["nodes"] = nodes;
462
}
463
return OK;
464
}
465
466
String GLTFDocument::_gen_unique_name(Ref<GLTFState> p_state, const String &p_name) {
467
return _gen_unique_name_static(p_state->unique_names, p_name);
468
}
469
470
String GLTFDocument::_sanitize_animation_name(const String &p_name) {
471
String anim_name = p_name.validate_node_name();
472
return AnimationLibrary::validate_library_name(anim_name);
473
}
474
475
String GLTFDocument::_gen_unique_animation_name(Ref<GLTFState> p_state, const String &p_name) {
476
const String s_name = _sanitize_animation_name(p_name);
477
478
String u_name;
479
int index = 1;
480
while (true) {
481
u_name = s_name;
482
483
if (index > 1) {
484
u_name += itos(index);
485
}
486
if (!p_state->unique_animation_names.has(u_name)) {
487
break;
488
}
489
index++;
490
}
491
492
p_state->unique_animation_names.insert(u_name);
493
494
return u_name;
495
}
496
497
String GLTFDocument::_sanitize_bone_name(const String &p_name) {
498
String bone_name = p_name;
499
bone_name = bone_name.replace_chars(":/", '_');
500
return bone_name;
501
}
502
503
String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> p_state, const GLTFSkeletonIndex p_skel_i, const String &p_name) {
504
String s_name = _sanitize_bone_name(p_name);
505
if (s_name.is_empty()) {
506
s_name = "bone";
507
}
508
String u_name;
509
int index = 1;
510
while (true) {
511
u_name = s_name;
512
513
if (index > 1) {
514
u_name += "_" + itos(index);
515
}
516
if (!p_state->skeletons[p_skel_i]->unique_names.has(u_name)) {
517
break;
518
}
519
index++;
520
}
521
522
p_state->skeletons.write[p_skel_i]->unique_names.insert(u_name);
523
524
return u_name;
525
}
526
527
Error GLTFDocument::_parse_scenes(Ref<GLTFState> p_state) {
528
p_state->unique_names.insert("Skeleton3D"); // Reserve skeleton name.
529
if (!p_state->json.has("scenes")) {
530
return OK; // No scenes.
531
}
532
const Array &scenes = p_state->json["scenes"];
533
int loaded_scene = 0;
534
if (p_state->json.has("scene")) {
535
loaded_scene = p_state->json["scene"];
536
} else {
537
WARN_PRINT("The load-time scene is not defined in the glTF2 file. Picking the first scene.");
538
}
539
540
if (scenes.size()) {
541
ERR_FAIL_COND_V(loaded_scene >= scenes.size(), ERR_FILE_CORRUPT);
542
const Dictionary &scene_dict = scenes[loaded_scene];
543
if (scene_dict.has("nodes")) {
544
const Array &nodes = scene_dict["nodes"];
545
for (const Variant &node : nodes) {
546
p_state->root_nodes.push_back(node);
547
}
548
}
549
// Determine what to use for the scene name.
550
if (scene_dict.has("name") && !String(scene_dict["name"]).is_empty() && !((String)scene_dict["name"]).begins_with("Scene")) {
551
p_state->scene_name = scene_dict["name"];
552
} else if (p_state->scene_name.is_empty()) {
553
p_state->scene_name = p_state->filename;
554
}
555
if (_naming_version == 0) {
556
p_state->scene_name = _gen_unique_name(p_state, p_state->scene_name);
557
}
558
}
559
560
return OK;
561
}
562
563
Error GLTFDocument::_parse_nodes(Ref<GLTFState> p_state) {
564
if (!p_state->json.has("nodes")) {
565
return OK; // No nodes to parse.
566
}
567
const Array &nodes = p_state->json["nodes"];
568
for (int i = 0; i < nodes.size(); i++) {
569
Ref<GLTFNode> node;
570
node.instantiate();
571
const Dictionary &n = nodes[i];
572
573
if (n.has("name")) {
574
node->set_original_name(n["name"]);
575
node->set_name(n["name"]);
576
}
577
if (n.has("camera")) {
578
node->camera = n["camera"];
579
}
580
if (n.has("mesh")) {
581
node->mesh = n["mesh"];
582
}
583
if (n.has("skin")) {
584
node->skin = n["skin"];
585
}
586
if (n.has("matrix")) {
587
node->transform = _arr_to_xform(n["matrix"]);
588
} else {
589
if (n.has("translation")) {
590
node->set_position(_arr_to_vec3(n["translation"]));
591
}
592
if (n.has("rotation")) {
593
node->set_rotation(_arr_to_quaternion(n["rotation"]));
594
}
595
if (n.has("scale")) {
596
node->set_scale(_arr_to_vec3(n["scale"]));
597
}
598
}
599
node->set_additional_data("GODOT_rest_transform", node->transform);
600
601
if (n.has("extensions")) {
602
Dictionary extensions = n["extensions"];
603
if (extensions.has("KHR_lights_punctual")) {
604
Dictionary lights_punctual = extensions["KHR_lights_punctual"];
605
if (lights_punctual.has("light")) {
606
GLTFLightIndex light = lights_punctual["light"];
607
node->light = light;
608
}
609
}
610
if (extensions.has("KHR_node_visibility")) {
611
Dictionary khr_node_visibility = extensions["KHR_node_visibility"];
612
if (khr_node_visibility.has("visible")) {
613
node->visible = khr_node_visibility["visible"];
614
}
615
}
616
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
617
ERR_CONTINUE(ext.is_null());
618
Error err = ext->parse_node_extensions(p_state, node, extensions);
619
ERR_CONTINUE_MSG(err != OK, "glTF: Encountered error " + itos(err) + " when parsing node extensions for node " + node->get_name() + " in file " + p_state->filename + ". Continuing.");
620
}
621
}
622
623
if (n.has("extras")) {
624
_attach_extras_to_meta(n["extras"], node);
625
}
626
627
if (n.has("children")) {
628
const Array &children = n["children"];
629
for (int j = 0; j < children.size(); j++) {
630
node->children.push_back(children[j]);
631
}
632
}
633
634
p_state->nodes.push_back(node);
635
}
636
637
// build the hierarchy
638
for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); node_i++) {
639
for (int j = 0; j < p_state->nodes[node_i]->children.size(); j++) {
640
GLTFNodeIndex child_i = p_state->nodes[node_i]->children[j];
641
642
ERR_FAIL_INDEX_V(child_i, p_state->nodes.size(), ERR_FILE_CORRUPT);
643
ERR_CONTINUE(p_state->nodes[child_i]->parent != -1); //node already has a parent, wtf.
644
645
p_state->nodes.write[child_i]->parent = node_i;
646
}
647
}
648
649
_compute_node_heights(p_state);
650
651
return OK;
652
}
653
654
void GLTFDocument::_compute_node_heights(Ref<GLTFState> p_state) {
655
if (_naming_version < 2) {
656
p_state->root_nodes.clear();
657
}
658
for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); ++node_i) {
659
Ref<GLTFNode> node = p_state->nodes[node_i];
660
node->height = 0;
661
662
GLTFNodeIndex current_i = node_i;
663
while (current_i >= 0) {
664
const GLTFNodeIndex parent_i = p_state->nodes[current_i]->parent;
665
if (parent_i >= 0) {
666
++node->height;
667
}
668
current_i = parent_i;
669
}
670
671
if (_naming_version < 2) {
672
// This is incorrect, but required for compatibility with previous Godot versions.
673
if (node->height == 0) {
674
p_state->root_nodes.push_back(node_i);
675
}
676
}
677
}
678
}
679
680
static Vector<uint8_t> _parse_base64_uri(const String &p_uri) {
681
int start = p_uri.find_char(',');
682
ERR_FAIL_COND_V(start == -1, Vector<uint8_t>());
683
684
CharString substr = p_uri.substr(start + 1).ascii();
685
686
int strlen = substr.length();
687
688
Vector<uint8_t> buf;
689
buf.resize(strlen / 4 * 3 + 1 + 1);
690
691
size_t len = 0;
692
ERR_FAIL_COND_V(CryptoCore::b64_decode(buf.ptrw(), buf.size(), &len, (unsigned char *)substr.get_data(), strlen) != OK, Vector<uint8_t>());
693
694
buf.resize(len);
695
696
return buf;
697
}
698
699
Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> p_state, const String &p_path) {
700
print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size()));
701
702
if (p_state->buffers.is_empty()) {
703
return OK;
704
}
705
Array buffers;
706
if (!p_state->buffers.is_empty()) {
707
Vector<uint8_t> buffer_data = p_state->buffers[0];
708
Dictionary gltf_buffer;
709
710
gltf_buffer["byteLength"] = buffer_data.size();
711
buffers.push_back(gltf_buffer);
712
}
713
714
for (GLTFBufferIndex i = 1; i < p_state->buffers.size(); i++) {
715
Vector<uint8_t> buffer_data = p_state->buffers[i];
716
Dictionary gltf_buffer;
717
String filename = p_path.get_basename().get_file() + itos(i) + ".bin";
718
String path = p_path.get_base_dir() + "/" + filename;
719
Error err;
720
Ref<FileAccess> file = FileAccess::open(path, FileAccess::WRITE, &err);
721
if (file.is_null()) {
722
return err;
723
}
724
if (buffer_data.is_empty()) {
725
return OK;
726
}
727
file->create(FileAccess::ACCESS_RESOURCES);
728
file->store_buffer(buffer_data.ptr(), buffer_data.size());
729
gltf_buffer["uri"] = filename;
730
gltf_buffer["byteLength"] = buffer_data.size();
731
buffers.push_back(gltf_buffer);
732
}
733
p_state->json["buffers"] = buffers;
734
735
return OK;
736
}
737
738
Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> p_state, const String &p_path) {
739
print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size()));
740
741
if (p_state->buffers.is_empty()) {
742
return OK;
743
}
744
Array buffers;
745
746
for (GLTFBufferIndex i = 0; i < p_state->buffers.size(); i++) {
747
Vector<uint8_t> buffer_data = p_state->buffers[i];
748
Dictionary gltf_buffer;
749
String filename = p_path.get_basename().get_file() + itos(i) + ".bin";
750
String path = p_path.get_base_dir() + "/" + filename;
751
Error err;
752
Ref<FileAccess> file = FileAccess::open(path, FileAccess::WRITE, &err);
753
if (file.is_null()) {
754
return err;
755
}
756
if (buffer_data.is_empty()) {
757
return OK;
758
}
759
file->create(FileAccess::ACCESS_RESOURCES);
760
file->store_buffer(buffer_data.ptr(), buffer_data.size());
761
gltf_buffer["uri"] = filename;
762
gltf_buffer["byteLength"] = buffer_data.size();
763
buffers.push_back(gltf_buffer);
764
}
765
p_state->json["buffers"] = buffers;
766
767
return OK;
768
}
769
770
Error GLTFDocument::_parse_buffers(Ref<GLTFState> p_state, const String &p_base_path) {
771
if (!p_state->json.has("buffers")) {
772
return OK;
773
}
774
775
const Array &buffers = p_state->json["buffers"];
776
for (GLTFBufferIndex i = 0; i < buffers.size(); i++) {
777
const Dictionary &buffer = buffers[i];
778
Vector<uint8_t> buffer_data;
779
if (buffer.has("uri")) {
780
String uri = buffer["uri"];
781
782
if (uri.begins_with("data:")) { // Embedded data using base64.
783
// Validate data MIME types and throw an error if it's one we don't know/support.
784
if (!uri.begins_with("data:application/octet-stream;base64") &&
785
!uri.begins_with("data:application/gltf-buffer;base64")) {
786
ERR_PRINT("glTF: Got buffer with an unknown URI data type: " + uri);
787
}
788
buffer_data = _parse_base64_uri(uri);
789
} else { // Relative path to an external image file.
790
ERR_FAIL_COND_V(p_base_path.is_empty(), ERR_INVALID_PARAMETER);
791
uri = uri.uri_file_decode();
792
uri = p_base_path.path_join(uri).replace_char('\\', '/'); // Fix for Windows.
793
ERR_FAIL_COND_V_MSG(!FileAccess::exists(uri), ERR_FILE_NOT_FOUND, "glTF: Binary file not found: " + uri);
794
buffer_data = FileAccess::get_file_as_bytes(uri);
795
ERR_FAIL_COND_V_MSG(buffer_data.is_empty(), ERR_PARSE_ERROR, "glTF: Couldn't load binary file as an array: " + uri);
796
}
797
798
ERR_FAIL_COND_V(!buffer.has("byteLength"), ERR_PARSE_ERROR);
799
int64_t byteLength = buffer["byteLength"];
800
ERR_FAIL_COND_V(byteLength < buffer_data.size(), ERR_PARSE_ERROR);
801
} else if (i == 0 && p_state->glb_data.size()) {
802
buffer_data = p_state->glb_data;
803
} else {
804
ERR_PRINT("glTF: Buffer " + itos(i) + " has no data and cannot be loaded.");
805
}
806
p_state->buffers.push_back(buffer_data);
807
}
808
809
print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size()));
810
811
return OK;
812
}
813
814
Error GLTFDocument::_encode_buffer_views(Ref<GLTFState> p_state) {
815
Array buffers;
816
for (GLTFBufferViewIndex i = 0; i < p_state->buffer_views.size(); i++) {
817
const Ref<GLTFBufferView> buffer_view = p_state->buffer_views[i];
818
buffers.push_back(buffer_view->to_dictionary());
819
}
820
print_verbose("glTF: Total buffer views: " + itos(p_state->buffer_views.size()));
821
if (!buffers.size()) {
822
return OK;
823
}
824
p_state->json["bufferViews"] = buffers;
825
return OK;
826
}
827
828
Error GLTFDocument::_parse_buffer_views(Ref<GLTFState> p_state) {
829
if (!p_state->json.has("bufferViews")) {
830
return OK;
831
}
832
const Array &buffers = p_state->json["bufferViews"];
833
for (GLTFBufferViewIndex i = 0; i < buffers.size(); i++) {
834
const Dictionary &dict = buffers[i];
835
// Both "buffer" and "byteLength" are required by the spec.
836
ERR_FAIL_COND_V(!dict.has("buffer"), ERR_PARSE_ERROR);
837
ERR_FAIL_COND_V(!dict.has("byteLength"), ERR_PARSE_ERROR);
838
Ref<GLTFBufferView> buffer_view = GLTFBufferView::from_dictionary(dict);
839
p_state->buffer_views.push_back(buffer_view);
840
}
841
842
print_verbose("glTF: Total buffer views: " + itos(p_state->buffer_views.size()));
843
844
return OK;
845
}
846
847
Error GLTFDocument::_encode_accessors(Ref<GLTFState> p_state) {
848
Array accessors;
849
for (GLTFAccessorIndex i = 0; i < p_state->accessors.size(); i++) {
850
const Ref<GLTFAccessor> accessor = p_state->accessors[i];
851
accessors.push_back(accessor->to_dictionary());
852
}
853
854
if (!accessors.size()) {
855
return OK;
856
}
857
p_state->json["accessors"] = accessors;
858
ERR_FAIL_COND_V(!p_state->json.has("accessors"), ERR_FILE_CORRUPT);
859
print_verbose("glTF: Total accessors: " + itos(p_state->accessors.size()));
860
861
return OK;
862
}
863
864
Error GLTFDocument::_parse_accessors(Ref<GLTFState> p_state) {
865
if (!p_state->json.has("accessors")) {
866
return OK;
867
}
868
const Array &accessors = p_state->json["accessors"];
869
for (GLTFAccessorIndex i = 0; i < accessors.size(); i++) {
870
const Dictionary &dict = accessors[i];
871
// All of these fields are required by the spec.
872
ERR_FAIL_COND_V(!dict.has("componentType"), ERR_PARSE_ERROR);
873
ERR_FAIL_COND_V(!dict.has("count"), ERR_PARSE_ERROR);
874
ERR_FAIL_COND_V(!dict.has("type"), ERR_PARSE_ERROR);
875
Ref<GLTFAccessor> accessor = GLTFAccessor::from_dictionary(dict);
876
p_state->accessors.push_back(accessor);
877
}
878
879
print_verbose("glTF: Total accessors: " + itos(p_state->accessors.size()));
880
881
return OK;
882
}
883
884
template <typename T>
885
T GLTFDocument::_decode_unpack_indexed_data(const T &p_source, const PackedInt32Array &p_indices) {
886
// Handle unpacking indexed data as if it was a regular array.
887
// This isn't a feature of accessors, rather a feature of places using accessors like
888
// indexed meshes, but GLTFDocument needs it in several places when reading accessors.
889
T ret;
890
const int64_t last_index = p_indices[p_indices.size() - 1];
891
ERR_FAIL_COND_V(last_index >= p_source.size(), ret);
892
ret.resize(p_indices.size());
893
for (int64_t i = 0; i < p_indices.size(); i++) {
894
const int64_t source_index = p_indices[i];
895
ret.set(i, p_source[source_index]);
896
}
897
return ret;
898
}
899
900
PackedFloat32Array GLTFDocument::_decode_accessor_as_float32s(const Ref<GLTFState> p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids) {
901
ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), PackedFloat32Array());
902
Ref<GLTFAccessor> accessor = p_gltf_state->accessors[p_accessor_index];
903
PackedFloat32Array numbers = accessor->decode_as_float32s(p_gltf_state);
904
if (p_packed_vertex_ids.is_empty()) {
905
return numbers;
906
}
907
return _decode_unpack_indexed_data<PackedFloat32Array>(numbers, p_packed_vertex_ids);
908
}
909
910
PackedFloat64Array GLTFDocument::_decode_accessor_as_float64s(const Ref<GLTFState> p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids) {
911
ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), PackedFloat64Array());
912
Ref<GLTFAccessor> accessor = p_gltf_state->accessors[p_accessor_index];
913
PackedFloat64Array numbers = accessor->decode_as_float64s(p_gltf_state);
914
if (p_packed_vertex_ids.is_empty()) {
915
return numbers;
916
}
917
return _decode_unpack_indexed_data<PackedFloat64Array>(numbers, p_packed_vertex_ids);
918
}
919
920
PackedInt32Array GLTFDocument::_decode_accessor_as_int32s(const Ref<GLTFState> p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids) {
921
ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), PackedInt32Array());
922
Ref<GLTFAccessor> accessor = p_gltf_state->accessors[p_accessor_index];
923
PackedInt32Array numbers = accessor->decode_as_int32s(p_gltf_state);
924
if (p_packed_vertex_ids.is_empty()) {
925
return numbers;
926
}
927
return _decode_unpack_indexed_data<PackedInt32Array>(numbers, p_packed_vertex_ids);
928
}
929
930
PackedVector2Array GLTFDocument::_decode_accessor_as_vec2(const Ref<GLTFState> p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids) {
931
ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), PackedVector2Array());
932
Ref<GLTFAccessor> accessor = p_gltf_state->accessors[p_accessor_index];
933
PackedVector2Array vectors = accessor->decode_as_vector2s(p_gltf_state);
934
if (p_packed_vertex_ids.is_empty()) {
935
return vectors;
936
}
937
return _decode_unpack_indexed_data<PackedVector2Array>(vectors, p_packed_vertex_ids);
938
}
939
940
PackedVector3Array GLTFDocument::_decode_accessor_as_vec3(const Ref<GLTFState> p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids) {
941
ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), PackedVector3Array());
942
Ref<GLTFAccessor> accessor = p_gltf_state->accessors[p_accessor_index];
943
PackedVector3Array vectors = accessor->decode_as_vector3s(p_gltf_state);
944
if (p_packed_vertex_ids.is_empty()) {
945
return vectors;
946
}
947
return _decode_unpack_indexed_data<PackedVector3Array>(vectors, p_packed_vertex_ids);
948
}
949
950
PackedColorArray GLTFDocument::_decode_accessor_as_color(const Ref<GLTFState> p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids) {
951
ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), PackedColorArray());
952
Ref<GLTFAccessor> accessor = p_gltf_state->accessors[p_accessor_index];
953
PackedColorArray colors = accessor->decode_as_colors(p_gltf_state);
954
if (p_packed_vertex_ids.is_empty()) {
955
return colors;
956
}
957
return _decode_unpack_indexed_data<PackedColorArray>(colors, p_packed_vertex_ids);
958
}
959
960
Vector<Quaternion> GLTFDocument::_decode_accessor_as_quaternion(const Ref<GLTFState> p_gltf_state, GLTFAccessorIndex p_accessor_index) {
961
ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), Vector<Quaternion>());
962
Ref<GLTFAccessor> accessor = p_gltf_state->accessors[p_accessor_index];
963
Vector<Quaternion> quaternions = accessor->decode_as_quaternions(p_gltf_state);
964
return quaternions;
965
}
966
967
Array GLTFDocument::_decode_accessor_as_variants(const Ref<GLTFState> p_gltf_state, GLTFAccessorIndex p_accessor_index, Variant::Type p_variant_type) {
968
ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), Array());
969
Ref<GLTFAccessor> accessor = p_gltf_state->accessors[p_accessor_index];
970
Array variants = accessor->decode_as_variants(p_gltf_state, p_variant_type);
971
return variants;
972
}
973
974
Error GLTFDocument::_serialize_meshes(Ref<GLTFState> p_state) {
975
Array meshes;
976
for (GLTFMeshIndex gltf_mesh_i = 0; gltf_mesh_i < p_state->meshes.size(); gltf_mesh_i++) {
977
print_verbose("glTF: Serializing mesh: " + itos(gltf_mesh_i));
978
Ref<GLTFMesh> &gltf_mesh = p_state->meshes.write[gltf_mesh_i];
979
Ref<ImporterMesh> import_mesh = gltf_mesh->get_mesh();
980
if (import_mesh.is_null()) {
981
continue;
982
}
983
const Array &instance_materials = gltf_mesh->get_instance_materials();
984
Array primitives;
985
Dictionary mesh_dict;
986
Array target_names;
987
Array weights;
988
for (int morph_i = 0; morph_i < import_mesh->get_blend_shape_count(); morph_i++) {
989
target_names.push_back(import_mesh->get_blend_shape_name(morph_i));
990
}
991
for (int surface_i = 0; surface_i < import_mesh->get_surface_count(); surface_i++) {
992
Array targets;
993
Dictionary primitive;
994
Mesh::PrimitiveType primitive_type = import_mesh->get_surface_primitive_type(surface_i);
995
switch (primitive_type) {
996
case Mesh::PRIMITIVE_POINTS: {
997
primitive["mode"] = 0;
998
break;
999
}
1000
case Mesh::PRIMITIVE_LINES: {
1001
primitive["mode"] = 1;
1002
break;
1003
}
1004
// case Mesh::PRIMITIVE_LINE_LOOP: {
1005
// primitive["mode"] = 2;
1006
// break;
1007
// }
1008
case Mesh::PRIMITIVE_LINE_STRIP: {
1009
primitive["mode"] = 3;
1010
break;
1011
}
1012
case Mesh::PRIMITIVE_TRIANGLES: {
1013
primitive["mode"] = 4;
1014
break;
1015
}
1016
case Mesh::PRIMITIVE_TRIANGLE_STRIP: {
1017
primitive["mode"] = 5;
1018
break;
1019
}
1020
// case Mesh::PRIMITIVE_TRIANGLE_FAN: {
1021
// primitive["mode"] = 6;
1022
// break;
1023
// }
1024
default: {
1025
ERR_FAIL_V(FAILED);
1026
}
1027
}
1028
1029
Array array = import_mesh->get_surface_arrays(surface_i);
1030
uint64_t format = import_mesh->get_surface_format(surface_i);
1031
int32_t vertex_num = 0;
1032
Dictionary attributes;
1033
{
1034
Vector<Vector3> a = array[Mesh::ARRAY_VERTEX];
1035
ERR_FAIL_COND_V(a.is_empty(), ERR_INVALID_DATA);
1036
attributes["POSITION"] = GLTFAccessor::encode_new_accessor_from_vector3s(p_state, a, GLTFBufferView::TARGET_ARRAY_BUFFER);
1037
vertex_num = a.size();
1038
}
1039
{
1040
Vector<real_t> a = array[Mesh::ARRAY_TANGENT];
1041
if (a.size()) {
1042
const int64_t ret_size = a.size() / 4;
1043
Vector<Color> attribs;
1044
attribs.resize(ret_size);
1045
for (int64_t i = 0; i < ret_size; i++) {
1046
Color out;
1047
out.r = a[(i * 4) + 0];
1048
out.g = a[(i * 4) + 1];
1049
out.b = a[(i * 4) + 2];
1050
out.a = a[(i * 4) + 3];
1051
attribs.write[i] = out;
1052
}
1053
attributes["TANGENT"] = GLTFAccessor::encode_new_accessor_from_colors(p_state, attribs, GLTFBufferView::TARGET_ARRAY_BUFFER);
1054
}
1055
}
1056
{
1057
Vector<Vector3> a = array[Mesh::ARRAY_NORMAL];
1058
if (a.size()) {
1059
const int64_t ret_size = a.size();
1060
Vector<Vector3> attribs;
1061
attribs.resize(ret_size);
1062
for (int64_t i = 0; i < ret_size; i++) {
1063
attribs.write[i] = Vector3(a[i]).normalized();
1064
}
1065
attributes["NORMAL"] = GLTFAccessor::encode_new_accessor_from_vector3s(p_state, attribs, GLTFBufferView::TARGET_ARRAY_BUFFER);
1066
}
1067
}
1068
{
1069
Vector<Vector2> a = array[Mesh::ARRAY_TEX_UV];
1070
if (a.size()) {
1071
attributes["TEXCOORD_0"] = GLTFAccessor::encode_new_accessor_from_vector2s(p_state, a, GLTFBufferView::TARGET_ARRAY_BUFFER);
1072
}
1073
}
1074
{
1075
Vector<Vector2> a = array[Mesh::ARRAY_TEX_UV2];
1076
if (a.size()) {
1077
attributes["TEXCOORD_1"] = GLTFAccessor::encode_new_accessor_from_vector2s(p_state, a, GLTFBufferView::TARGET_ARRAY_BUFFER);
1078
}
1079
}
1080
for (int custom_i = 0; custom_i < 3; custom_i++) {
1081
Vector<float> a = array[Mesh::ARRAY_CUSTOM0 + custom_i];
1082
if (a.size()) {
1083
int num_channels = 4;
1084
int custom_shift = Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT + custom_i * Mesh::ARRAY_FORMAT_CUSTOM_BITS;
1085
switch ((format >> custom_shift) & Mesh::ARRAY_FORMAT_CUSTOM_MASK) {
1086
case Mesh::ARRAY_CUSTOM_R_FLOAT:
1087
num_channels = 1;
1088
break;
1089
case Mesh::ARRAY_CUSTOM_RG_FLOAT:
1090
num_channels = 2;
1091
break;
1092
case Mesh::ARRAY_CUSTOM_RGB_FLOAT:
1093
num_channels = 3;
1094
break;
1095
case Mesh::ARRAY_CUSTOM_RGBA_FLOAT:
1096
num_channels = 4;
1097
break;
1098
}
1099
int texcoord_i = 2 + 2 * custom_i;
1100
String gltf_texcoord_key;
1101
for (int prev_texcoord_i = 0; prev_texcoord_i < texcoord_i; prev_texcoord_i++) {
1102
gltf_texcoord_key = vformat("TEXCOORD_%d", prev_texcoord_i);
1103
if (!attributes.has(gltf_texcoord_key)) {
1104
Vector<Vector2> empty;
1105
empty.resize(vertex_num);
1106
attributes[gltf_texcoord_key] = GLTFAccessor::encode_new_accessor_from_vector2s(p_state, empty, GLTFBufferView::TARGET_ARRAY_BUFFER);
1107
}
1108
}
1109
1110
LocalVector<Vector2> first_channel;
1111
first_channel.resize(vertex_num);
1112
LocalVector<Vector2> second_channel;
1113
second_channel.resize(vertex_num);
1114
for (int32_t vert_i = 0; vert_i < vertex_num; vert_i++) {
1115
float u = a[vert_i * num_channels + 0];
1116
float v = (num_channels == 1 ? 0.0f : a[vert_i * num_channels + 1]);
1117
first_channel[vert_i] = Vector2(u, v);
1118
u = 0;
1119
v = 0;
1120
if (num_channels >= 3) {
1121
u = a[vert_i * num_channels + 2];
1122
v = (num_channels == 3 ? 0.0f : a[vert_i * num_channels + 3]);
1123
second_channel[vert_i] = Vector2(u, v);
1124
}
1125
}
1126
gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i);
1127
attributes[gltf_texcoord_key] = GLTFAccessor::encode_new_accessor_from_vector2s(p_state, PackedVector2Array(first_channel), GLTFBufferView::TARGET_ARRAY_BUFFER);
1128
gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1);
1129
attributes[gltf_texcoord_key] = GLTFAccessor::encode_new_accessor_from_vector2s(p_state, PackedVector2Array(second_channel), GLTFBufferView::TARGET_ARRAY_BUFFER);
1130
}
1131
}
1132
{
1133
Vector<Color> a = array[Mesh::ARRAY_COLOR];
1134
if (a.size()) {
1135
attributes["COLOR_0"] = GLTFAccessor::encode_new_accessor_from_colors(p_state, a, GLTFBufferView::TARGET_ARRAY_BUFFER);
1136
}
1137
}
1138
HashMap<int, int> joint_i_to_bone_i;
1139
for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); node_i++) {
1140
GLTFSkinIndex skin_i = -1;
1141
if (p_state->nodes[node_i]->mesh == gltf_mesh_i) {
1142
skin_i = p_state->nodes[node_i]->skin;
1143
}
1144
if (skin_i != -1) {
1145
joint_i_to_bone_i = p_state->skins[skin_i]->joint_i_to_bone_i;
1146
break;
1147
}
1148
}
1149
{
1150
const Array &a = array[Mesh::ARRAY_BONES];
1151
const Vector<Vector3> &vertex_array = array[Mesh::ARRAY_VERTEX];
1152
if ((a.size() / JOINT_GROUP_SIZE) == vertex_array.size()) {
1153
const int ret_size = a.size() / JOINT_GROUP_SIZE;
1154
Vector<Vector4i> attribs;
1155
attribs.resize(ret_size);
1156
{
1157
for (int array_i = 0; array_i < attribs.size(); array_i++) {
1158
int32_t joint_0 = a[(array_i * JOINT_GROUP_SIZE) + 0];
1159
int32_t joint_1 = a[(array_i * JOINT_GROUP_SIZE) + 1];
1160
int32_t joint_2 = a[(array_i * JOINT_GROUP_SIZE) + 2];
1161
int32_t joint_3 = a[(array_i * JOINT_GROUP_SIZE) + 3];
1162
attribs.write[array_i] = Vector4i(joint_0, joint_1, joint_2, joint_3);
1163
}
1164
}
1165
attributes["JOINTS_0"] = GLTFAccessor::encode_new_accessor_from_vector4is(p_state, attribs, GLTFBufferView::TARGET_ARRAY_BUFFER);
1166
} else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) {
1167
Vector<Vector4i> joints_0;
1168
joints_0.resize(vertex_num);
1169
Vector<Vector4i> joints_1;
1170
joints_1.resize(vertex_num);
1171
int32_t weights_8_count = JOINT_GROUP_SIZE * 2;
1172
for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) {
1173
Vector4i joint_0;
1174
joint_0.x = a[vertex_i * weights_8_count + 0];
1175
joint_0.y = a[vertex_i * weights_8_count + 1];
1176
joint_0.z = a[vertex_i * weights_8_count + 2];
1177
joint_0.w = a[vertex_i * weights_8_count + 3];
1178
joints_0.write[vertex_i] = joint_0;
1179
Vector4i joint_1;
1180
joint_1.x = a[vertex_i * weights_8_count + 4];
1181
joint_1.y = a[vertex_i * weights_8_count + 5];
1182
joint_1.z = a[vertex_i * weights_8_count + 6];
1183
joint_1.w = a[vertex_i * weights_8_count + 7];
1184
joints_1.write[vertex_i] = joint_1;
1185
}
1186
attributes["JOINTS_0"] = GLTFAccessor::encode_new_accessor_from_vector4is(p_state, joints_0, GLTFBufferView::TARGET_ARRAY_BUFFER);
1187
attributes["JOINTS_1"] = GLTFAccessor::encode_new_accessor_from_vector4is(p_state, joints_1, GLTFBufferView::TARGET_ARRAY_BUFFER);
1188
}
1189
}
1190
{
1191
const PackedRealArray &a = array[Mesh::ARRAY_WEIGHTS];
1192
const Vector<Vector3> &vertex_array = array[Mesh::ARRAY_VERTEX];
1193
if ((a.size() / JOINT_GROUP_SIZE) == vertex_array.size()) {
1194
int32_t vertex_count = vertex_array.size();
1195
Vector<Vector4> attribs;
1196
attribs.resize(vertex_count);
1197
for (int i = 0; i < vertex_count; i++) {
1198
Vector4 weight_0(a[(i * JOINT_GROUP_SIZE) + 0], a[(i * JOINT_GROUP_SIZE) + 1], a[(i * JOINT_GROUP_SIZE) + 2], a[(i * JOINT_GROUP_SIZE) + 3]);
1199
float divisor = weight_0.x + weight_0.y + weight_0.z + weight_0.w;
1200
if (Math::is_zero_approx(divisor) || !Math::is_finite(divisor)) {
1201
attribs.write[i] = Vector4(1, 0, 0, 0);
1202
} else {
1203
attribs.write[i] = weight_0 / divisor;
1204
}
1205
}
1206
attributes["WEIGHTS_0"] = GLTFAccessor::encode_new_accessor_from_vector4s(p_state, attribs, GLTFBufferView::TARGET_ARRAY_BUFFER);
1207
} else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) {
1208
Vector<Vector4> weights_0;
1209
weights_0.resize(vertex_num);
1210
Vector<Vector4> weights_1;
1211
weights_1.resize(vertex_num);
1212
int32_t weights_8_count = JOINT_GROUP_SIZE * 2;
1213
for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) {
1214
Vector4 weight_0;
1215
weight_0.x = a[vertex_i * weights_8_count + 0];
1216
weight_0.y = a[vertex_i * weights_8_count + 1];
1217
weight_0.z = a[vertex_i * weights_8_count + 2];
1218
weight_0.w = a[vertex_i * weights_8_count + 3];
1219
Vector4 weight_1;
1220
weight_1.x = a[vertex_i * weights_8_count + 4];
1221
weight_1.y = a[vertex_i * weights_8_count + 5];
1222
weight_1.z = a[vertex_i * weights_8_count + 6];
1223
weight_1.w = a[vertex_i * weights_8_count + 7];
1224
float divisor = weight_0.x + weight_0.y + weight_0.z + weight_0.w + weight_1.x + weight_1.y + weight_1.z + weight_1.w;
1225
if (Math::is_zero_approx(divisor) || !Math::is_finite(divisor)) {
1226
weights_0.write[vertex_i] = Vector4(1, 0, 0, 0);
1227
weights_1.write[vertex_i] = Vector4(0, 0, 0, 0);
1228
} else {
1229
weights_0.write[vertex_i] = weight_0 / divisor;
1230
weights_1.write[vertex_i] = weight_1 / divisor;
1231
}
1232
}
1233
attributes["WEIGHTS_0"] = GLTFAccessor::encode_new_accessor_from_vector4s(p_state, weights_0, GLTFBufferView::TARGET_ARRAY_BUFFER);
1234
attributes["WEIGHTS_1"] = GLTFAccessor::encode_new_accessor_from_vector4s(p_state, weights_1, GLTFBufferView::TARGET_ARRAY_BUFFER);
1235
}
1236
}
1237
{
1238
Vector<int32_t> mesh_indices = array[Mesh::ARRAY_INDEX];
1239
if (mesh_indices.size()) {
1240
if (primitive_type == Mesh::PRIMITIVE_TRIANGLES) {
1241
// Swap around indices, convert ccw to cw for front face.
1242
const int is = mesh_indices.size();
1243
for (int k = 0; k < is; k += 3) {
1244
SWAP(mesh_indices.write[k + 0], mesh_indices.write[k + 2]);
1245
}
1246
}
1247
primitive["indices"] = GLTFAccessor::encode_new_accessor_from_int32s(p_state, mesh_indices, GLTFBufferView::TARGET_ELEMENT_ARRAY_BUFFER);
1248
} else {
1249
if (primitive_type == Mesh::PRIMITIVE_TRIANGLES) {
1250
// Generate indices because they need to be swapped for CW/CCW.
1251
const Vector<Vector3> &vertices = array[Mesh::ARRAY_VERTEX];
1252
Ref<SurfaceTool> st;
1253
st.instantiate();
1254
st->create_from_triangle_arrays(array);
1255
st->index();
1256
Vector<int32_t> generated_indices = st->commit_to_arrays()[Mesh::ARRAY_INDEX];
1257
const int vs = vertices.size();
1258
generated_indices.resize(vs);
1259
{
1260
for (int k = 0; k < vs; k += 3) {
1261
generated_indices.write[k] = k;
1262
generated_indices.write[k + 1] = k + 2;
1263
generated_indices.write[k + 2] = k + 1;
1264
}
1265
}
1266
primitive["indices"] = GLTFAccessor::encode_new_accessor_from_int32s(p_state, generated_indices, GLTFBufferView::TARGET_ELEMENT_ARRAY_BUFFER);
1267
}
1268
}
1269
}
1270
1271
primitive["attributes"] = attributes;
1272
1273
// Blend shapes
1274
print_verbose("glTF: Mesh has targets");
1275
if (import_mesh->get_blend_shape_count()) {
1276
ArrayMesh::BlendShapeMode shape_mode = import_mesh->get_blend_shape_mode();
1277
const float normal_tangent_sparse_rounding = 0.001;
1278
for (int morph_i = 0; morph_i < import_mesh->get_blend_shape_count(); morph_i++) {
1279
Array array_morph = import_mesh->get_surface_blend_shape_arrays(surface_i, morph_i);
1280
Dictionary t;
1281
Vector<Vector3> varr = array_morph[Mesh::ARRAY_VERTEX];
1282
Vector<Vector3> src_varr = array[Mesh::ARRAY_VERTEX];
1283
Array mesh_arrays = import_mesh->get_surface_arrays(surface_i);
1284
if (varr.size() && varr.size() == src_varr.size()) {
1285
if (shape_mode == ArrayMesh::BlendShapeMode::BLEND_SHAPE_MODE_NORMALIZED) {
1286
const int max_idx = src_varr.size();
1287
for (int blend_i = 0; blend_i < max_idx; blend_i++) {
1288
varr.write[blend_i] = varr[blend_i] - src_varr[blend_i];
1289
}
1290
}
1291
const GLTFAccessorIndex position_accessor = attributes["POSITION"];
1292
if (position_accessor != -1) {
1293
const GLTFAccessorIndex new_accessor = GLTFAccessor::encode_new_sparse_accessor_from_vec3s(p_state, varr, Vector<Vector3>(), 1.0, GLTFBufferView::TARGET_ARRAY_BUFFER);
1294
if (new_accessor != -1) {
1295
t["POSITION"] = new_accessor;
1296
}
1297
}
1298
}
1299
1300
Vector<Vector3> narr = array_morph[Mesh::ARRAY_NORMAL];
1301
Vector<Vector3> src_narr = array[Mesh::ARRAY_NORMAL];
1302
if (narr.size() && narr.size() == src_narr.size()) {
1303
if (shape_mode == ArrayMesh::BlendShapeMode::BLEND_SHAPE_MODE_NORMALIZED) {
1304
const int max_idx = src_narr.size();
1305
for (int blend_i = 0; blend_i < max_idx; blend_i++) {
1306
narr.write[blend_i] = narr[blend_i] - src_narr[blend_i];
1307
}
1308
}
1309
const GLTFAccessorIndex normal_accessor = attributes["NORMAL"];
1310
if (normal_accessor != -1) {
1311
const GLTFAccessorIndex new_accessor = GLTFAccessor::encode_new_sparse_accessor_from_vec3s(p_state, narr, Vector<Vector3>(), normal_tangent_sparse_rounding, GLTFBufferView::TARGET_ARRAY_BUFFER);
1312
if (new_accessor != -1) {
1313
t["NORMAL"] = new_accessor;
1314
}
1315
}
1316
}
1317
Vector<real_t> tarr = array_morph[Mesh::ARRAY_TANGENT];
1318
Vector<real_t> src_tarr = array[Mesh::ARRAY_TANGENT];
1319
if (tarr.size() && tarr.size() == src_tarr.size()) {
1320
const int ret_size = tarr.size() / 4;
1321
Vector<Vector3> attribs;
1322
attribs.resize(ret_size);
1323
for (int i = 0; i < ret_size; i++) {
1324
Vector3 vec3;
1325
vec3.x = tarr[(i * 4) + 0] - src_tarr[(i * 4) + 0];
1326
vec3.y = tarr[(i * 4) + 1] - src_tarr[(i * 4) + 1];
1327
vec3.z = tarr[(i * 4) + 2] - src_tarr[(i * 4) + 2];
1328
attribs.write[i] = vec3;
1329
}
1330
const GLTFAccessorIndex tangent_accessor = attributes["TANGENT"];
1331
if (tangent_accessor != -1) {
1332
const GLTFAccessorIndex new_accessor = GLTFAccessor::encode_new_sparse_accessor_from_vec3s(p_state, attribs, Vector<Vector3>(), normal_tangent_sparse_rounding, GLTFBufferView::TARGET_ARRAY_BUFFER);
1333
if (new_accessor != -1) {
1334
t["TANGENT"] = new_accessor;
1335
}
1336
}
1337
}
1338
targets.push_back(t);
1339
}
1340
}
1341
1342
Variant v;
1343
if (surface_i < instance_materials.size()) {
1344
v = instance_materials.get(surface_i);
1345
}
1346
Ref<Material> mat = v;
1347
if (mat.is_null()) {
1348
mat = import_mesh->get_surface_material(surface_i);
1349
}
1350
if (mat.is_valid()) {
1351
HashMap<Ref<Material>, GLTFMaterialIndex>::Iterator material_cache_i = p_state->material_cache.find(mat);
1352
if (material_cache_i && material_cache_i->value != -1) {
1353
primitive["material"] = material_cache_i->value;
1354
} else {
1355
GLTFMaterialIndex mat_i = p_state->materials.size();
1356
p_state->materials.push_back(mat);
1357
primitive["material"] = mat_i;
1358
p_state->material_cache.insert(mat, mat_i);
1359
}
1360
}
1361
1362
if (targets.size()) {
1363
primitive["targets"] = targets;
1364
}
1365
1366
primitives.push_back(primitive);
1367
}
1368
1369
if (!target_names.is_empty()) {
1370
Dictionary e;
1371
e["targetNames"] = target_names;
1372
mesh_dict["extras"] = e;
1373
}
1374
_attach_meta_to_extras(import_mesh, mesh_dict);
1375
1376
weights.resize(target_names.size());
1377
for (int name_i = 0; name_i < target_names.size(); name_i++) {
1378
real_t weight = 0.0;
1379
if (name_i < gltf_mesh->get_blend_weights().size()) {
1380
weight = gltf_mesh->get_blend_weights()[name_i];
1381
}
1382
weights[name_i] = weight;
1383
}
1384
if (weights.size()) {
1385
mesh_dict["weights"] = weights;
1386
}
1387
1388
ERR_FAIL_COND_V(target_names.size() != weights.size(), FAILED);
1389
1390
mesh_dict["primitives"] = primitives;
1391
1392
if (!gltf_mesh->get_name().is_empty()) {
1393
mesh_dict["name"] = gltf_mesh->get_name();
1394
}
1395
1396
meshes.push_back(mesh_dict);
1397
}
1398
1399
if (!meshes.size()) {
1400
return OK;
1401
}
1402
p_state->json["meshes"] = meshes;
1403
print_verbose("glTF: Total meshes: " + itos(meshes.size()));
1404
1405
return OK;
1406
}
1407
1408
Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
1409
if (!p_state->json.has("meshes")) {
1410
return OK;
1411
}
1412
1413
Array meshes = p_state->json["meshes"];
1414
for (GLTFMeshIndex i = 0; i < meshes.size(); i++) {
1415
print_verbose("glTF: Parsing mesh: " + itos(i));
1416
Dictionary mesh_dict = meshes[i];
1417
1418
Ref<GLTFMesh> mesh;
1419
mesh.instantiate();
1420
bool has_vertex_color = false;
1421
1422
ERR_FAIL_COND_V(!mesh_dict.has("primitives"), ERR_PARSE_ERROR);
1423
1424
Array primitives = mesh_dict["primitives"];
1425
const Dictionary &extras = mesh_dict.has("extras") ? (Dictionary)mesh_dict["extras"] : Dictionary();
1426
_attach_extras_to_meta(extras, mesh);
1427
Ref<ImporterMesh> import_mesh;
1428
import_mesh.instantiate();
1429
String mesh_name = "mesh";
1430
if (mesh_dict.has("name") && !String(mesh_dict["name"]).is_empty()) {
1431
mesh_name = mesh_dict["name"];
1432
mesh->set_original_name(mesh_name);
1433
}
1434
import_mesh->set_name(_gen_unique_name(p_state, vformat("%s_%s", p_state->scene_name, mesh_name)));
1435
mesh->set_name(import_mesh->get_name());
1436
TypedArray<Material> instance_materials;
1437
1438
for (int j = 0; j < primitives.size(); j++) {
1439
uint64_t flags = RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES;
1440
Dictionary mesh_prim = primitives[j];
1441
1442
Array array;
1443
array.resize(Mesh::ARRAY_MAX);
1444
1445
ERR_FAIL_COND_V(!mesh_prim.has("attributes"), ERR_PARSE_ERROR);
1446
1447
Dictionary a = mesh_prim["attributes"];
1448
1449
Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES;
1450
if (mesh_prim.has("mode")) {
1451
const int mode = mesh_prim["mode"];
1452
ERR_FAIL_INDEX_V(mode, 7, ERR_FILE_CORRUPT);
1453
// Convert mesh.primitive.mode to Godot Mesh enum. See:
1454
// https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_mesh_primitive_mode
1455
static const Mesh::PrimitiveType primitives2[7] = {
1456
Mesh::PRIMITIVE_POINTS, // 0 POINTS
1457
Mesh::PRIMITIVE_LINES, // 1 LINES
1458
Mesh::PRIMITIVE_LINES, // 2 LINE_LOOP; loop not supported, should be converted
1459
Mesh::PRIMITIVE_LINE_STRIP, // 3 LINE_STRIP
1460
Mesh::PRIMITIVE_TRIANGLES, // 4 TRIANGLES
1461
Mesh::PRIMITIVE_TRIANGLE_STRIP, // 5 TRIANGLE_STRIP
1462
Mesh::PRIMITIVE_TRIANGLES, // 6 TRIANGLE_FAN fan not supported, should be converted
1463
// TODO: Line loop and triangle fan are not supported and need to be converted to lines and triangles.
1464
};
1465
1466
primitive = primitives2[mode];
1467
}
1468
1469
int32_t orig_vertex_num = 0;
1470
ERR_FAIL_COND_V(!a.has("POSITION"), ERR_PARSE_ERROR);
1471
if (a.has("POSITION")) {
1472
PackedVector3Array vertices = _decode_accessor_as_vec3(p_state, a["POSITION"]);
1473
array[Mesh::ARRAY_VERTEX] = vertices;
1474
orig_vertex_num = vertices.size();
1475
}
1476
int32_t vertex_num = orig_vertex_num;
1477
1478
Vector<int> indices;
1479
Vector<int> indices_mapping;
1480
Vector<int> indices_rev_mapping;
1481
Vector<int> indices_vec4_mapping;
1482
if (mesh_prim.has("indices")) {
1483
indices = _decode_accessor_as_int32s(p_state, mesh_prim["indices"]);
1484
const int index_count = indices.size();
1485
1486
if (primitive == Mesh::PRIMITIVE_TRIANGLES) {
1487
ERR_FAIL_COND_V_MSG(index_count % 3 != 0, ERR_PARSE_ERROR, "glTF import: Mesh " + itos(i) + " surface " + itos(j) + " in file " + p_state->filename + " is invalid. Indexed triangle meshes MUST have an index array with a size that is a multiple of 3, but got " + itos(index_count) + " indices.");
1488
// Swap around indices, convert ccw to cw for front face.
1489
1490
int *w = indices.ptrw();
1491
for (int k = 0; k < index_count; k += 3) {
1492
SWAP(w[k + 1], w[k + 2]);
1493
}
1494
}
1495
1496
const int *indices_w = indices.ptrw();
1497
Vector<bool> used_indices;
1498
used_indices.resize_initialized(orig_vertex_num);
1499
bool *used_w = used_indices.ptrw();
1500
for (int idx_i = 0; idx_i < index_count; idx_i++) {
1501
ERR_FAIL_INDEX_V(indices_w[idx_i], orig_vertex_num, ERR_INVALID_DATA);
1502
used_w[indices_w[idx_i]] = true;
1503
}
1504
indices_rev_mapping.resize_initialized(orig_vertex_num);
1505
int *rev_w = indices_rev_mapping.ptrw();
1506
vertex_num = 0;
1507
for (int vert_i = 0; vert_i < orig_vertex_num; vert_i++) {
1508
if (used_w[vert_i]) {
1509
rev_w[vert_i] = indices_mapping.size();
1510
indices_mapping.push_back(vert_i);
1511
indices_vec4_mapping.push_back(vert_i * 4 + 0);
1512
indices_vec4_mapping.push_back(vert_i * 4 + 1);
1513
indices_vec4_mapping.push_back(vert_i * 4 + 2);
1514
indices_vec4_mapping.push_back(vert_i * 4 + 3);
1515
vertex_num++;
1516
}
1517
}
1518
}
1519
ERR_FAIL_COND_V(vertex_num <= 0, ERR_INVALID_DECLARATION);
1520
1521
if (a.has("POSITION")) {
1522
PackedVector3Array vertices = _decode_accessor_as_vec3(p_state, a["POSITION"], indices_mapping);
1523
array[Mesh::ARRAY_VERTEX] = vertices;
1524
}
1525
if (a.has("NORMAL")) {
1526
array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(p_state, a["NORMAL"], indices_mapping);
1527
}
1528
if (a.has("TANGENT")) {
1529
array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_float32s(p_state, a["TANGENT"], indices_vec4_mapping);
1530
}
1531
if (a.has("TEXCOORD_0")) {
1532
array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_0"], indices_mapping);
1533
}
1534
if (a.has("TEXCOORD_1")) {
1535
array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_1"], indices_mapping);
1536
}
1537
for (int custom_i = 0; custom_i < 3; custom_i++) {
1538
Vector<float> cur_custom;
1539
Vector<Vector2> texcoord_first;
1540
Vector<Vector2> texcoord_second;
1541
1542
int texcoord_i = 2 + 2 * custom_i;
1543
String gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i);
1544
int num_channels = 0;
1545
if (a.has(gltf_texcoord_key)) {
1546
texcoord_first = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], indices_mapping);
1547
num_channels = 2;
1548
}
1549
gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1);
1550
if (a.has(gltf_texcoord_key)) {
1551
texcoord_second = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], indices_mapping);
1552
num_channels = 4;
1553
}
1554
if (!num_channels) {
1555
break;
1556
}
1557
if (num_channels == 2 || num_channels == 4) {
1558
cur_custom.resize(vertex_num * num_channels);
1559
for (int32_t uv_i = 0; uv_i < texcoord_first.size() && uv_i < vertex_num; uv_i++) {
1560
cur_custom.write[uv_i * num_channels + 0] = texcoord_first[uv_i].x;
1561
cur_custom.write[uv_i * num_channels + 1] = texcoord_first[uv_i].y;
1562
}
1563
// Vector.resize seems to not zero-initialize. Ensure all unused elements are 0:
1564
for (int32_t uv_i = texcoord_first.size(); uv_i < vertex_num; uv_i++) {
1565
cur_custom.write[uv_i * num_channels + 0] = 0;
1566
cur_custom.write[uv_i * num_channels + 1] = 0;
1567
}
1568
}
1569
if (num_channels == 4) {
1570
for (int32_t uv_i = 0; uv_i < texcoord_second.size() && uv_i < vertex_num; uv_i++) {
1571
// num_channels must be 4
1572
cur_custom.write[uv_i * num_channels + 2] = texcoord_second[uv_i].x;
1573
cur_custom.write[uv_i * num_channels + 3] = texcoord_second[uv_i].y;
1574
}
1575
// Vector.resize seems to not zero-initialize. Ensure all unused elements are 0:
1576
for (int32_t uv_i = texcoord_second.size(); uv_i < vertex_num; uv_i++) {
1577
cur_custom.write[uv_i * num_channels + 2] = 0;
1578
cur_custom.write[uv_i * num_channels + 3] = 0;
1579
}
1580
}
1581
if (cur_custom.size() > 0) {
1582
array[Mesh::ARRAY_CUSTOM0 + custom_i] = cur_custom;
1583
int custom_shift = Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT + custom_i * Mesh::ARRAY_FORMAT_CUSTOM_BITS;
1584
if (num_channels == 2) {
1585
flags |= Mesh::ARRAY_CUSTOM_RG_FLOAT << custom_shift;
1586
} else {
1587
flags |= Mesh::ARRAY_CUSTOM_RGBA_FLOAT << custom_shift;
1588
}
1589
}
1590
}
1591
if (a.has("COLOR_0")) {
1592
array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(p_state, a["COLOR_0"], indices_mapping);
1593
has_vertex_color = true;
1594
}
1595
if (a.has("JOINTS_0") && !a.has("JOINTS_1")) {
1596
PackedInt32Array joints_0 = _decode_accessor_as_int32s(p_state, a["JOINTS_0"], indices_vec4_mapping);
1597
ERR_FAIL_COND_V(joints_0.size() != 4 * vertex_num, ERR_INVALID_DATA);
1598
array[Mesh::ARRAY_BONES] = joints_0;
1599
} else if (a.has("JOINTS_0") && a.has("JOINTS_1")) {
1600
PackedInt32Array joints_0 = _decode_accessor_as_int32s(p_state, a["JOINTS_0"], indices_vec4_mapping);
1601
PackedInt32Array joints_1 = _decode_accessor_as_int32s(p_state, a["JOINTS_1"], indices_vec4_mapping);
1602
ERR_FAIL_COND_V(joints_0.size() != joints_1.size(), ERR_INVALID_DATA);
1603
ERR_FAIL_COND_V(joints_0.size() != 4 * vertex_num, ERR_INVALID_DATA);
1604
int32_t weight_8_count = JOINT_GROUP_SIZE * 2;
1605
Vector<int> joints;
1606
joints.resize(vertex_num * weight_8_count);
1607
for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) {
1608
joints.write[vertex_i * weight_8_count + 0] = joints_0[vertex_i * JOINT_GROUP_SIZE + 0];
1609
joints.write[vertex_i * weight_8_count + 1] = joints_0[vertex_i * JOINT_GROUP_SIZE + 1];
1610
joints.write[vertex_i * weight_8_count + 2] = joints_0[vertex_i * JOINT_GROUP_SIZE + 2];
1611
joints.write[vertex_i * weight_8_count + 3] = joints_0[vertex_i * JOINT_GROUP_SIZE + 3];
1612
joints.write[vertex_i * weight_8_count + 4] = joints_1[vertex_i * JOINT_GROUP_SIZE + 0];
1613
joints.write[vertex_i * weight_8_count + 5] = joints_1[vertex_i * JOINT_GROUP_SIZE + 1];
1614
joints.write[vertex_i * weight_8_count + 6] = joints_1[vertex_i * JOINT_GROUP_SIZE + 2];
1615
joints.write[vertex_i * weight_8_count + 7] = joints_1[vertex_i * JOINT_GROUP_SIZE + 3];
1616
}
1617
array[Mesh::ARRAY_BONES] = joints;
1618
}
1619
// glTF stores weights as a VEC4 array or multiple VEC4 arrays, but Godot's
1620
// ArrayMesh uses a flat array of either 4 or 8 floats per vertex.
1621
// Therefore, decode up to two glTF VEC4 arrays as float arrays.
1622
if (a.has("WEIGHTS_0") && !a.has("WEIGHTS_1")) {
1623
Vector<float> weights = _decode_accessor_as_float32s(p_state, a["WEIGHTS_0"], indices_vec4_mapping);
1624
ERR_FAIL_COND_V(weights.size() != 4 * vertex_num, ERR_INVALID_DATA);
1625
{ // glTF does not seem to normalize the weights for some reason.
1626
int wc = weights.size();
1627
float *w = weights.ptrw();
1628
1629
for (int k = 0; k < wc; k += 4) {
1630
float total = 0.0;
1631
total += w[k + 0];
1632
total += w[k + 1];
1633
total += w[k + 2];
1634
total += w[k + 3];
1635
if (total > 0.0) {
1636
w[k + 0] /= total;
1637
w[k + 1] /= total;
1638
w[k + 2] /= total;
1639
w[k + 3] /= total;
1640
}
1641
}
1642
}
1643
array[Mesh::ARRAY_WEIGHTS] = weights;
1644
} else if (a.has("WEIGHTS_0") && a.has("WEIGHTS_1")) {
1645
Vector<float> weights_0 = _decode_accessor_as_float32s(p_state, a["WEIGHTS_0"], indices_vec4_mapping);
1646
Vector<float> weights_1 = _decode_accessor_as_float32s(p_state, a["WEIGHTS_1"], indices_vec4_mapping);
1647
Vector<float> weights;
1648
ERR_FAIL_COND_V(weights_0.size() != weights_1.size(), ERR_INVALID_DATA);
1649
ERR_FAIL_COND_V(weights_0.size() != 4 * vertex_num, ERR_INVALID_DATA);
1650
int32_t weight_8_count = JOINT_GROUP_SIZE * 2;
1651
weights.resize(vertex_num * weight_8_count);
1652
for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) {
1653
weights.write[vertex_i * weight_8_count + 0] = weights_0[vertex_i * JOINT_GROUP_SIZE + 0];
1654
weights.write[vertex_i * weight_8_count + 1] = weights_0[vertex_i * JOINT_GROUP_SIZE + 1];
1655
weights.write[vertex_i * weight_8_count + 2] = weights_0[vertex_i * JOINT_GROUP_SIZE + 2];
1656
weights.write[vertex_i * weight_8_count + 3] = weights_0[vertex_i * JOINT_GROUP_SIZE + 3];
1657
weights.write[vertex_i * weight_8_count + 4] = weights_1[vertex_i * JOINT_GROUP_SIZE + 0];
1658
weights.write[vertex_i * weight_8_count + 5] = weights_1[vertex_i * JOINT_GROUP_SIZE + 1];
1659
weights.write[vertex_i * weight_8_count + 6] = weights_1[vertex_i * JOINT_GROUP_SIZE + 2];
1660
weights.write[vertex_i * weight_8_count + 7] = weights_1[vertex_i * JOINT_GROUP_SIZE + 3];
1661
}
1662
{ // glTF does not seem to normalize the weights for some reason.
1663
int wc = weights.size();
1664
float *w = weights.ptrw();
1665
1666
for (int k = 0; k < wc; k += weight_8_count) {
1667
float total = 0.0;
1668
total += w[k + 0];
1669
total += w[k + 1];
1670
total += w[k + 2];
1671
total += w[k + 3];
1672
total += w[k + 4];
1673
total += w[k + 5];
1674
total += w[k + 6];
1675
total += w[k + 7];
1676
if (total > 0.0) {
1677
w[k + 0] /= total;
1678
w[k + 1] /= total;
1679
w[k + 2] /= total;
1680
w[k + 3] /= total;
1681
w[k + 4] /= total;
1682
w[k + 5] /= total;
1683
w[k + 6] /= total;
1684
w[k + 7] /= total;
1685
}
1686
}
1687
}
1688
array[Mesh::ARRAY_WEIGHTS] = weights;
1689
flags |= Mesh::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
1690
}
1691
1692
if (!indices.is_empty()) {
1693
int *w = indices.ptrw();
1694
const int is = indices.size();
1695
for (int ind_i = 0; ind_i < is; ind_i++) {
1696
w[ind_i] = indices_rev_mapping[indices[ind_i]];
1697
}
1698
array[Mesh::ARRAY_INDEX] = indices;
1699
1700
} else if (primitive == Mesh::PRIMITIVE_TRIANGLES) {
1701
// Generate indices because they need to be swapped for CW/CCW.
1702
const Vector<Vector3> &vertices = array[Mesh::ARRAY_VERTEX];
1703
ERR_FAIL_COND_V(vertices.is_empty(), ERR_PARSE_ERROR);
1704
const int vertex_count = vertices.size();
1705
ERR_FAIL_COND_V_MSG(vertex_count % 3 != 0, ERR_PARSE_ERROR, "glTF import: Mesh " + itos(i) + " surface " + itos(j) + " in file " + p_state->filename + " is invalid. Non-indexed triangle meshes MUST have a vertex array with a size that is a multiple of 3, but got " + itos(vertex_count) + " vertices.");
1706
indices.resize(vertex_count);
1707
{
1708
int *w = indices.ptrw();
1709
for (int k = 0; k < vertex_count; k += 3) {
1710
w[k] = k;
1711
w[k + 1] = k + 2;
1712
w[k + 2] = k + 1;
1713
}
1714
}
1715
array[Mesh::ARRAY_INDEX] = indices;
1716
}
1717
1718
bool generate_tangents = p_state->force_generate_tangents && (primitive == Mesh::PRIMITIVE_TRIANGLES && !a.has("TANGENT") && a.has("NORMAL"));
1719
1720
if (generate_tangents && !a.has("TEXCOORD_0")) {
1721
// If we don't have UVs we provide a dummy tangent array.
1722
Vector<float> tangents;
1723
tangents.resize(vertex_num * 4);
1724
float *tangentsw = tangents.ptrw();
1725
1726
Vector<Vector3> normals = array[Mesh::ARRAY_NORMAL];
1727
for (int k = 0; k < vertex_num; k++) {
1728
Vector3 tan = Vector3(normals[k].z, -normals[k].x, normals[k].y).cross(normals[k].normalized()).normalized();
1729
tangentsw[k * 4 + 0] = tan.x;
1730
tangentsw[k * 4 + 1] = tan.y;
1731
tangentsw[k * 4 + 2] = tan.z;
1732
tangentsw[k * 4 + 3] = 1.0;
1733
}
1734
array[Mesh::ARRAY_TANGENT] = tangents;
1735
}
1736
1737
// Disable compression if all z equals 0 (the mesh is 2D).
1738
const Vector<Vector3> &vertices = array[Mesh::ARRAY_VERTEX];
1739
bool is_mesh_2d = true;
1740
for (int k = 0; k < vertices.size(); k++) {
1741
if (!Math::is_zero_approx(vertices[k].z)) {
1742
is_mesh_2d = false;
1743
break;
1744
}
1745
}
1746
1747
if (p_state->force_disable_compression || is_mesh_2d || !a.has("POSITION") || !a.has("NORMAL") || mesh_prim.has("targets") || (a.has("JOINTS_0") || a.has("JOINTS_1"))) {
1748
flags &= ~RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES;
1749
}
1750
1751
Ref<SurfaceTool> mesh_surface_tool;
1752
mesh_surface_tool.instantiate();
1753
mesh_surface_tool->create_from_triangle_arrays(array);
1754
if (a.has("JOINTS_0") && a.has("JOINTS_1")) {
1755
mesh_surface_tool->set_skin_weight_count(SurfaceTool::SKIN_8_WEIGHTS);
1756
}
1757
mesh_surface_tool->index();
1758
if (generate_tangents && a.has("TEXCOORD_0")) {
1759
//must generate mikktspace tangents.. ergh..
1760
mesh_surface_tool->generate_tangents();
1761
}
1762
array = mesh_surface_tool->commit_to_arrays();
1763
1764
if ((flags & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && a.has("NORMAL") && (a.has("TANGENT") || generate_tangents)) {
1765
// Compression is enabled, so let's validate that the normals and tangents are correct.
1766
Vector<Vector3> normals = array[Mesh::ARRAY_NORMAL];
1767
Vector<float> tangents = array[Mesh::ARRAY_TANGENT];
1768
if (unlikely(tangents.size() < normals.size() * 4)) {
1769
ERR_PRINT("glTF import: Mesh " + itos(i) + " has invalid tangents.");
1770
flags &= ~RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES;
1771
} else {
1772
for (int vert = 0; vert < normals.size(); vert++) {
1773
Vector3 tan = Vector3(tangents[vert * 4 + 0], tangents[vert * 4 + 1], tangents[vert * 4 + 2]);
1774
if (std::abs(tan.dot(normals[vert])) > 0.0001) {
1775
// Tangent is not perpendicular to the normal, so we can't use compression.
1776
flags &= ~RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES;
1777
}
1778
}
1779
}
1780
}
1781
1782
Array morphs;
1783
// Blend shapes
1784
if (mesh_prim.has("targets")) {
1785
print_verbose("glTF: Mesh has targets");
1786
const Array &targets = mesh_prim["targets"];
1787
1788
import_mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);
1789
1790
if (j == 0) {
1791
const Array &target_names = extras.has("targetNames") ? (Array)extras["targetNames"] : Array();
1792
for (int k = 0; k < targets.size(); k++) {
1793
String bs_name;
1794
if (k < target_names.size() && ((String)target_names[k]).size() != 0) {
1795
bs_name = (String)target_names[k];
1796
} else {
1797
bs_name = String("morph_") + itos(k);
1798
}
1799
import_mesh->add_blend_shape(bs_name);
1800
}
1801
}
1802
1803
for (int k = 0; k < targets.size(); k++) {
1804
const Dictionary &t = targets[k];
1805
1806
Array array_copy;
1807
array_copy.resize(Mesh::ARRAY_MAX);
1808
1809
for (int l = 0; l < Mesh::ARRAY_MAX; l++) {
1810
array_copy[l] = array[l];
1811
}
1812
1813
if (t.has("POSITION")) {
1814
Vector<Vector3> varr = _decode_accessor_as_vec3(p_state, t["POSITION"], indices_mapping);
1815
const Vector<Vector3> src_varr = array[Mesh::ARRAY_VERTEX];
1816
const int size = src_varr.size();
1817
ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR);
1818
{
1819
const int max_idx = varr.size();
1820
varr.resize(size);
1821
1822
Vector3 *w_varr = varr.ptrw();
1823
const Vector3 *r_varr = varr.ptr();
1824
const Vector3 *r_src_varr = src_varr.ptr();
1825
for (int l = 0; l < size; l++) {
1826
if (l < max_idx) {
1827
w_varr[l] = r_varr[l] + r_src_varr[l];
1828
} else {
1829
w_varr[l] = r_src_varr[l];
1830
}
1831
}
1832
}
1833
array_copy[Mesh::ARRAY_VERTEX] = varr;
1834
}
1835
if (t.has("NORMAL")) {
1836
Vector<Vector3> narr = _decode_accessor_as_vec3(p_state, t["NORMAL"], indices_mapping);
1837
const Vector<Vector3> src_narr = array[Mesh::ARRAY_NORMAL];
1838
int size = src_narr.size();
1839
ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR);
1840
{
1841
int max_idx = narr.size();
1842
narr.resize(size);
1843
1844
Vector3 *w_narr = narr.ptrw();
1845
const Vector3 *r_narr = narr.ptr();
1846
const Vector3 *r_src_narr = src_narr.ptr();
1847
for (int l = 0; l < size; l++) {
1848
if (l < max_idx) {
1849
w_narr[l] = r_narr[l] + r_src_narr[l];
1850
} else {
1851
w_narr[l] = r_src_narr[l];
1852
}
1853
}
1854
}
1855
array_copy[Mesh::ARRAY_NORMAL] = narr;
1856
}
1857
if (t.has("TANGENT")) {
1858
const Vector<Vector3> tangents_v3 = _decode_accessor_as_vec3(p_state, t["TANGENT"], indices_mapping);
1859
const Vector<float> src_tangents = array[Mesh::ARRAY_TANGENT];
1860
ERR_FAIL_COND_V(src_tangents.is_empty(), ERR_PARSE_ERROR);
1861
1862
Vector<float> tangents_v4;
1863
1864
{
1865
int max_idx = tangents_v3.size();
1866
1867
int size4 = src_tangents.size();
1868
tangents_v4.resize(size4);
1869
float *w4 = tangents_v4.ptrw();
1870
1871
const Vector3 *r3 = tangents_v3.ptr();
1872
const float *r4 = src_tangents.ptr();
1873
1874
for (int l = 0; l < size4 / 4; l++) {
1875
if (l < max_idx) {
1876
w4[l * 4 + 0] = r3[l].x + r4[l * 4 + 0];
1877
w4[l * 4 + 1] = r3[l].y + r4[l * 4 + 1];
1878
w4[l * 4 + 2] = r3[l].z + r4[l * 4 + 2];
1879
} else {
1880
w4[l * 4 + 0] = r4[l * 4 + 0];
1881
w4[l * 4 + 1] = r4[l * 4 + 1];
1882
w4[l * 4 + 2] = r4[l * 4 + 2];
1883
}
1884
w4[l * 4 + 3] = r4[l * 4 + 3]; //copy flip value
1885
}
1886
}
1887
1888
array_copy[Mesh::ARRAY_TANGENT] = tangents_v4;
1889
}
1890
1891
Ref<SurfaceTool> blend_surface_tool;
1892
blend_surface_tool.instantiate();
1893
blend_surface_tool->create_from_triangle_arrays(array_copy);
1894
if (a.has("JOINTS_0") && a.has("JOINTS_1")) {
1895
blend_surface_tool->set_skin_weight_count(SurfaceTool::SKIN_8_WEIGHTS);
1896
}
1897
blend_surface_tool->index();
1898
if (generate_tangents) {
1899
blend_surface_tool->generate_tangents();
1900
}
1901
array_copy = blend_surface_tool->commit_to_arrays();
1902
1903
// Enforce blend shape mask array format
1904
for (int l = 0; l < Mesh::ARRAY_MAX; l++) {
1905
if (!(Mesh::ARRAY_FORMAT_BLEND_SHAPE_MASK & (1ULL << l))) {
1906
array_copy[l] = Variant();
1907
}
1908
}
1909
1910
morphs.push_back(array_copy);
1911
}
1912
}
1913
1914
Ref<Material> mat;
1915
String mat_name;
1916
if (!p_state->discard_meshes_and_materials) {
1917
if (mesh_prim.has("material")) {
1918
const int material = mesh_prim["material"];
1919
ERR_FAIL_INDEX_V(material, p_state->materials.size(), ERR_FILE_CORRUPT);
1920
Ref<Material> mat3d = p_state->materials[material];
1921
ERR_FAIL_COND_V(mat3d.is_null(), ERR_FILE_CORRUPT);
1922
1923
Ref<BaseMaterial3D> base_material = mat3d;
1924
if (has_vertex_color && base_material.is_valid()) {
1925
base_material->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
1926
}
1927
mat = mat3d;
1928
1929
} else {
1930
Ref<StandardMaterial3D> mat3d;
1931
mat3d.instantiate();
1932
if (has_vertex_color) {
1933
mat3d->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
1934
}
1935
mat = mat3d;
1936
}
1937
ERR_FAIL_COND_V(mat.is_null(), ERR_FILE_CORRUPT);
1938
instance_materials.append(mat);
1939
mat_name = mat->get_name();
1940
}
1941
import_mesh->add_surface(primitive, array, morphs,
1942
Dictionary(), mat, mat_name, flags);
1943
}
1944
1945
Vector<float> blend_weights;
1946
blend_weights.resize(import_mesh->get_blend_shape_count());
1947
for (int32_t weight_i = 0; weight_i < blend_weights.size(); weight_i++) {
1948
blend_weights.write[weight_i] = 0.0f;
1949
}
1950
1951
if (mesh_dict.has("weights")) {
1952
const Array &weights = mesh_dict["weights"];
1953
for (int j = 0; j < weights.size(); j++) {
1954
if (j >= blend_weights.size()) {
1955
break;
1956
}
1957
blend_weights.write[j] = weights[j];
1958
}
1959
}
1960
mesh->set_blend_weights(blend_weights);
1961
mesh->set_instance_materials(instance_materials);
1962
mesh->set_mesh(import_mesh);
1963
1964
p_state->meshes.push_back(mesh);
1965
}
1966
1967
print_verbose("glTF: Total meshes: " + itos(p_state->meshes.size()));
1968
1969
return OK;
1970
}
1971
1972
void GLTFDocument::set_naming_version(int p_version) {
1973
_naming_version = p_version;
1974
}
1975
1976
int GLTFDocument::get_naming_version() const {
1977
return _naming_version;
1978
}
1979
1980
void GLTFDocument::set_image_format(const String &p_image_format) {
1981
_image_format = p_image_format;
1982
}
1983
1984
String GLTFDocument::get_image_format() const {
1985
return _image_format;
1986
}
1987
1988
void GLTFDocument::set_lossy_quality(float p_lossy_quality) {
1989
_lossy_quality = p_lossy_quality;
1990
}
1991
1992
float GLTFDocument::get_lossy_quality() const {
1993
return _lossy_quality;
1994
}
1995
1996
void GLTFDocument::set_fallback_image_format(const String &p_fallback_image_format) {
1997
_fallback_image_format = p_fallback_image_format;
1998
}
1999
2000
String GLTFDocument::get_fallback_image_format() const {
2001
return _fallback_image_format;
2002
}
2003
2004
void GLTFDocument::set_fallback_image_quality(float p_fallback_image_quality) {
2005
_fallback_image_quality = p_fallback_image_quality;
2006
}
2007
2008
float GLTFDocument::get_fallback_image_quality() const {
2009
return _fallback_image_quality;
2010
}
2011
2012
Error GLTFDocument::_serialize_images(Ref<GLTFState> p_state) {
2013
Array images;
2014
// Check if any extension wants to be the image saver.
2015
_image_save_extension = Ref<GLTFDocumentExtension>();
2016
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
2017
ERR_CONTINUE(ext.is_null());
2018
Vector<String> image_formats = ext->get_saveable_image_formats();
2019
if (image_formats.has(_image_format)) {
2020
_image_save_extension = ext;
2021
break;
2022
}
2023
}
2024
// Serialize every image in the state's images array.
2025
for (int i = 0; i < p_state->images.size(); i++) {
2026
Dictionary image_dict;
2027
if (p_state->images[i].is_null()) {
2028
ERR_PRINT("glTF export: Image Texture2D is null.");
2029
} else {
2030
Ref<Image> image = p_state->images[i]->get_image();
2031
if (image.is_null()) {
2032
ERR_PRINT("glTF export: Image's image is null.");
2033
} else {
2034
String image_name = p_state->images[i]->get_name();
2035
if (image_name.is_empty()) {
2036
image_name = itos(i).pad_zeros(3);
2037
}
2038
image_name = _gen_unique_name(p_state, image_name);
2039
image->set_name(image_name);
2040
image_dict = _serialize_image(p_state, image, _image_format, _lossy_quality, _image_save_extension);
2041
}
2042
}
2043
images.push_back(image_dict);
2044
}
2045
2046
print_verbose("Total images: " + itos(p_state->images.size()));
2047
2048
if (!images.size()) {
2049
return OK;
2050
}
2051
p_state->json["images"] = images;
2052
2053
return OK;
2054
}
2055
2056
static inline Ref<Image> _duplicate_and_decompress_image(const Ref<Image> &p_image) {
2057
Ref<Image> img = p_image->duplicate();
2058
if (img->is_compressed()) {
2059
img->decompress();
2060
}
2061
return img;
2062
}
2063
2064
Dictionary GLTFDocument::_serialize_image(Ref<GLTFState> p_state, Ref<Image> p_image, const String &p_image_format, float p_lossy_quality, Ref<GLTFDocumentExtension> p_image_save_extension) {
2065
Dictionary image_dict;
2066
if (p_image->is_compressed()) {
2067
p_image = _duplicate_and_decompress_image(p_image);
2068
ERR_FAIL_COND_V_MSG(p_image->is_compressed(), image_dict, "glTF: Image was compressed, but could not be decompressed.");
2069
}
2070
2071
if (!p_image->get_name().is_empty()) {
2072
image_dict["name"] = p_image->get_name();
2073
}
2074
2075
if (p_state->filename.to_lower().ends_with("gltf")) {
2076
String relative_texture_dir = "textures";
2077
String full_texture_dir = p_state->base_path.path_join(relative_texture_dir);
2078
Ref<DirAccess> da = DirAccess::open(p_state->base_path);
2079
ERR_FAIL_COND_V(da.is_null(), image_dict);
2080
2081
if (!da->dir_exists(full_texture_dir)) {
2082
da->make_dir(full_texture_dir);
2083
}
2084
String image_file_name = p_image->get_name();
2085
if (p_image_save_extension.is_valid()) {
2086
image_file_name = image_file_name + p_image_save_extension->get_image_file_extension();
2087
Error err = p_image_save_extension->save_image_at_path(p_state, p_image, full_texture_dir.path_join(image_file_name), p_image_format, p_lossy_quality);
2088
ERR_FAIL_COND_V_MSG(err != OK, image_dict, "glTF: Failed to save image in '" + p_image_format + "' format as a separate file, error " + itos(err) + ".");
2089
} else if (p_image_format == "PNG") {
2090
image_file_name = image_file_name + ".png";
2091
p_image->save_png(full_texture_dir.path_join(image_file_name));
2092
} else if (p_image_format == "JPEG") {
2093
image_file_name = image_file_name + ".jpg";
2094
p_image->save_jpg(full_texture_dir.path_join(image_file_name), p_lossy_quality);
2095
} else {
2096
ERR_FAIL_V_MSG(image_dict, "glTF: Unknown image format '" + p_image_format + "'.");
2097
}
2098
image_dict["uri"] = relative_texture_dir.path_join(image_file_name).uri_encode();
2099
} else {
2100
GLTFBufferViewIndex bvi;
2101
2102
Ref<GLTFBufferView> bv;
2103
bv.instantiate();
2104
2105
const GLTFBufferIndex bi = 0;
2106
bv->buffer = bi;
2107
ERR_FAIL_INDEX_V(bi, p_state->buffers.size(), image_dict);
2108
bv->byte_offset = p_state->buffers[bi].size();
2109
2110
Vector<uint8_t> buffer;
2111
// Save in various image formats. Note that if the format is "None",
2112
// the state's images will be empty, so this code will not be reached.
2113
if (_image_save_extension.is_valid()) {
2114
buffer = _image_save_extension->serialize_image_to_bytes(p_state, p_image, image_dict, p_image_format, p_lossy_quality);
2115
} else if (p_image_format == "PNG") {
2116
buffer = p_image->save_png_to_buffer();
2117
image_dict["mimeType"] = "image/png";
2118
} else if (p_image_format == "JPEG") {
2119
buffer = p_image->save_jpg_to_buffer(p_lossy_quality);
2120
image_dict["mimeType"] = "image/jpeg";
2121
} else {
2122
ERR_FAIL_V_MSG(image_dict, "glTF: Unknown image format '" + p_image_format + "'.");
2123
}
2124
ERR_FAIL_COND_V_MSG(buffer.is_empty(), image_dict, "glTF: Failed to save image in '" + p_image_format + "' format.");
2125
2126
bv->byte_length = buffer.size();
2127
p_state->buffers.write[bi].resize(p_state->buffers[bi].size() + bv->byte_length);
2128
memcpy(&p_state->buffers.write[bi].write[bv->byte_offset], buffer.ptr(), buffer.size());
2129
ERR_FAIL_COND_V(bv->byte_offset + bv->byte_length > p_state->buffers[bi].size(), image_dict);
2130
2131
p_state->buffer_views.push_back(bv);
2132
bvi = p_state->buffer_views.size() - 1;
2133
image_dict["bufferView"] = bvi;
2134
}
2135
return image_dict;
2136
}
2137
2138
Ref<Image> GLTFDocument::_parse_image_bytes_into_image(Ref<GLTFState> p_state, const Vector<uint8_t> &p_bytes, const String &p_mime_type, int p_index, String &r_file_extension) {
2139
Ref<Image> r_image;
2140
r_image.instantiate();
2141
// Check if any GLTFDocumentExtensions want to import this data as an image.
2142
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
2143
ERR_CONTINUE(ext.is_null());
2144
Error err = ext->parse_image_data(p_state, p_bytes, p_mime_type, r_image);
2145
ERR_CONTINUE_MSG(err != OK, "glTF: Encountered error " + itos(err) + " when parsing image " + itos(p_index) + " in file " + p_state->filename + ". Continuing.");
2146
if (!r_image->is_empty()) {
2147
r_file_extension = ext->get_image_file_extension();
2148
return r_image;
2149
}
2150
}
2151
// If no extension wanted to import this data as an image, try to load a PNG or JPEG.
2152
// First we honor the mime types if they were defined.
2153
if (p_mime_type == "image/png") { // Load buffer as PNG.
2154
r_image->load_png_from_buffer(p_bytes);
2155
r_file_extension = ".png";
2156
} else if (p_mime_type == "image/jpeg") { // Loader buffer as JPEG.
2157
r_image->load_jpg_from_buffer(p_bytes);
2158
r_file_extension = ".jpg";
2159
}
2160
// If we didn't pass the above tests, we attempt loading as PNG and then JPEG directly.
2161
// This covers URIs with base64-encoded data with application/* type but
2162
// no optional mimeType property, or bufferViews with a bogus mimeType
2163
// (e.g. `image/jpeg` but the data is actually PNG).
2164
// That's not *exactly* what the spec mandates but this lets us be
2165
// lenient with bogus glb files which do exist in production.
2166
if (r_image->is_empty()) { // Try PNG first.
2167
r_image->load_png_from_buffer(p_bytes);
2168
}
2169
if (r_image->is_empty()) { // And then JPEG.
2170
r_image->load_jpg_from_buffer(p_bytes);
2171
}
2172
// If it still can't be loaded, give up and insert an empty image as placeholder.
2173
if (r_image->is_empty()) {
2174
ERR_PRINT(vformat("glTF: Couldn't load image index '%d' with its given mimetype: %s.", p_index, p_mime_type));
2175
}
2176
return r_image;
2177
}
2178
2179
void GLTFDocument::_parse_image_save_image(Ref<GLTFState> p_state, const Vector<uint8_t> &p_bytes, const String &p_resource_uri, const String &p_file_extension, int p_index, Ref<Image> p_image) {
2180
GLTFState::HandleBinaryImageMode handling = GLTFState::HandleBinaryImageMode(p_state->handle_binary_image_mode);
2181
if (p_image->is_empty() || handling == GLTFState::HandleBinaryImageMode::HANDLE_BINARY_IMAGE_MODE_DISCARD_TEXTURES) {
2182
p_state->images.push_back(Ref<Texture2D>());
2183
p_state->source_images.push_back(Ref<Image>());
2184
return;
2185
}
2186
#ifdef TOOLS_ENABLED
2187
if (Engine::get_singleton()->is_editor_hint() && handling == GLTFState::HandleBinaryImageMode::HANDLE_BINARY_IMAGE_MODE_EXTRACT_TEXTURES) {
2188
if (p_state->extract_path.is_empty()) {
2189
WARN_PRINT("glTF: Couldn't extract image because the base and extract paths are empty. It will be loaded directly instead, uncompressed.");
2190
} else if (p_state->extract_path.begins_with("res://.godot/imported")) {
2191
WARN_PRINT(vformat("glTF: Extract path is in the imported directory. Image index '%d' will be loaded directly, uncompressed.", p_index));
2192
} else {
2193
if (p_image->get_name().is_empty()) {
2194
WARN_PRINT(vformat("glTF: Image index '%d' did not have a name. It will be automatically given a name based on its index.", p_index));
2195
p_image->set_name(itos(p_index));
2196
}
2197
bool must_write = true; // If the resource does not exist on the disk within res:// directory write it.
2198
bool must_import = true; // Trigger import.
2199
Vector<uint8_t> img_data = p_image->get_data();
2200
Dictionary generator_parameters;
2201
String file_path;
2202
// If resource_uri is within res:// folder but outside of .godot/imported folder, use it.
2203
if (!p_resource_uri.is_empty() && !p_resource_uri.begins_with("res://.godot/imported") && !p_resource_uri.begins_with("res://..")) {
2204
file_path = p_resource_uri;
2205
must_import = true;
2206
must_write = !FileAccess::exists(file_path);
2207
} else {
2208
// Texture data has to be written to the res:// folder and imported.
2209
file_path = p_state->get_extract_path().path_join(p_state->get_extract_prefix() + "_" + p_image->get_name());
2210
file_path += p_file_extension.is_empty() ? ".png" : p_file_extension;
2211
if (FileAccess::exists(file_path + ".import")) {
2212
Ref<ConfigFile> config;
2213
config.instantiate();
2214
config->load(file_path + ".import");
2215
if (config->has_section_key("remap", "generator_parameters")) {
2216
generator_parameters = (Dictionary)config->get_value("remap", "generator_parameters");
2217
}
2218
if (!generator_parameters.has("md5")) {
2219
must_write = false; // Didn't come from a gltf document; don't overwrite.
2220
must_import = false; // And don't import.
2221
}
2222
}
2223
}
2224
2225
if (must_write) {
2226
String existing_md5 = generator_parameters["md5"];
2227
unsigned char md5_hash[16];
2228
CryptoCore::md5(img_data.ptr(), img_data.size(), md5_hash);
2229
String new_md5 = String::hex_encode_buffer(md5_hash, 16);
2230
generator_parameters["md5"] = new_md5;
2231
if (new_md5 == existing_md5) {
2232
must_write = false;
2233
must_import = false;
2234
}
2235
}
2236
if (must_write) {
2237
Error err = OK;
2238
if (p_file_extension.is_empty()) {
2239
// If a file extension was not specified, save the image data to a PNG file.
2240
err = p_image->save_png(file_path);
2241
ERR_FAIL_COND(err != OK);
2242
} else {
2243
// If a file extension was specified, save the original bytes to a file with that extension.
2244
Ref<FileAccess> file = FileAccess::open(file_path, FileAccess::WRITE, &err);
2245
ERR_FAIL_COND(err != OK);
2246
file->store_buffer(p_bytes);
2247
file->close();
2248
}
2249
}
2250
if (must_import) {
2251
// ResourceLoader::import will crash if not is_editor_hint(), so this case is protected above and will fall through to uncompressed.
2252
HashMap<StringName, Variant> custom_options;
2253
custom_options[SNAME("mipmaps/generate")] = true;
2254
// Will only use project settings defaults if custom_importer is empty.
2255
2256
EditorFileSystem::get_singleton()->update_file(file_path);
2257
EditorFileSystem::get_singleton()->reimport_append(file_path, custom_options, String(), generator_parameters);
2258
}
2259
Ref<Texture2D> saved_image = ResourceLoader::load(file_path, "Texture2D");
2260
if (saved_image.is_valid()) {
2261
p_state->images.push_back(saved_image);
2262
p_state->source_images.push_back(saved_image->get_image());
2263
return;
2264
} else {
2265
WARN_PRINT(vformat("glTF: Image index '%d' with the name '%s' resolved to %s couldn't be imported. It will be loaded directly instead, uncompressed.", p_index, p_image->get_name(), file_path));
2266
}
2267
}
2268
}
2269
#endif // TOOLS_ENABLED
2270
if (handling == GLTFState::HandleBinaryImageMode::HANDLE_BINARY_IMAGE_MODE_EMBED_AS_BASISU) {
2271
Ref<PortableCompressedTexture2D> tex;
2272
tex.instantiate();
2273
tex->set_name(p_image->get_name());
2274
tex->set_keep_compressed_buffer(true);
2275
tex->create_from_image(p_image, PortableCompressedTexture2D::COMPRESSION_MODE_BASIS_UNIVERSAL);
2276
p_state->images.push_back(tex);
2277
p_state->source_images.push_back(p_image);
2278
return;
2279
}
2280
// This handles the case of HANDLE_BINARY_IMAGE_MODE_EMBED_AS_UNCOMPRESSED, and it also serves
2281
// as a fallback for HANDLE_BINARY_IMAGE_MODE_EXTRACT_TEXTURES when this is not the editor.
2282
Ref<ImageTexture> tex;
2283
tex.instantiate();
2284
tex->set_name(p_image->get_name());
2285
tex->set_image(p_image);
2286
p_state->images.push_back(tex);
2287
p_state->source_images.push_back(p_image);
2288
}
2289
2290
Error GLTFDocument::_parse_images(Ref<GLTFState> p_state, const String &p_base_path) {
2291
ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER);
2292
if (!p_state->json.has("images")) {
2293
return OK;
2294
}
2295
2296
// Ref: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#images
2297
2298
const Array &images = p_state->json["images"];
2299
HashSet<String> used_names;
2300
for (int i = 0; i < images.size(); i++) {
2301
const Dictionary &dict = images[i];
2302
2303
// glTF 2.0 supports PNG and JPEG types, which can be specified as (from spec):
2304
// "- a URI to an external file in one of the supported images formats, or
2305
// - a URI with embedded base64-encoded data, or
2306
// - a reference to a bufferView; in that case mimeType must be defined."
2307
// Since mimeType is optional for external files and base64 data, we'll have to
2308
// fall back on letting Godot parse the data to figure out if it's PNG or JPEG.
2309
2310
// We'll assume that we use either URI or bufferView, so let's warn the user
2311
// if their image somehow uses both. And fail if it has neither.
2312
ERR_CONTINUE_MSG(!dict.has("uri") && !dict.has("bufferView"), "Invalid image definition in glTF file, it should specify an 'uri' or 'bufferView'.");
2313
if (dict.has("uri") && dict.has("bufferView")) {
2314
WARN_PRINT("Invalid image definition in glTF file using both 'uri' and 'bufferView'. 'uri' will take precedence.");
2315
}
2316
2317
String mime_type;
2318
if (dict.has("mimeType")) { // Should be "image/png", "image/jpeg", or something handled by an extension.
2319
mime_type = dict["mimeType"];
2320
}
2321
2322
String image_name;
2323
if (dict.has("name")) {
2324
image_name = dict["name"];
2325
image_name = image_name.get_file().get_basename().validate_filename();
2326
}
2327
if (image_name.is_empty()) {
2328
image_name = itos(i);
2329
}
2330
while (used_names.has(image_name)) {
2331
image_name += "_" + itos(i);
2332
}
2333
2334
String resource_uri;
2335
2336
used_names.insert(image_name);
2337
// Load the image data. If we get a byte array, store here for later.
2338
Vector<uint8_t> data;
2339
if (dict.has("uri")) {
2340
// Handles the first two bullet points from the spec (embedded data, or external file).
2341
String uri = dict["uri"];
2342
if (uri.begins_with("data:")) { // Embedded data using base64.
2343
data = _parse_base64_uri(uri);
2344
// mimeType is optional, but if we have it defined in the URI, let's use it.
2345
if (mime_type.is_empty() && uri.contains_char(';')) {
2346
// Trim "data:" prefix which is 5 characters long, and end at ";base64".
2347
mime_type = uri.substr(5, uri.find(";base64") - 5);
2348
}
2349
} else { // Relative path to an external image file.
2350
ERR_FAIL_COND_V(p_base_path.is_empty(), ERR_INVALID_PARAMETER);
2351
uri = uri.uri_file_decode();
2352
uri = p_base_path.path_join(uri).replace_char('\\', '/'); // Fix for Windows.
2353
resource_uri = uri.simplify_path();
2354
// ResourceLoader will rely on the file extension to use the relevant loader.
2355
// The spec says that if mimeType is defined, it should take precedence (e.g.
2356
// there could be a `.png` image which is actually JPEG), but there's no easy
2357
// API for that in Godot, so we'd have to load as a buffer (i.e. embedded in
2358
// the material), so we only do that only as fallback.
2359
if (ResourceLoader::exists(resource_uri)) {
2360
Ref<Texture2D> texture = ResourceLoader::load(resource_uri, "Texture2D");
2361
if (texture.is_valid()) {
2362
p_state->images.push_back(texture);
2363
p_state->source_images.push_back(texture->get_image());
2364
continue;
2365
}
2366
}
2367
// mimeType is optional, but if we have it in the file extension, let's use it.
2368
// If the mimeType does not match with the file extension, either it should be
2369
// specified in the file, or the GLTFDocumentExtension should handle it.
2370
if (mime_type.is_empty()) {
2371
mime_type = "image/" + resource_uri.get_extension();
2372
}
2373
// Fallback to loading as byte array. This enables us to support the
2374
// spec's requirement that we honor mimetype regardless of file URI.
2375
data = FileAccess::get_file_as_bytes(resource_uri);
2376
if (data.is_empty()) {
2377
WARN_PRINT(vformat("glTF: Image index '%d' couldn't be loaded as a buffer of MIME type '%s' from URI: %s because there was no data to load. Skipping it.", i, mime_type, resource_uri));
2378
p_state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count.
2379
p_state->source_images.push_back(Ref<Image>());
2380
continue;
2381
}
2382
}
2383
} else if (dict.has("bufferView")) {
2384
// Handles the third bullet point from the spec (bufferView).
2385
ERR_FAIL_COND_V_MSG(mime_type.is_empty(), ERR_FILE_CORRUPT, vformat("glTF: Image index '%d' specifies 'bufferView' but no 'mimeType', which is invalid.", i));
2386
const GLTFBufferViewIndex bvi = dict["bufferView"];
2387
ERR_FAIL_INDEX_V(bvi, p_state->buffer_views.size(), ERR_PARAMETER_RANGE_ERROR);
2388
Ref<GLTFBufferView> bv = p_state->buffer_views[bvi];
2389
const GLTFBufferIndex bi = bv->buffer;
2390
ERR_FAIL_INDEX_V(bi, p_state->buffers.size(), ERR_PARAMETER_RANGE_ERROR);
2391
ERR_FAIL_COND_V(bv->byte_offset + bv->byte_length > p_state->buffers[bi].size(), ERR_FILE_CORRUPT);
2392
const PackedByteArray &buffer = p_state->buffers[bi];
2393
data = buffer.slice(bv->byte_offset, bv->byte_offset + bv->byte_length);
2394
}
2395
// Done loading the image data bytes. Check that we actually got data to parse.
2396
// Note: There are paths above that return early, so this point might not be reached.
2397
if (data.is_empty()) {
2398
WARN_PRINT(vformat("glTF: Image index '%d' couldn't be loaded, no data found. Skipping it.", i));
2399
p_state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count.
2400
p_state->source_images.push_back(Ref<Image>());
2401
continue;
2402
}
2403
// Parse the image data from bytes into an Image resource and save if needed.
2404
String file_extension;
2405
Ref<Image> img = _parse_image_bytes_into_image(p_state, data, mime_type, i, file_extension);
2406
img->set_name(image_name);
2407
_parse_image_save_image(p_state, data, resource_uri, file_extension, i, img);
2408
}
2409
2410
print_verbose("glTF: Total images: " + itos(p_state->images.size()));
2411
2412
return OK;
2413
}
2414
2415
Error GLTFDocument::_serialize_textures(Ref<GLTFState> p_state) {
2416
if (!p_state->textures.size()) {
2417
return OK;
2418
}
2419
2420
Array textures;
2421
for (int32_t i = 0; i < p_state->textures.size(); i++) {
2422
Dictionary texture_dict;
2423
Ref<GLTFTexture> gltf_texture = p_state->textures[i];
2424
if (_image_save_extension.is_valid()) {
2425
Error err = _image_save_extension->serialize_texture_json(p_state, texture_dict, gltf_texture, _image_format);
2426
ERR_FAIL_COND_V(err != OK, err);
2427
// If a fallback image format was specified, serialize another image for it.
2428
// Note: This must only be done after serializing other images to keep the indices of those consistent.
2429
if (_fallback_image_format != "None" && p_state->json.has("images")) {
2430
Array json_images = p_state->json["images"];
2431
texture_dict["source"] = json_images.size();
2432
Ref<Image> image = p_state->source_images[gltf_texture->get_src_image()];
2433
String fallback_name = _gen_unique_name(p_state, image->get_name() + "_fallback");
2434
image = image->duplicate();
2435
image->set_name(fallback_name);
2436
ERR_CONTINUE(image.is_null());
2437
if (_fallback_image_format == "PNG") {
2438
image->resize(image->get_width() * _fallback_image_quality, image->get_height() * _fallback_image_quality);
2439
}
2440
json_images.push_back(_serialize_image(p_state, image, _fallback_image_format, _fallback_image_quality, nullptr));
2441
}
2442
} else {
2443
ERR_CONTINUE(gltf_texture->get_src_image() == -1);
2444
texture_dict["source"] = gltf_texture->get_src_image();
2445
}
2446
GLTFTextureSamplerIndex sampler_index = gltf_texture->get_sampler();
2447
if (sampler_index != -1) {
2448
texture_dict["sampler"] = sampler_index;
2449
}
2450
textures.push_back(texture_dict);
2451
}
2452
p_state->json["textures"] = textures;
2453
2454
return OK;
2455
}
2456
2457
Error GLTFDocument::_parse_textures(Ref<GLTFState> p_state) {
2458
if (!p_state->json.has("textures")) {
2459
return OK;
2460
}
2461
2462
const Array &textures = p_state->json["textures"];
2463
for (GLTFTextureIndex i = 0; i < textures.size(); i++) {
2464
const Dictionary &texture_dict = textures[i];
2465
Ref<GLTFTexture> gltf_texture;
2466
gltf_texture.instantiate();
2467
// Check if any GLTFDocumentExtensions want to handle this texture JSON.
2468
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
2469
ERR_CONTINUE(ext.is_null());
2470
Error err = ext->parse_texture_json(p_state, texture_dict, gltf_texture);
2471
ERR_CONTINUE_MSG(err != OK, "glTF: Encountered error " + itos(err) + " when parsing texture JSON " + String(Variant(texture_dict)) + " in file " + p_state->filename + ". Continuing.");
2472
if (gltf_texture->get_src_image() != -1) {
2473
break;
2474
}
2475
}
2476
if (gltf_texture->get_src_image() == -1) {
2477
// No extensions handled it, so use the base glTF source.
2478
// This may be the fallback, or the only option anyway.
2479
ERR_FAIL_COND_V(!texture_dict.has("source"), ERR_PARSE_ERROR);
2480
gltf_texture->set_src_image(texture_dict["source"]);
2481
}
2482
if (gltf_texture->get_sampler() == -1 && texture_dict.has("sampler")) {
2483
gltf_texture->set_sampler(texture_dict["sampler"]);
2484
}
2485
p_state->textures.push_back(gltf_texture);
2486
}
2487
2488
return OK;
2489
}
2490
2491
GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> p_state, Ref<Texture2D> p_texture, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) {
2492
ERR_FAIL_COND_V(p_texture.is_null(), -1);
2493
Ref<GLTFTexture> gltf_texture;
2494
gltf_texture.instantiate();
2495
ERR_FAIL_COND_V(p_texture->get_image().is_null(), -1);
2496
GLTFImageIndex gltf_src_image_i = p_state->images.find(p_texture);
2497
if (gltf_src_image_i == -1) {
2498
gltf_src_image_i = p_state->images.size();
2499
p_state->images.push_back(p_texture);
2500
p_state->source_images.push_back(p_texture->get_image());
2501
}
2502
gltf_texture->set_src_image(gltf_src_image_i);
2503
gltf_texture->set_sampler(_set_sampler_for_mode(p_state, p_filter_mode, p_repeats));
2504
GLTFTextureIndex gltf_texture_i = p_state->textures.size();
2505
p_state->textures.push_back(gltf_texture);
2506
return gltf_texture_i;
2507
}
2508
2509
Ref<Texture2D> GLTFDocument::_get_texture(Ref<GLTFState> p_state, const GLTFTextureIndex p_texture, int p_texture_types) {
2510
ERR_FAIL_COND_V_MSG(p_state->textures.is_empty(), Ref<Texture2D>(), "glTF import: Tried to read texture at index " + itos(p_texture) + ", but this glTF file does not contain any textures.");
2511
ERR_FAIL_INDEX_V(p_texture, p_state->textures.size(), Ref<Texture2D>());
2512
const GLTFImageIndex image = p_state->textures[p_texture]->get_src_image();
2513
ERR_FAIL_INDEX_V(image, p_state->images.size(), Ref<Texture2D>());
2514
if (GLTFState::HandleBinaryImageMode(p_state->handle_binary_image_mode) == GLTFState::HandleBinaryImageMode::HANDLE_BINARY_IMAGE_MODE_EMBED_AS_BASISU) {
2515
ERR_FAIL_INDEX_V(image, p_state->source_images.size(), Ref<Texture2D>());
2516
Ref<PortableCompressedTexture2D> portable_texture;
2517
portable_texture.instantiate();
2518
portable_texture->set_keep_compressed_buffer(true);
2519
Ref<Image> new_img = p_state->source_images[image]->duplicate();
2520
ERR_FAIL_COND_V(new_img.is_null(), Ref<Texture2D>());
2521
new_img->generate_mipmaps();
2522
if (p_texture_types) {
2523
portable_texture->create_from_image(new_img, PortableCompressedTexture2D::COMPRESSION_MODE_BASIS_UNIVERSAL, true);
2524
} else {
2525
portable_texture->create_from_image(new_img, PortableCompressedTexture2D::COMPRESSION_MODE_BASIS_UNIVERSAL, false);
2526
}
2527
p_state->images.write[image] = portable_texture;
2528
p_state->source_images.write[image] = new_img;
2529
}
2530
return p_state->images[image];
2531
}
2532
2533
GLTFTextureSamplerIndex GLTFDocument::_set_sampler_for_mode(Ref<GLTFState> p_state, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) {
2534
for (int i = 0; i < p_state->texture_samplers.size(); ++i) {
2535
if (p_state->texture_samplers[i]->get_filter_mode() == p_filter_mode) {
2536
return i;
2537
}
2538
}
2539
2540
GLTFTextureSamplerIndex gltf_sampler_i = p_state->texture_samplers.size();
2541
Ref<GLTFTextureSampler> gltf_sampler;
2542
gltf_sampler.instantiate();
2543
gltf_sampler->set_filter_mode(p_filter_mode);
2544
gltf_sampler->set_wrap_mode(p_repeats);
2545
p_state->texture_samplers.push_back(gltf_sampler);
2546
return gltf_sampler_i;
2547
}
2548
2549
Ref<GLTFTextureSampler> GLTFDocument::_get_sampler_for_texture(Ref<GLTFState> p_state, const GLTFTextureIndex p_texture) {
2550
ERR_FAIL_COND_V_MSG(p_state->textures.is_empty(), Ref<GLTFTextureSampler>(), "glTF import: Tried to read sampler for texture at index " + itos(p_texture) + ", but this glTF file does not contain any textures.");
2551
ERR_FAIL_INDEX_V(p_texture, p_state->textures.size(), Ref<GLTFTextureSampler>());
2552
const GLTFTextureSamplerIndex sampler = p_state->textures[p_texture]->get_sampler();
2553
2554
if (sampler == -1) {
2555
return p_state->default_texture_sampler;
2556
} else {
2557
ERR_FAIL_INDEX_V(sampler, p_state->texture_samplers.size(), Ref<GLTFTextureSampler>());
2558
2559
return p_state->texture_samplers[sampler];
2560
}
2561
}
2562
2563
Error GLTFDocument::_serialize_texture_samplers(Ref<GLTFState> p_state) {
2564
if (!p_state->texture_samplers.size()) {
2565
return OK;
2566
}
2567
2568
Array samplers;
2569
for (int32_t i = 0; i < p_state->texture_samplers.size(); ++i) {
2570
Dictionary d;
2571
Ref<GLTFTextureSampler> s = p_state->texture_samplers[i];
2572
d["magFilter"] = s->get_mag_filter();
2573
d["minFilter"] = s->get_min_filter();
2574
d["wrapS"] = s->get_wrap_s();
2575
d["wrapT"] = s->get_wrap_t();
2576
samplers.push_back(d);
2577
}
2578
p_state->json["samplers"] = samplers;
2579
2580
return OK;
2581
}
2582
2583
Error GLTFDocument::_parse_texture_samplers(Ref<GLTFState> p_state) {
2584
p_state->default_texture_sampler.instantiate();
2585
p_state->default_texture_sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR);
2586
p_state->default_texture_sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR);
2587
p_state->default_texture_sampler->set_wrap_s(GLTFTextureSampler::WrapMode::REPEAT);
2588
p_state->default_texture_sampler->set_wrap_t(GLTFTextureSampler::WrapMode::REPEAT);
2589
2590
if (!p_state->json.has("samplers")) {
2591
return OK;
2592
}
2593
2594
const Array &samplers = p_state->json["samplers"];
2595
for (int i = 0; i < samplers.size(); ++i) {
2596
const Dictionary &d = samplers[i];
2597
2598
Ref<GLTFTextureSampler> sampler;
2599
sampler.instantiate();
2600
2601
if (d.has("minFilter")) {
2602
sampler->set_min_filter(d["minFilter"]);
2603
} else {
2604
sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR);
2605
}
2606
if (d.has("magFilter")) {
2607
sampler->set_mag_filter(d["magFilter"]);
2608
} else {
2609
sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR);
2610
}
2611
2612
if (d.has("wrapS")) {
2613
sampler->set_wrap_s(d["wrapS"]);
2614
} else {
2615
sampler->set_wrap_s(GLTFTextureSampler::WrapMode::DEFAULT);
2616
}
2617
2618
if (d.has("wrapT")) {
2619
sampler->set_wrap_t(d["wrapT"]);
2620
} else {
2621
sampler->set_wrap_t(GLTFTextureSampler::WrapMode::DEFAULT);
2622
}
2623
2624
p_state->texture_samplers.push_back(sampler);
2625
}
2626
2627
return OK;
2628
}
2629
2630
static inline void _set_material_texture_name(const Ref<Texture2D> &p_texture, const String &p_path, const String &p_mat_name, const String &p_suffix) {
2631
if (p_texture->get_name().is_empty()) {
2632
if (p_path.is_empty()) {
2633
p_texture->set_name(p_mat_name + p_suffix);
2634
} else {
2635
p_texture->set_name(p_path.get_file().get_basename());
2636
}
2637
}
2638
}
2639
2640
Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
2641
Array materials;
2642
for (int32_t i = 0; i < p_state->materials.size(); i++) {
2643
Dictionary mat_dict;
2644
Ref<Material> material = p_state->materials[i];
2645
if (material.is_null()) {
2646
materials.push_back(mat_dict);
2647
continue;
2648
}
2649
String mat_name = material->get_name();
2650
if (mat_name.is_empty()) {
2651
const String &mat_path = material->get_path();
2652
if (!mat_path.is_empty() && !mat_path.contains("::")) {
2653
mat_name = mat_path.get_file().get_basename();
2654
}
2655
}
2656
if (!mat_name.is_empty()) {
2657
mat_dict["name"] = _gen_unique_name(p_state, mat_name);
2658
}
2659
2660
Ref<BaseMaterial3D> base_material = material;
2661
if (base_material.is_null()) {
2662
materials.push_back(mat_dict);
2663
continue;
2664
}
2665
2666
Dictionary mr;
2667
{
2668
const Color c = base_material->get_albedo().srgb_to_linear();
2669
Array arr = { c.r, c.g, c.b, c.a };
2670
mr["baseColorFactor"] = arr;
2671
}
2672
if (_image_format != "None") {
2673
Dictionary bct;
2674
Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
2675
GLTFTextureIndex gltf_texture_index = -1;
2676
2677
if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
2678
_set_material_texture_name(albedo_texture, albedo_texture->get_path(), mat_name, "_albedo");
2679
gltf_texture_index = _set_texture(p_state, albedo_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
2680
}
2681
if (gltf_texture_index != -1) {
2682
bct["index"] = gltf_texture_index;
2683
Dictionary extensions = _serialize_texture_transform_uv1(material);
2684
if (!extensions.is_empty()) {
2685
bct["extensions"] = extensions;
2686
p_state->use_khr_texture_transform = true;
2687
}
2688
mr["baseColorTexture"] = bct;
2689
}
2690
}
2691
2692
mr["metallicFactor"] = base_material->get_metallic();
2693
mr["roughnessFactor"] = base_material->get_roughness();
2694
if (_image_format != "None") {
2695
bool has_roughness = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_image().is_valid();
2696
bool has_ao = base_material->get_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION) && base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid();
2697
bool has_metalness = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_image().is_valid();
2698
Ref<Texture2D> original_orm_tex = base_material->get_texture(BaseMaterial3D::TEXTURE_ORM);
2699
GLTFTextureIndex orm_texture_index = -1;
2700
if (has_ao || has_roughness || has_metalness) {
2701
Ref<Texture2D> roughness_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS);
2702
BaseMaterial3D::TextureChannel roughness_channel = base_material->get_roughness_texture_channel();
2703
Ref<Texture2D> metallic_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC);
2704
BaseMaterial3D::TextureChannel metalness_channel = base_material->get_metallic_texture_channel();
2705
Ref<Texture2D> ao_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION);
2706
BaseMaterial3D::TextureChannel ao_channel = base_material->get_ao_texture_channel();
2707
Ref<ImageTexture> orm_texture;
2708
orm_texture.instantiate();
2709
Ref<Image> orm_image;
2710
orm_image.instantiate();
2711
int32_t height = 0;
2712
int32_t width = 0;
2713
Ref<Image> ao_image;
2714
HashSet<String> common_paths; // For setting name
2715
if (has_ao) {
2716
height = ao_texture->get_height();
2717
width = ao_texture->get_width();
2718
ao_image = _duplicate_and_decompress_image(ao_texture->get_image());
2719
if (!ao_texture->get_path().is_empty()) {
2720
common_paths.insert(ao_texture->get_path());
2721
}
2722
}
2723
Ref<Image> roughness_image;
2724
if (has_roughness) {
2725
height = roughness_texture->get_height();
2726
width = roughness_texture->get_width();
2727
roughness_image = _duplicate_and_decompress_image(roughness_texture->get_image());
2728
if (!roughness_texture->get_path().is_empty()) {
2729
common_paths.insert(roughness_texture->get_path());
2730
}
2731
}
2732
Ref<Image> metallness_image;
2733
if (has_metalness) {
2734
height = metallic_texture->get_height();
2735
width = metallic_texture->get_width();
2736
metallness_image = _duplicate_and_decompress_image(metallic_texture->get_image());
2737
if (!metallic_texture->get_path().is_empty()) {
2738
common_paths.insert(metallic_texture->get_path());
2739
}
2740
}
2741
Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
2742
if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
2743
height = albedo_texture->get_height();
2744
width = albedo_texture->get_width();
2745
}
2746
orm_image->initialize_data(width, height, false, Image::FORMAT_RGBA8);
2747
if (ao_image.is_valid() && ao_image->get_size() != Vector2(width, height)) {
2748
ao_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
2749
}
2750
if (roughness_image.is_valid() && roughness_image->get_size() != Vector2(width, height)) {
2751
roughness_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
2752
}
2753
if (metallness_image.is_valid() && metallness_image->get_size() != Vector2(width, height)) {
2754
metallness_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
2755
}
2756
for (int32_t h = 0; h < height; h++) {
2757
for (int32_t w = 0; w < width; w++) {
2758
Color c = Color(1.0f, 1.0f, 1.0f);
2759
if (has_ao) {
2760
if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == ao_channel) {
2761
c.r = ao_image->get_pixel(w, h).r;
2762
} else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == ao_channel) {
2763
c.r = ao_image->get_pixel(w, h).g;
2764
} else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == ao_channel) {
2765
c.r = ao_image->get_pixel(w, h).b;
2766
} else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == ao_channel) {
2767
c.r = ao_image->get_pixel(w, h).a;
2768
}
2769
}
2770
if (has_roughness) {
2771
if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == roughness_channel) {
2772
c.g = roughness_image->get_pixel(w, h).r;
2773
} else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == roughness_channel) {
2774
c.g = roughness_image->get_pixel(w, h).g;
2775
} else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == roughness_channel) {
2776
c.g = roughness_image->get_pixel(w, h).b;
2777
} else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == roughness_channel) {
2778
c.g = roughness_image->get_pixel(w, h).a;
2779
}
2780
}
2781
if (has_metalness) {
2782
if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == metalness_channel) {
2783
c.b = metallness_image->get_pixel(w, h).r;
2784
} else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == metalness_channel) {
2785
c.b = metallness_image->get_pixel(w, h).g;
2786
} else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == metalness_channel) {
2787
c.b = metallness_image->get_pixel(w, h).b;
2788
} else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == metalness_channel) {
2789
c.b = metallness_image->get_pixel(w, h).a;
2790
}
2791
}
2792
orm_image->set_pixel(w, h, c);
2793
}
2794
}
2795
orm_image->generate_mipmaps();
2796
orm_texture->set_image(orm_image);
2797
if (has_ao || has_roughness || has_metalness) {
2798
// If they all share the same path, use it for the name.
2799
const String path = common_paths.size() == 1 ? *common_paths.begin() : String();
2800
_set_material_texture_name(orm_texture, path, mat_name, "_orm");
2801
orm_texture_index = _set_texture(p_state, orm_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
2802
}
2803
} else if (original_orm_tex.is_valid() && original_orm_tex->get_image().is_valid()) {
2804
has_ao = true;
2805
has_roughness = true;
2806
has_metalness = true;
2807
2808
_set_material_texture_name(original_orm_tex, original_orm_tex->get_path(), mat_name, "_orm");
2809
orm_texture_index = _set_texture(p_state, original_orm_tex, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
2810
}
2811
if (orm_texture_index != -1) {
2812
if (has_ao) {
2813
Dictionary occt;
2814
occt["index"] = orm_texture_index;
2815
mat_dict["occlusionTexture"] = occt;
2816
}
2817
if (has_roughness || has_metalness) {
2818
Dictionary mrt;
2819
mrt["index"] = orm_texture_index;
2820
Dictionary extensions = _serialize_texture_transform_uv1(material);
2821
if (!extensions.is_empty()) {
2822
mrt["extensions"] = extensions;
2823
p_state->use_khr_texture_transform = true;
2824
}
2825
mr["metallicRoughnessTexture"] = mrt;
2826
}
2827
}
2828
}
2829
2830
mat_dict["pbrMetallicRoughness"] = mr;
2831
if (base_material->get_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING) && _image_format != "None") {
2832
Dictionary nt;
2833
Ref<ImageTexture> tex;
2834
tex.instantiate();
2835
String path;
2836
{
2837
Ref<Texture2D> normal_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_NORMAL);
2838
if (normal_texture.is_valid() && normal_texture->get_image().is_valid()) {
2839
path = normal_texture->get_path();
2840
// Code for uncompressing RG normal maps
2841
Ref<Image> img = _duplicate_and_decompress_image(normal_texture->get_image());
2842
img->convert(Image::FORMAT_RGBA8);
2843
for (int32_t y = 0; y < img->get_height(); y++) {
2844
for (int32_t x = 0; x < img->get_width(); x++) {
2845
Color c = img->get_pixel(x, y);
2846
Vector2 red_green = Vector2(c.r, c.g);
2847
red_green = red_green * Vector2(2.0f, 2.0f) - Vector2(1.0f, 1.0f);
2848
float blue = 1.0f - red_green.dot(red_green);
2849
blue = MAX(0.0f, blue);
2850
c.b = Math::sqrt(blue);
2851
img->set_pixel(x, y, c);
2852
}
2853
}
2854
tex->set_image(img);
2855
}
2856
}
2857
GLTFTextureIndex gltf_texture_index = -1;
2858
if (tex.is_valid() && tex->get_image().is_valid()) {
2859
_set_material_texture_name(tex, path, mat_name, "_normal");
2860
gltf_texture_index = _set_texture(p_state, tex, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
2861
}
2862
nt["scale"] = base_material->get_normal_scale();
2863
if (gltf_texture_index != -1) {
2864
nt["index"] = gltf_texture_index;
2865
mat_dict["normalTexture"] = nt;
2866
}
2867
}
2868
2869
if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
2870
const Color c = base_material->get_emission().linear_to_srgb();
2871
Array arr = { c.r, c.g, c.b };
2872
mat_dict["emissiveFactor"] = arr;
2873
}
2874
2875
if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION) && _image_format != "None") {
2876
Dictionary et;
2877
Ref<Texture2D> emission_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_EMISSION);
2878
GLTFTextureIndex gltf_texture_index = -1;
2879
if (emission_texture.is_valid() && emission_texture->get_image().is_valid()) {
2880
_set_material_texture_name(emission_texture, emission_texture->get_path(), mat_name, "_emission");
2881
gltf_texture_index = _set_texture(p_state, emission_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
2882
}
2883
2884
if (gltf_texture_index != -1) {
2885
et["index"] = gltf_texture_index;
2886
mat_dict["emissiveTexture"] = et;
2887
}
2888
}
2889
2890
const bool ds = base_material->get_cull_mode() == BaseMaterial3D::CULL_DISABLED;
2891
if (ds) {
2892
mat_dict["doubleSided"] = ds;
2893
}
2894
2895
if (base_material->get_transparency() == BaseMaterial3D::TRANSPARENCY_ALPHA_SCISSOR) {
2896
mat_dict["alphaMode"] = "MASK";
2897
mat_dict["alphaCutoff"] = base_material->get_alpha_scissor_threshold();
2898
} else if (base_material->get_transparency() != BaseMaterial3D::TRANSPARENCY_DISABLED) {
2899
mat_dict["alphaMode"] = "BLEND";
2900
}
2901
2902
Dictionary extensions;
2903
if (base_material->get_shading_mode() == BaseMaterial3D::SHADING_MODE_UNSHADED) {
2904
Dictionary mat_unlit;
2905
extensions["KHR_materials_unlit"] = mat_unlit;
2906
p_state->add_used_extension("KHR_materials_unlit");
2907
}
2908
if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION) && !Math::is_equal_approx(base_material->get_emission_energy_multiplier(), 1.0f)) {
2909
Dictionary mat_emissive_strength;
2910
mat_emissive_strength["emissiveStrength"] = base_material->get_emission_energy_multiplier();
2911
extensions["KHR_materials_emissive_strength"] = mat_emissive_strength;
2912
p_state->add_used_extension("KHR_materials_emissive_strength");
2913
}
2914
if (!extensions.is_empty()) {
2915
mat_dict["extensions"] = extensions;
2916
}
2917
2918
_attach_meta_to_extras(material, mat_dict);
2919
materials.push_back(mat_dict);
2920
}
2921
if (!materials.size()) {
2922
return OK;
2923
}
2924
p_state->json["materials"] = materials;
2925
print_verbose("Total materials: " + itos(p_state->materials.size()));
2926
2927
return OK;
2928
}
2929
2930
Error GLTFDocument::_parse_materials(Ref<GLTFState> p_state) {
2931
if (!p_state->json.has("materials")) {
2932
return OK;
2933
}
2934
2935
const Array &materials = p_state->json["materials"];
2936
for (GLTFMaterialIndex i = 0; i < materials.size(); i++) {
2937
const Dictionary &material_dict = materials[i];
2938
2939
Ref<StandardMaterial3D> material;
2940
material.instantiate();
2941
if (material_dict.has("name") && !String(material_dict["name"]).is_empty()) {
2942
material->set_name(material_dict["name"]);
2943
} else {
2944
material->set_name(vformat("material_%s", itos(i)));
2945
}
2946
Dictionary material_extensions;
2947
if (material_dict.has("extensions")) {
2948
material_extensions = material_dict["extensions"];
2949
}
2950
2951
if (material_extensions.has("KHR_materials_unlit")) {
2952
material->set_shading_mode(BaseMaterial3D::SHADING_MODE_UNSHADED);
2953
}
2954
2955
if (material_extensions.has("KHR_materials_emissive_strength")) {
2956
Dictionary emissive_strength = material_extensions["KHR_materials_emissive_strength"];
2957
if (emissive_strength.has("emissiveStrength")) {
2958
material->set_emission_energy_multiplier(emissive_strength["emissiveStrength"]);
2959
}
2960
}
2961
2962
if (material_extensions.has("KHR_materials_pbrSpecularGlossiness")) {
2963
WARN_PRINT("Material uses a specular and glossiness workflow. Textures will be converted to roughness and metallic workflow, which may not be 100% accurate.");
2964
Dictionary sgm = material_extensions["KHR_materials_pbrSpecularGlossiness"];
2965
2966
Ref<GLTFSpecGloss> spec_gloss;
2967
spec_gloss.instantiate();
2968
if (sgm.has("diffuseTexture")) {
2969
const Dictionary &diffuse_texture_dict = sgm["diffuseTexture"];
2970
if (diffuse_texture_dict.has("index")) {
2971
Ref<GLTFTextureSampler> diffuse_sampler = _get_sampler_for_texture(p_state, diffuse_texture_dict["index"]);
2972
if (diffuse_sampler.is_valid()) {
2973
material->set_texture_filter(diffuse_sampler->get_filter_mode());
2974
material->set_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT, diffuse_sampler->get_wrap_mode());
2975
}
2976
Ref<Texture2D> diffuse_texture = _get_texture(p_state, diffuse_texture_dict["index"], TEXTURE_TYPE_GENERIC);
2977
if (diffuse_texture.is_valid()) {
2978
spec_gloss->diffuse_img = diffuse_texture->get_image();
2979
material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, diffuse_texture);
2980
}
2981
}
2982
}
2983
if (sgm.has("diffuseFactor")) {
2984
const Array &arr = sgm["diffuseFactor"];
2985
ERR_FAIL_COND_V(arr.size() != 4, ERR_PARSE_ERROR);
2986
const Color c = Color(arr[0], arr[1], arr[2], arr[3]).linear_to_srgb();
2987
spec_gloss->diffuse_factor = c;
2988
material->set_albedo(spec_gloss->diffuse_factor);
2989
}
2990
2991
if (sgm.has("specularFactor")) {
2992
const Array &arr = sgm["specularFactor"];
2993
ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR);
2994
spec_gloss->specular_factor = Color(arr[0], arr[1], arr[2]);
2995
}
2996
2997
if (sgm.has("glossinessFactor")) {
2998
spec_gloss->gloss_factor = sgm["glossinessFactor"];
2999
material->set_roughness(1.0f - CLAMP(spec_gloss->gloss_factor, 0.0f, 1.0f));
3000
}
3001
if (sgm.has("specularGlossinessTexture")) {
3002
const Dictionary &spec_gloss_texture = sgm["specularGlossinessTexture"];
3003
if (spec_gloss_texture.has("index")) {
3004
const Ref<Texture2D> orig_texture = _get_texture(p_state, spec_gloss_texture["index"], TEXTURE_TYPE_GENERIC);
3005
if (orig_texture.is_valid()) {
3006
spec_gloss->spec_gloss_img = orig_texture->get_image();
3007
}
3008
}
3009
}
3010
spec_gloss_to_rough_metal(spec_gloss, material);
3011
3012
} else if (material_dict.has("pbrMetallicRoughness")) {
3013
const Dictionary &mr = material_dict["pbrMetallicRoughness"];
3014
if (mr.has("baseColorFactor")) {
3015
const Array &arr = mr["baseColorFactor"];
3016
ERR_FAIL_COND_V(arr.size() != 4, ERR_PARSE_ERROR);
3017
const Color c = Color(arr[0], arr[1], arr[2], arr[3]).linear_to_srgb();
3018
material->set_albedo(c);
3019
}
3020
3021
if (mr.has("baseColorTexture")) {
3022
const Dictionary &bct = mr["baseColorTexture"];
3023
if (bct.has("index")) {
3024
const GLTFTextureIndex base_color_texture_index = bct["index"];
3025
material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, _get_texture(p_state, base_color_texture_index, TEXTURE_TYPE_GENERIC));
3026
const Ref<GLTFTextureSampler> bct_sampler = _get_sampler_for_texture(p_state, base_color_texture_index);
3027
if (bct_sampler.is_valid()) {
3028
material->set_texture_filter(bct_sampler->get_filter_mode());
3029
material->set_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT, bct_sampler->get_wrap_mode());
3030
}
3031
}
3032
if (!mr.has("baseColorFactor")) {
3033
material->set_albedo(Color(1, 1, 1));
3034
}
3035
_set_texture_transform_uv1(bct, material);
3036
}
3037
3038
if (mr.has("metallicFactor")) {
3039
material->set_metallic(mr["metallicFactor"]);
3040
} else {
3041
material->set_metallic(1.0);
3042
}
3043
3044
if (mr.has("roughnessFactor")) {
3045
material->set_roughness(mr["roughnessFactor"]);
3046
} else {
3047
material->set_roughness(1.0);
3048
}
3049
3050
if (mr.has("metallicRoughnessTexture")) {
3051
const Dictionary &bct = mr["metallicRoughnessTexture"];
3052
if (bct.has("index")) {
3053
const Ref<Texture2D> t = _get_texture(p_state, bct["index"], TEXTURE_TYPE_GENERIC);
3054
material->set_texture(BaseMaterial3D::TEXTURE_METALLIC, t);
3055
material->set_metallic_texture_channel(BaseMaterial3D::TEXTURE_CHANNEL_BLUE);
3056
material->set_texture(BaseMaterial3D::TEXTURE_ROUGHNESS, t);
3057
material->set_roughness_texture_channel(BaseMaterial3D::TEXTURE_CHANNEL_GREEN);
3058
if (!mr.has("metallicFactor")) {
3059
material->set_metallic(1);
3060
}
3061
if (!mr.has("roughnessFactor")) {
3062
material->set_roughness(1);
3063
}
3064
}
3065
}
3066
}
3067
3068
if (material_dict.has("normalTexture")) {
3069
const Dictionary &bct = material_dict["normalTexture"];
3070
if (bct.has("index")) {
3071
material->set_texture(BaseMaterial3D::TEXTURE_NORMAL, _get_texture(p_state, bct["index"], TEXTURE_TYPE_NORMAL));
3072
material->set_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING, true);
3073
}
3074
if (bct.has("scale")) {
3075
material->set_normal_scale(bct["scale"]);
3076
}
3077
}
3078
if (material_dict.has("occlusionTexture")) {
3079
const Dictionary &bct = material_dict["occlusionTexture"];
3080
if (bct.has("index")) {
3081
material->set_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION, _get_texture(p_state, bct["index"], TEXTURE_TYPE_GENERIC));
3082
material->set_ao_texture_channel(BaseMaterial3D::TEXTURE_CHANNEL_RED);
3083
material->set_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION, true);
3084
}
3085
}
3086
3087
if (material_dict.has("emissiveFactor")) {
3088
const Array &arr = material_dict["emissiveFactor"];
3089
ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR);
3090
const Color c = Color(arr[0], arr[1], arr[2]).linear_to_srgb();
3091
material->set_feature(BaseMaterial3D::FEATURE_EMISSION, true);
3092
3093
material->set_emission(c);
3094
}
3095
3096
if (material_dict.has("emissiveTexture")) {
3097
const Dictionary &bct = material_dict["emissiveTexture"];
3098
if (bct.has("index")) {
3099
material->set_texture(BaseMaterial3D::TEXTURE_EMISSION, _get_texture(p_state, bct["index"], TEXTURE_TYPE_GENERIC));
3100
material->set_feature(BaseMaterial3D::FEATURE_EMISSION, true);
3101
material->set_emission_operator(BaseMaterial3D::EMISSION_OP_MULTIPLY);
3102
// glTF spec: emissiveFactor × emissiveTexture. Use WHITE if no factor specified.
3103
if (!material_dict.has("emissiveFactor")) {
3104
material->set_emission(Color(1, 1, 1));
3105
}
3106
}
3107
}
3108
3109
if (material_dict.has("doubleSided")) {
3110
const bool ds = material_dict["doubleSided"];
3111
if (ds) {
3112
material->set_cull_mode(BaseMaterial3D::CULL_DISABLED);
3113
}
3114
}
3115
if (material_dict.has("alphaMode")) {
3116
const String &am = material_dict["alphaMode"];
3117
if (am == "BLEND") {
3118
material->set_transparency(BaseMaterial3D::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS);
3119
} else if (am == "MASK") {
3120
material->set_transparency(BaseMaterial3D::TRANSPARENCY_ALPHA_SCISSOR);
3121
}
3122
}
3123
if (material_dict.has("alphaCutoff")) {
3124
material->set_alpha_scissor_threshold(material_dict["alphaCutoff"]);
3125
} else {
3126
material->set_alpha_scissor_threshold(0.5f);
3127
}
3128
3129
if (material_dict.has("extras")) {
3130
_attach_extras_to_meta(material_dict["extras"], material);
3131
}
3132
p_state->materials.push_back(material);
3133
}
3134
3135
print_verbose("Total materials: " + itos(p_state->materials.size()));
3136
3137
return OK;
3138
}
3139
3140
void GLTFDocument::_set_texture_transform_uv1(const Dictionary &p_dict, Ref<BaseMaterial3D> p_material) {
3141
if (p_dict.has("extensions")) {
3142
const Dictionary &extensions = p_dict["extensions"];
3143
if (extensions.has("KHR_texture_transform")) {
3144
if (p_material.is_valid()) {
3145
const Dictionary &texture_transform = extensions["KHR_texture_transform"];
3146
if (texture_transform.has("offset")) {
3147
const Array offset_arr = texture_transform["offset"];
3148
if (offset_arr.size() == 2) {
3149
const Vector3 offset_vector3 = Vector3(offset_arr[0], offset_arr[1], 0.0f);
3150
p_material->set_uv1_offset(offset_vector3);
3151
}
3152
}
3153
3154
if (texture_transform.has("scale")) {
3155
const Array scale_arr = texture_transform["scale"];
3156
if (scale_arr.size() == 2) {
3157
const Vector3 scale_vector3 = Vector3(scale_arr[0], scale_arr[1], 1.0f);
3158
p_material->set_uv1_scale(scale_vector3);
3159
}
3160
}
3161
}
3162
}
3163
}
3164
}
3165
3166
void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Ref<BaseMaterial3D> p_material) {
3167
if (r_spec_gloss.is_null()) {
3168
return;
3169
}
3170
if (r_spec_gloss->spec_gloss_img.is_null()) {
3171
return;
3172
}
3173
if (r_spec_gloss->diffuse_img.is_null()) {
3174
return;
3175
}
3176
if (p_material.is_null()) {
3177
return;
3178
}
3179
bool has_roughness = false;
3180
bool has_metal = false;
3181
p_material->set_roughness(1.0f);
3182
p_material->set_metallic(1.0f);
3183
Ref<Image> rm_img = Image::create_empty(r_spec_gloss->spec_gloss_img->get_width(), r_spec_gloss->spec_gloss_img->get_height(), false, Image::FORMAT_RGBA8);
3184
r_spec_gloss->spec_gloss_img->decompress();
3185
if (r_spec_gloss->diffuse_img.is_valid()) {
3186
r_spec_gloss->diffuse_img->decompress();
3187
r_spec_gloss->diffuse_img->resize(r_spec_gloss->spec_gloss_img->get_width(), r_spec_gloss->spec_gloss_img->get_height(), Image::INTERPOLATE_LANCZOS);
3188
r_spec_gloss->spec_gloss_img->resize(r_spec_gloss->diffuse_img->get_width(), r_spec_gloss->diffuse_img->get_height(), Image::INTERPOLATE_LANCZOS);
3189
}
3190
for (int32_t y = 0; y < r_spec_gloss->spec_gloss_img->get_height(); y++) {
3191
for (int32_t x = 0; x < r_spec_gloss->spec_gloss_img->get_width(); x++) {
3192
const Color specular_pixel = r_spec_gloss->spec_gloss_img->get_pixel(x, y).srgb_to_linear();
3193
Color specular = Color(specular_pixel.r, specular_pixel.g, specular_pixel.b);
3194
specular *= r_spec_gloss->specular_factor;
3195
Color diffuse = Color(1.0f, 1.0f, 1.0f);
3196
diffuse *= r_spec_gloss->diffuse_img->get_pixel(x, y).srgb_to_linear();
3197
float metallic = 0.0f;
3198
Color base_color;
3199
spec_gloss_to_metal_base_color(specular, diffuse, base_color, metallic);
3200
Color mr = Color(1.0f, 1.0f, 1.0f);
3201
mr.g = specular_pixel.a;
3202
mr.b = metallic;
3203
if (!Math::is_equal_approx(mr.g, 1.0f)) {
3204
has_roughness = true;
3205
}
3206
if (!Math::is_zero_approx(mr.b)) {
3207
has_metal = true;
3208
}
3209
mr.g *= r_spec_gloss->gloss_factor;
3210
mr.g = 1.0f - mr.g;
3211
rm_img->set_pixel(x, y, mr);
3212
if (r_spec_gloss->diffuse_img.is_valid()) {
3213
r_spec_gloss->diffuse_img->set_pixel(x, y, base_color.linear_to_srgb());
3214
}
3215
}
3216
}
3217
rm_img->generate_mipmaps();
3218
r_spec_gloss->diffuse_img->generate_mipmaps();
3219
p_material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, ImageTexture::create_from_image(r_spec_gloss->diffuse_img));
3220
Ref<ImageTexture> rm_image_texture = ImageTexture::create_from_image(rm_img);
3221
if (has_roughness) {
3222
p_material->set_texture(BaseMaterial3D::TEXTURE_ROUGHNESS, rm_image_texture);
3223
p_material->set_roughness_texture_channel(BaseMaterial3D::TEXTURE_CHANNEL_GREEN);
3224
}
3225
3226
if (has_metal) {
3227
p_material->set_texture(BaseMaterial3D::TEXTURE_METALLIC, rm_image_texture);
3228
p_material->set_metallic_texture_channel(BaseMaterial3D::TEXTURE_CHANNEL_BLUE);
3229
}
3230
}
3231
3232
void GLTFDocument::spec_gloss_to_metal_base_color(const Color &p_specular_factor, const Color &p_diffuse, Color &r_base_color, float &r_metallic) {
3233
const Color DIELECTRIC_SPECULAR = Color(0.04f, 0.04f, 0.04f);
3234
Color specular = Color(p_specular_factor.r, p_specular_factor.g, p_specular_factor.b);
3235
const float one_minus_specular_strength = 1.0f - get_max_component(specular);
3236
const float dielectric_specular_red = DIELECTRIC_SPECULAR.r;
3237
float brightness_diffuse = get_perceived_brightness(p_diffuse);
3238
const float brightness_specular = get_perceived_brightness(specular);
3239
r_metallic = solve_metallic(dielectric_specular_red, brightness_diffuse, brightness_specular, one_minus_specular_strength);
3240
const float one_minus_metallic = 1.0f - r_metallic;
3241
const Color base_color_from_diffuse = p_diffuse * (one_minus_specular_strength / (1.0f - dielectric_specular_red) / MAX(one_minus_metallic, CMP_EPSILON));
3242
const Color base_color_from_specular = (specular - (DIELECTRIC_SPECULAR * (one_minus_metallic))) * (1.0f / MAX(r_metallic, CMP_EPSILON));
3243
r_base_color.r = Math::lerp(base_color_from_diffuse.r, base_color_from_specular.r, r_metallic * r_metallic);
3244
r_base_color.g = Math::lerp(base_color_from_diffuse.g, base_color_from_specular.g, r_metallic * r_metallic);
3245
r_base_color.b = Math::lerp(base_color_from_diffuse.b, base_color_from_specular.b, r_metallic * r_metallic);
3246
r_base_color.a = p_diffuse.a;
3247
r_base_color = r_base_color.clamp();
3248
}
3249
Error GLTFDocument::_parse_skins(Ref<GLTFState> p_state) {
3250
if (!p_state->json.has("skins")) {
3251
return OK;
3252
}
3253
3254
const Array &skins = p_state->json["skins"];
3255
3256
// Create the base skins, and mark nodes that are joints
3257
for (int i = 0; i < skins.size(); i++) {
3258
const Dictionary &d = skins[i];
3259
3260
Ref<GLTFSkin> skin;
3261
skin.instantiate();
3262
3263
ERR_FAIL_COND_V(!d.has("joints"), ERR_PARSE_ERROR);
3264
3265
const Array &joints = d["joints"];
3266
3267
if (d.has("inverseBindMatrices")) {
3268
const GLTFAccessorIndex inv_bind_accessor_index = d["inverseBindMatrices"];
3269
Array inv_binds_arr = _decode_accessor_as_variants(p_state, inv_bind_accessor_index, Variant::TRANSFORM3D);
3270
ERR_FAIL_COND_V(inv_binds_arr.size() != joints.size(), ERR_PARSE_ERROR);
3271
GLTFTemplateConvert::set_from_array(skin->inverse_binds, inv_binds_arr);
3272
}
3273
3274
for (int j = 0; j < joints.size(); j++) {
3275
const GLTFNodeIndex node = joints[j];
3276
ERR_FAIL_INDEX_V(node, p_state->nodes.size(), ERR_PARSE_ERROR);
3277
3278
skin->joints.push_back(node);
3279
skin->joints_original.push_back(node);
3280
3281
p_state->nodes.write[node]->joint = true;
3282
}
3283
3284
if (d.has("name") && !String(d["name"]).is_empty()) {
3285
skin->set_name(d["name"]);
3286
} else {
3287
skin->set_name(vformat("skin_%s", itos(i)));
3288
}
3289
3290
if (d.has("skeleton")) {
3291
skin->skin_root = d["skeleton"];
3292
}
3293
3294
p_state->skins.push_back(skin);
3295
}
3296
3297
for (GLTFSkinIndex i = 0; i < p_state->skins.size(); ++i) {
3298
Ref<GLTFSkin> skin = p_state->skins.write[i];
3299
3300
// Expand the skin to capture all the extra non-joints that lie in between the actual joints,
3301
// and expand the hierarchy to ensure multi-rooted trees lie on the same height level
3302
ERR_FAIL_COND_V(SkinTool::_expand_skin(p_state->nodes, skin), ERR_PARSE_ERROR);
3303
ERR_FAIL_COND_V(SkinTool::_verify_skin(p_state->nodes, skin), ERR_PARSE_ERROR);
3304
}
3305
3306
print_verbose("glTF: Total skins: " + itos(p_state->skins.size()));
3307
3308
return OK;
3309
}
3310
Error GLTFDocument::_serialize_skins(Ref<GLTFState> p_state) {
3311
_remove_duplicate_skins(p_state);
3312
Array json_skins;
3313
for (int skin_i = 0; skin_i < p_state->skins.size(); skin_i++) {
3314
Ref<GLTFSkin> gltf_skin = p_state->skins[skin_i];
3315
Dictionary json_skin;
3316
Array inv_binds_arr = GLTFTemplateConvert::to_array(gltf_skin->inverse_binds);
3317
json_skin["inverseBindMatrices"] = GLTFAccessor::encode_new_accessor_from_variants(p_state, inv_binds_arr, Variant::TRANSFORM3D, GLTFAccessor::TYPE_MAT4, GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT);
3318
json_skin["joints"] = gltf_skin->get_joints();
3319
json_skin["name"] = gltf_skin->get_name();
3320
json_skins.push_back(json_skin);
3321
}
3322
if (!p_state->skins.size()) {
3323
return OK;
3324
}
3325
3326
p_state->json["skins"] = json_skins;
3327
return OK;
3328
}
3329
3330
Error GLTFDocument::_create_skins(Ref<GLTFState> p_state) {
3331
for (GLTFSkinIndex skin_i = 0; skin_i < p_state->skins.size(); ++skin_i) {
3332
Ref<GLTFSkin> gltf_skin = p_state->skins.write[skin_i];
3333
3334
Ref<Skin> skin;
3335
skin.instantiate();
3336
3337
// Some skins don't have IBM's! What absolute monsters!
3338
const bool has_ibms = !gltf_skin->inverse_binds.is_empty();
3339
3340
for (int joint_i = 0; joint_i < gltf_skin->joints_original.size(); ++joint_i) {
3341
GLTFNodeIndex node = gltf_skin->joints_original[joint_i];
3342
String bone_name = p_state->nodes[node]->get_name();
3343
3344
Transform3D xform;
3345
if (has_ibms) {
3346
xform = gltf_skin->inverse_binds[joint_i];
3347
}
3348
3349
if (p_state->use_named_skin_binds) {
3350
skin->add_named_bind(bone_name, xform);
3351
} else {
3352
int32_t bone_i = gltf_skin->joint_i_to_bone_i[joint_i];
3353
skin->add_bind(bone_i, xform);
3354
}
3355
}
3356
3357
gltf_skin->godot_skin = skin;
3358
}
3359
3360
// Purge the duplicates!
3361
_remove_duplicate_skins(p_state);
3362
3363
// Create unique names now, after removing duplicates
3364
for (GLTFSkinIndex skin_i = 0; skin_i < p_state->skins.size(); ++skin_i) {
3365
Ref<Skin> skin = p_state->skins.write[skin_i]->godot_skin;
3366
if (skin->get_name().is_empty()) {
3367
// Make a unique name, no gltf node represents this skin
3368
skin->set_name(_gen_unique_name(p_state, "Skin"));
3369
}
3370
}
3371
3372
return OK;
3373
}
3374
3375
bool GLTFDocument::_skins_are_same(const Ref<Skin> &p_skin_a, const Ref<Skin> &p_skin_b) {
3376
if (p_skin_a->get_bind_count() != p_skin_b->get_bind_count()) {
3377
return false;
3378
}
3379
3380
for (int i = 0; i < p_skin_a->get_bind_count(); ++i) {
3381
if (p_skin_a->get_bind_bone(i) != p_skin_b->get_bind_bone(i)) {
3382
return false;
3383
}
3384
if (p_skin_a->get_bind_name(i) != p_skin_b->get_bind_name(i)) {
3385
return false;
3386
}
3387
3388
Transform3D a_xform = p_skin_a->get_bind_pose(i);
3389
Transform3D b_xform = p_skin_b->get_bind_pose(i);
3390
3391
if (a_xform != b_xform) {
3392
return false;
3393
}
3394
}
3395
3396
return true;
3397
}
3398
3399
void GLTFDocument::_remove_duplicate_skins(Ref<GLTFState> p_state) {
3400
for (int i = 0; i < p_state->skins.size(); ++i) {
3401
for (int j = i + 1; j < p_state->skins.size(); ++j) {
3402
const Ref<Skin> skin_i = p_state->skins[i]->godot_skin;
3403
const Ref<Skin> skin_j = p_state->skins[j]->godot_skin;
3404
3405
if (_skins_are_same(skin_i, skin_j)) {
3406
// replace it and delete the old
3407
p_state->skins.write[j]->godot_skin = skin_i;
3408
}
3409
}
3410
}
3411
}
3412
3413
Error GLTFDocument::_serialize_lights(Ref<GLTFState> p_state) {
3414
if (p_state->lights.is_empty()) {
3415
return OK;
3416
}
3417
Array lights;
3418
for (GLTFLightIndex i = 0; i < p_state->lights.size(); i++) {
3419
lights.push_back(p_state->lights[i]->to_dictionary());
3420
}
3421
3422
Dictionary extensions;
3423
if (p_state->json.has("extensions")) {
3424
extensions = p_state->json["extensions"];
3425
} else {
3426
p_state->json["extensions"] = extensions;
3427
}
3428
Dictionary lights_punctual;
3429
extensions["KHR_lights_punctual"] = lights_punctual;
3430
lights_punctual["lights"] = lights;
3431
3432
print_verbose("glTF: Total lights: " + itos(p_state->lights.size()));
3433
3434
return OK;
3435
}
3436
3437
Error GLTFDocument::_serialize_cameras(Ref<GLTFState> p_state) {
3438
Array cameras;
3439
cameras.resize(p_state->cameras.size());
3440
for (GLTFCameraIndex i = 0; i < p_state->cameras.size(); i++) {
3441
cameras[i] = p_state->cameras[i]->to_dictionary();
3442
}
3443
3444
if (!p_state->cameras.size()) {
3445
return OK;
3446
}
3447
3448
p_state->json["cameras"] = cameras;
3449
3450
print_verbose("glTF: Total cameras: " + itos(p_state->cameras.size()));
3451
3452
return OK;
3453
}
3454
3455
Error GLTFDocument::_parse_lights(Ref<GLTFState> p_state) {
3456
if (!p_state->json.has("extensions")) {
3457
return OK;
3458
}
3459
Dictionary extensions = p_state->json["extensions"];
3460
if (!extensions.has("KHR_lights_punctual")) {
3461
return OK;
3462
}
3463
Dictionary lights_punctual = extensions["KHR_lights_punctual"];
3464
if (!lights_punctual.has("lights")) {
3465
return OK;
3466
}
3467
3468
const Array &lights = lights_punctual["lights"];
3469
3470
for (GLTFLightIndex light_i = 0; light_i < lights.size(); light_i++) {
3471
Ref<GLTFLight> light = GLTFLight::from_dictionary(lights[light_i]);
3472
if (light.is_null()) {
3473
return Error::ERR_PARSE_ERROR;
3474
}
3475
p_state->lights.push_back(light);
3476
}
3477
3478
print_verbose("glTF: Total lights: " + itos(p_state->lights.size()));
3479
3480
return OK;
3481
}
3482
3483
Error GLTFDocument::_parse_cameras(Ref<GLTFState> p_state) {
3484
if (!p_state->json.has("cameras")) {
3485
return OK;
3486
}
3487
3488
const Array cameras = p_state->json["cameras"];
3489
3490
for (GLTFCameraIndex i = 0; i < cameras.size(); i++) {
3491
p_state->cameras.push_back(GLTFCamera::from_dictionary(cameras[i]));
3492
}
3493
3494
print_verbose("glTF: Total cameras: " + itos(p_state->cameras.size()));
3495
3496
return OK;
3497
}
3498
3499
String GLTFDocument::interpolation_to_string(const GLTFAnimation::Interpolation p_interp) {
3500
String interp = "LINEAR";
3501
if (p_interp == GLTFAnimation::INTERP_STEP) {
3502
interp = "STEP";
3503
} else if (p_interp == GLTFAnimation::INTERP_LINEAR) {
3504
interp = "LINEAR";
3505
} else if (p_interp == GLTFAnimation::INTERP_CATMULLROMSPLINE) {
3506
interp = "CATMULLROMSPLINE";
3507
} else if (p_interp == GLTFAnimation::INTERP_CUBIC_SPLINE) {
3508
interp = "CUBICSPLINE";
3509
}
3510
3511
return interp;
3512
}
3513
3514
Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) {
3515
if (!p_state->animation_players.size()) {
3516
return OK;
3517
}
3518
for (int32_t player_i = 0; player_i < p_state->animation_players.size(); player_i++) {
3519
AnimationPlayer *animation_player = p_state->animation_players[player_i];
3520
List<StringName> animations;
3521
animation_player->get_animation_list(&animations);
3522
for (const StringName &animation_name : animations) {
3523
_convert_animation(p_state, animation_player, animation_name);
3524
}
3525
}
3526
Array animations;
3527
for (GLTFAnimationIndex animation_i = 0; animation_i < p_state->animations.size(); animation_i++) {
3528
Dictionary d;
3529
Ref<GLTFAnimation> gltf_animation = p_state->animations[animation_i];
3530
if (gltf_animation->is_empty_of_tracks()) {
3531
continue;
3532
}
3533
3534
if (!gltf_animation->get_name().is_empty()) {
3535
d["name"] = gltf_animation->get_name();
3536
}
3537
Array channels;
3538
Array samplers;
3539
// Serialize glTF node tracks with the vanilla glTF animation system.
3540
for (KeyValue<int, GLTFAnimation::NodeTrack> &track_i : gltf_animation->get_node_tracks()) {
3541
GLTFAnimation::NodeTrack track = track_i.value;
3542
if (track.position_track.times.size()) {
3543
Dictionary t;
3544
t["sampler"] = samplers.size();
3545
Dictionary s;
3546
3547
s["interpolation"] = interpolation_to_string(track.position_track.interpolation);
3548
Vector<double> times = track.position_track.times;
3549
s["input"] = GLTFAccessor::encode_new_accessor_from_float64s(p_state, times);
3550
Vector<Vector3> values = track.position_track.values;
3551
s["output"] = GLTFAccessor::encode_new_accessor_from_vector3s(p_state, values);
3552
3553
samplers.push_back(s);
3554
3555
Dictionary target;
3556
target["path"] = "translation";
3557
target["node"] = track_i.key;
3558
3559
t["target"] = target;
3560
channels.push_back(t);
3561
}
3562
if (track.rotation_track.times.size()) {
3563
Dictionary t;
3564
t["sampler"] = samplers.size();
3565
Dictionary s;
3566
3567
s["interpolation"] = interpolation_to_string(track.rotation_track.interpolation);
3568
Vector<double> times = track.rotation_track.times;
3569
s["input"] = GLTFAccessor::encode_new_accessor_from_float64s(p_state, times);
3570
Vector<Quaternion> values = track.rotation_track.values;
3571
s["output"] = GLTFAccessor::encode_new_accessor_from_quaternions(p_state, values);
3572
3573
samplers.push_back(s);
3574
3575
Dictionary target;
3576
target["path"] = "rotation";
3577
target["node"] = track_i.key;
3578
3579
t["target"] = target;
3580
channels.push_back(t);
3581
}
3582
if (track.scale_track.times.size()) {
3583
Dictionary t;
3584
t["sampler"] = samplers.size();
3585
Dictionary s;
3586
3587
s["interpolation"] = interpolation_to_string(track.scale_track.interpolation);
3588
Vector<double> times = track.scale_track.times;
3589
s["input"] = GLTFAccessor::encode_new_accessor_from_float64s(p_state, times);
3590
Vector<Vector3> values = track.scale_track.values;
3591
s["output"] = GLTFAccessor::encode_new_accessor_from_vector3s(p_state, values);
3592
3593
samplers.push_back(s);
3594
3595
Dictionary target;
3596
target["path"] = "scale";
3597
target["node"] = track_i.key;
3598
3599
t["target"] = target;
3600
channels.push_back(t);
3601
}
3602
if (track.weight_tracks.size()) {
3603
double length = 0.0f;
3604
3605
for (int32_t track_idx = 0; track_idx < track.weight_tracks.size(); track_idx++) {
3606
int32_t last_time_index = track.weight_tracks[track_idx].times.size() - 1;
3607
length = MAX(length, track.weight_tracks[track_idx].times[last_time_index]);
3608
}
3609
3610
Dictionary t;
3611
t["sampler"] = samplers.size();
3612
Dictionary s;
3613
Vector<double> times;
3614
const double increment = 1.0 / p_state->get_bake_fps();
3615
{
3616
double time = 0.0;
3617
bool last = false;
3618
while (true) {
3619
times.push_back(time);
3620
if (last) {
3621
break;
3622
}
3623
time += increment;
3624
if (time >= length) {
3625
last = true;
3626
time = length;
3627
}
3628
}
3629
}
3630
3631
for (int32_t track_idx = 0; track_idx < track.weight_tracks.size(); track_idx++) {
3632
double time = 0.0;
3633
bool last = false;
3634
Vector<real_t> weight_track;
3635
while (true) {
3636
float weight = _interpolate_track<real_t>(track.weight_tracks[track_idx].times,
3637
track.weight_tracks[track_idx].values,
3638
time,
3639
track.weight_tracks[track_idx].interpolation);
3640
weight_track.push_back(weight);
3641
if (last) {
3642
break;
3643
}
3644
time += increment;
3645
if (time >= length) {
3646
last = true;
3647
time = length;
3648
}
3649
}
3650
track.weight_tracks.write[track_idx].times = times;
3651
track.weight_tracks.write[track_idx].values = weight_track;
3652
}
3653
3654
Vector<double> all_track_times = times;
3655
Vector<double> all_track_values;
3656
int32_t values_size = track.weight_tracks[0].values.size();
3657
int32_t weight_tracks_size = track.weight_tracks.size();
3658
all_track_values.resize(weight_tracks_size * values_size);
3659
for (int k = 0; k < track.weight_tracks.size(); k++) {
3660
Vector<real_t> wdata = track.weight_tracks[k].values;
3661
for (int l = 0; l < wdata.size(); l++) {
3662
int32_t index = l * weight_tracks_size + k;
3663
ERR_BREAK(index >= all_track_values.size());
3664
all_track_values.write[index] = wdata.write[l];
3665
}
3666
}
3667
3668
s["interpolation"] = interpolation_to_string(track.weight_tracks[track.weight_tracks.size() - 1].interpolation);
3669
s["input"] = GLTFAccessor::encode_new_accessor_from_float64s(p_state, all_track_times);
3670
s["output"] = GLTFAccessor::encode_new_accessor_from_float64s(p_state, all_track_values);
3671
3672
samplers.push_back(s);
3673
3674
Dictionary target;
3675
target["path"] = "weights";
3676
target["node"] = track_i.key;
3677
3678
t["target"] = target;
3679
channels.push_back(t);
3680
}
3681
}
3682
if (!gltf_animation->get_pointer_tracks().is_empty()) {
3683
// Serialize glTF pointer tracks with the KHR_animation_pointer extension.
3684
if (!p_state->extensions_used.has("KHR_animation_pointer")) {
3685
p_state->extensions_used.push_back("KHR_animation_pointer");
3686
}
3687
for (KeyValue<String, GLTFAnimation::Channel<Variant>> &pointer_track_iter : gltf_animation->get_pointer_tracks()) {
3688
const String &json_pointer = pointer_track_iter.key;
3689
const GLTFAnimation::Channel<Variant> &pointer_track = pointer_track_iter.value;
3690
const Ref<GLTFObjectModelProperty> &obj_model_prop = p_state->object_model_properties[json_pointer];
3691
Dictionary channel;
3692
channel["sampler"] = samplers.size();
3693
Dictionary channel_target;
3694
channel_target["path"] = "pointer";
3695
Dictionary channel_target_ext;
3696
Dictionary channel_target_ext_khr_anim_ptr;
3697
channel_target_ext_khr_anim_ptr["pointer"] = json_pointer;
3698
channel_target_ext["KHR_animation_pointer"] = channel_target_ext_khr_anim_ptr;
3699
channel_target["extensions"] = channel_target_ext;
3700
channel["target"] = channel_target;
3701
channels.push_back(channel);
3702
Dictionary sampler;
3703
sampler["input"] = GLTFAccessor::encode_new_accessor_from_float64s(p_state, pointer_track.times);
3704
sampler["interpolation"] = interpolation_to_string(pointer_track.interpolation);
3705
GLTFAccessor::GLTFComponentType component_type = obj_model_prop->get_component_type(pointer_track.values);
3706
// TODO: This can be made faster after this pull request is merged: https://github.com/godotengine/godot/pull/109003
3707
Array values_arr = GLTFTemplateConvert::to_array(pointer_track.values);
3708
sampler["output"] = GLTFAccessor::encode_new_accessor_from_variants(p_state, values_arr, obj_model_prop->get_variant_type(), obj_model_prop->get_accessor_type(), component_type);
3709
samplers.push_back(sampler);
3710
}
3711
}
3712
if (channels.size() && samplers.size()) {
3713
d["channels"] = channels;
3714
d["samplers"] = samplers;
3715
animations.push_back(d);
3716
}
3717
}
3718
3719
if (!animations.size()) {
3720
return OK;
3721
}
3722
p_state->json["animations"] = animations;
3723
3724
print_verbose("glTF: Total animations '" + itos(p_state->animations.size()) + "'.");
3725
3726
return OK;
3727
}
3728
3729
Error GLTFDocument::_parse_animations(Ref<GLTFState> p_state) {
3730
if (!p_state->json.has("animations")) {
3731
return OK;
3732
}
3733
3734
const Array &animations = p_state->json["animations"];
3735
3736
for (GLTFAnimationIndex anim_index = 0; anim_index < animations.size(); anim_index++) {
3737
const Dictionary &anim_dict = animations[anim_index];
3738
3739
Ref<GLTFAnimation> animation;
3740
animation.instantiate();
3741
3742
if (!anim_dict.has("channels") || !anim_dict.has("samplers")) {
3743
continue;
3744
}
3745
3746
Array channels = anim_dict["channels"];
3747
Array samplers = anim_dict["samplers"];
3748
3749
if (anim_dict.has("name")) {
3750
const String anim_name = anim_dict["name"];
3751
const String anim_name_lower = anim_name.to_lower();
3752
if (anim_name_lower.begins_with("loop") || anim_name_lower.ends_with("loop") || anim_name_lower.begins_with("cycle") || anim_name_lower.ends_with("cycle")) {
3753
animation->set_loop(true);
3754
}
3755
animation->set_original_name(anim_name);
3756
animation->set_name(_gen_unique_animation_name(p_state, anim_name));
3757
}
3758
3759
for (int channel_index = 0; channel_index < channels.size(); channel_index++) {
3760
const Dictionary &anim_channel = channels[channel_index];
3761
ERR_FAIL_COND_V_MSG(!anim_channel.has("sampler"), ERR_PARSE_ERROR, "glTF: Animation channel missing required 'sampler' property.");
3762
ERR_FAIL_COND_V_MSG(!anim_channel.has("target"), ERR_PARSE_ERROR, "glTF: Animation channel missing required 'target' property.");
3763
// Parse sampler.
3764
const int sampler_index = anim_channel["sampler"];
3765
ERR_FAIL_INDEX_V(sampler_index, samplers.size(), ERR_PARSE_ERROR);
3766
const Dictionary &sampler_dict = samplers[sampler_index];
3767
ERR_FAIL_COND_V(!sampler_dict.has("input"), ERR_PARSE_ERROR);
3768
ERR_FAIL_COND_V(!sampler_dict.has("output"), ERR_PARSE_ERROR);
3769
const int input_time_accessor_index = sampler_dict["input"];
3770
const int output_value_accessor_index = sampler_dict["output"];
3771
GLTFAnimation::Interpolation interp = GLTFAnimation::INTERP_LINEAR;
3772
int output_count = 1;
3773
if (sampler_dict.has("interpolation")) {
3774
const String &in = sampler_dict["interpolation"];
3775
if (in == "STEP") {
3776
interp = GLTFAnimation::INTERP_STEP;
3777
} else if (in == "LINEAR") {
3778
interp = GLTFAnimation::INTERP_LINEAR;
3779
} else if (in == "CATMULLROMSPLINE") {
3780
interp = GLTFAnimation::INTERP_CATMULLROMSPLINE;
3781
output_count = 3;
3782
} else if (in == "CUBICSPLINE") {
3783
interp = GLTFAnimation::INTERP_CUBIC_SPLINE;
3784
output_count = 3;
3785
}
3786
}
3787
const PackedFloat64Array times = _decode_accessor_as_float64s(p_state, input_time_accessor_index);
3788
// Parse target.
3789
const Dictionary &anim_target = anim_channel["target"];
3790
ERR_FAIL_COND_V_MSG(!anim_target.has("path"), ERR_PARSE_ERROR, "glTF: Animation channel target missing required 'path' property.");
3791
String path = anim_target["path"];
3792
if (path == "pointer") {
3793
ERR_FAIL_COND_V(!anim_target.has("extensions"), ERR_PARSE_ERROR);
3794
Dictionary target_extensions = anim_target["extensions"];
3795
ERR_FAIL_COND_V(!target_extensions.has("KHR_animation_pointer"), ERR_PARSE_ERROR);
3796
Dictionary khr_anim_ptr = target_extensions["KHR_animation_pointer"];
3797
ERR_FAIL_COND_V(!khr_anim_ptr.has("pointer"), ERR_PARSE_ERROR);
3798
String anim_json_ptr = khr_anim_ptr["pointer"];
3799
_parse_animation_pointer(p_state, anim_json_ptr, animation, interp, times, output_value_accessor_index);
3800
} else {
3801
// If it's not a pointer, it's a regular animation channel from vanilla glTF (pos/rot/scale/weights).
3802
if (!anim_target.has("node")) {
3803
WARN_PRINT("glTF: Animation channel target missing 'node' property. Ignoring this channel.");
3804
continue;
3805
}
3806
3807
GLTFNodeIndex node = anim_target["node"];
3808
3809
ERR_FAIL_INDEX_V(node, p_state->nodes.size(), ERR_PARSE_ERROR);
3810
3811
GLTFAnimation::NodeTrack *track = nullptr;
3812
3813
if (!animation->get_node_tracks().has(node)) {
3814
animation->get_node_tracks()[node] = GLTFAnimation::NodeTrack();
3815
}
3816
3817
track = &animation->get_node_tracks()[node];
3818
3819
if (path == "translation") {
3820
const Vector<Vector3> positions = _decode_accessor_as_vec3(p_state, output_value_accessor_index);
3821
track->position_track.interpolation = interp;
3822
track->position_track.times = times;
3823
track->position_track.values = positions;
3824
} else if (path == "rotation") {
3825
const Vector<Quaternion> rotations = _decode_accessor_as_quaternion(p_state, output_value_accessor_index);
3826
track->rotation_track.interpolation = interp;
3827
track->rotation_track.times = times;
3828
track->rotation_track.values = rotations;
3829
} else if (path == "scale") {
3830
const Vector<Vector3> scales = _decode_accessor_as_vec3(p_state, output_value_accessor_index);
3831
track->scale_track.interpolation = interp;
3832
track->scale_track.times = times;
3833
track->scale_track.values = scales;
3834
} else if (path == "weights") {
3835
const Vector<float> weights = _decode_accessor_as_float32s(p_state, output_value_accessor_index);
3836
3837
ERR_FAIL_INDEX_V(p_state->nodes[node]->mesh, p_state->meshes.size(), ERR_PARSE_ERROR);
3838
Ref<GLTFMesh> mesh = p_state->meshes[p_state->nodes[node]->mesh];
3839
const int wc = mesh->get_blend_weights().size();
3840
ERR_CONTINUE_MSG(wc == 0, "glTF: Animation tried to animate weights, but mesh has no weights.");
3841
3842
track->weight_tracks.resize(wc);
3843
3844
const int expected_value_count = times.size() * output_count * wc;
3845
ERR_CONTINUE_MSG(weights.size() != expected_value_count, "Invalid weight data, expected " + itos(expected_value_count) + " weight values, got " + itos(weights.size()) + " instead.");
3846
3847
const int wlen = weights.size() / wc;
3848
for (int k = 0; k < wc; k++) { //separate tracks, having them together is not such a good idea
3849
GLTFAnimation::Channel<real_t> cf;
3850
cf.interpolation = interp;
3851
cf.times = Variant(times);
3852
Vector<real_t> wdata;
3853
wdata.resize(wlen);
3854
for (int l = 0; l < wlen; l++) {
3855
wdata.write[l] = weights[l * wc + k];
3856
}
3857
3858
cf.values = wdata;
3859
track->weight_tracks.write[k] = cf;
3860
}
3861
} else {
3862
WARN_PRINT("Invalid path '" + path + "'.");
3863
}
3864
}
3865
}
3866
3867
p_state->animations.push_back(animation);
3868
}
3869
3870
print_verbose("glTF: Total animations '" + itos(p_state->animations.size()) + "'.");
3871
3872
return OK;
3873
}
3874
3875
void GLTFDocument::_parse_animation_pointer(Ref<GLTFState> p_state, const String &p_animation_json_pointer, const Ref<GLTFAnimation> p_gltf_animation, const GLTFAnimation::Interpolation p_interp, const Vector<double> &p_times, const int p_output_value_accessor_index) {
3876
// Special case: Convert TRS animation pointers to node track pos/rot/scale.
3877
// This is required to handle skeleton bones, and improves performance for regular nodes.
3878
// Mark this as unlikely because TRS animation pointers are not recommended,
3879
// since vanilla glTF animations can already animate TRS properties directly.
3880
// But having this code exist is required to be spec-compliant and handle all test files.
3881
// Note that TRS still needs to be handled in the general case as well, for KHR_interactivity.
3882
const PackedStringArray split = p_animation_json_pointer.split("/", false, 3);
3883
if (unlikely(split.size() == 3 && split[0] == "nodes" && (split[2] == "translation" || split[2] == "rotation" || split[2] == "scale" || split[2] == "matrix" || split[2] == "weights"))) {
3884
const GLTFNodeIndex node_index = split[1].to_int();
3885
HashMap<int, GLTFAnimation::NodeTrack> &node_tracks = p_gltf_animation->get_node_tracks();
3886
if (!node_tracks.has(node_index)) {
3887
node_tracks[node_index] = GLTFAnimation::NodeTrack();
3888
}
3889
GLTFAnimation::NodeTrack *track = &node_tracks[node_index];
3890
if (split[2] == "translation") {
3891
const Vector<Vector3> positions = _decode_accessor_as_vec3(p_state, p_output_value_accessor_index);
3892
track->position_track.interpolation = p_interp;
3893
track->position_track.times = p_times;
3894
track->position_track.values = positions;
3895
} else if (split[2] == "rotation") {
3896
const Vector<Quaternion> rotations = _decode_accessor_as_quaternion(p_state, p_output_value_accessor_index);
3897
track->rotation_track.interpolation = p_interp;
3898
track->rotation_track.times = p_times;
3899
track->rotation_track.values = rotations;
3900
} else if (split[2] == "scale") {
3901
const Vector<Vector3> scales = _decode_accessor_as_vec3(p_state, p_output_value_accessor_index);
3902
track->scale_track.interpolation = p_interp;
3903
track->scale_track.times = p_times;
3904
track->scale_track.values = scales;
3905
} else if (split[2] == "matrix") {
3906
Array transforms = _decode_accessor_as_variants(p_state, p_output_value_accessor_index, Variant::TRANSFORM3D);
3907
track->position_track.interpolation = p_interp;
3908
track->position_track.times = p_times;
3909
track->position_track.values.resize(transforms.size());
3910
track->rotation_track.interpolation = p_interp;
3911
track->rotation_track.times = p_times;
3912
track->rotation_track.values.resize(transforms.size());
3913
track->scale_track.interpolation = p_interp;
3914
track->scale_track.times = p_times;
3915
track->scale_track.values.resize(transforms.size());
3916
for (int i = 0; i < transforms.size(); i++) {
3917
Transform3D transform = transforms[i];
3918
track->position_track.values.write[i] = transform.get_origin();
3919
track->rotation_track.values.write[i] = transform.basis.get_rotation_quaternion();
3920
track->scale_track.values.write[i] = transform.basis.get_scale();
3921
}
3922
} else { // if (split[2] == "weights")
3923
const Vector<float> accessor_weights = _decode_accessor_as_float32s(p_state, p_output_value_accessor_index);
3924
const GLTFMeshIndex mesh_index = p_state->nodes[node_index]->mesh;
3925
ERR_FAIL_INDEX(mesh_index, p_state->meshes.size());
3926
const Ref<GLTFMesh> gltf_mesh = p_state->meshes[mesh_index];
3927
const Vector<float> &blend_weights = gltf_mesh->get_blend_weights();
3928
const int blend_weight_count = gltf_mesh->get_blend_weights().size();
3929
const int anim_weights_size = accessor_weights.size();
3930
// For example, if a mesh has 2 blend weights, and the accessor provides 10 values, then there are 5 frames of animation, each with 2 blend weights.
3931
ERR_FAIL_COND_MSG(blend_weight_count == 0 || ((anim_weights_size % blend_weight_count) != 0), "glTF: Cannot apply " + itos(accessor_weights.size()) + " weights to a mesh with " + itos(blend_weights.size()) + " blend weights.");
3932
const int frame_count = anim_weights_size / blend_weight_count;
3933
track->weight_tracks.resize(blend_weight_count);
3934
for (int blend_weight_index = 0; blend_weight_index < blend_weight_count; blend_weight_index++) {
3935
GLTFAnimation::Channel<real_t> weight_track;
3936
weight_track.interpolation = p_interp;
3937
weight_track.times = p_times;
3938
weight_track.values.resize(frame_count);
3939
for (int frame_index = 0; frame_index < frame_count; frame_index++) {
3940
// For example, if a mesh has 2 blend weights, and the accessor provides 10 values,
3941
// then the first frame has indices [0, 1], the second frame has [2, 3], and so on.
3942
// Here we process all frames of one blend weight, so we want [0, 2, 4, 6, 8] or [1, 3, 5, 7, 9].
3943
// For the fist one we calculate 0 * 2 + 0, 1 * 2 + 0, 2 * 2 + 0, etc, then for the second 0 * 2 + 1, 1 * 2 + 1, 2 * 2 + 1, etc.
3944
weight_track.values.write[frame_index] = accessor_weights[frame_index * blend_weight_count + blend_weight_index];
3945
}
3946
track->weight_tracks.write[blend_weight_index] = weight_track;
3947
}
3948
}
3949
// The special case was handled, return to skip the general case.
3950
return;
3951
}
3952
// General case: Convert animation pointers to Variant value pointer tracks.
3953
Ref<GLTFObjectModelProperty> obj_model_prop = import_object_model_property(p_state, p_animation_json_pointer);
3954
if (obj_model_prop.is_null() || !obj_model_prop->has_node_paths()) {
3955
// Exit quietly, `import_object_model_property` already prints a warning if the property is not found.
3956
return;
3957
}
3958
HashMap<String, GLTFAnimation::Channel<Variant>> &anim_ptr_map = p_gltf_animation->get_pointer_tracks();
3959
GLTFAnimation::Channel<Variant> channel;
3960
channel.interpolation = p_interp;
3961
channel.times = p_times;
3962
Array values_arr = _decode_accessor_as_variants(p_state, p_output_value_accessor_index, obj_model_prop->get_variant_type());
3963
// TODO: This can be made faster after this pull request is merged: https://github.com/godotengine/godot/pull/109003
3964
GLTFTemplateConvert::set_from_array(channel.values, values_arr);
3965
anim_ptr_map[p_animation_json_pointer] = channel;
3966
}
3967
3968
void GLTFDocument::_assign_node_names(Ref<GLTFState> p_state) {
3969
for (int i = 0; i < p_state->nodes.size(); i++) {
3970
Ref<GLTFNode> gltf_node = p_state->nodes[i];
3971
// Any joints get unique names generated when the skeleton is made, unique to the skeleton
3972
if (gltf_node->skeleton >= 0) {
3973
continue;
3974
}
3975
String gltf_node_name = gltf_node->get_name();
3976
if (gltf_node_name.is_empty()) {
3977
if (_naming_version == 0) {
3978
if (gltf_node->mesh >= 0) {
3979
gltf_node_name = _gen_unique_name(p_state, "Mesh");
3980
} else if (gltf_node->camera >= 0) {
3981
gltf_node_name = _gen_unique_name(p_state, "Camera3D");
3982
} else {
3983
gltf_node_name = _gen_unique_name(p_state, "Node");
3984
}
3985
} else {
3986
if (gltf_node->mesh >= 0) {
3987
gltf_node_name = "Mesh";
3988
} else if (gltf_node->camera >= 0) {
3989
gltf_node_name = "Camera";
3990
} else {
3991
gltf_node_name = "Node";
3992
}
3993
}
3994
}
3995
gltf_node->set_name(_gen_unique_name(p_state, gltf_node_name));
3996
}
3997
}
3998
3999
BoneAttachment3D *GLTFDocument::_generate_bone_attachment(Skeleton3D *p_godot_skeleton, const Ref<GLTFNode> &p_bone_node) {
4000
BoneAttachment3D *bone_attachment = memnew(BoneAttachment3D);
4001
print_verbose("glTF: Creating bone attachment for: " + p_bone_node->get_name());
4002
bone_attachment->set_name(p_bone_node->get_name());
4003
p_godot_skeleton->add_child(bone_attachment, true);
4004
bone_attachment->set_bone_name(p_bone_node->get_name());
4005
return bone_attachment;
4006
}
4007
4008
BoneAttachment3D *GLTFDocument::_generate_bone_attachment_compat_4pt4(Ref<GLTFState> p_state, Skeleton3D *p_skeleton, const GLTFNodeIndex p_node_index, const GLTFNodeIndex p_bone_index) {
4009
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
4010
Ref<GLTFNode> bone_node = p_state->nodes[p_bone_index];
4011
BoneAttachment3D *bone_attachment = memnew(BoneAttachment3D);
4012
print_verbose("glTF: Creating bone attachment for: " + gltf_node->get_name());
4013
4014
ERR_FAIL_COND_V(!bone_node->joint, nullptr);
4015
4016
bone_attachment->set_bone_name(bone_node->get_name());
4017
4018
return bone_attachment;
4019
}
4020
4021
GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref<GLTFState> p_state, MeshInstance3D *p_mesh_instance) {
4022
ERR_FAIL_NULL_V(p_mesh_instance, -1);
4023
ERR_FAIL_COND_V_MSG(p_mesh_instance->get_mesh().is_null(), -1, "glTF: Tried to export a MeshInstance3D node named " + p_mesh_instance->get_name() + ", but it has no mesh. This node will be exported without a mesh.");
4024
Ref<Mesh> mesh_resource = p_mesh_instance->get_mesh();
4025
ERR_FAIL_COND_V_MSG(mesh_resource->get_surface_count() == 0, -1, "glTF: Tried to export a MeshInstance3D node named " + p_mesh_instance->get_name() + ", but its mesh has no surfaces. This node will be exported without a mesh.");
4026
TypedArray<Material> instance_materials;
4027
for (int32_t surface_i = 0; surface_i < mesh_resource->get_surface_count(); surface_i++) {
4028
Ref<Material> mat = p_mesh_instance->get_active_material(surface_i);
4029
instance_materials.append(mat);
4030
}
4031
Vector<float> blend_weights;
4032
int32_t blend_count = mesh_resource->get_blend_shape_count();
4033
blend_weights.resize(blend_count);
4034
for (int32_t blend_i = 0; blend_i < blend_count; blend_i++) {
4035
blend_weights.write[blend_i] = 0.0f;
4036
}
4037
4038
Ref<GLTFMesh> gltf_mesh;
4039
gltf_mesh.instantiate();
4040
if (!mesh_resource->get_name().is_empty()) {
4041
gltf_mesh->set_original_name(mesh_resource->get_name());
4042
gltf_mesh->set_name(_gen_unique_name(p_state, mesh_resource->get_name()));
4043
}
4044
gltf_mesh->set_instance_materials(instance_materials);
4045
gltf_mesh->set_mesh(ImporterMesh::from_mesh(mesh_resource));
4046
gltf_mesh->set_blend_weights(blend_weights);
4047
GLTFMeshIndex mesh_i = p_state->meshes.size();
4048
p_state->meshes.push_back(gltf_mesh);
4049
return mesh_i;
4050
}
4051
4052
ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index) {
4053
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
4054
4055
ERR_FAIL_INDEX_V(gltf_node->mesh, p_state->meshes.size(), nullptr);
4056
4057
ImporterMeshInstance3D *mi = memnew(ImporterMeshInstance3D);
4058
print_verbose("glTF: Creating mesh for: " + gltf_node->get_name());
4059
4060
p_state->scene_mesh_instances.insert(p_node_index, mi);
4061
Ref<GLTFMesh> mesh = p_state->meshes.write[gltf_node->mesh];
4062
if (mesh.is_null()) {
4063
return mi;
4064
}
4065
Ref<ImporterMesh> import_mesh = mesh->get_mesh();
4066
if (import_mesh.is_null()) {
4067
return mi;
4068
}
4069
mi->set_mesh(import_mesh);
4070
import_mesh->merge_meta_from(*mesh);
4071
return mi;
4072
}
4073
4074
Light3D *GLTFDocument::_generate_light(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index) {
4075
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
4076
4077
ERR_FAIL_INDEX_V(gltf_node->light, p_state->lights.size(), nullptr);
4078
4079
print_verbose("glTF: Creating light for: " + gltf_node->get_name());
4080
4081
Ref<GLTFLight> l = p_state->lights[gltf_node->light];
4082
return l->to_node();
4083
}
4084
4085
Camera3D *GLTFDocument::_generate_camera(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index) {
4086
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
4087
4088
ERR_FAIL_INDEX_V(gltf_node->camera, p_state->cameras.size(), nullptr);
4089
4090
print_verbose("glTF: Creating camera for: " + gltf_node->get_name());
4091
4092
Ref<GLTFCamera> c = p_state->cameras[gltf_node->camera];
4093
return c->to_node();
4094
}
4095
4096
GLTFCameraIndex GLTFDocument::_convert_camera(Ref<GLTFState> p_state, Camera3D *p_camera) {
4097
print_verbose("glTF: Converting camera: " + p_camera->get_name());
4098
4099
Ref<GLTFCamera> c = GLTFCamera::from_node(p_camera);
4100
GLTFCameraIndex camera_index = p_state->cameras.size();
4101
p_state->cameras.push_back(c);
4102
return camera_index;
4103
}
4104
4105
GLTFLightIndex GLTFDocument::_convert_light(Ref<GLTFState> p_state, Light3D *p_light) {
4106
print_verbose("glTF: Converting light: " + p_light->get_name());
4107
4108
Ref<GLTFLight> l = GLTFLight::from_node(p_light);
4109
4110
GLTFLightIndex light_index = p_state->lights.size();
4111
p_state->lights.push_back(l);
4112
return light_index;
4113
}
4114
4115
void GLTFDocument::_convert_spatial(Ref<GLTFState> p_state, Node3D *p_spatial, Ref<GLTFNode> p_node) {
4116
p_node->transform = p_spatial->get_transform();
4117
}
4118
4119
Node3D *GLTFDocument::_generate_spatial(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index) {
4120
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
4121
4122
Node3D *spatial = memnew(Node3D);
4123
print_verbose("glTF: Converting spatial: " + gltf_node->get_name());
4124
4125
return spatial;
4126
}
4127
4128
void GLTFDocument::_convert_scene_node(Ref<GLTFState> p_state, Node *p_current, const GLTFNodeIndex p_gltf_parent, const GLTFNodeIndex p_gltf_root) {
4129
#ifdef TOOLS_ENABLED
4130
if (Engine::get_singleton()->is_editor_hint() && p_gltf_root != -1 && p_current->get_owner() == nullptr) {
4131
WARN_VERBOSE("glTF export warning: Node '" + p_current->get_name() + "' has no owner. This is likely a temporary node generated by a @tool script. This would not be saved when saving the Godot scene, therefore it will not be exported to glTF.");
4132
return;
4133
}
4134
#endif // TOOLS_ENABLED
4135
Ref<GLTFNode> gltf_node;
4136
gltf_node.instantiate();
4137
if (p_current->has_method("is_visible")) {
4138
bool visible = p_current->call("is_visible");
4139
if (!visible && _visibility_mode == VISIBILITY_MODE_EXCLUDE) {
4140
return;
4141
}
4142
gltf_node->visible = visible;
4143
}
4144
gltf_node->set_original_name(p_current->get_name());
4145
gltf_node->set_name(_gen_unique_name(p_state, p_current->get_name()));
4146
gltf_node->merge_meta_from(p_current);
4147
if (Object::cast_to<Node3D>(p_current)) {
4148
Node3D *spatial = Object::cast_to<Node3D>(p_current);
4149
_convert_spatial(p_state, spatial, gltf_node);
4150
}
4151
if (Object::cast_to<MeshInstance3D>(p_current)) {
4152
MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_current);
4153
_convert_mesh_instance_to_gltf(mi, p_state, gltf_node);
4154
} else if (Object::cast_to<BoneAttachment3D>(p_current)) {
4155
BoneAttachment3D *bone = Object::cast_to<BoneAttachment3D>(p_current);
4156
_convert_bone_attachment_to_gltf(bone, p_state, p_gltf_parent, p_gltf_root, gltf_node);
4157
return;
4158
} else if (Object::cast_to<Skeleton3D>(p_current)) {
4159
Skeleton3D *skel = Object::cast_to<Skeleton3D>(p_current);
4160
_convert_skeleton_to_gltf(skel, p_state, p_gltf_parent, p_gltf_root, gltf_node);
4161
// We ignore the Godot Engine node that is the skeleton.
4162
return;
4163
} else if (Object::cast_to<MultiMeshInstance3D>(p_current)) {
4164
MultiMeshInstance3D *multi = Object::cast_to<MultiMeshInstance3D>(p_current);
4165
_convert_multi_mesh_instance_to_gltf(multi, p_gltf_parent, p_gltf_root, gltf_node, p_state);
4166
#ifdef MODULE_CSG_ENABLED
4167
} else if (Object::cast_to<CSGShape3D>(p_current)) {
4168
CSGShape3D *shape = Object::cast_to<CSGShape3D>(p_current);
4169
if (shape->get_parent() && shape->is_root_shape()) {
4170
_convert_csg_shape_to_gltf(shape, p_gltf_parent, gltf_node, p_state);
4171
}
4172
#endif // MODULE_CSG_ENABLED
4173
#ifdef MODULE_GRIDMAP_ENABLED
4174
} else if (Object::cast_to<GridMap>(p_current)) {
4175
GridMap *gridmap = Object::cast_to<GridMap>(p_current);
4176
_convert_grid_map_to_gltf(gridmap, p_gltf_parent, p_gltf_root, gltf_node, p_state);
4177
#endif // MODULE_GRIDMAP_ENABLED
4178
} else if (Object::cast_to<Camera3D>(p_current)) {
4179
Camera3D *camera = Object::cast_to<Camera3D>(p_current);
4180
_convert_camera_to_gltf(camera, p_state, gltf_node);
4181
} else if (Object::cast_to<Light3D>(p_current)) {
4182
Light3D *light = Object::cast_to<Light3D>(p_current);
4183
_convert_light_to_gltf(light, p_state, gltf_node);
4184
} else if (Object::cast_to<AnimationPlayer>(p_current)) {
4185
AnimationPlayer *animation_player = Object::cast_to<AnimationPlayer>(p_current);
4186
p_state->animation_players.push_back(animation_player);
4187
if (animation_player->get_child_count() == 0) {
4188
gltf_node->set_parent(-2); // Don't export AnimationPlayer nodes as glTF nodes (unless they have children).
4189
}
4190
}
4191
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
4192
ERR_CONTINUE(ext.is_null());
4193
ext->convert_scene_node(p_state, gltf_node, p_current);
4194
}
4195
GLTFNodeIndex current_node_i;
4196
if (gltf_node->get_parent() == -1) {
4197
current_node_i = p_state->append_gltf_node(gltf_node, p_current, p_gltf_parent);
4198
} else if (gltf_node->get_parent() < -1) {
4199
return;
4200
} else {
4201
current_node_i = p_state->nodes.size() - 1;
4202
while (gltf_node != p_state->nodes[current_node_i]) {
4203
current_node_i--;
4204
}
4205
}
4206
const GLTFNodeIndex gltf_root = (p_gltf_root == -1) ? current_node_i : p_gltf_root;
4207
for (int node_i = 0; node_i < p_current->get_child_count(); node_i++) {
4208
_convert_scene_node(p_state, p_current->get_child(node_i), current_node_i, gltf_root);
4209
}
4210
}
4211
4212
void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state) {
4213
#ifndef MODULE_CSG_ENABLED
4214
ERR_FAIL_MSG("csg module is disabled.");
4215
#else
4216
CSGShape3D *csg = p_current;
4217
csg->update_shape();
4218
Array meshes = csg->get_meshes();
4219
if (meshes.size() != 2) {
4220
return;
4221
}
4222
4223
Ref<ImporterMesh> mesh;
4224
mesh.instantiate();
4225
{
4226
Ref<ArrayMesh> csg_mesh = csg->get_meshes()[1];
4227
for (int32_t surface_i = 0; surface_i < csg_mesh->get_surface_count(); surface_i++) {
4228
Array array = csg_mesh->surface_get_arrays(surface_i);
4229
4230
Ref<Material> mat;
4231
4232
Ref<Material> mat_override = csg->get_material_override();
4233
if (mat_override.is_valid()) {
4234
mat = mat_override;
4235
}
4236
4237
Ref<Material> mat_surface_override = csg_mesh->surface_get_material(surface_i);
4238
if (mat_surface_override.is_valid() && mat.is_null()) {
4239
mat = mat_surface_override;
4240
}
4241
4242
String mat_name;
4243
if (mat.is_valid()) {
4244
mat_name = mat->get_name();
4245
} else {
4246
// Assign default material when no material is assigned.
4247
mat.instantiate();
4248
}
4249
4250
mesh->add_surface(csg_mesh->surface_get_primitive_type(surface_i),
4251
array, csg_mesh->surface_get_blend_shape_arrays(surface_i), csg_mesh->surface_get_lods(surface_i), mat,
4252
mat_name, csg_mesh->surface_get_format(surface_i));
4253
}
4254
}
4255
4256
Ref<GLTFMesh> gltf_mesh;
4257
gltf_mesh.instantiate();
4258
gltf_mesh->set_mesh(mesh);
4259
gltf_mesh->set_original_name(csg->get_name());
4260
const String unique_name = _gen_unique_name(p_state, csg->get_name());
4261
gltf_mesh->set_name(unique_name);
4262
GLTFMeshIndex mesh_i = p_state->meshes.size();
4263
p_state->meshes.push_back(gltf_mesh);
4264
p_gltf_node->mesh = mesh_i;
4265
p_gltf_node->transform = csg->get_transform();
4266
p_gltf_node->set_original_name(csg->get_name());
4267
p_gltf_node->set_name(unique_name);
4268
#endif // MODULE_CSG_ENABLED
4269
}
4270
4271
void GLTFDocument::_convert_camera_to_gltf(Camera3D *camera, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node) {
4272
ERR_FAIL_NULL(camera);
4273
GLTFCameraIndex camera_index = _convert_camera(p_state, camera);
4274
if (camera_index != -1) {
4275
p_gltf_node->camera = camera_index;
4276
}
4277
}
4278
4279
void GLTFDocument::_convert_light_to_gltf(Light3D *light, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node) {
4280
ERR_FAIL_NULL(light);
4281
GLTFLightIndex light_index = _convert_light(p_state, light);
4282
if (light_index != -1) {
4283
p_gltf_node->light = light_index;
4284
}
4285
}
4286
4287
void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state) {
4288
#ifndef MODULE_GRIDMAP_ENABLED
4289
ERR_FAIL_MSG("gridmap module is disabled.");
4290
#else
4291
const Array &cells = p_grid_map->get_used_cells();
4292
for (int32_t k = 0; k < cells.size(); k++) {
4293
GLTFNode *new_gltf_node = memnew(GLTFNode);
4294
p_gltf_node->children.push_back(p_state->nodes.size());
4295
p_state->nodes.push_back(new_gltf_node);
4296
Vector3 cell_location = cells[k];
4297
int32_t cell = p_grid_map->get_cell_item(
4298
Vector3(cell_location.x, cell_location.y, cell_location.z));
4299
Transform3D cell_xform;
4300
cell_xform.basis = p_grid_map->get_basis_with_orthogonal_index(
4301
p_grid_map->get_cell_item_orientation(
4302
Vector3(cell_location.x, cell_location.y, cell_location.z)));
4303
cell_xform.basis.scale(Vector3(p_grid_map->get_cell_scale(),
4304
p_grid_map->get_cell_scale(),
4305
p_grid_map->get_cell_scale()));
4306
cell_xform.set_origin(p_grid_map->map_to_local(
4307
Vector3(cell_location.x, cell_location.y, cell_location.z)));
4308
Ref<GLTFMesh> gltf_mesh;
4309
gltf_mesh.instantiate();
4310
gltf_mesh->set_mesh(ImporterMesh::from_mesh(p_grid_map->get_mesh_library()->get_item_mesh(cell)));
4311
gltf_mesh->set_original_name(p_grid_map->get_mesh_library()->get_item_name(cell));
4312
const String unique_name = _gen_unique_name(p_state, p_grid_map->get_mesh_library()->get_item_name(cell));
4313
gltf_mesh->set_name(unique_name);
4314
new_gltf_node->mesh = p_state->meshes.size();
4315
p_state->meshes.push_back(gltf_mesh);
4316
new_gltf_node->transform = cell_xform * p_grid_map->get_transform();
4317
new_gltf_node->set_original_name(p_grid_map->get_mesh_library()->get_item_name(cell));
4318
new_gltf_node->set_name(unique_name);
4319
}
4320
#endif // MODULE_GRIDMAP_ENABLED
4321
}
4322
4323
void GLTFDocument::_convert_multi_mesh_instance_to_gltf(
4324
MultiMeshInstance3D *p_multi_mesh_instance,
4325
GLTFNodeIndex p_parent_node_index,
4326
GLTFNodeIndex p_root_node_index,
4327
Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state) {
4328
ERR_FAIL_NULL(p_multi_mesh_instance);
4329
Ref<MultiMesh> multi_mesh = p_multi_mesh_instance->get_multimesh();
4330
if (multi_mesh.is_null()) {
4331
return;
4332
}
4333
Ref<GLTFMesh> gltf_mesh;
4334
gltf_mesh.instantiate();
4335
Ref<Mesh> mesh = multi_mesh->get_mesh();
4336
if (mesh.is_null()) {
4337
return;
4338
}
4339
gltf_mesh->set_original_name(multi_mesh->get_name());
4340
gltf_mesh->set_name(multi_mesh->get_name());
4341
gltf_mesh->set_mesh(ImporterMesh::from_mesh(mesh));
4342
GLTFMeshIndex mesh_index = p_state->meshes.size();
4343
p_state->meshes.push_back(gltf_mesh);
4344
for (int32_t instance_i = 0; instance_i < multi_mesh->get_instance_count();
4345
instance_i++) {
4346
Transform3D transform;
4347
if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_2D) {
4348
Transform2D xform_2d = multi_mesh->get_instance_transform_2d(instance_i);
4349
transform.origin =
4350
Vector3(xform_2d.get_origin().x, 0, xform_2d.get_origin().y);
4351
real_t rotation = xform_2d.get_rotation();
4352
Quaternion quaternion(Vector3(0, 1, 0), rotation);
4353
Size2 scale = xform_2d.get_scale();
4354
transform.basis.set_quaternion_scale(quaternion,
4355
Vector3(scale.x, 0, scale.y));
4356
transform = p_multi_mesh_instance->get_transform() * transform;
4357
} else if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_3D) {
4358
transform = p_multi_mesh_instance->get_transform() *
4359
multi_mesh->get_instance_transform(instance_i);
4360
}
4361
Ref<GLTFNode> new_gltf_node;
4362
new_gltf_node.instantiate();
4363
new_gltf_node->mesh = mesh_index;
4364
new_gltf_node->transform = transform;
4365
new_gltf_node->set_original_name(p_multi_mesh_instance->get_name());
4366
new_gltf_node->set_name(_gen_unique_name(p_state, p_multi_mesh_instance->get_name()));
4367
p_gltf_node->children.push_back(p_state->nodes.size());
4368
p_state->nodes.push_back(new_gltf_node);
4369
}
4370
}
4371
4372
void GLTFDocument::_convert_skeleton_to_gltf(Skeleton3D *p_skeleton3d, Ref<GLTFState> p_state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> p_gltf_node) {
4373
Skeleton3D *skeleton = p_skeleton3d;
4374
Ref<GLTFSkeleton> gltf_skeleton;
4375
gltf_skeleton.instantiate();
4376
// GLTFSkeleton is only used to hold internal p_state data. It will not be written to the document.
4377
//
4378
gltf_skeleton->godot_skeleton = skeleton;
4379
GLTFSkeletonIndex skeleton_i = p_state->skeletons.size();
4380
p_state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()] = skeleton_i;
4381
p_state->skeletons.push_back(gltf_skeleton);
4382
4383
BoneId bone_count = skeleton->get_bone_count();
4384
for (BoneId bone_i = 0; bone_i < bone_count; bone_i++) {
4385
Ref<GLTFNode> joint_node;
4386
joint_node.instantiate();
4387
// Note that we cannot use _gen_unique_bone_name here, because glTF spec requires all node
4388
// names to be unique regardless of whether or not they are used as joints.
4389
joint_node->set_original_name(skeleton->get_bone_name(bone_i));
4390
joint_node->set_name(_gen_unique_name(p_state, skeleton->get_bone_name(bone_i)));
4391
joint_node->transform = skeleton->get_bone_pose(bone_i);
4392
joint_node->joint = true;
4393
4394
if (p_skeleton3d->has_bone_meta(bone_i, "extras")) {
4395
joint_node->set_meta("extras", p_skeleton3d->get_bone_meta(bone_i, "extras"));
4396
}
4397
GLTFNodeIndex current_node_i = p_state->nodes.size();
4398
p_state->scene_nodes.insert(current_node_i, skeleton);
4399
p_state->nodes.push_back(joint_node);
4400
4401
gltf_skeleton->joints.push_back(current_node_i);
4402
if (skeleton->get_bone_parent(bone_i) == -1) {
4403
gltf_skeleton->roots.push_back(current_node_i);
4404
}
4405
gltf_skeleton->godot_bone_node.insert(bone_i, current_node_i);
4406
}
4407
for (BoneId bone_i = 0; bone_i < bone_count; bone_i++) {
4408
GLTFNodeIndex current_node_i = gltf_skeleton->godot_bone_node[bone_i];
4409
BoneId parent_bone_id = skeleton->get_bone_parent(bone_i);
4410
if (parent_bone_id == -1) {
4411
if (p_parent_node_index != -1) {
4412
p_state->nodes.write[current_node_i]->parent = p_parent_node_index;
4413
p_state->nodes.write[p_parent_node_index]->children.push_back(current_node_i);
4414
}
4415
} else {
4416
GLTFNodeIndex parent_node_i = gltf_skeleton->godot_bone_node[parent_bone_id];
4417
p_state->nodes.write[current_node_i]->parent = parent_node_i;
4418
p_state->nodes.write[parent_node_i]->children.push_back(current_node_i);
4419
}
4420
}
4421
// Remove placeholder skeleton3d node by not creating the gltf node
4422
// Skins are per mesh
4423
for (int node_i = 0; node_i < skeleton->get_child_count(); node_i++) {
4424
_convert_scene_node(p_state, skeleton->get_child(node_i), p_parent_node_index, p_root_node_index);
4425
}
4426
}
4427
4428
void GLTFDocument::_convert_bone_attachment_to_gltf(BoneAttachment3D *p_bone_attachment, Ref<GLTFState> p_state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> p_gltf_node) {
4429
Skeleton3D *skeleton;
4430
// Note that relative transforms to external skeletons and pose overrides are not supported.
4431
if (p_bone_attachment->get_use_external_skeleton()) {
4432
skeleton = Object::cast_to<Skeleton3D>(p_bone_attachment->get_node_or_null(p_bone_attachment->get_external_skeleton()));
4433
} else {
4434
skeleton = Object::cast_to<Skeleton3D>(p_bone_attachment->get_parent());
4435
}
4436
GLTFSkeletonIndex skel_gltf_i = -1;
4437
if (skeleton != nullptr && p_state->skeleton3d_to_gltf_skeleton.has(skeleton->get_instance_id())) {
4438
skel_gltf_i = p_state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()];
4439
}
4440
int bone_idx = -1;
4441
if (skeleton != nullptr) {
4442
bone_idx = p_bone_attachment->get_bone_idx();
4443
if (bone_idx == -1) {
4444
bone_idx = skeleton->find_bone(p_bone_attachment->get_bone_name());
4445
}
4446
}
4447
GLTFNodeIndex par_node_index = p_parent_node_index;
4448
if (skeleton != nullptr && bone_idx != -1 && skel_gltf_i != -1) {
4449
Ref<GLTFSkeleton> gltf_skeleton = p_state->skeletons.write[skel_gltf_i];
4450
gltf_skeleton->bone_attachments.push_back(p_bone_attachment);
4451
par_node_index = gltf_skeleton->joints[bone_idx];
4452
}
4453
4454
for (int node_i = 0; node_i < p_bone_attachment->get_child_count(); node_i++) {
4455
_convert_scene_node(p_state, p_bone_attachment->get_child(node_i), par_node_index, p_root_node_index);
4456
}
4457
}
4458
4459
void GLTFDocument::_convert_mesh_instance_to_gltf(MeshInstance3D *p_scene_parent, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node) {
4460
GLTFMeshIndex gltf_mesh_index = _convert_mesh_to_gltf(p_state, p_scene_parent);
4461
if (gltf_mesh_index != -1) {
4462
p_gltf_node->mesh = gltf_mesh_index;
4463
}
4464
}
4465
4466
void _set_node_tree_owner(Node *p_current_node, Node *&p_scene_root) {
4467
// Note: p_scene_parent and p_scene_root must either both be null or both be valid.
4468
if (p_scene_root == nullptr) {
4469
// If the root node argument is null, this is the root node.
4470
p_scene_root = p_current_node;
4471
// If multiple nodes were generated under the root node, ensure they have the owner set.
4472
if (unlikely(p_current_node->get_child_count() > 0)) {
4473
Array args;
4474
args.append(p_scene_root);
4475
for (int i = 0; i < p_current_node->get_child_count(); i++) {
4476
Node *child = p_current_node->get_child(i);
4477
child->propagate_call(StringName("set_owner"), args);
4478
}
4479
}
4480
} else {
4481
// Add the node we generated and set the owner to the scene root.
4482
Array args;
4483
args.append(p_scene_root);
4484
p_current_node->propagate_call(StringName("set_owner"), args);
4485
}
4486
}
4487
4488
bool GLTFDocument::_does_skinned_mesh_require_placeholder_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node) {
4489
if (p_gltf_node->skin < 0) {
4490
return false; // Not a skinned mesh.
4491
}
4492
// Check for child nodes that aren't joints/bones.
4493
for (int i = 0; i < p_gltf_node->children.size(); ++i) {
4494
Ref<GLTFNode> child = p_state->nodes[p_gltf_node->children[i]];
4495
if (!child->joint) {
4496
return true;
4497
}
4498
// Edge case: If a child's skeleton is not yet in the tree, then we must add it as a child of this node.
4499
// While the Skeleton3D node isn't a glTF node, it's still a case where we need a placeholder.
4500
// This is required to handle this issue: https://github.com/godotengine/godot/issues/67773
4501
const GLTFSkeletonIndex skel_index = child->skeleton;
4502
ERR_FAIL_INDEX_V(skel_index, p_state->skeletons.size(), false);
4503
if (p_state->skeletons[skel_index]->godot_skeleton->get_parent() == nullptr) {
4504
return true;
4505
}
4506
}
4507
return false;
4508
}
4509
4510
void GLTFDocument::_generate_scene_node(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node *p_scene_parent, Node *p_scene_root) {
4511
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
4512
Node3D *current_node = nullptr;
4513
// Check if any GLTFDocumentExtension classes want to generate a node for us.
4514
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
4515
ERR_CONTINUE(ext.is_null());
4516
current_node = ext->generate_scene_node(p_state, gltf_node, p_scene_parent);
4517
if (current_node) {
4518
break;
4519
}
4520
}
4521
// If none of our GLTFDocumentExtension classes generated us a node, try using built-in glTF types.
4522
if (!current_node) {
4523
if (gltf_node->mesh >= 0) {
4524
current_node = _generate_mesh_instance(p_state, p_node_index);
4525
// glTF specifies that skinned meshes should ignore their node transforms,
4526
// only being controlled by the skeleton, so Godot will reparent a skinned
4527
// mesh to its skeleton. However, we still need to ensure any child nodes
4528
// keep their place in the tree, so if there are any child nodes, the skinned
4529
// mesh must not be the base node, so generate an empty spatial base.
4530
if (_does_skinned_mesh_require_placeholder_node(p_state, gltf_node)) {
4531
Node3D *placeholder;
4532
// We need a placeholder, but maybe the Skeleton3D *is* the placeholder?
4533
const GLTFSkeletonIndex skel_index = gltf_node->skeleton;
4534
if (skel_index >= 0 && skel_index < p_state->skeletons.size() && p_state->skeletons[skel_index]->godot_skeleton->get_parent() == nullptr) {
4535
placeholder = p_state->skeletons[skel_index]->godot_skeleton;
4536
} else {
4537
placeholder = _generate_spatial(p_state, p_node_index);
4538
}
4539
current_node->set_name(gltf_node->get_name());
4540
placeholder->add_child(current_node, true);
4541
current_node = placeholder;
4542
}
4543
} else if (gltf_node->camera >= 0) {
4544
current_node = _generate_camera(p_state, p_node_index);
4545
} else if (gltf_node->light >= 0) {
4546
current_node = _generate_light(p_state, p_node_index);
4547
}
4548
}
4549
// The only case where current_node is a Skeleton3D is when it is the placeholder for a skinned mesh.
4550
// In that case, we don't set the name or possibly generate a bone attachment. But usually, we do.
4551
// It is also possible that user code generates a Skeleton3D node, and this code also works for that case.
4552
if (likely(!Object::cast_to<Skeleton3D>(current_node))) {
4553
if (current_node) {
4554
// Set the name of the Godot node to the name of the glTF node.
4555
String gltf_node_name = gltf_node->get_name();
4556
if (!gltf_node_name.is_empty()) {
4557
current_node->set_name(gltf_node_name);
4558
}
4559
}
4560
// Skeleton stuff: If this node is in a skeleton, we need to attach it to a bone attachment pointing to its bone.
4561
if (gltf_node->skeleton >= 0) {
4562
_generate_skeleton_bone_node(p_state, p_node_index, current_node, p_scene_parent, p_scene_root);
4563
return;
4564
}
4565
}
4566
// Skeleton stuff: If the parent node is in a skeleton, we need to attach this node to a bone attachment pointing to the parent's bone.
4567
if (Object::cast_to<Skeleton3D>(p_scene_parent)) {
4568
Skeleton3D *parent_skeleton = Object::cast_to<Skeleton3D>(p_scene_parent);
4569
_attach_node_to_skeleton(p_state, p_node_index, current_node, parent_skeleton, p_scene_root);
4570
return;
4571
}
4572
// Not a skeleton bone, so definitely some kind of node that goes in the Godot scene tree.
4573
if (current_node == nullptr) {
4574
current_node = _generate_spatial(p_state, p_node_index);
4575
// Set the name of the Godot node to the name of the glTF node.
4576
String gltf_node_name = gltf_node->get_name();
4577
if (!gltf_node_name.is_empty()) {
4578
current_node->set_name(gltf_node_name);
4579
}
4580
}
4581
if (p_scene_parent) {
4582
p_scene_parent->add_child(current_node, true);
4583
}
4584
// Set the owner of the nodes to the scene root.
4585
// Note: p_scene_parent and p_scene_root must either both be null or both be valid.
4586
_set_node_tree_owner(current_node, p_scene_root);
4587
current_node->set_transform(gltf_node->transform);
4588
current_node->set_visible(gltf_node->visible);
4589
current_node->merge_meta_from(*gltf_node);
4590
p_state->scene_nodes.insert(p_node_index, current_node);
4591
for (int i = 0; i < gltf_node->children.size(); ++i) {
4592
_generate_scene_node(p_state, gltf_node->children[i], current_node, p_scene_root);
4593
}
4594
}
4595
4596
void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node3D *p_current_node, Node *p_scene_parent, Node *p_scene_root) {
4597
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
4598
// Grab the current skeleton, and ensure it's added to the tree.
4599
Skeleton3D *godot_skeleton = p_state->skeletons[gltf_node->skeleton]->godot_skeleton;
4600
if (godot_skeleton->get_parent() == nullptr) {
4601
if (p_scene_root) {
4602
if (Object::cast_to<Skeleton3D>(p_scene_parent)) {
4603
Skeleton3D *parent_skeleton = Object::cast_to<Skeleton3D>(p_scene_parent);
4604
// Explicitly specifying the bone of the parent glTF node is required to
4605
// handle the edge case where a skeleton is a child of another skeleton.
4606
_attach_node_to_skeleton(p_state, p_node_index, godot_skeleton, parent_skeleton, p_scene_root, gltf_node->parent);
4607
} else {
4608
p_scene_parent->add_child(godot_skeleton, true);
4609
godot_skeleton->set_owner(p_scene_root);
4610
}
4611
} else {
4612
p_scene_root = godot_skeleton;
4613
}
4614
}
4615
_attach_node_to_skeleton(p_state, p_node_index, p_current_node, godot_skeleton, p_scene_root);
4616
}
4617
4618
void GLTFDocument::_attach_node_to_skeleton(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node3D *p_current_node, Skeleton3D *p_godot_skeleton, Node *p_scene_root, GLTFNodeIndex p_bone_node_index) {
4619
ERR_FAIL_NULL(p_godot_skeleton->get_parent());
4620
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
4621
if (Object::cast_to<ImporterMeshInstance3D>(p_current_node) && gltf_node->skin >= 0) {
4622
// Skinned meshes should be attached directly to the skeleton without a BoneAttachment3D.
4623
ERR_FAIL_COND_MSG(p_current_node->get_child_count() > 0, "Skinned mesh nodes passed to this function should not have children (a placeholder should be inserted by `_generate_scene_node`).");
4624
p_godot_skeleton->add_child(p_current_node, true);
4625
} else if (p_current_node || !gltf_node->joint) {
4626
// If we have a node in need of attaching, we need a BoneAttachment3D.
4627
// This happens when a node in Blender has Relations -> Parent set to a bone.
4628
GLTFNodeIndex attachment_node_index = likely(p_bone_node_index == -1) ? (gltf_node->joint ? p_node_index : gltf_node->parent) : p_bone_node_index;
4629
ERR_FAIL_COND(!p_state->scene_nodes.has(attachment_node_index));
4630
Node *attachment_godot_node = p_state->scene_nodes[attachment_node_index];
4631
// If the parent is a Skeleton3D, we need to make a BoneAttachment3D.
4632
if (Object::cast_to<Skeleton3D>(attachment_godot_node)) {
4633
Ref<GLTFNode> attachment_gltf_node = p_state->nodes[attachment_node_index];
4634
BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_godot_skeleton, attachment_gltf_node);
4635
bone_attachment->set_owner(p_scene_root);
4636
bone_attachment->merge_meta_from(*p_state->nodes[attachment_node_index]);
4637
p_state->scene_nodes.insert(attachment_node_index, bone_attachment);
4638
attachment_godot_node = bone_attachment;
4639
}
4640
// By this point, `attachment_godot_node` is either a BoneAttachment3D or part of a BoneAttachment3D subtree.
4641
// If the node is a plain non-joint, we should generate a Godot node for it.
4642
if (p_current_node == nullptr) {
4643
DEV_ASSERT(!gltf_node->joint);
4644
p_current_node = _generate_spatial(p_state, p_node_index);
4645
}
4646
if (!gltf_node->joint) {
4647
p_current_node->set_transform(gltf_node->transform);
4648
}
4649
p_current_node->set_name(gltf_node->get_name());
4650
attachment_godot_node->add_child(p_current_node, true);
4651
} else {
4652
// If this glTF is a plain joint, this glTF node only becomes a Godot bone.
4653
// We refer to the skeleton itself as this glTF node's corresponding Godot node.
4654
// This may be overridden later if the joint has a non-joint as a child in need of an attachment.
4655
p_current_node = p_godot_skeleton;
4656
}
4657
_set_node_tree_owner(p_current_node, p_scene_root);
4658
p_current_node->merge_meta_from(*gltf_node);
4659
p_state->scene_nodes.insert(p_node_index, p_current_node);
4660
for (int i = 0; i < gltf_node->children.size(); ++i) {
4661
_generate_scene_node(p_state, gltf_node->children[i], p_current_node, p_scene_root);
4662
}
4663
}
4664
4665
// Deprecated code used when naming_version is 0 or 1 (Godot 4.0 to 4.4).
4666
void GLTFDocument::_generate_scene_node_compat_4pt4(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node *p_scene_parent, Node *p_scene_root) {
4667
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
4668
4669
if (gltf_node->skeleton >= 0) {
4670
_generate_skeleton_bone_node_compat_4pt4(p_state, p_node_index, p_scene_parent, p_scene_root);
4671
return;
4672
}
4673
4674
Node3D *current_node = nullptr;
4675
4676
// Is our parent a skeleton
4677
Skeleton3D *active_skeleton = Object::cast_to<Skeleton3D>(p_scene_parent);
4678
4679
const bool non_bone_parented_to_skeleton = active_skeleton;
4680
4681
// skinned meshes must not be placed in a bone attachment.
4682
if (non_bone_parented_to_skeleton && gltf_node->skin < 0) {
4683
// Bone Attachment - Parent Case
4684
BoneAttachment3D *bone_attachment = _generate_bone_attachment_compat_4pt4(p_state, active_skeleton, p_node_index, gltf_node->parent);
4685
4686
p_scene_parent->add_child(bone_attachment, true);
4687
4688
// Find the correct bone_idx so we can properly serialize it.
4689
bone_attachment->set_bone_idx(active_skeleton->find_bone(gltf_node->get_name()));
4690
4691
bone_attachment->set_owner(p_scene_root);
4692
4693
// There is no gltf_node that represent this, so just directly create a unique name
4694
bone_attachment->set_name(gltf_node->get_name());
4695
4696
// We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node
4697
// and attach it to the bone_attachment
4698
p_scene_parent = bone_attachment;
4699
}
4700
// Check if any GLTFDocumentExtension classes want to generate a node for us.
4701
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
4702
ERR_CONTINUE(ext.is_null());
4703
current_node = ext->generate_scene_node(p_state, gltf_node, p_scene_parent);
4704
if (current_node) {
4705
break;
4706
}
4707
}
4708
// If none of our GLTFDocumentExtension classes generated us a node, we generate one.
4709
if (!current_node) {
4710
if (gltf_node->skin >= 0 && gltf_node->mesh >= 0 && !gltf_node->children.is_empty()) {
4711
// glTF specifies that skinned meshes should ignore their node transforms,
4712
// only being controlled by the skeleton, so Godot will reparent a skinned
4713
// mesh to its skeleton. However, we still need to ensure any child nodes
4714
// keep their place in the tree, so if there are any child nodes, the skinned
4715
// mesh must not be the base node, so generate an empty spatial base.
4716
current_node = _generate_spatial(p_state, p_node_index);
4717
Node3D *mesh_inst = _generate_mesh_instance(p_state, p_node_index);
4718
mesh_inst->set_name(gltf_node->get_name());
4719
current_node->add_child(mesh_inst, true);
4720
} else if (gltf_node->mesh >= 0) {
4721
current_node = _generate_mesh_instance(p_state, p_node_index);
4722
} else if (gltf_node->camera >= 0) {
4723
current_node = _generate_camera(p_state, p_node_index);
4724
} else if (gltf_node->light >= 0) {
4725
current_node = _generate_light(p_state, p_node_index);
4726
} else {
4727
current_node = _generate_spatial(p_state, p_node_index);
4728
}
4729
}
4730
String gltf_node_name = gltf_node->get_name();
4731
if (!gltf_node_name.is_empty()) {
4732
current_node->set_name(gltf_node_name);
4733
}
4734
current_node->set_visible(gltf_node->visible);
4735
// Note: p_scene_parent and p_scene_root must either both be null or both be valid.
4736
if (p_scene_root == nullptr) {
4737
// If the root node argument is null, this is the root node.
4738
p_scene_root = current_node;
4739
// If multiple nodes were generated under the root node, ensure they have the owner set.
4740
if (unlikely(current_node->get_child_count() > 0)) {
4741
Array args;
4742
args.append(p_scene_root);
4743
for (int i = 0; i < current_node->get_child_count(); i++) {
4744
Node *child = current_node->get_child(i);
4745
child->propagate_call(StringName("set_owner"), args);
4746
}
4747
}
4748
} else {
4749
// Add the node we generated and set the owner to the scene root.
4750
p_scene_parent->add_child(current_node, true);
4751
Array args;
4752
args.append(p_scene_root);
4753
current_node->propagate_call(StringName("set_owner"), args);
4754
current_node->set_transform(gltf_node->transform);
4755
}
4756
4757
current_node->merge_meta_from(*gltf_node);
4758
4759
p_state->scene_nodes.insert(p_node_index, current_node);
4760
for (int i = 0; i < gltf_node->children.size(); ++i) {
4761
_generate_scene_node_compat_4pt4(p_state, gltf_node->children[i], current_node, p_scene_root);
4762
}
4763
}
4764
4765
// Deprecated code used when naming_version is 0 or 1 (Godot 4.0 to 4.4).
4766
void GLTFDocument::_generate_skeleton_bone_node_compat_4pt4(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node *p_scene_parent, Node *p_scene_root) {
4767
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
4768
4769
Node3D *current_node = nullptr;
4770
4771
Skeleton3D *skeleton = p_state->skeletons[gltf_node->skeleton]->godot_skeleton;
4772
// In this case, this node is already a bone in skeleton.
4773
const bool is_skinned_mesh = (gltf_node->skin >= 0 && gltf_node->mesh >= 0);
4774
const bool requires_extra_node = (gltf_node->mesh >= 0 || gltf_node->camera >= 0 || gltf_node->light >= 0);
4775
4776
Skeleton3D *active_skeleton = Object::cast_to<Skeleton3D>(p_scene_parent);
4777
if (active_skeleton != skeleton) {
4778
if (active_skeleton) {
4779
// Should no longer be possible.
4780
ERR_PRINT(vformat("glTF: Generating scene detected direct parented Skeletons at node %d", p_node_index));
4781
BoneAttachment3D *bone_attachment = _generate_bone_attachment_compat_4pt4(p_state, active_skeleton, p_node_index, gltf_node->parent);
4782
p_scene_parent->add_child(bone_attachment, true);
4783
bone_attachment->set_owner(p_scene_root);
4784
// There is no gltf_node that represent this, so just directly create a unique name
4785
bone_attachment->set_name(_gen_unique_name(p_state, "BoneAttachment3D"));
4786
// We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node
4787
// and attach it to the bone_attachment
4788
p_scene_parent = bone_attachment;
4789
}
4790
if (skeleton->get_parent() == nullptr) {
4791
if (p_scene_root) {
4792
p_scene_parent->add_child(skeleton, true);
4793
skeleton->set_owner(p_scene_root);
4794
} else {
4795
p_scene_parent = skeleton;
4796
p_scene_root = skeleton;
4797
}
4798
}
4799
}
4800
4801
active_skeleton = skeleton;
4802
current_node = active_skeleton;
4803
if (active_skeleton) {
4804
p_scene_parent = active_skeleton;
4805
}
4806
4807
if (requires_extra_node) {
4808
current_node = nullptr;
4809
// skinned meshes must not be placed in a bone attachment.
4810
if (!is_skinned_mesh) {
4811
// Bone Attachment - Same Node Case
4812
BoneAttachment3D *bone_attachment = _generate_bone_attachment_compat_4pt4(p_state, active_skeleton, p_node_index, p_node_index);
4813
4814
p_scene_parent->add_child(bone_attachment, true);
4815
4816
// Find the correct bone_idx so we can properly serialize it.
4817
bone_attachment->set_bone_idx(active_skeleton->find_bone(gltf_node->get_name()));
4818
4819
bone_attachment->set_owner(p_scene_root);
4820
4821
// There is no gltf_node that represent this, so just directly create a unique name
4822
bone_attachment->set_name(gltf_node->get_name());
4823
4824
// We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node
4825
// and attach it to the bone_attachment
4826
p_scene_parent = bone_attachment;
4827
}
4828
// Check if any GLTFDocumentExtension classes want to generate a node for us.
4829
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
4830
ERR_CONTINUE(ext.is_null());
4831
current_node = ext->generate_scene_node(p_state, gltf_node, p_scene_parent);
4832
if (current_node) {
4833
break;
4834
}
4835
}
4836
// If none of our GLTFDocumentExtension classes generated us a node, we generate one.
4837
if (!current_node) {
4838
if (gltf_node->mesh >= 0) {
4839
current_node = _generate_mesh_instance(p_state, p_node_index);
4840
} else if (gltf_node->camera >= 0) {
4841
current_node = _generate_camera(p_state, p_node_index);
4842
} else if (gltf_node->light >= 0) {
4843
current_node = _generate_light(p_state, p_node_index);
4844
} else {
4845
current_node = _generate_spatial(p_state, p_node_index);
4846
}
4847
}
4848
// Add the node we generated and set the owner to the scene root.
4849
p_scene_parent->add_child(current_node, true);
4850
if (current_node != p_scene_root) {
4851
Array args;
4852
args.append(p_scene_root);
4853
current_node->propagate_call(StringName("set_owner"), args);
4854
}
4855
// Do not set transform here. Transform is already applied to our bone.
4856
current_node->set_name(gltf_node->get_name());
4857
}
4858
4859
p_state->scene_nodes.insert(p_node_index, current_node);
4860
4861
for (int i = 0; i < gltf_node->children.size(); ++i) {
4862
_generate_scene_node_compat_4pt4(p_state, gltf_node->children[i], active_skeleton, p_scene_root);
4863
}
4864
}
4865
4866
template <typename T>
4867
struct SceneFormatImporterGLTFInterpolate {
4868
T lerp(const T &a, const T &b, float c) const {
4869
return a + (b - a) * c;
4870
}
4871
4872
T catmull_rom(const T &p0, const T &p1, const T &p2, const T &p3, float t) {
4873
const float t2 = t * t;
4874
const float t3 = t2 * t;
4875
4876
return 0.5f * ((2.0f * p1) + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3) * t2 + (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
4877
}
4878
4879
T hermite(T start, T tan_start, T end, T tan_end, float t) {
4880
/* Formula from the glTF 2.0 specification. */
4881
const real_t t2 = t * t;
4882
const real_t t3 = t2 * t;
4883
4884
const real_t h00 = 2.0 * t3 - 3.0 * t2 + 1.0;
4885
const real_t h10 = t3 - 2.0 * t2 + t;
4886
const real_t h01 = -2.0 * t3 + 3.0 * t2;
4887
const real_t h11 = t3 - t2;
4888
4889
return start * h00 + tan_start * h10 + end * h01 + tan_end * h11;
4890
}
4891
};
4892
4893
// thank you for existing, partial specialization
4894
template <>
4895
struct SceneFormatImporterGLTFInterpolate<Quaternion> {
4896
Quaternion lerp(const Quaternion &a, const Quaternion &b, const float c) const {
4897
ERR_FAIL_COND_V_MSG(!a.is_normalized(), Quaternion(), vformat("The quaternion \"a\" %s must be normalized.", a));
4898
ERR_FAIL_COND_V_MSG(!b.is_normalized(), Quaternion(), vformat("The quaternion \"b\" %s must be normalized.", b));
4899
4900
return a.slerp(b, c).normalized();
4901
}
4902
4903
Quaternion catmull_rom(const Quaternion &p0, const Quaternion &p1, const Quaternion &p2, const Quaternion &p3, const float c) {
4904
ERR_FAIL_COND_V_MSG(!p1.is_normalized(), Quaternion(), vformat("The quaternion \"p1\" (%s) must be normalized.", p1));
4905
ERR_FAIL_COND_V_MSG(!p2.is_normalized(), Quaternion(), vformat("The quaternion \"p2\" (%s) must be normalized.", p2));
4906
4907
return p1.slerp(p2, c).normalized();
4908
}
4909
4910
Quaternion hermite(const Quaternion start, const Quaternion tan_start, const Quaternion end, const Quaternion tan_end, const float t) {
4911
ERR_FAIL_COND_V_MSG(!start.is_normalized(), Quaternion(), vformat("The start quaternion %s must be normalized.", start));
4912
ERR_FAIL_COND_V_MSG(!end.is_normalized(), Quaternion(), vformat("The end quaternion %s must be normalized.", end));
4913
4914
return start.slerp(end, t).normalized();
4915
}
4916
};
4917
4918
template <typename T>
4919
T GLTFDocument::_interpolate_track(const Vector<double> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp) {
4920
ERR_FAIL_COND_V(p_values.is_empty(), T());
4921
if (p_times.size() != (p_values.size() / (p_interp == GLTFAnimation::INTERP_CUBIC_SPLINE ? 3 : 1))) {
4922
ERR_PRINT_ONCE("The interpolated values are not corresponding to its times.");
4923
return p_values[0];
4924
}
4925
//could use binary search, worth it?
4926
int idx = -1;
4927
for (int i = 0; i < p_times.size(); i++) {
4928
if (p_times[i] > p_time) {
4929
break;
4930
}
4931
idx++;
4932
}
4933
4934
SceneFormatImporterGLTFInterpolate<T> interp;
4935
4936
switch (p_interp) {
4937
case GLTFAnimation::INTERP_LINEAR: {
4938
if (idx == -1) {
4939
return p_values[0];
4940
} else if (idx >= p_times.size() - 1) {
4941
return p_values[p_times.size() - 1];
4942
}
4943
4944
const float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
4945
4946
return interp.lerp(p_values[idx], p_values[idx + 1], c);
4947
} break;
4948
case GLTFAnimation::INTERP_STEP: {
4949
if (idx == -1) {
4950
return p_values[0];
4951
} else if (idx >= p_times.size() - 1) {
4952
return p_values[p_times.size() - 1];
4953
}
4954
4955
return p_values[idx];
4956
} break;
4957
case GLTFAnimation::INTERP_CATMULLROMSPLINE: {
4958
if (idx == -1) {
4959
return p_values[1];
4960
} else if (idx >= p_times.size() - 1) {
4961
return p_values[1 + p_times.size() - 1];
4962
}
4963
4964
const float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
4965
4966
return interp.catmull_rom(p_values[idx - 1], p_values[idx], p_values[idx + 1], p_values[idx + 3], c);
4967
} break;
4968
case GLTFAnimation::INTERP_CUBIC_SPLINE: {
4969
if (idx == -1) {
4970
return p_values[1];
4971
} else if (idx >= p_times.size() - 1) {
4972
return p_values[(p_times.size() - 1) * 3 + 1];
4973
}
4974
4975
const float td = (p_times[idx + 1] - p_times[idx]);
4976
const float c = (p_time - p_times[idx]) / td;
4977
4978
const T &from = p_values[idx * 3 + 1];
4979
const T tan_from = td * p_values[idx * 3 + 2];
4980
const T &to = p_values[idx * 3 + 4];
4981
const T tan_to = td * p_values[idx * 3 + 3];
4982
4983
return interp.hermite(from, tan_from, to, tan_to, c);
4984
} break;
4985
}
4986
4987
ERR_FAIL_V(p_values[0]);
4988
}
4989
4990
NodePath GLTFDocument::_find_material_node_path(Ref<GLTFState> p_state, const Ref<Material> &p_material) {
4991
int mesh_index = 0;
4992
for (Ref<GLTFMesh> gltf_mesh : p_state->meshes) {
4993
TypedArray<Material> materials = gltf_mesh->get_instance_materials();
4994
for (int mat_index = 0; mat_index < materials.size(); mat_index++) {
4995
if (materials[mat_index] == p_material) {
4996
for (Ref<GLTFNode> gltf_node : p_state->nodes) {
4997
if (gltf_node->mesh == mesh_index) {
4998
NodePath node_path = gltf_node->get_scene_node_path(p_state);
4999
// Example: MyNode:mesh:surface_0/material:albedo_color, so we want the mesh:surface_0/material part.
5000
Vector<StringName> subpath;
5001
subpath.append("mesh");
5002
subpath.append("surface_" + itos(mat_index) + "/material");
5003
return NodePath(node_path.get_names(), subpath, false);
5004
}
5005
}
5006
}
5007
}
5008
mesh_index++;
5009
}
5010
return NodePath();
5011
}
5012
5013
Ref<GLTFObjectModelProperty> GLTFDocument::import_object_model_property(Ref<GLTFState> p_state, const String &p_json_pointer) {
5014
if (p_state->object_model_properties.has(p_json_pointer)) {
5015
return p_state->object_model_properties[p_json_pointer];
5016
}
5017
Ref<GLTFObjectModelProperty> ret;
5018
// Split the JSON pointer into its components.
5019
const PackedStringArray split = p_json_pointer.split("/", false);
5020
ERR_FAIL_COND_V_MSG(split.size() < 3, ret, "glTF: Cannot use JSON pointer '" + p_json_pointer + "' because it does not contain enough elements. The only animatable properties are at least 3 levels deep (ex: '/nodes/0/translation' or '/materials/0/emissiveFactor').");
5021
ret.instantiate();
5022
ret->set_json_pointers({ split });
5023
// Partial paths are passed to GLTFDocumentExtension classes if GLTFDocument cannot handle a given JSON pointer.
5024
TypedArray<NodePath> partial_paths;
5025
// Note: This might not be an integer, but in that case, we don't use this value anyway.
5026
const int top_level_index = split[1].to_int();
5027
// For JSON pointers present in the core glTF Object Model, hard-code them in GLTFDocument.
5028
// https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/ObjectModel.adoc
5029
if (split[0] == "nodes") {
5030
ERR_FAIL_INDEX_V_MSG(top_level_index, p_state->nodes.size(), ret, vformat("glTF: Unable to find node %d for JSON pointer '%s'.", top_level_index, p_json_pointer));
5031
Ref<GLTFNode> pointed_gltf_node = p_state->nodes[top_level_index];
5032
NodePath node_path = pointed_gltf_node->get_scene_node_path(p_state);
5033
partial_paths.append(node_path);
5034
// Check if it's something we should be able to handle.
5035
const String &node_prop = split[2];
5036
if (node_prop == "translation") {
5037
ret->append_path_to_property(node_path, "position");
5038
ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3);
5039
} else if (node_prop == "rotation") {
5040
ret->append_path_to_property(node_path, "quaternion");
5041
ret->set_types(Variant::QUATERNION, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4);
5042
} else if (node_prop == "scale") {
5043
ret->append_path_to_property(node_path, "scale");
5044
ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3);
5045
} else if (node_prop == "matrix") {
5046
ret->append_path_to_property(node_path, "transform");
5047
ret->set_types(Variant::TRANSFORM3D, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4X4);
5048
} else if (node_prop == "globalMatrix") {
5049
ret->append_path_to_property(node_path, "global_transform");
5050
ret->set_types(Variant::TRANSFORM3D, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4X4);
5051
} else if (node_prop == "weights") {
5052
if (split.size() > 3) {
5053
const String &weight_index_string = split[3];
5054
ret->append_path_to_property(node_path, "blend_shapes/morph_" + weight_index_string);
5055
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5056
}
5057
// Else, Godot's MeshInstance3D does not expose the blend shape weights as one property.
5058
// But that's fine, we handle this case in _parse_animation_pointer instead.
5059
} else if (node_prop == "extensions") {
5060
ERR_FAIL_COND_V(split.size() < 5, ret);
5061
const String &ext_name = split[3];
5062
const String &ext_prop = split[4];
5063
if (ext_name == "KHR_node_visibility" && ext_prop == "visible") {
5064
ret->append_path_to_property(node_path, "visible");
5065
ret->set_types(Variant::BOOL, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_BOOL);
5066
}
5067
}
5068
} else if (split[0] == "cameras") {
5069
const String &camera_prop = split[2];
5070
for (Ref<GLTFNode> gltf_node : p_state->nodes) {
5071
if (gltf_node->camera == top_level_index) {
5072
NodePath node_path = gltf_node->get_scene_node_path(p_state);
5073
partial_paths.append(node_path);
5074
// Check if it's something we should be able to handle.
5075
if (camera_prop == "orthographic" || camera_prop == "perspective") {
5076
ERR_FAIL_COND_V(split.size() < 4, ret);
5077
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5078
const String &sub_prop = split[3];
5079
if (sub_prop == "xmag" || sub_prop == "ymag") {
5080
ret->append_path_to_property(node_path, "size");
5081
} else if (sub_prop == "yfov") {
5082
ret->append_path_to_property(node_path, "fov");
5083
GLTFCamera::set_fov_conversion_expressions(ret);
5084
} else if (sub_prop == "zfar") {
5085
ret->append_path_to_property(node_path, "far");
5086
} else if (sub_prop == "znear") {
5087
ret->append_path_to_property(node_path, "near");
5088
}
5089
}
5090
}
5091
}
5092
} else if (split[0] == "materials") {
5093
ERR_FAIL_INDEX_V_MSG(top_level_index, p_state->materials.size(), ret, vformat("glTF: Unable to find material %d for JSON pointer '%s'.", top_level_index, p_json_pointer));
5094
Ref<Material> pointed_material = p_state->materials[top_level_index];
5095
NodePath mat_path = _find_material_node_path(p_state, pointed_material);
5096
if (mat_path.is_empty()) {
5097
WARN_PRINT(vformat("glTF: Unable to find a path to the material %d for JSON pointer '%s'. This is likely bad data but it's also possible this is intentional. Continuing anyway.", top_level_index, p_json_pointer));
5098
} else {
5099
partial_paths.append(mat_path);
5100
const String &mat_prop = split[2];
5101
if (mat_prop == "alphaCutoff") {
5102
ret->append_path_to_property(mat_path, "alpha_scissor_threshold");
5103
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5104
} else if (mat_prop == "emissiveFactor") {
5105
ret->append_path_to_property(mat_path, "emission");
5106
ret->set_types(Variant::COLOR, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3);
5107
} else if (mat_prop == "extensions") {
5108
ERR_FAIL_COND_V(split.size() < 5, ret);
5109
const String &ext_name = split[3];
5110
const String &ext_prop = split[4];
5111
if (ext_name == "KHR_materials_emissive_strength" && ext_prop == "emissiveStrength") {
5112
ret->append_path_to_property(mat_path, "emission_energy_multiplier");
5113
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5114
}
5115
} else {
5116
ERR_FAIL_COND_V(split.size() < 4, ret);
5117
const String &sub_prop = split[3];
5118
if (mat_prop == "normalTexture") {
5119
if (sub_prop == "scale") {
5120
ret->append_path_to_property(mat_path, "normal_scale");
5121
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5122
}
5123
} else if (mat_prop == "occlusionTexture") {
5124
if (sub_prop == "strength") {
5125
// This is the closest thing Godot has to an occlusion strength property.
5126
ret->append_path_to_property(mat_path, "ao_light_affect");
5127
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5128
}
5129
} else if (mat_prop == "pbrMetallicRoughness") {
5130
if (sub_prop == "baseColorFactor") {
5131
ret->append_path_to_property(mat_path, "albedo_color");
5132
ret->set_types(Variant::COLOR, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4);
5133
} else if (sub_prop == "metallicFactor") {
5134
ret->append_path_to_property(mat_path, "metallic");
5135
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5136
} else if (sub_prop == "roughnessFactor") {
5137
ret->append_path_to_property(mat_path, "roughness");
5138
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5139
} else if (sub_prop == "baseColorTexture") {
5140
ERR_FAIL_COND_V(split.size() < 6, ret);
5141
const String &tex_ext_dict = split[4];
5142
const String &tex_ext_name = split[5];
5143
const String &tex_ext_prop = split[6];
5144
if (tex_ext_dict == "extensions" && tex_ext_name == "KHR_texture_transform") {
5145
// Godot only supports UVs for the whole material, not per texture.
5146
// We treat the albedo texture as the main texture, and import as UV1.
5147
// Godot does not support texture rotation, only offset and scale.
5148
if (tex_ext_prop == "offset") {
5149
ret->append_path_to_property(mat_path, "uv1_offset");
5150
ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT2);
5151
} else if (tex_ext_prop == "scale") {
5152
ret->append_path_to_property(mat_path, "uv1_scale");
5153
ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT2);
5154
}
5155
}
5156
}
5157
}
5158
}
5159
}
5160
} else if (split[0] == "meshes") {
5161
for (Ref<GLTFNode> gltf_node : p_state->nodes) {
5162
if (gltf_node->mesh == top_level_index) {
5163
NodePath node_path = gltf_node->get_scene_node_path(p_state);
5164
Vector<StringName> subpath;
5165
subpath.append("mesh");
5166
partial_paths.append(NodePath(node_path.get_names(), subpath, false));
5167
break;
5168
}
5169
}
5170
} else if (split[0] == "extensions") {
5171
if (split[1] == "KHR_lights_punctual" && split[2] == "lights" && split.size() > 4) {
5172
const int light_index = split[3].to_int();
5173
ERR_FAIL_INDEX_V_MSG(light_index, p_state->lights.size(), ret, vformat("glTF: Unable to find light %d for JSON pointer '%s'.", light_index, p_json_pointer));
5174
const String &light_prop = split[4];
5175
const Ref<GLTFLight> pointed_light = p_state->lights[light_index];
5176
for (Ref<GLTFNode> gltf_node : p_state->nodes) {
5177
if (gltf_node->light == light_index) {
5178
NodePath node_path = gltf_node->get_scene_node_path(p_state);
5179
partial_paths.append(node_path);
5180
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5181
// Check if it's something we should be able to handle.
5182
if (light_prop == "color") {
5183
ret->append_path_to_property(node_path, "light_color");
5184
ret->set_types(Variant::COLOR, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3);
5185
} else if (light_prop == "intensity") {
5186
ret->append_path_to_property(node_path, "light_energy");
5187
} else if (light_prop == "range") {
5188
const String &light_type = p_state->lights[light_index]->light_type;
5189
if (light_type == "spot") {
5190
ret->append_path_to_property(node_path, "spot_range");
5191
} else {
5192
ret->append_path_to_property(node_path, "omni_range");
5193
}
5194
} else if (light_prop == "spot") {
5195
ERR_FAIL_COND_V(split.size() < 6, ret);
5196
const String &sub_prop = split[5];
5197
if (sub_prop == "innerConeAngle") {
5198
ret->append_path_to_property(node_path, "spot_angle_attenuation");
5199
GLTFLight::set_cone_inner_attenuation_conversion_expressions(ret);
5200
} else if (sub_prop == "outerConeAngle") {
5201
ret->append_path_to_property(node_path, "spot_angle");
5202
}
5203
}
5204
}
5205
}
5206
}
5207
}
5208
// Additional JSON pointers can be added by GLTFDocumentExtension classes.
5209
// We only need this if no mapping has been found yet from GLTFDocument's internal code.
5210
// When available, we pass the partial paths to the extension to help it generate the full path.
5211
// For example, for `/nodes/3/extensions/MY_ext/prop`, we pass a NodePath that leads to node 3,
5212
// so the GLTFDocumentExtension class only needs to resolve the last `MY_ext/prop` part of the path.
5213
// It should check `split.size() > 4 and split[0] == "nodes" and split[2] == "extensions" and split[3] == "MY_ext"`
5214
// at the start of the function to check if this JSON pointer applies to it, then it can handle `split[4]`.
5215
if (!ret->has_node_paths()) {
5216
for (Ref<GLTFDocumentExtension> ext : all_document_extensions) {
5217
ret = ext->import_object_model_property(p_state, split, partial_paths);
5218
if (ret.is_valid() && ret->has_node_paths()) {
5219
if (!ret->has_json_pointers()) {
5220
ret->set_json_pointers({ split });
5221
}
5222
break;
5223
}
5224
}
5225
if (ret.is_null() || !ret->has_node_paths()) {
5226
if (split.has("KHR_texture_transform")) {
5227
WARN_VERBOSE(vformat("glTF: Texture transforms are only supported per material in Godot. All KHR_texture_transform properties will be ignored except for the albedo texture. Ignoring JSON pointer '%s'.", p_json_pointer));
5228
} else {
5229
WARN_PRINT(vformat("glTF: Animation contained JSON pointer '%s' which could not be resolved. This property will not be animated.", p_json_pointer));
5230
}
5231
}
5232
}
5233
p_state->object_model_properties[p_json_pointer] = ret;
5234
return ret;
5235
}
5236
5237
Ref<GLTFObjectModelProperty> GLTFDocument::export_object_model_property(Ref<GLTFState> p_state, const NodePath &p_node_path, const Node *p_godot_node, GLTFNodeIndex p_gltf_node_index) {
5238
Ref<GLTFObjectModelProperty> ret;
5239
const Object *target_object = p_godot_node;
5240
const Vector<StringName> subpath = p_node_path.get_subnames();
5241
ERR_FAIL_COND_V_MSG(subpath.is_empty(), ret, "glTF: Cannot export empty property. No property was specified in the NodePath: " + String(p_node_path));
5242
int target_prop_depth = 0;
5243
for (int64_t i = 0; i < subpath.size() - 1; i++) {
5244
const StringName &subname = subpath[i];
5245
Variant target_property = target_object->get(subname);
5246
if (target_property.get_type() == Variant::OBJECT) {
5247
target_object = target_property;
5248
if (target_object) {
5249
target_prop_depth++;
5250
continue;
5251
}
5252
}
5253
break;
5254
}
5255
const String &target_prop = subpath[target_prop_depth];
5256
ret.instantiate();
5257
ret->set_node_paths({ p_node_path });
5258
Vector<PackedStringArray> split_json_pointers;
5259
PackedStringArray split_json_pointer;
5260
if (Object::cast_to<BaseMaterial3D>(target_object)) {
5261
for (int i = 0; i < p_state->materials.size(); i++) {
5262
if (p_state->materials[i].ptr() == target_object) {
5263
split_json_pointer.append("materials");
5264
split_json_pointer.append(itos(i));
5265
if (target_prop == "alpha_scissor_threshold") {
5266
split_json_pointer.append("alphaCutoff");
5267
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5268
} else if (target_prop == "emission") {
5269
split_json_pointer.append("emissiveFactor");
5270
ret->set_types(Variant::COLOR, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3);
5271
} else if (target_prop == "emission_energy_multiplier") {
5272
split_json_pointer.append("extensions");
5273
split_json_pointer.append("KHR_materials_emissive_strength");
5274
split_json_pointer.append("emissiveStrength");
5275
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5276
} else if (target_prop == "normal_scale") {
5277
split_json_pointer.append("normalTexture");
5278
split_json_pointer.append("scale");
5279
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5280
} else if (target_prop == "ao_light_affect") {
5281
split_json_pointer.append("occlusionTexture");
5282
split_json_pointer.append("strength");
5283
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5284
} else if (target_prop == "albedo_color") {
5285
split_json_pointer.append("pbrMetallicRoughness");
5286
split_json_pointer.append("baseColorFactor");
5287
ret->set_types(Variant::COLOR, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4);
5288
} else if (target_prop == "metallic") {
5289
split_json_pointer.append("pbrMetallicRoughness");
5290
split_json_pointer.append("metallicFactor");
5291
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5292
} else if (target_prop == "roughness") {
5293
split_json_pointer.append("pbrMetallicRoughness");
5294
split_json_pointer.append("roughnessFactor");
5295
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5296
} else if (target_prop == "uv1_offset" || target_prop == "uv1_scale") {
5297
split_json_pointer.append("pbrMetallicRoughness");
5298
split_json_pointer.append("baseColorTexture");
5299
split_json_pointer.append("extensions");
5300
split_json_pointer.append("KHR_texture_transform");
5301
if (target_prop == "uv1_offset") {
5302
split_json_pointer.append("offset");
5303
} else {
5304
split_json_pointer.append("scale");
5305
}
5306
ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT2);
5307
} else {
5308
split_json_pointer.clear();
5309
}
5310
break;
5311
}
5312
}
5313
} else {
5314
// Properties directly on Godot nodes.
5315
Ref<GLTFNode> gltf_node = p_state->nodes[p_gltf_node_index];
5316
if (Object::cast_to<Camera3D>(target_object) && gltf_node->camera >= 0) {
5317
split_json_pointer.append("cameras");
5318
split_json_pointer.append(itos(gltf_node->camera));
5319
const Camera3D *camera_node = Object::cast_to<Camera3D>(target_object);
5320
const Camera3D::ProjectionType projection_type = camera_node->get_projection();
5321
if (projection_type == Camera3D::PROJECTION_PERSPECTIVE) {
5322
split_json_pointer.append("perspective");
5323
} else {
5324
split_json_pointer.append("orthographic");
5325
}
5326
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5327
if (target_prop == "size") {
5328
PackedStringArray xmag = split_json_pointer.duplicate();
5329
xmag.append("xmag");
5330
split_json_pointers.append(xmag);
5331
split_json_pointer.append("ymag");
5332
} else if (target_prop == "fov") {
5333
split_json_pointer.append("yfov");
5334
GLTFCamera::set_fov_conversion_expressions(ret);
5335
} else if (target_prop == "far") {
5336
split_json_pointer.append("zfar");
5337
} else if (target_prop == "near") {
5338
split_json_pointer.append("znear");
5339
} else {
5340
split_json_pointer.clear();
5341
}
5342
} else if (Object::cast_to<Light3D>(target_object) && gltf_node->light >= 0) {
5343
split_json_pointer.append("extensions");
5344
split_json_pointer.append("KHR_lights_punctual");
5345
split_json_pointer.append("lights");
5346
split_json_pointer.append(itos(gltf_node->light));
5347
ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT);
5348
if (target_prop == "light_color") {
5349
split_json_pointer.append("color");
5350
ret->set_types(Variant::COLOR, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3);
5351
} else if (target_prop == "light_energy") {
5352
split_json_pointer.append("intensity");
5353
} else if (target_prop == "spot_range") {
5354
split_json_pointer.append("range");
5355
} else if (target_prop == "omni_range") {
5356
split_json_pointer.append("range");
5357
} else if (target_prop == "spot_angle") {
5358
split_json_pointer.append("spot");
5359
split_json_pointer.append("outerConeAngle");
5360
} else if (target_prop == "spot_angle_attenuation") {
5361
split_json_pointer.append("spot");
5362
split_json_pointer.append("innerConeAngle");
5363
GLTFLight::set_cone_inner_attenuation_conversion_expressions(ret);
5364
} else {
5365
split_json_pointer.clear();
5366
}
5367
} else if (Object::cast_to<MeshInstance3D>(target_object) && target_prop.begins_with("blend_shapes/morph_")) {
5368
const String &weight_index_string = target_prop.trim_prefix("blend_shapes/morph_");
5369
split_json_pointer.append("nodes");
5370
split_json_pointer.append(itos(p_gltf_node_index));
5371
split_json_pointer.append("weights");
5372
split_json_pointer.append(weight_index_string);
5373
}
5374
// Transform and visibility properties. Check for all 3D nodes if we haven't resolved the JSON pointer yet.
5375
// Note: Do not put this in an `else`, because otherwise this will not be reached.
5376
if (split_json_pointer.is_empty() && Object::cast_to<Node3D>(target_object)) {
5377
split_json_pointer.append("nodes");
5378
split_json_pointer.append(itos(p_gltf_node_index));
5379
if (target_prop == "position") {
5380
split_json_pointer.append("translation");
5381
ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3);
5382
} else if (target_prop == "quaternion") {
5383
// Note: Only Quaternion rotation can be converted from Godot in this mapping.
5384
// Struct methods like from_euler are not accessible from the Expression class. :(
5385
split_json_pointer.append("rotation");
5386
ret->set_types(Variant::QUATERNION, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4);
5387
} else if (target_prop == "scale") {
5388
split_json_pointer.append("scale");
5389
ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3);
5390
} else if (target_prop == "transform") {
5391
split_json_pointer.append("matrix");
5392
ret->set_types(Variant::TRANSFORM3D, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4X4);
5393
} else if (target_prop == "global_transform") {
5394
split_json_pointer.append("globalMatrix");
5395
ret->set_types(Variant::TRANSFORM3D, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4X4);
5396
} else if (target_prop == "visible") {
5397
split_json_pointer.append("extensions");
5398
split_json_pointer.append("KHR_node_visibility");
5399
split_json_pointer.append("visible");
5400
ret->set_types(Variant::BOOL, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_BOOL);
5401
} else {
5402
split_json_pointer.clear();
5403
}
5404
}
5405
}
5406
// Additional JSON pointers can be added by GLTFDocumentExtension classes.
5407
// We only need this if no mapping has been found yet from GLTFDocument's internal code.
5408
// We pass as many pieces of information as we can to the extension to give it lots of context.
5409
if (split_json_pointer.is_empty()) {
5410
for (Ref<GLTFDocumentExtension> ext : all_document_extensions) {
5411
ret = ext->export_object_model_property(p_state, p_node_path, p_godot_node, p_gltf_node_index, target_object, target_prop_depth);
5412
if (ret.is_valid() && ret->has_json_pointers()) {
5413
if (!ret->has_node_paths()) {
5414
ret->set_node_paths({ p_node_path });
5415
}
5416
break;
5417
}
5418
}
5419
} else {
5420
// GLTFDocument's internal code found a mapping, so set it and return it.
5421
split_json_pointers.append(split_json_pointer);
5422
ret->set_json_pointers(split_json_pointers);
5423
}
5424
return ret;
5425
}
5426
5427
void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, const GLTFAnimationIndex p_index, const bool p_trimming, const bool p_remove_immutable_tracks) {
5428
ERR_FAIL_COND(p_state.is_null());
5429
Node *scene_root = p_animation_player->get_parent();
5430
ERR_FAIL_NULL(scene_root);
5431
Ref<GLTFAnimation> anim = p_state->animations[p_index];
5432
5433
String anim_name = anim->get_name();
5434
if (anim_name.is_empty()) {
5435
// No node represent these, and they are not in the hierarchy, so just make a unique name
5436
anim_name = _gen_unique_name(p_state, "Animation");
5437
}
5438
5439
Ref<Animation> animation;
5440
animation.instantiate();
5441
animation->set_name(anim_name);
5442
animation->set_step(1.0 / p_state->get_bake_fps());
5443
5444
if (anim->get_loop()) {
5445
animation->set_loop_mode(Animation::LOOP_LINEAR);
5446
}
5447
5448
double anim_start = p_trimming ? Math::INF : 0.0;
5449
double anim_end = 0.0;
5450
5451
for (const KeyValue<int, GLTFAnimation::NodeTrack> &track_i : anim->get_node_tracks()) {
5452
const GLTFAnimation::NodeTrack &track = track_i.value;
5453
//need to find the path: for skeletons, weight tracks will affect the mesh
5454
NodePath node_path;
5455
//for skeletons, transform tracks always affect bones
5456
NodePath transform_node_path;
5457
//for meshes, especially skinned meshes, there are cases where it will be added as a child
5458
NodePath mesh_instance_node_path;
5459
5460
GLTFNodeIndex node_index = track_i.key;
5461
5462
const Ref<GLTFNode> gltf_node = p_state->nodes[track_i.key];
5463
5464
HashMap<GLTFNodeIndex, Node *>::Iterator node_element = p_state->scene_nodes.find(node_index);
5465
ERR_CONTINUE_MSG(!node_element, vformat("Unable to find node %d for animation.", node_index));
5466
node_path = scene_root->get_path_to(node_element->value);
5467
HashMap<GLTFNodeIndex, ImporterMeshInstance3D *>::Iterator mesh_instance_element = p_state->scene_mesh_instances.find(node_index);
5468
if (mesh_instance_element) {
5469
mesh_instance_node_path = scene_root->get_path_to(mesh_instance_element->value);
5470
} else {
5471
mesh_instance_node_path = node_path;
5472
}
5473
5474
if (gltf_node->skeleton >= 0) {
5475
const Skeleton3D *sk = p_state->skeletons[gltf_node->skeleton]->godot_skeleton;
5476
ERR_FAIL_NULL(sk);
5477
5478
const String path = String(p_animation_player->get_parent()->get_path_to(sk));
5479
const String bone = gltf_node->get_name();
5480
transform_node_path = path + ":" + bone;
5481
} else {
5482
transform_node_path = node_path;
5483
}
5484
5485
if (p_trimming) {
5486
for (int i = 0; i < track.rotation_track.times.size(); i++) {
5487
anim_start = MIN(anim_start, track.rotation_track.times[i]);
5488
anim_end = MAX(anim_end, track.rotation_track.times[i]);
5489
}
5490
for (int i = 0; i < track.position_track.times.size(); i++) {
5491
anim_start = MIN(anim_start, track.position_track.times[i]);
5492
anim_end = MAX(anim_end, track.position_track.times[i]);
5493
}
5494
for (int i = 0; i < track.scale_track.times.size(); i++) {
5495
anim_start = MIN(anim_start, track.scale_track.times[i]);
5496
anim_end = MAX(anim_end, track.scale_track.times[i]);
5497
}
5498
for (int i = 0; i < track.weight_tracks.size(); i++) {
5499
for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
5500
anim_start = MIN(anim_start, track.weight_tracks[i].times[j]);
5501
anim_end = MAX(anim_end, track.weight_tracks[i].times[j]);
5502
}
5503
}
5504
} else {
5505
// If you don't use trimming and the first key time is not at 0.0, fake keys will be inserted.
5506
for (int i = 0; i < track.rotation_track.times.size(); i++) {
5507
anim_end = MAX(anim_end, track.rotation_track.times[i]);
5508
}
5509
for (int i = 0; i < track.position_track.times.size(); i++) {
5510
anim_end = MAX(anim_end, track.position_track.times[i]);
5511
}
5512
for (int i = 0; i < track.scale_track.times.size(); i++) {
5513
anim_end = MAX(anim_end, track.scale_track.times[i]);
5514
}
5515
for (int i = 0; i < track.weight_tracks.size(); i++) {
5516
for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
5517
anim_end = MAX(anim_end, track.weight_tracks[i].times[j]);
5518
}
5519
}
5520
}
5521
5522
// Animated TRS properties will not affect a skinned mesh.
5523
const bool transform_affects_skinned_mesh_instance = gltf_node->skeleton < 0 && gltf_node->skin >= 0;
5524
if ((track.rotation_track.values.size() || track.position_track.values.size() || track.scale_track.values.size()) && !transform_affects_skinned_mesh_instance) {
5525
//make transform track
5526
int base_idx = animation->get_track_count();
5527
int position_idx = -1;
5528
int rotation_idx = -1;
5529
int scale_idx = -1;
5530
5531
if (track.position_track.values.size()) {
5532
bool is_default = true; //discard the track if all it contains is default values
5533
if (p_remove_immutable_tracks) {
5534
Vector3 base_pos = gltf_node->get_position();
5535
for (int i = 0; i < track.position_track.times.size(); i++) {
5536
int value_index = track.position_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i;
5537
ERR_FAIL_COND_MSG(value_index >= track.position_track.values.size(), "Animation sampler output accessor with 'CUBICSPLINE' interpolation doesn't have enough elements.");
5538
Vector3 value = track.position_track.values[value_index];
5539
if (!value.is_equal_approx(base_pos)) {
5540
is_default = false;
5541
break;
5542
}
5543
}
5544
}
5545
if (!p_remove_immutable_tracks || !is_default) {
5546
position_idx = base_idx;
5547
animation->add_track(Animation::TYPE_POSITION_3D);
5548
animation->track_set_path(position_idx, transform_node_path);
5549
animation->track_set_imported(position_idx, true); //helps merging later
5550
if (track.position_track.interpolation == GLTFAnimation::INTERP_STEP) {
5551
animation->track_set_interpolation_type(position_idx, Animation::InterpolationType::INTERPOLATION_NEAREST);
5552
}
5553
base_idx++;
5554
}
5555
}
5556
if (track.rotation_track.values.size()) {
5557
bool is_default = true; //discard the track if all it contains is default values
5558
if (p_remove_immutable_tracks) {
5559
Quaternion base_rot = gltf_node->get_rotation();
5560
for (int i = 0; i < track.rotation_track.times.size(); i++) {
5561
int value_index = track.rotation_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i;
5562
ERR_FAIL_COND_MSG(value_index >= track.rotation_track.values.size(), "Animation sampler output accessor with 'CUBICSPLINE' interpolation doesn't have enough elements.");
5563
Quaternion value = track.rotation_track.values[value_index].normalized();
5564
if (!value.is_equal_approx(base_rot)) {
5565
is_default = false;
5566
break;
5567
}
5568
}
5569
}
5570
if (!p_remove_immutable_tracks || !is_default) {
5571
rotation_idx = base_idx;
5572
animation->add_track(Animation::TYPE_ROTATION_3D);
5573
animation->track_set_path(rotation_idx, transform_node_path);
5574
animation->track_set_imported(rotation_idx, true); //helps merging later
5575
if (track.rotation_track.interpolation == GLTFAnimation::INTERP_STEP) {
5576
animation->track_set_interpolation_type(rotation_idx, Animation::InterpolationType::INTERPOLATION_NEAREST);
5577
}
5578
base_idx++;
5579
}
5580
}
5581
if (track.scale_track.values.size()) {
5582
bool is_default = true; //discard the track if all it contains is default values
5583
if (p_remove_immutable_tracks) {
5584
Vector3 base_scale = gltf_node->get_scale();
5585
for (int i = 0; i < track.scale_track.times.size(); i++) {
5586
int value_index = track.scale_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i;
5587
ERR_FAIL_COND_MSG(value_index >= track.scale_track.values.size(), "Animation sampler output accessor with 'CUBICSPLINE' interpolation doesn't have enough elements.");
5588
Vector3 value = track.scale_track.values[value_index];
5589
if (!value.is_equal_approx(base_scale)) {
5590
is_default = false;
5591
break;
5592
}
5593
}
5594
}
5595
if (!p_remove_immutable_tracks || !is_default) {
5596
scale_idx = base_idx;
5597
animation->add_track(Animation::TYPE_SCALE_3D);
5598
animation->track_set_path(scale_idx, transform_node_path);
5599
animation->track_set_imported(scale_idx, true); //helps merging later
5600
if (track.scale_track.interpolation == GLTFAnimation::INTERP_STEP) {
5601
animation->track_set_interpolation_type(scale_idx, Animation::InterpolationType::INTERPOLATION_NEAREST);
5602
}
5603
base_idx++;
5604
}
5605
}
5606
5607
const double increment = 1.0 / p_state->get_bake_fps();
5608
double time = anim_start;
5609
5610
Vector3 base_pos;
5611
Quaternion base_rot;
5612
Vector3 base_scale = Vector3(1, 1, 1);
5613
5614
if (rotation_idx == -1) {
5615
base_rot = gltf_node->get_rotation();
5616
}
5617
5618
if (position_idx == -1) {
5619
base_pos = gltf_node->get_position();
5620
}
5621
5622
if (scale_idx == -1) {
5623
base_scale = gltf_node->get_scale();
5624
}
5625
5626
bool last = false;
5627
while (true) {
5628
Vector3 pos = base_pos;
5629
Quaternion rot = base_rot;
5630
Vector3 scale = base_scale;
5631
5632
if (position_idx >= 0) {
5633
pos = _interpolate_track<Vector3>(track.position_track.times, track.position_track.values, time, track.position_track.interpolation);
5634
animation->position_track_insert_key(position_idx, time - anim_start, pos);
5635
}
5636
5637
if (rotation_idx >= 0) {
5638
rot = _interpolate_track<Quaternion>(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation);
5639
animation->rotation_track_insert_key(rotation_idx, time - anim_start, rot);
5640
}
5641
5642
if (scale_idx >= 0) {
5643
scale = _interpolate_track<Vector3>(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation);
5644
animation->scale_track_insert_key(scale_idx, time - anim_start, scale);
5645
}
5646
5647
if (last) {
5648
break;
5649
}
5650
time += increment;
5651
if (time >= anim_end) {
5652
last = true;
5653
time = anim_end;
5654
}
5655
}
5656
}
5657
5658
for (int i = 0; i < track.weight_tracks.size(); i++) {
5659
ERR_CONTINUE(gltf_node->mesh < 0 || gltf_node->mesh >= p_state->meshes.size());
5660
Ref<GLTFMesh> mesh = p_state->meshes[gltf_node->mesh];
5661
ERR_CONTINUE(mesh.is_null());
5662
ERR_CONTINUE(mesh->get_mesh().is_null());
5663
ERR_CONTINUE(mesh->get_mesh()->get_mesh().is_null());
5664
5665
const String blend_path = String(mesh_instance_node_path) + ":" + String(mesh->get_mesh()->get_blend_shape_name(i));
5666
5667
const int track_idx = animation->get_track_count();
5668
animation->add_track(Animation::TYPE_BLEND_SHAPE);
5669
animation->track_set_path(track_idx, blend_path);
5670
animation->track_set_imported(track_idx, true); //helps merging later
5671
5672
// Only LINEAR and STEP (NEAREST) can be supported out of the box by Godot's Animation,
5673
// the other modes have to be baked.
5674
GLTFAnimation::Interpolation gltf_interp = track.weight_tracks[i].interpolation;
5675
if (gltf_interp == GLTFAnimation::INTERP_LINEAR || gltf_interp == GLTFAnimation::INTERP_STEP) {
5676
animation->track_set_interpolation_type(track_idx, gltf_interp == GLTFAnimation::INTERP_STEP ? Animation::INTERPOLATION_NEAREST : Animation::INTERPOLATION_LINEAR);
5677
for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
5678
const float t = track.weight_tracks[i].times[j];
5679
const float attribs = track.weight_tracks[i].values[j];
5680
animation->blend_shape_track_insert_key(track_idx, t, attribs);
5681
}
5682
} else {
5683
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
5684
const double increment = 1.0 / p_state->get_bake_fps();
5685
double time = 0.0;
5686
bool last = false;
5687
while (true) {
5688
real_t blend = _interpolate_track<real_t>(track.weight_tracks[i].times, track.weight_tracks[i].values, time, gltf_interp);
5689
animation->blend_shape_track_insert_key(track_idx, time - anim_start, blend);
5690
if (last) {
5691
break;
5692
}
5693
time += increment;
5694
if (time >= anim_end) {
5695
last = true;
5696
time = anim_end;
5697
}
5698
}
5699
}
5700
}
5701
}
5702
5703
for (const KeyValue<String, GLTFAnimation::Channel<Variant>> &track_iter : anim->get_pointer_tracks()) {
5704
// Determine the property to animate.
5705
const String json_pointer = track_iter.key;
5706
const Ref<GLTFObjectModelProperty> prop = import_object_model_property(p_state, json_pointer);
5707
ERR_FAIL_COND(prop.is_null());
5708
// Adjust the animation duration to encompass all keyframes.
5709
const GLTFAnimation::Channel<Variant> &channel = track_iter.value;
5710
ERR_CONTINUE_MSG(channel.times.size() != channel.values.size(), vformat("glTF: Animation pointer '%s' has mismatched keyframe times and values.", json_pointer));
5711
if (p_trimming) {
5712
for (int i = 0; i < channel.times.size(); i++) {
5713
anim_start = MIN(anim_start, channel.times[i]);
5714
anim_end = MAX(anim_end, channel.times[i]);
5715
}
5716
} else {
5717
for (int i = 0; i < channel.times.size(); i++) {
5718
anim_end = MAX(anim_end, channel.times[i]);
5719
}
5720
}
5721
// Begin converting the glTF animation to a Godot animation.
5722
const Ref<Expression> gltf_to_godot_expr = prop->get_gltf_to_godot_expression();
5723
const bool is_gltf_to_godot_expr_valid = gltf_to_godot_expr.is_valid();
5724
for (const NodePath node_path : prop->get_node_paths()) {
5725
// If using an expression, determine the base instance to pass to the expression.
5726
Object *base_instance = nullptr;
5727
if (is_gltf_to_godot_expr_valid) {
5728
Ref<Resource> resource;
5729
Vector<StringName> leftover_subpath;
5730
base_instance = scene_root->get_node_and_resource(node_path, resource, leftover_subpath);
5731
if (resource.is_valid()) {
5732
base_instance = resource.ptr();
5733
}
5734
}
5735
// Add a track and insert all keys and values.
5736
const int track_index = animation->get_track_count();
5737
animation->add_track(Animation::TYPE_VALUE);
5738
animation->track_set_interpolation_type(track_index, GLTFAnimation::gltf_to_godot_interpolation(channel.interpolation));
5739
animation->track_set_path(track_index, node_path);
5740
for (int i = 0; i < channel.times.size(); i++) {
5741
const double time = channel.times[i];
5742
Variant value = channel.values[i];
5743
if (is_gltf_to_godot_expr_valid) {
5744
Array inputs;
5745
inputs.append(value);
5746
value = gltf_to_godot_expr->execute(inputs, base_instance);
5747
}
5748
animation->track_insert_key(track_index, time, value);
5749
}
5750
}
5751
}
5752
5753
animation->set_length(anim_end - anim_start);
5754
5755
Ref<AnimationLibrary> library;
5756
if (!p_animation_player->has_animation_library("")) {
5757
library.instantiate();
5758
p_animation_player->add_animation_library("", library);
5759
} else {
5760
library = p_animation_player->get_animation_library("");
5761
}
5762
library->add_animation(anim_name, animation);
5763
}
5764
5765
void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> p_state) {
5766
for (GLTFNodeIndex mi_node_i = 0; mi_node_i < p_state->nodes.size(); ++mi_node_i) {
5767
Ref<GLTFNode> node = p_state->nodes[mi_node_i];
5768
5769
if (node->mesh < 0) {
5770
continue;
5771
}
5772
HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = p_state->scene_nodes.find(mi_node_i);
5773
if (!mi_element) {
5774
continue;
5775
}
5776
MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(mi_element->value);
5777
if (!mi) {
5778
continue;
5779
}
5780
node->transform = mi->get_transform();
5781
5782
Node *skel_node = mi->get_node_or_null(mi->get_skeleton_path());
5783
Skeleton3D *godot_skeleton = Object::cast_to<Skeleton3D>(skel_node);
5784
if (!godot_skeleton || godot_skeleton->get_bone_count() == 0) {
5785
continue;
5786
}
5787
// At this point in the code, we know we have a Skeleton3D with at least one bone.
5788
Ref<Skin> skin = mi->get_skin();
5789
Ref<GLTFSkin> gltf_skin;
5790
gltf_skin.instantiate();
5791
Array json_joints;
5792
if (p_state->skeleton3d_to_gltf_skeleton.has(godot_skeleton->get_instance_id())) {
5793
// This is a skinned mesh. If the mesh has no ARRAY_WEIGHTS or ARRAY_BONES, it will be invisible.
5794
const GLTFSkeletonIndex skeleton_gltf_i = p_state->skeleton3d_to_gltf_skeleton[godot_skeleton->get_instance_id()];
5795
Ref<GLTFSkeleton> gltf_skeleton = p_state->skeletons[skeleton_gltf_i];
5796
int bone_cnt = godot_skeleton->get_bone_count();
5797
ERR_FAIL_COND(bone_cnt != gltf_skeleton->joints.size());
5798
5799
ObjectID gltf_skin_key;
5800
if (skin.is_valid()) {
5801
gltf_skin_key = skin->get_instance_id();
5802
}
5803
ObjectID gltf_skel_key = godot_skeleton->get_instance_id();
5804
GLTFSkinIndex skin_gltf_i = -1;
5805
GLTFNodeIndex root_gltf_i = -1;
5806
if (!gltf_skeleton->roots.is_empty()) {
5807
root_gltf_i = gltf_skeleton->roots[0];
5808
}
5809
if (p_state->skin_and_skeleton3d_to_gltf_skin.has(gltf_skin_key) && p_state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key].has(gltf_skel_key)) {
5810
skin_gltf_i = p_state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key][gltf_skel_key];
5811
} else {
5812
if (skin.is_null()) {
5813
// Note that gltf_skin_key should remain null, so these can share a reference.
5814
skin = godot_skeleton->create_skin_from_rest_transforms();
5815
}
5816
gltf_skin.instantiate();
5817
gltf_skin->godot_skin = skin;
5818
gltf_skin->set_name(skin->get_name());
5819
gltf_skin->skeleton = skeleton_gltf_i;
5820
gltf_skin->skin_root = root_gltf_i;
5821
//gltf_state->godot_to_gltf_node[skel_node]
5822
HashMap<StringName, int> bone_name_to_idx;
5823
for (int bone_i = 0; bone_i < bone_cnt; bone_i++) {
5824
bone_name_to_idx[godot_skeleton->get_bone_name(bone_i)] = bone_i;
5825
}
5826
for (int bind_i = 0, cnt = skin->get_bind_count(); bind_i < cnt; bind_i++) {
5827
int bone_i = skin->get_bind_bone(bind_i);
5828
Transform3D bind_pose = skin->get_bind_pose(bind_i);
5829
StringName bind_name = skin->get_bind_name(bind_i);
5830
if (bind_name != StringName()) {
5831
bone_i = bone_name_to_idx[bind_name];
5832
}
5833
ERR_CONTINUE(bone_i < 0 || bone_i >= bone_cnt);
5834
if (bind_name == StringName()) {
5835
bind_name = godot_skeleton->get_bone_name(bone_i);
5836
}
5837
GLTFNodeIndex skeleton_bone_i = gltf_skeleton->joints[bone_i];
5838
gltf_skin->joints_original.push_back(skeleton_bone_i);
5839
gltf_skin->joints.push_back(skeleton_bone_i);
5840
gltf_skin->inverse_binds.push_back(bind_pose);
5841
if (godot_skeleton->get_bone_parent(bone_i) == -1) {
5842
gltf_skin->roots.push_back(skeleton_bone_i);
5843
}
5844
gltf_skin->joint_i_to_bone_i[bind_i] = bone_i;
5845
gltf_skin->joint_i_to_name[bind_i] = bind_name;
5846
}
5847
skin_gltf_i = p_state->skins.size();
5848
p_state->skins.push_back(gltf_skin);
5849
p_state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key][gltf_skel_key] = skin_gltf_i;
5850
}
5851
node->skin = skin_gltf_i;
5852
node->skeleton = skeleton_gltf_i;
5853
}
5854
}
5855
}
5856
5857
float GLTFDocument::solve_metallic(float p_dielectric_specular, float p_diffuse, float p_specular, float p_one_minus_specular_strength) {
5858
if (p_specular <= p_dielectric_specular) {
5859
return 0.0f;
5860
}
5861
5862
const float a = p_dielectric_specular;
5863
const float b = p_diffuse * p_one_minus_specular_strength / (1.0f - p_dielectric_specular) + p_specular - 2.0f * p_dielectric_specular;
5864
const float c = p_dielectric_specular - p_specular;
5865
const float D = b * b - 4.0f * a * c;
5866
return CLAMP((-b + Math::sqrt(D)) / (2.0f * a), 0.0f, 1.0f);
5867
}
5868
5869
float GLTFDocument::get_perceived_brightness(const Color p_color) {
5870
const Color coeff = Color(R_BRIGHTNESS_COEFF, G_BRIGHTNESS_COEFF, B_BRIGHTNESS_COEFF);
5871
const Color value = coeff * (p_color * p_color);
5872
5873
const float r = value.r;
5874
const float g = value.g;
5875
const float b = value.b;
5876
5877
return Math::sqrt(r + g + b);
5878
}
5879
5880
float GLTFDocument::get_max_component(const Color &p_color) {
5881
const float r = p_color.r;
5882
const float g = p_color.g;
5883
const float b = p_color.b;
5884
5885
return MAX(MAX(r, g), b);
5886
}
5887
5888
void GLTFDocument::_process_mesh_instances(Ref<GLTFState> p_state, Node *p_scene_root) {
5889
for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); ++node_i) {
5890
Ref<GLTFNode> node = p_state->nodes[node_i];
5891
5892
if (node->skin >= 0 && node->mesh >= 0) {
5893
const GLTFSkinIndex skin_i = node->skin;
5894
5895
ImporterMeshInstance3D *mi = nullptr;
5896
HashMap<GLTFNodeIndex, ImporterMeshInstance3D *>::Iterator mi_element = p_state->scene_mesh_instances.find(node_i);
5897
if (mi_element) {
5898
mi = mi_element->value;
5899
} else {
5900
HashMap<GLTFNodeIndex, Node *>::Iterator si_element = p_state->scene_nodes.find(node_i);
5901
ERR_CONTINUE_MSG(!si_element, vformat("Unable to find node %d", node_i));
5902
mi = Object::cast_to<ImporterMeshInstance3D>(si_element->value);
5903
ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to ImporterMeshInstance3D", node_i, si_element->value->get_class_name()));
5904
}
5905
ERR_CONTINUE_MSG(mi->get_child_count() > 0, "The glTF importer must generate skinned mesh instances as leaf nodes without any children to allow them to be repositioned in the tree without affecting other nodes.");
5906
5907
const GLTFSkeletonIndex skel_i = p_state->skins.write[node->skin]->skeleton;
5908
Ref<GLTFSkeleton> gltf_skeleton = p_state->skeletons.write[skel_i];
5909
Skeleton3D *skeleton = gltf_skeleton->godot_skeleton;
5910
ERR_CONTINUE_MSG(skeleton == nullptr, vformat("Unable to find Skeleton for node %d skin %d", node_i, skin_i));
5911
5912
mi->get_parent()->remove_child(mi);
5913
mi->set_owner(nullptr);
5914
skeleton->add_child(mi, true);
5915
mi->set_owner(p_scene_root);
5916
5917
mi->set_skin(p_state->skins.write[skin_i]->godot_skin);
5918
mi->set_skeleton_path(mi->get_path_to(skeleton));
5919
mi->set_transform(Transform3D());
5920
}
5921
}
5922
}
5923
5924
GLTFNodeIndex GLTFDocument::_node_and_or_bone_to_gltf_node_index(Ref<GLTFState> p_state, const Vector<StringName> &p_node_subpath, const Node *p_godot_node) {
5925
const Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_godot_node);
5926
if (skeleton && p_node_subpath.size() == 1) {
5927
// Special case: Handle skeleton bone TRS tracks. They use the format `A/B/C/Skeleton3D:bone_name`.
5928
// We have a Skeleton3D, check if it has a bone with the same name as this subpath.
5929
const String &bone_name = p_node_subpath[0];
5930
const int32_t bone_index = skeleton->find_bone(bone_name);
5931
if (bone_index != -1) {
5932
// A bone was found! But we still need to figure out which glTF node it corresponds to.
5933
for (GLTFSkeletonIndex skeleton_i = 0; skeleton_i < p_state->skeletons.size(); skeleton_i++) {
5934
const Ref<GLTFSkeleton> &skeleton_gltf = p_state->skeletons[skeleton_i];
5935
if (skeleton == skeleton_gltf->godot_skeleton) {
5936
GLTFNodeIndex node_i = skeleton_gltf->godot_bone_node[bone_index];
5937
return node_i;
5938
}
5939
}
5940
ERR_FAIL_V_MSG(-1, vformat("glTF: Found a bone %s in a Skeleton3D that wasn't in the GLTFState. Ensure that all nodes referenced by the AnimationPlayer are in the scene you are exporting.", bone_name));
5941
}
5942
}
5943
// General case: Not a skeleton bone, usually this means a normal node, or it could be the Skeleton3D itself.
5944
for (const KeyValue<GLTFNodeIndex, Node *> &scene_node_i : p_state->scene_nodes) {
5945
if (scene_node_i.value == p_godot_node) {
5946
return scene_node_i.key;
5947
}
5948
}
5949
ERR_FAIL_V_MSG(-1, vformat("glTF: A node was animated, but it wasn't found in the GLTFState. Ensure that all nodes referenced by the AnimationPlayer are in the scene you are exporting."));
5950
}
5951
5952
bool GLTFDocument::_convert_animation_node_track(Ref<GLTFState> p_state, GLTFAnimation::NodeTrack &p_gltf_node_track, const Ref<Animation> &p_godot_animation, int32_t p_godot_anim_track_index, Vector<double> &p_times) {
5953
GLTFAnimation::Interpolation gltf_interpolation = GLTFAnimation::godot_to_gltf_interpolation(p_godot_animation, p_godot_anim_track_index);
5954
const Animation::TrackType track_type = p_godot_animation->track_get_type(p_godot_anim_track_index);
5955
const int32_t key_count = p_godot_animation->track_get_key_count(p_godot_anim_track_index);
5956
const NodePath node_path = p_godot_animation->track_get_path(p_godot_anim_track_index);
5957
const Vector<StringName> subpath = node_path.get_subnames();
5958
double anim_end = p_godot_animation->get_length();
5959
if (track_type == Animation::TYPE_SCALE_3D) {
5960
if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
5961
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
5962
p_gltf_node_track.scale_track.times.clear();
5963
p_gltf_node_track.scale_track.values.clear();
5964
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
5965
const double increment = 1.0 / p_state->get_bake_fps();
5966
double time = 0.0;
5967
bool last = false;
5968
while (true) {
5969
Vector3 scale;
5970
Error err = p_godot_animation->try_scale_track_interpolate(p_godot_anim_track_index, time, &scale);
5971
if (err == OK) {
5972
p_gltf_node_track.scale_track.values.push_back(scale);
5973
p_gltf_node_track.scale_track.times.push_back(time);
5974
} else {
5975
ERR_PRINT(vformat("Error interpolating animation %s scale track %d at time %f", p_godot_animation->get_name(), p_godot_anim_track_index, time));
5976
}
5977
if (last) {
5978
break;
5979
}
5980
time += increment;
5981
if (time >= anim_end) {
5982
last = true;
5983
time = anim_end;
5984
}
5985
}
5986
} else {
5987
p_gltf_node_track.scale_track.times = p_times;
5988
p_gltf_node_track.scale_track.interpolation = gltf_interpolation;
5989
p_gltf_node_track.scale_track.values.resize(key_count);
5990
for (int32_t key_i = 0; key_i < key_count; key_i++) {
5991
Vector3 scale;
5992
Error err = p_godot_animation->scale_track_get_key(p_godot_anim_track_index, key_i, &scale);
5993
ERR_CONTINUE(err != OK);
5994
p_gltf_node_track.scale_track.values.write[key_i] = scale;
5995
}
5996
}
5997
} else if (track_type == Animation::TYPE_POSITION_3D) {
5998
if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
5999
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
6000
p_gltf_node_track.position_track.times.clear();
6001
p_gltf_node_track.position_track.values.clear();
6002
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
6003
const double increment = 1.0 / p_state->get_bake_fps();
6004
double time = 0.0;
6005
bool last = false;
6006
while (true) {
6007
Vector3 scale;
6008
Error err = p_godot_animation->try_position_track_interpolate(p_godot_anim_track_index, time, &scale);
6009
if (err == OK) {
6010
p_gltf_node_track.position_track.values.push_back(scale);
6011
p_gltf_node_track.position_track.times.push_back(time);
6012
} else {
6013
ERR_PRINT(vformat("Error interpolating animation %s position track %d at time %f", p_godot_animation->get_name(), p_godot_anim_track_index, time));
6014
}
6015
if (last) {
6016
break;
6017
}
6018
time += increment;
6019
if (time >= anim_end) {
6020
last = true;
6021
time = anim_end;
6022
}
6023
}
6024
} else {
6025
p_gltf_node_track.position_track.times = p_times;
6026
p_gltf_node_track.position_track.values.resize(key_count);
6027
p_gltf_node_track.position_track.interpolation = gltf_interpolation;
6028
for (int32_t key_i = 0; key_i < key_count; key_i++) {
6029
Vector3 position;
6030
Error err = p_godot_animation->position_track_get_key(p_godot_anim_track_index, key_i, &position);
6031
ERR_CONTINUE(err != OK);
6032
p_gltf_node_track.position_track.values.write[key_i] = position;
6033
}
6034
}
6035
} else if (track_type == Animation::TYPE_ROTATION_3D) {
6036
if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
6037
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
6038
p_gltf_node_track.rotation_track.times.clear();
6039
p_gltf_node_track.rotation_track.values.clear();
6040
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
6041
const double increment = 1.0 / p_state->get_bake_fps();
6042
double time = 0.0;
6043
bool last = false;
6044
while (true) {
6045
Quaternion rotation;
6046
Error err = p_godot_animation->try_rotation_track_interpolate(p_godot_anim_track_index, time, &rotation);
6047
if (err == OK) {
6048
p_gltf_node_track.rotation_track.values.push_back(rotation);
6049
p_gltf_node_track.rotation_track.times.push_back(time);
6050
} else {
6051
ERR_PRINT(vformat("Error interpolating animation %s value rotation track %d at time %f", p_godot_animation->get_name(), p_godot_anim_track_index, time));
6052
}
6053
if (last) {
6054
break;
6055
}
6056
time += increment;
6057
if (time >= anim_end) {
6058
last = true;
6059
time = anim_end;
6060
}
6061
}
6062
} else {
6063
p_gltf_node_track.rotation_track.times = p_times;
6064
p_gltf_node_track.rotation_track.values.resize(key_count);
6065
p_gltf_node_track.rotation_track.interpolation = gltf_interpolation;
6066
for (int32_t key_i = 0; key_i < key_count; key_i++) {
6067
Quaternion rotation;
6068
Error err = p_godot_animation->rotation_track_get_key(p_godot_anim_track_index, key_i, &rotation);
6069
ERR_CONTINUE(err != OK);
6070
p_gltf_node_track.rotation_track.values.write[key_i] = rotation;
6071
}
6072
}
6073
} else if (subpath.size() > 0) {
6074
const StringName &node_prop = subpath[0];
6075
if (track_type == Animation::TYPE_VALUE) {
6076
if (node_prop == "position") {
6077
p_gltf_node_track.position_track.interpolation = gltf_interpolation;
6078
p_gltf_node_track.position_track.times = p_times;
6079
p_gltf_node_track.position_track.values.resize(key_count);
6080
6081
if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
6082
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
6083
p_gltf_node_track.position_track.times.clear();
6084
p_gltf_node_track.position_track.values.clear();
6085
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
6086
const double increment = 1.0 / p_state->get_bake_fps();
6087
double time = 0.0;
6088
bool last = false;
6089
while (true) {
6090
Vector3 position;
6091
Error err = p_godot_animation->try_position_track_interpolate(p_godot_anim_track_index, time, &position);
6092
if (err == OK) {
6093
p_gltf_node_track.position_track.values.push_back(position);
6094
p_gltf_node_track.position_track.times.push_back(time);
6095
} else {
6096
ERR_PRINT(vformat("Error interpolating animation %s value position track %d at time %f", p_godot_animation->get_name(), p_godot_anim_track_index, time));
6097
}
6098
if (last) {
6099
break;
6100
}
6101
time += increment;
6102
if (time >= anim_end) {
6103
last = true;
6104
time = anim_end;
6105
}
6106
}
6107
} else {
6108
for (int32_t key_i = 0; key_i < key_count; key_i++) {
6109
Vector3 position = p_godot_animation->track_get_key_value(p_godot_anim_track_index, key_i);
6110
p_gltf_node_track.position_track.values.write[key_i] = position;
6111
}
6112
}
6113
} else if (node_prop == "rotation" || node_prop == "rotation_degrees" || node_prop == "quaternion") {
6114
p_gltf_node_track.rotation_track.interpolation = gltf_interpolation;
6115
p_gltf_node_track.rotation_track.times = p_times;
6116
p_gltf_node_track.rotation_track.values.resize(key_count);
6117
if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
6118
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
6119
p_gltf_node_track.rotation_track.times.clear();
6120
p_gltf_node_track.rotation_track.values.clear();
6121
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
6122
const double increment = 1.0 / p_state->get_bake_fps();
6123
double time = 0.0;
6124
bool last = false;
6125
while (true) {
6126
Quaternion rotation;
6127
Error err = p_godot_animation->try_rotation_track_interpolate(p_godot_anim_track_index, time, &rotation);
6128
if (err == OK) {
6129
p_gltf_node_track.rotation_track.values.push_back(rotation);
6130
p_gltf_node_track.rotation_track.times.push_back(time);
6131
} else {
6132
ERR_PRINT(vformat("Error interpolating animation %s value rotation track %d at time %f", p_godot_animation->get_name(), p_godot_anim_track_index, time));
6133
}
6134
if (last) {
6135
break;
6136
}
6137
time += increment;
6138
if (time >= anim_end) {
6139
last = true;
6140
time = anim_end;
6141
}
6142
}
6143
} else {
6144
for (int32_t key_i = 0; key_i < key_count; key_i++) {
6145
Quaternion rotation_quaternion;
6146
if (node_prop == "quaternion") {
6147
rotation_quaternion = p_godot_animation->track_get_key_value(p_godot_anim_track_index, key_i);
6148
} else {
6149
Vector3 rotation_euler = p_godot_animation->track_get_key_value(p_godot_anim_track_index, key_i);
6150
if (node_prop == "rotation_degrees") {
6151
rotation_euler *= Math::TAU / 360.0;
6152
}
6153
rotation_quaternion = Quaternion::from_euler(rotation_euler);
6154
}
6155
p_gltf_node_track.rotation_track.values.write[key_i] = rotation_quaternion;
6156
}
6157
}
6158
} else if (node_prop == "scale") {
6159
p_gltf_node_track.scale_track.interpolation = gltf_interpolation;
6160
p_gltf_node_track.scale_track.times = p_times;
6161
p_gltf_node_track.scale_track.values.resize(key_count);
6162
6163
if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
6164
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
6165
p_gltf_node_track.scale_track.times.clear();
6166
p_gltf_node_track.scale_track.values.clear();
6167
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
6168
const double increment = 1.0 / p_state->get_bake_fps();
6169
double time = 0.0;
6170
bool last = false;
6171
while (true) {
6172
Vector3 scale;
6173
Error err = p_godot_animation->try_scale_track_interpolate(p_godot_anim_track_index, time, &scale);
6174
if (err == OK) {
6175
p_gltf_node_track.scale_track.values.push_back(scale);
6176
p_gltf_node_track.scale_track.times.push_back(time);
6177
} else {
6178
ERR_PRINT(vformat("Error interpolating animation %s scale track %d at time %f", p_godot_animation->get_name(), p_godot_anim_track_index, time));
6179
}
6180
if (last) {
6181
break;
6182
}
6183
time += increment;
6184
if (time >= anim_end) {
6185
last = true;
6186
time = anim_end;
6187
}
6188
}
6189
} else {
6190
for (int32_t key_i = 0; key_i < key_count; key_i++) {
6191
Vector3 scale_track = p_godot_animation->track_get_key_value(p_godot_anim_track_index, key_i);
6192
p_gltf_node_track.scale_track.values.write[key_i] = scale_track;
6193
}
6194
}
6195
} else if (node_prop == "transform") {
6196
p_gltf_node_track.position_track.interpolation = gltf_interpolation;
6197
p_gltf_node_track.position_track.times = p_times;
6198
p_gltf_node_track.position_track.values.resize(key_count);
6199
p_gltf_node_track.rotation_track.interpolation = gltf_interpolation;
6200
p_gltf_node_track.rotation_track.times = p_times;
6201
p_gltf_node_track.rotation_track.values.resize(key_count);
6202
p_gltf_node_track.scale_track.interpolation = gltf_interpolation;
6203
p_gltf_node_track.scale_track.times = p_times;
6204
p_gltf_node_track.scale_track.values.resize(key_count);
6205
if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
6206
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
6207
p_gltf_node_track.position_track.times.clear();
6208
p_gltf_node_track.position_track.values.clear();
6209
p_gltf_node_track.rotation_track.times.clear();
6210
p_gltf_node_track.rotation_track.values.clear();
6211
p_gltf_node_track.scale_track.times.clear();
6212
p_gltf_node_track.scale_track.values.clear();
6213
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
6214
const double increment = 1.0 / p_state->get_bake_fps();
6215
double time = 0.0;
6216
bool last = false;
6217
while (true) {
6218
Vector3 position;
6219
Quaternion rotation;
6220
Vector3 scale;
6221
Error err = p_godot_animation->try_position_track_interpolate(p_godot_anim_track_index, time, &position);
6222
if (err == OK) {
6223
err = p_godot_animation->try_rotation_track_interpolate(p_godot_anim_track_index, time, &rotation);
6224
if (err == OK) {
6225
err = p_godot_animation->try_scale_track_interpolate(p_godot_anim_track_index, time, &scale);
6226
}
6227
}
6228
if (err == OK) {
6229
p_gltf_node_track.position_track.values.push_back(position);
6230
p_gltf_node_track.position_track.times.push_back(time);
6231
p_gltf_node_track.rotation_track.values.push_back(rotation);
6232
p_gltf_node_track.rotation_track.times.push_back(time);
6233
p_gltf_node_track.scale_track.values.push_back(scale);
6234
p_gltf_node_track.scale_track.times.push_back(time);
6235
} else {
6236
ERR_PRINT(vformat("Error interpolating animation %s transform track %d at time %f", p_godot_animation->get_name(), p_godot_anim_track_index, time));
6237
}
6238
if (last) {
6239
break;
6240
}
6241
time += increment;
6242
if (time >= anim_end) {
6243
last = true;
6244
time = anim_end;
6245
}
6246
}
6247
} else {
6248
for (int32_t key_i = 0; key_i < key_count; key_i++) {
6249
Transform3D transform = p_godot_animation->track_get_key_value(p_godot_anim_track_index, key_i);
6250
p_gltf_node_track.position_track.values.write[key_i] = transform.get_origin();
6251
p_gltf_node_track.rotation_track.values.write[key_i] = transform.basis.get_rotation_quaternion();
6252
p_gltf_node_track.scale_track.values.write[key_i] = transform.basis.get_scale();
6253
}
6254
}
6255
} else {
6256
// This is a Value track animating a property, but not a TRS property, so it can't be converted into a node track.
6257
return false;
6258
}
6259
} else if (track_type == Animation::TYPE_BEZIER) {
6260
const int32_t keys = anim_end * p_state->get_bake_fps();
6261
if (node_prop == "scale") {
6262
if (p_gltf_node_track.scale_track.times.is_empty()) {
6263
p_gltf_node_track.scale_track.interpolation = gltf_interpolation;
6264
Vector<double> new_times;
6265
new_times.resize(keys);
6266
for (int32_t key_i = 0; key_i < keys; key_i++) {
6267
new_times.write[key_i] = key_i / p_state->get_bake_fps();
6268
}
6269
p_gltf_node_track.scale_track.times = new_times;
6270
6271
p_gltf_node_track.scale_track.values.resize(keys);
6272
6273
for (int32_t key_i = 0; key_i < keys; key_i++) {
6274
p_gltf_node_track.scale_track.values.write[key_i] = Vector3(1.0f, 1.0f, 1.0f);
6275
}
6276
6277
for (int32_t key_i = 0; key_i < keys; key_i++) {
6278
Vector3 bezier_track = p_gltf_node_track.scale_track.values[key_i];
6279
if (subpath.size() == 2) {
6280
if (subpath[1] == StringName("x")) {
6281
bezier_track.x = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps());
6282
} else if (subpath[1] == StringName("y")) {
6283
bezier_track.y = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps());
6284
} else if (subpath[1] == StringName("z")) {
6285
bezier_track.z = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps());
6286
}
6287
}
6288
p_gltf_node_track.scale_track.values.write[key_i] = bezier_track;
6289
}
6290
}
6291
} else if (node_prop == "position") {
6292
if (p_gltf_node_track.position_track.times.is_empty()) {
6293
p_gltf_node_track.position_track.interpolation = gltf_interpolation;
6294
Vector<double> new_times;
6295
new_times.resize(keys);
6296
for (int32_t key_i = 0; key_i < keys; key_i++) {
6297
new_times.write[key_i] = key_i / p_state->get_bake_fps();
6298
}
6299
p_gltf_node_track.position_track.times = new_times;
6300
6301
p_gltf_node_track.position_track.values.resize(keys);
6302
}
6303
6304
for (int32_t key_i = 0; key_i < keys; key_i++) {
6305
Vector3 bezier_track = p_gltf_node_track.position_track.values[key_i];
6306
if (subpath.size() == 2) {
6307
if (subpath[1] == StringName("x")) {
6308
bezier_track.x = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps());
6309
} else if (subpath[1] == StringName("y")) {
6310
bezier_track.y = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps());
6311
} else if (subpath[1] == StringName("z")) {
6312
bezier_track.z = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps());
6313
}
6314
}
6315
p_gltf_node_track.position_track.values.write[key_i] = bezier_track;
6316
}
6317
} else if (node_prop == "quaternion") {
6318
if (p_gltf_node_track.rotation_track.times.is_empty()) {
6319
p_gltf_node_track.rotation_track.interpolation = gltf_interpolation;
6320
Vector<double> new_times;
6321
new_times.resize(keys);
6322
for (int32_t key_i = 0; key_i < keys; key_i++) {
6323
new_times.write[key_i] = key_i / p_state->get_bake_fps();
6324
}
6325
p_gltf_node_track.rotation_track.times = new_times;
6326
6327
p_gltf_node_track.rotation_track.values.resize(keys);
6328
}
6329
for (int32_t key_i = 0; key_i < keys; key_i++) {
6330
Quaternion bezier_track = p_gltf_node_track.rotation_track.values[key_i];
6331
if (subpath.size() == 2) {
6332
if (subpath[1] == StringName("x")) {
6333
bezier_track.x = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps());
6334
} else if (subpath[1] == StringName("y")) {
6335
bezier_track.y = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps());
6336
} else if (subpath[1] == StringName("z")) {
6337
bezier_track.z = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps());
6338
} else if (subpath[1] == StringName("w")) {
6339
bezier_track.w = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps());
6340
}
6341
}
6342
p_gltf_node_track.rotation_track.values.write[key_i] = bezier_track;
6343
}
6344
} else {
6345
// This is a Bezier track animating a property, but not a TRS property, so it can't be converted into a node track.
6346
return false;
6347
}
6348
} else {
6349
// This property track isn't a Value track or Bezier track, so it can't be converted into a node track.
6350
return false;
6351
}
6352
} else {
6353
// This isn't a TRS track or a property track, so it can't be converted into a node track.
6354
return false;
6355
}
6356
// If we reached this point, the track was some kind of TRS track and was successfully converted.
6357
// All failure paths should return false before this point to indicate this
6358
// isn't a node track so it can be handled by KHR_animation_pointer instead.
6359
return true;
6360
}
6361
6362
void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, const String &p_animation_track_name) {
6363
Ref<Animation> animation = p_animation_player->get_animation(p_animation_track_name);
6364
Ref<GLTFAnimation> gltf_animation;
6365
gltf_animation.instantiate();
6366
gltf_animation->set_original_name(p_animation_track_name);
6367
gltf_animation->set_name(_gen_unique_name(p_state, p_animation_track_name));
6368
HashMap<int, GLTFAnimation::NodeTrack> &node_tracks = gltf_animation->get_node_tracks();
6369
for (int32_t track_index = 0; track_index < animation->get_track_count(); track_index++) {
6370
if (!animation->track_is_enabled(track_index)) {
6371
continue;
6372
}
6373
// Get the Godot node and the glTF node index for the animation track.
6374
const NodePath track_path = animation->track_get_path(track_index);
6375
const NodePath root_node = p_animation_player->get_root_node();
6376
const Node *anim_player_parent = p_animation_player->get_node_or_null(root_node);
6377
ERR_CONTINUE_MSG(!anim_player_parent, "glTF: Cannot get root node for animation player: " + String(root_node));
6378
const Node *animated_node = anim_player_parent->get_node_or_null(track_path);
6379
ERR_CONTINUE_MSG(!animated_node, "glTF: Cannot get node for animated track using path: " + String(track_path));
6380
const GLTFAnimation::Interpolation gltf_interpolation = GLTFAnimation::godot_to_gltf_interpolation(animation, track_index);
6381
// First, check if it's a Blend Shape track.
6382
if (animation->track_get_type(track_index) == Animation::TYPE_BLEND_SHAPE) {
6383
const MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(animated_node);
6384
ERR_CONTINUE_MSG(!mesh_instance, "glTF: Animation had a Blend Shape track, but the node wasn't a MeshInstance3D. Ignoring this track.");
6385
Ref<Mesh> mesh = mesh_instance->get_mesh();
6386
ERR_CONTINUE(mesh.is_null());
6387
int32_t mesh_index = -1;
6388
for (const KeyValue<GLTFNodeIndex, Node *> &mesh_track_i : p_state->scene_nodes) {
6389
if (mesh_track_i.value == animated_node) {
6390
mesh_index = mesh_track_i.key;
6391
}
6392
}
6393
ERR_CONTINUE(mesh_index == -1);
6394
GLTFAnimation::NodeTrack track = node_tracks.has(mesh_index) ? node_tracks[mesh_index] : GLTFAnimation::NodeTrack();
6395
if (!node_tracks.has(mesh_index)) {
6396
for (int32_t shape_i = 0; shape_i < mesh->get_blend_shape_count(); shape_i++) {
6397
String shape_name = mesh->get_blend_shape_name(shape_i);
6398
NodePath shape_path = NodePath(track_path.get_names(), { shape_name }, false);
6399
int32_t shape_track_i = animation->find_track(shape_path, Animation::TYPE_BLEND_SHAPE);
6400
if (shape_track_i == -1) {
6401
GLTFAnimation::Channel<real_t> weight;
6402
weight.interpolation = GLTFAnimation::INTERP_LINEAR;
6403
weight.times.push_back(0.0f);
6404
weight.times.push_back(0.0f);
6405
weight.values.push_back(0.0f);
6406
weight.values.push_back(0.0f);
6407
track.weight_tracks.push_back(weight);
6408
continue;
6409
}
6410
int32_t key_count = animation->track_get_key_count(shape_track_i);
6411
GLTFAnimation::Channel<real_t> weight;
6412
weight.interpolation = gltf_interpolation;
6413
weight.times.resize(key_count);
6414
for (int32_t time_i = 0; time_i < key_count; time_i++) {
6415
weight.times.write[time_i] = animation->track_get_key_time(shape_track_i, time_i);
6416
}
6417
weight.values.resize(key_count);
6418
for (int32_t value_i = 0; value_i < key_count; value_i++) {
6419
weight.values.write[value_i] = animation->track_get_key_value(shape_track_i, value_i);
6420
}
6421
track.weight_tracks.push_back(weight);
6422
}
6423
node_tracks[mesh_index] = track;
6424
}
6425
continue;
6426
}
6427
// If it's not a Blend Shape track, it must either be a TRS track, a property Value track, or something we can't handle.
6428
// For the cases we can handle, we will need to know the glTF node index, glTF interpolation, and the times of the track.
6429
const Vector<StringName> subnames = track_path.get_subnames();
6430
const GLTFNodeIndex node_i = _node_and_or_bone_to_gltf_node_index(p_state, subnames, animated_node);
6431
ERR_CONTINUE_MSG(node_i == -1, "glTF: Cannot get glTF node index for animated track using path: " + String(track_path));
6432
const int anim_key_count = animation->track_get_key_count(track_index);
6433
Vector<double> times;
6434
times.resize(anim_key_count);
6435
for (int32_t key_i = 0; key_i < anim_key_count; key_i++) {
6436
times.write[key_i] = animation->track_get_key_time(track_index, key_i);
6437
}
6438
// Try converting the track to a TRS glTF node track. This will only succeed if the Godot animation is a TRS track.
6439
const HashMap<int, GLTFAnimation::NodeTrack>::Iterator node_track_iter = node_tracks.find(node_i);
6440
GLTFAnimation::NodeTrack track;
6441
if (node_track_iter) {
6442
track = node_track_iter->value;
6443
}
6444
if (_convert_animation_node_track(p_state, track, animation, track_index, times)) {
6445
// If the track was successfully converted, save it and continue to the next track.
6446
node_tracks[node_i] = track;
6447
continue;
6448
}
6449
// If the track wasn't a TRS track or Blend Shape track, it might be a Value track animating a property.
6450
// Then this is something that we need to handle with KHR_animation_pointer.
6451
Ref<GLTFObjectModelProperty> obj_model_prop = export_object_model_property(p_state, track_path, animated_node, node_i);
6452
if (obj_model_prop.is_valid() && obj_model_prop->has_json_pointers()) {
6453
// Insert the property track into the KHR_animation_pointer pointer tracks.
6454
GLTFAnimation::Channel<Variant> channel;
6455
// Animation samplers used with `int` or `bool` Object Model Data Types **MUST** use `STEP` interpolation.
6456
// https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_animation_pointer
6457
switch (obj_model_prop->get_object_model_type()) {
6458
case GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_BOOL:
6459
case GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_INT: {
6460
channel.interpolation = GLTFAnimation::INTERP_STEP;
6461
if (gltf_interpolation != GLTFAnimation::INTERP_STEP) {
6462
WARN_PRINT(vformat("glTF export: Animation track %d on property %s is animating an int or bool, so it MUST use STEP interpolation (Godot \"Nearest\"), but the track in the Godot AnimationPlayer is using a different interpolation. Forcing STEP interpolation. Correct this track's interpolation in the source AnimationPlayer to avoid this warning.", track_index, String(track_path)));
6463
}
6464
} break;
6465
default: {
6466
channel.interpolation = gltf_interpolation;
6467
} break;
6468
}
6469
channel.times = times;
6470
channel.values.resize(anim_key_count);
6471
// If using an expression, determine the base instance to pass to the expression.
6472
const Ref<Expression> godot_to_gltf_expr = obj_model_prop->get_godot_to_gltf_expression();
6473
const bool is_godot_to_gltf_expr_valid = godot_to_gltf_expr.is_valid();
6474
Object *base_instance = nullptr;
6475
if (is_godot_to_gltf_expr_valid) {
6476
Ref<Resource> resource;
6477
Vector<StringName> leftover_subpath;
6478
base_instance = anim_player_parent->get_node_and_resource(track_path, resource, leftover_subpath);
6479
if (resource.is_valid()) {
6480
base_instance = resource.ptr();
6481
}
6482
}
6483
// Convert the Godot animation values into glTF animation values (still Variant).
6484
for (int32_t key_i = 0; key_i < anim_key_count; key_i++) {
6485
Variant value = animation->track_get_key_value(track_index, key_i);
6486
if (is_godot_to_gltf_expr_valid) {
6487
Array inputs;
6488
inputs.append(value);
6489
value = godot_to_gltf_expr->execute(inputs, base_instance);
6490
}
6491
channel.values.write[key_i] = value;
6492
}
6493
// Use the JSON pointer to insert the property track into the pointer tracks. There will usually be just one JSON pointer.
6494
HashMap<String, GLTFAnimation::Channel<Variant>> &pointer_tracks = gltf_animation->get_pointer_tracks();
6495
Vector<PackedStringArray> split_json_pointers = obj_model_prop->get_json_pointers();
6496
for (const PackedStringArray &split_json_pointer : split_json_pointers) {
6497
String json_pointer_str = "/" + String("/").join(split_json_pointer);
6498
p_state->object_model_properties[json_pointer_str] = obj_model_prop;
6499
pointer_tracks[json_pointer_str] = channel;
6500
}
6501
}
6502
}
6503
if (!gltf_animation->is_empty_of_tracks()) {
6504
p_state->animations.push_back(gltf_animation);
6505
}
6506
}
6507
6508
Error GLTFDocument::_parse(Ref<GLTFState> p_state, const String &p_path, Ref<FileAccess> p_file) {
6509
Error err;
6510
if (p_file.is_null()) {
6511
return FAILED;
6512
}
6513
p_file->seek(0);
6514
uint32_t magic = p_file->get_32();
6515
if (magic == 0x46546C67) {
6516
// Binary file.
6517
p_file->seek(0);
6518
err = _parse_glb(p_file, p_state);
6519
if (err != OK) {
6520
return err;
6521
}
6522
} else {
6523
// Text file.
6524
p_file->seek(0);
6525
String text = p_file->get_as_utf8_string();
6526
JSON json;
6527
err = json.parse(text);
6528
ERR_FAIL_COND_V_MSG(err != OK, err, "glTF: Error parsing .gltf JSON data: " + json.get_error_message() + " at line: " + itos(json.get_error_line()));
6529
p_state->json = json.get_data();
6530
}
6531
6532
err = _parse_asset_header(p_state);
6533
ERR_FAIL_COND_V(err != OK, err);
6534
6535
document_extensions.clear();
6536
for (Ref<GLTFDocumentExtension> ext : all_document_extensions) {
6537
ERR_CONTINUE(ext.is_null());
6538
err = ext->import_preflight(p_state, p_state->json["extensionsUsed"]);
6539
if (err == OK) {
6540
document_extensions.push_back(ext);
6541
}
6542
}
6543
6544
err = _parse_gltf_state(p_state, p_path);
6545
ERR_FAIL_COND_V(err != OK, err);
6546
6547
return OK;
6548
}
6549
6550
Dictionary _serialize_texture_transform_uv(Vector2 p_offset, Vector2 p_scale) {
6551
Dictionary texture_transform;
6552
bool is_offset = p_offset != Vector2(0.0, 0.0);
6553
if (is_offset) {
6554
Array offset;
6555
offset.resize(2);
6556
offset[0] = p_offset.x;
6557
offset[1] = p_offset.y;
6558
texture_transform["offset"] = offset;
6559
}
6560
bool is_scaled = p_scale != Vector2(1.0, 1.0);
6561
if (is_scaled) {
6562
Array scale;
6563
scale.resize(2);
6564
scale[0] = p_scale.x;
6565
scale[1] = p_scale.y;
6566
texture_transform["scale"] = scale;
6567
}
6568
Dictionary extension;
6569
// Note: Godot doesn't support texture rotation.
6570
if (is_offset || is_scaled) {
6571
extension["KHR_texture_transform"] = texture_transform;
6572
}
6573
return extension;
6574
}
6575
6576
Dictionary GLTFDocument::_serialize_texture_transform_uv1(const Ref<BaseMaterial3D> &p_material) {
6577
ERR_FAIL_COND_V(p_material.is_null(), Dictionary());
6578
Vector3 offset = p_material->get_uv1_offset();
6579
Vector3 scale = p_material->get_uv1_scale();
6580
return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y));
6581
}
6582
6583
Dictionary GLTFDocument::_serialize_texture_transform_uv2(const Ref<BaseMaterial3D> &p_material) {
6584
ERR_FAIL_COND_V(p_material.is_null(), Dictionary());
6585
Vector3 offset = p_material->get_uv2_offset();
6586
Vector3 scale = p_material->get_uv2_scale();
6587
return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y));
6588
}
6589
6590
Error GLTFDocument::_serialize_asset_header(Ref<GLTFState> p_state) {
6591
const String version = "2.0";
6592
p_state->major_version = version.get_slicec('.', 0).to_int();
6593
p_state->minor_version = version.get_slicec('.', 1).to_int();
6594
Dictionary asset;
6595
asset["version"] = version;
6596
if (!p_state->copyright.is_empty()) {
6597
asset["copyright"] = p_state->copyright;
6598
}
6599
String hash = String(GODOT_VERSION_HASH);
6600
asset["generator"] = String(GODOT_VERSION_FULL_NAME) + String("@") + (hash.is_empty() ? String("unknown") : hash);
6601
p_state->json["asset"] = asset;
6602
ERR_FAIL_COND_V(!asset.has("version"), Error::FAILED);
6603
ERR_FAIL_COND_V(!p_state->json.has("asset"), Error::FAILED);
6604
return OK;
6605
}
6606
6607
Error GLTFDocument::_serialize_file(Ref<GLTFState> p_state, const String p_path) {
6608
Error err = FAILED;
6609
if (p_path.to_lower().ends_with("glb")) {
6610
err = _encode_buffer_glb(p_state, p_path);
6611
ERR_FAIL_COND_V(err != OK, err);
6612
Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
6613
ERR_FAIL_COND_V(file.is_null(), FAILED);
6614
6615
constexpr uint64_t header_size = 12;
6616
constexpr uint64_t chunk_header_size = 8;
6617
constexpr uint32_t magic = 0x46546C67; // The byte sequence "glTF" as little-endian.
6618
constexpr uint32_t text_chunk_type = 0x4E4F534A; // The byte sequence "JSON" as little-endian.
6619
constexpr uint32_t binary_chunk_type = 0x004E4942; // The byte sequence "BIN\0" as little-endian.
6620
6621
String json_string = JSON::stringify(p_state->json, "", true, true);
6622
CharString cs = json_string.utf8();
6623
uint64_t text_data_length = cs.length();
6624
uint64_t text_chunk_length = ((text_data_length + 3) & (~3));
6625
uint64_t total_file_length = header_size + chunk_header_size + text_chunk_length;
6626
uint64_t binary_data_length = 0;
6627
uint64_t binary_chunk_length = 0;
6628
if (p_state->buffers.size() > 0) {
6629
binary_data_length = p_state->buffers[0].size();
6630
binary_chunk_length = ((binary_data_length + 3) & (~3));
6631
const uint64_t file_length_with_buffer = total_file_length + chunk_header_size + binary_chunk_length;
6632
// Check if the file length with the buffer is greater than glTF's maximum of 4 GiB.
6633
// If it is, we can't write the buffer into the file, but can write it separately.
6634
if (unlikely(file_length_with_buffer > (uint64_t)UINT32_MAX)) {
6635
err = _encode_buffer_bins(p_state, p_path);
6636
ERR_FAIL_COND_V(err != OK, err);
6637
// Since the buffer bins were re-encoded, we need to re-convert the JSON to string.
6638
json_string = JSON::stringify(p_state->json, "", true, true);
6639
cs = json_string.utf8();
6640
text_data_length = cs.length();
6641
text_chunk_length = ((text_data_length + 3) & (~3));
6642
total_file_length = header_size + chunk_header_size + text_chunk_length;
6643
binary_data_length = 0;
6644
binary_chunk_length = 0;
6645
} else {
6646
total_file_length = file_length_with_buffer;
6647
}
6648
}
6649
ERR_FAIL_COND_V_MSG(total_file_length > (uint64_t)UINT32_MAX, ERR_CANT_CREATE,
6650
"glTF: File size exceeds glTF Binary's maximum of 4 GiB. Cannot serialize as a GLB file.");
6651
6652
file->create(FileAccess::ACCESS_RESOURCES);
6653
file->store_32(magic);
6654
file->store_32(p_state->major_version); // version
6655
file->store_32(total_file_length);
6656
6657
// Write the JSON text chunk.
6658
file->store_32(text_chunk_length);
6659
file->store_32(text_chunk_type);
6660
file->store_buffer((uint8_t *)&cs[0], text_data_length);
6661
for (uint64_t pad_i = text_data_length; pad_i < text_chunk_length; pad_i++) {
6662
file->store_8(' ');
6663
}
6664
6665
// Write a single binary chunk.
6666
if (binary_chunk_length) {
6667
file->store_32((uint32_t)binary_chunk_length);
6668
file->store_32(binary_chunk_type);
6669
file->store_buffer(p_state->buffers[0].ptr(), binary_data_length);
6670
for (uint32_t pad_i = binary_data_length; pad_i < binary_chunk_length; pad_i++) {
6671
file->store_8(0);
6672
}
6673
}
6674
} else {
6675
err = _encode_buffer_bins(p_state, p_path);
6676
ERR_FAIL_COND_V(err != OK, err);
6677
Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
6678
ERR_FAIL_COND_V(file.is_null(), FAILED);
6679
6680
file->create(FileAccess::ACCESS_RESOURCES);
6681
String json = JSON::stringify(p_state->json, "", true, true);
6682
file->store_string(json);
6683
}
6684
return err;
6685
}
6686
6687
void GLTFDocument::_bind_methods() {
6688
BIND_ENUM_CONSTANT(ROOT_NODE_MODE_SINGLE_ROOT);
6689
BIND_ENUM_CONSTANT(ROOT_NODE_MODE_KEEP_ROOT);
6690
BIND_ENUM_CONSTANT(ROOT_NODE_MODE_MULTI_ROOT);
6691
6692
BIND_ENUM_CONSTANT(VISIBILITY_MODE_INCLUDE_REQUIRED);
6693
BIND_ENUM_CONSTANT(VISIBILITY_MODE_INCLUDE_OPTIONAL);
6694
BIND_ENUM_CONSTANT(VISIBILITY_MODE_EXCLUDE);
6695
6696
ClassDB::bind_method(D_METHOD("set_image_format", "image_format"), &GLTFDocument::set_image_format);
6697
ClassDB::bind_method(D_METHOD("get_image_format"), &GLTFDocument::get_image_format);
6698
ClassDB::bind_method(D_METHOD("set_lossy_quality", "lossy_quality"), &GLTFDocument::set_lossy_quality);
6699
ClassDB::bind_method(D_METHOD("get_lossy_quality"), &GLTFDocument::get_lossy_quality);
6700
ClassDB::bind_method(D_METHOD("set_fallback_image_format", "fallback_image_format"), &GLTFDocument::set_fallback_image_format);
6701
ClassDB::bind_method(D_METHOD("get_fallback_image_format"), &GLTFDocument::get_fallback_image_format);
6702
ClassDB::bind_method(D_METHOD("set_fallback_image_quality", "fallback_image_quality"), &GLTFDocument::set_fallback_image_quality);
6703
ClassDB::bind_method(D_METHOD("get_fallback_image_quality"), &GLTFDocument::get_fallback_image_quality);
6704
ClassDB::bind_method(D_METHOD("set_root_node_mode", "root_node_mode"), &GLTFDocument::set_root_node_mode);
6705
ClassDB::bind_method(D_METHOD("get_root_node_mode"), &GLTFDocument::get_root_node_mode);
6706
ClassDB::bind_method(D_METHOD("set_visibility_mode", "visibility_mode"), &GLTFDocument::set_visibility_mode);
6707
ClassDB::bind_method(D_METHOD("get_visibility_mode"), &GLTFDocument::get_visibility_mode);
6708
ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "base_path"),
6709
&GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(String()));
6710
ClassDB::bind_method(D_METHOD("append_from_buffer", "bytes", "base_path", "state", "flags"),
6711
&GLTFDocument::append_from_buffer, DEFVAL(0));
6712
ClassDB::bind_method(D_METHOD("append_from_scene", "node", "state", "flags"),
6713
&GLTFDocument::append_from_scene, DEFVAL(0));
6714
ClassDB::bind_method(D_METHOD("generate_scene", "state", "bake_fps", "trimming", "remove_immutable_tracks"),
6715
&GLTFDocument::generate_scene, DEFVAL(30), DEFVAL(false), DEFVAL(true));
6716
ClassDB::bind_method(D_METHOD("generate_buffer", "state"),
6717
&GLTFDocument::generate_buffer);
6718
ClassDB::bind_method(D_METHOD("write_to_filesystem", "state", "path"),
6719
&GLTFDocument::write_to_filesystem);
6720
6721
ADD_PROPERTY(PropertyInfo(Variant::STRING, "image_format"), "set_image_format", "get_image_format");
6722
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lossy_quality"), "set_lossy_quality", "get_lossy_quality");
6723
ADD_PROPERTY(PropertyInfo(Variant::STRING, "fallback_image_format"), "set_fallback_image_format", "get_fallback_image_format");
6724
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fallback_image_quality"), "set_fallback_image_quality", "get_fallback_image_quality");
6725
ADD_PROPERTY(PropertyInfo(Variant::INT, "root_node_mode"), "set_root_node_mode", "get_root_node_mode");
6726
ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_mode"), "set_visibility_mode", "get_visibility_mode");
6727
6728
ClassDB::bind_static_method("GLTFDocument", D_METHOD("import_object_model_property", "state", "json_pointer"), &GLTFDocument::import_object_model_property);
6729
ClassDB::bind_static_method("GLTFDocument", D_METHOD("export_object_model_property", "state", "node_path", "godot_node", "gltf_node_index"), &GLTFDocument::export_object_model_property);
6730
6731
ClassDB::bind_static_method("GLTFDocument", D_METHOD("register_gltf_document_extension", "extension", "first_priority"),
6732
&GLTFDocument::register_gltf_document_extension, DEFVAL(false));
6733
ClassDB::bind_static_method("GLTFDocument", D_METHOD("unregister_gltf_document_extension", "extension"),
6734
&GLTFDocument::unregister_gltf_document_extension);
6735
ClassDB::bind_static_method("GLTFDocument", D_METHOD("get_supported_gltf_extensions"),
6736
&GLTFDocument::get_supported_gltf_extensions);
6737
}
6738
6739
void GLTFDocument::_build_parent_hierarchy(Ref<GLTFState> p_state) {
6740
// build the hierarchy
6741
for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); node_i++) {
6742
for (int j = 0; j < p_state->nodes[node_i]->children.size(); j++) {
6743
GLTFNodeIndex child_i = p_state->nodes[node_i]->children[j];
6744
ERR_FAIL_INDEX(child_i, p_state->nodes.size());
6745
if (p_state->nodes.write[child_i]->parent != -1) {
6746
continue;
6747
}
6748
p_state->nodes.write[child_i]->parent = node_i;
6749
}
6750
}
6751
}
6752
6753
Vector<Ref<GLTFDocumentExtension>> GLTFDocument::all_document_extensions;
6754
6755
void GLTFDocument::register_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension, bool p_first_priority) {
6756
if (!all_document_extensions.has(p_extension)) {
6757
if (p_first_priority) {
6758
all_document_extensions.insert(0, p_extension);
6759
} else {
6760
all_document_extensions.push_back(p_extension);
6761
}
6762
}
6763
}
6764
6765
void GLTFDocument::unregister_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension) {
6766
all_document_extensions.erase(p_extension);
6767
}
6768
6769
void GLTFDocument::unregister_all_gltf_document_extensions() {
6770
all_document_extensions.clear();
6771
}
6772
6773
Vector<Ref<GLTFDocumentExtension>> GLTFDocument::get_all_gltf_document_extensions() {
6774
return all_document_extensions;
6775
}
6776
6777
Vector<String> GLTFDocument::get_supported_gltf_extensions() {
6778
HashSet<String> set = get_supported_gltf_extensions_hashset();
6779
Vector<String> vec;
6780
for (const String &s : set) {
6781
vec.append(s);
6782
}
6783
vec.sort();
6784
return vec;
6785
}
6786
6787
HashSet<String> GLTFDocument::get_supported_gltf_extensions_hashset() {
6788
HashSet<String> supported_extensions;
6789
// If the extension is supported directly in GLTFDocument, list it here.
6790
// Other built-in extensions are supported by GLTFDocumentExtension classes.
6791
supported_extensions.insert("GODOT_single_root");
6792
supported_extensions.insert("KHR_animation_pointer");
6793
supported_extensions.insert("KHR_lights_punctual");
6794
supported_extensions.insert("KHR_materials_emissive_strength");
6795
supported_extensions.insert("KHR_materials_pbrSpecularGlossiness");
6796
supported_extensions.insert("KHR_materials_unlit");
6797
supported_extensions.insert("KHR_node_visibility");
6798
supported_extensions.insert("KHR_texture_transform");
6799
for (Ref<GLTFDocumentExtension> ext : all_document_extensions) {
6800
ERR_CONTINUE(ext.is_null());
6801
Vector<String> ext_supported_extensions = ext->get_supported_extensions();
6802
for (int i = 0; i < ext_supported_extensions.size(); ++i) {
6803
supported_extensions.insert(ext_supported_extensions[i]);
6804
}
6805
}
6806
return supported_extensions;
6807
}
6808
6809
PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> p_state, Error *r_err) {
6810
Error err = _encode_buffer_glb(p_state, "");
6811
if (r_err) {
6812
*r_err = err;
6813
}
6814
ERR_FAIL_COND_V(err != OK, PackedByteArray());
6815
String json_string = JSON::stringify(p_state->json, "", true, true);
6816
6817
constexpr uint64_t header_size = 12;
6818
constexpr uint64_t chunk_header_size = 8;
6819
constexpr uint32_t magic = 0x46546C67; // The byte sequence "glTF" as little-endian.
6820
constexpr uint32_t text_chunk_type = 0x4E4F534A; // The byte sequence "JSON" as little-endian.
6821
constexpr uint32_t binary_chunk_type = 0x004E4942; // The byte sequence "BIN\0" as little-endian.
6822
const CharString cs = json_string.utf8();
6823
const uint64_t text_data_length = cs.length();
6824
const uint64_t text_chunk_length = ((text_data_length + 3) & (~3));
6825
6826
uint64_t total_file_length = header_size + chunk_header_size + text_chunk_length;
6827
ERR_FAIL_COND_V(total_file_length > (uint64_t)UINT32_MAX, PackedByteArray());
6828
uint64_t binary_data_length = 0;
6829
if (p_state->buffers.size() > 0) {
6830
binary_data_length = p_state->buffers[0].size();
6831
const uint64_t file_length_with_buffer = total_file_length + chunk_header_size + binary_data_length;
6832
total_file_length = file_length_with_buffer;
6833
}
6834
ERR_FAIL_COND_V_MSG(total_file_length > (uint64_t)UINT32_MAX, PackedByteArray(),
6835
"glTF: File size exceeds glTF Binary's maximum of 4 GiB. Cannot serialize as a single GLB in-memory buffer.");
6836
const uint32_t binary_chunk_length = binary_data_length;
6837
6838
Ref<StreamPeerBuffer> buffer;
6839
buffer.instantiate();
6840
buffer->put_32(magic);
6841
buffer->put_32(p_state->major_version); // version
6842
buffer->put_32((uint32_t)total_file_length); // length
6843
buffer->put_32((uint32_t)text_chunk_length);
6844
buffer->put_32(text_chunk_type);
6845
buffer->put_data((uint8_t *)&cs[0], text_data_length);
6846
for (uint64_t pad_i = text_data_length; pad_i < text_chunk_length; pad_i++) {
6847
buffer->put_8(' ');
6848
}
6849
if (binary_chunk_length) {
6850
buffer->put_32(binary_chunk_length);
6851
buffer->put_32(binary_chunk_type);
6852
buffer->put_data(p_state->buffers[0].ptr(), binary_data_length);
6853
}
6854
return buffer->get_data_array();
6855
}
6856
6857
Node *GLTFDocument::_generate_scene_node_tree(Ref<GLTFState> p_state) {
6858
// Generate the skeletons and skins (if any).
6859
HashMap<ObjectID, SkinSkeletonIndex> skeleton_map;
6860
Error err = SkinTool::_create_skeletons(p_state->unique_names, p_state->skins, p_state->nodes,
6861
skeleton_map, p_state->skeletons, p_state->scene_nodes, _naming_version);
6862
ERR_FAIL_COND_V_MSG(err != OK, nullptr, "glTF: Failed to create skeletons.");
6863
err = _create_skins(p_state);
6864
ERR_FAIL_COND_V_MSG(err != OK, nullptr, "glTF: Failed to create skins.");
6865
// Run pre-generate for each extension, in case an extension needs to do something before generating the scene.
6866
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
6867
ERR_CONTINUE(ext.is_null());
6868
err = ext->import_pre_generate(p_state);
6869
ERR_CONTINUE(err != OK);
6870
}
6871
// Generate the node tree.
6872
Node *single_root;
6873
if (p_state->extensions_used.has("GODOT_single_root")) {
6874
ERR_FAIL_COND_V_MSG(p_state->nodes.is_empty(), nullptr, "glTF: Single root file has no nodes. This glTF file is invalid.");
6875
if (_naming_version < 2) {
6876
_generate_scene_node_compat_4pt4(p_state, 0, nullptr, nullptr);
6877
} else {
6878
_generate_scene_node(p_state, 0, nullptr, nullptr);
6879
}
6880
single_root = p_state->scene_nodes[0];
6881
if (single_root && single_root->get_owner() && single_root->get_owner() != single_root) {
6882
single_root = single_root->get_owner();
6883
}
6884
} else {
6885
single_root = memnew(Node3D);
6886
for (int32_t root_i = 0; root_i < p_state->root_nodes.size(); root_i++) {
6887
if (_naming_version < 2) {
6888
_generate_scene_node_compat_4pt4(p_state, p_state->root_nodes[root_i], single_root, single_root);
6889
} else {
6890
_generate_scene_node(p_state, p_state->root_nodes[root_i], single_root, single_root);
6891
}
6892
}
6893
}
6894
// Assign the scene name and single root name to each other
6895
// if one is missing, or do nothing if both are already set.
6896
if (unlikely(p_state->scene_name.is_empty())) {
6897
p_state->scene_name = single_root->get_name();
6898
} else if (single_root->get_name() == StringName()) {
6899
if (_naming_version == 0) {
6900
single_root->set_name(p_state->scene_name);
6901
} else {
6902
single_root->set_name(_gen_unique_name(p_state, p_state->scene_name));
6903
}
6904
}
6905
return single_root;
6906
}
6907
6908
Error GLTFDocument::_parse_asset_header(Ref<GLTFState> p_state) {
6909
if (!p_state->json.has("asset")) {
6910
return ERR_PARSE_ERROR;
6911
}
6912
Dictionary asset = p_state->json["asset"];
6913
if (!asset.has("version")) {
6914
return ERR_PARSE_ERROR;
6915
}
6916
String version = asset["version"];
6917
p_state->major_version = version.get_slicec('.', 0).to_int();
6918
p_state->minor_version = version.get_slicec('.', 1).to_int();
6919
if (asset.has("copyright")) {
6920
p_state->copyright = asset["copyright"];
6921
}
6922
return OK;
6923
}
6924
6925
Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> p_state, const String &p_search_path) {
6926
Error err;
6927
6928
/* PARSE BUFFERS */
6929
err = _parse_buffers(p_state, p_search_path);
6930
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6931
6932
/* PARSE BUFFER VIEWS */
6933
err = _parse_buffer_views(p_state);
6934
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6935
6936
/* PARSE ACCESSORS */
6937
err = _parse_accessors(p_state);
6938
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6939
6940
/* PARSE EXTENSIONS */
6941
err = _parse_gltf_extensions(p_state);
6942
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6943
6944
/* PARSE SCENE */
6945
err = _parse_scenes(p_state);
6946
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6947
6948
/* PARSE NODES */
6949
err = _parse_nodes(p_state);
6950
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6951
6952
if (!p_state->discard_meshes_and_materials) {
6953
/* PARSE IMAGES */
6954
err = _parse_images(p_state, p_search_path);
6955
6956
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6957
6958
/* PARSE TEXTURE SAMPLERS */
6959
err = _parse_texture_samplers(p_state);
6960
6961
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6962
6963
/* PARSE TEXTURES */
6964
err = _parse_textures(p_state);
6965
6966
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6967
6968
/* PARSE TEXTURES */
6969
err = _parse_materials(p_state);
6970
6971
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6972
}
6973
6974
/* PARSE SKINS */
6975
err = _parse_skins(p_state);
6976
6977
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6978
6979
/* DETERMINE SKELETONS */
6980
if (p_state->get_import_as_skeleton_bones()) {
6981
err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons, p_state->root_nodes, true);
6982
} else {
6983
err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons, Vector<GLTFNodeIndex>(), _naming_version < 2);
6984
}
6985
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6986
6987
/* ASSIGN SCENE NODE NAMES */
6988
// This must be run AFTER determining skeletons, and BEFORE parsing animations.
6989
_assign_node_names(p_state);
6990
6991
/* PARSE MESHES (we have enough info now) */
6992
err = _parse_meshes(p_state);
6993
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6994
6995
/* PARSE LIGHTS */
6996
err = _parse_lights(p_state);
6997
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
6998
6999
/* PARSE CAMERAS */
7000
err = _parse_cameras(p_state);
7001
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
7002
7003
/* PARSE ANIMATIONS */
7004
err = _parse_animations(p_state);
7005
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
7006
7007
return OK;
7008
}
7009
7010
PackedByteArray GLTFDocument::generate_buffer(Ref<GLTFState> p_state) {
7011
Ref<GLTFState> state = p_state;
7012
ERR_FAIL_COND_V(state.is_null(), PackedByteArray());
7013
// For buffers, set the state filename to an empty string, but
7014
// don't touch the base path, in case the user set it manually.
7015
state->filename = "";
7016
Error err = _serialize(state);
7017
ERR_FAIL_COND_V(err != OK, PackedByteArray());
7018
PackedByteArray bytes = _serialize_glb_buffer(state, &err);
7019
return bytes;
7020
}
7021
7022
Error GLTFDocument::write_to_filesystem(Ref<GLTFState> p_state, const String &p_path) {
7023
Ref<GLTFState> state = p_state;
7024
ERR_FAIL_COND_V(state.is_null(), ERR_INVALID_PARAMETER);
7025
state->set_base_path(p_path.get_base_dir());
7026
state->filename = p_path.get_file();
7027
Error err = _serialize(state);
7028
if (err != OK) {
7029
return err;
7030
}
7031
err = _serialize_file(state, p_path);
7032
if (err != OK) {
7033
return Error::FAILED;
7034
}
7035
return OK;
7036
}
7037
7038
Node *GLTFDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, bool p_trimming, bool p_remove_immutable_tracks) {
7039
ERR_FAIL_COND_V(p_state.is_null(), nullptr);
7040
// The glTF file must have nodes, and have some marked as root nodes, in order to generate a scene.
7041
if (p_state->nodes.is_empty()) {
7042
WARN_PRINT("glTF: This glTF file has no nodes, the generated Godot scene will be empty.");
7043
}
7044
// Now that we know that we have glTF nodes, we can begin generating a scene from the parsed glTF data.
7045
Error err = OK;
7046
p_state->set_bake_fps(p_bake_fps);
7047
Node *godot_root_node = _generate_scene_node_tree(p_state);
7048
ERR_FAIL_NULL_V(godot_root_node, nullptr);
7049
_process_mesh_instances(p_state, godot_root_node);
7050
if (p_state->get_create_animations() && p_state->animations.size()) {
7051
AnimationPlayer *anim_player = memnew(AnimationPlayer);
7052
godot_root_node->add_child(anim_player, true);
7053
anim_player->set_owner(godot_root_node);
7054
for (int i = 0; i < p_state->animations.size(); i++) {
7055
_import_animation(p_state, anim_player, i, p_trimming, p_remove_immutable_tracks);
7056
}
7057
}
7058
for (KeyValue<GLTFNodeIndex, Node *> E : p_state->scene_nodes) {
7059
ERR_CONTINUE(!E.value);
7060
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
7061
ERR_CONTINUE(ext.is_null());
7062
Dictionary node_json;
7063
if (p_state->json.has("nodes")) {
7064
Array nodes = p_state->json["nodes"];
7065
if (0 <= E.key && E.key < nodes.size()) {
7066
node_json = nodes[E.key];
7067
}
7068
}
7069
Ref<GLTFNode> gltf_node = p_state->nodes[E.key];
7070
err = ext->import_node(p_state, gltf_node, node_json, E.value);
7071
ERR_CONTINUE(err != OK);
7072
}
7073
}
7074
ImporterMeshInstance3D *root_importer_mesh = Object::cast_to<ImporterMeshInstance3D>(godot_root_node);
7075
if (unlikely(root_importer_mesh)) {
7076
godot_root_node = GLTFDocumentExtensionConvertImporterMesh::convert_importer_mesh_instance_3d(root_importer_mesh);
7077
memdelete(root_importer_mesh);
7078
}
7079
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
7080
ERR_CONTINUE(ext.is_null());
7081
err = ext->import_post(p_state, godot_root_node);
7082
ERR_CONTINUE(err != OK);
7083
}
7084
ERR_FAIL_NULL_V(godot_root_node, nullptr);
7085
return godot_root_node;
7086
}
7087
7088
Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> p_state, uint32_t p_flags) {
7089
ERR_FAIL_NULL_V(p_node, FAILED);
7090
Ref<GLTFState> state = p_state;
7091
ERR_FAIL_COND_V(state.is_null(), FAILED);
7092
state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
7093
state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS;
7094
state->force_generate_tangents = p_flags & GLTF_IMPORT_GENERATE_TANGENT_ARRAYS;
7095
state->force_disable_compression = p_flags & GLTF_IMPORT_FORCE_DISABLE_MESH_COMPRESSION;
7096
if (!state->buffers.size()) {
7097
state->buffers.push_back(Vector<uint8_t>());
7098
}
7099
// Perform export preflight for document extensions. Only extensions that
7100
// return OK will be used for the rest of the export steps.
7101
document_extensions.clear();
7102
for (Ref<GLTFDocumentExtension> ext : all_document_extensions) {
7103
ERR_CONTINUE(ext.is_null());
7104
Error err = ext->export_preflight(state, p_node);
7105
if (err == OK) {
7106
document_extensions.push_back(ext);
7107
}
7108
}
7109
// Add the root node(s) and their descendants to the state.
7110
if (_root_node_mode == RootNodeMode::ROOT_NODE_MODE_MULTI_ROOT) {
7111
const int child_count = p_node->get_child_count();
7112
for (int i = 0; i < child_count; i++) {
7113
_convert_scene_node(state, p_node->get_child(i), -1, -1);
7114
}
7115
state->scene_name = p_node->get_name();
7116
} else {
7117
if (_root_node_mode == RootNodeMode::ROOT_NODE_MODE_SINGLE_ROOT) {
7118
state->extensions_used.append("GODOT_single_root");
7119
}
7120
_convert_scene_node(state, p_node, -1, -1);
7121
}
7122
// Run post-convert for each extension, in case an extension needs to do something after converting the scene.
7123
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
7124
ERR_CONTINUE(ext.is_null());
7125
Error err = ext->export_post_convert(p_state, p_node);
7126
ERR_CONTINUE(err != OK);
7127
}
7128
return OK;
7129
}
7130
7131
Error GLTFDocument::append_from_buffer(const PackedByteArray &p_bytes, const String &p_base_path, Ref<GLTFState> p_state, uint32_t p_flags) {
7132
Ref<GLTFState> state = p_state;
7133
ERR_FAIL_COND_V(state.is_null(), FAILED);
7134
// TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire
7135
Error err = FAILED;
7136
state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
7137
state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS;
7138
state->force_generate_tangents = p_flags & GLTF_IMPORT_GENERATE_TANGENT_ARRAYS;
7139
state->force_disable_compression = p_flags & GLTF_IMPORT_FORCE_DISABLE_MESH_COMPRESSION;
7140
7141
Ref<FileAccessMemory> file_access;
7142
file_access.instantiate();
7143
file_access->open_custom(p_bytes.ptr(), p_bytes.size());
7144
state->set_base_path(p_base_path.get_base_dir());
7145
err = _parse(p_state, state->base_path, file_access);
7146
ERR_FAIL_COND_V(err != OK, err);
7147
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
7148
ERR_CONTINUE(ext.is_null());
7149
err = ext->import_post_parse(state);
7150
ERR_FAIL_COND_V(err != OK, err);
7151
}
7152
return OK;
7153
}
7154
7155
Error GLTFDocument::append_from_file(const String &p_path, Ref<GLTFState> p_state, uint32_t p_flags, const String &p_base_path) {
7156
Ref<GLTFState> state = p_state;
7157
// TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire
7158
if (state == Ref<GLTFState>()) {
7159
state.instantiate();
7160
}
7161
state->set_filename(p_path.get_file().get_basename());
7162
state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
7163
state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS;
7164
state->force_generate_tangents = p_flags & GLTF_IMPORT_GENERATE_TANGENT_ARRAYS;
7165
state->force_disable_compression = p_flags & GLTF_IMPORT_FORCE_DISABLE_MESH_COMPRESSION;
7166
7167
Error err;
7168
Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ, &err);
7169
ERR_FAIL_COND_V_MSG(err != OK, err, vformat(R"(Can't open file at path "%s")", p_path));
7170
ERR_FAIL_COND_V(file.is_null(), ERR_FILE_CANT_OPEN);
7171
String base_path = p_base_path;
7172
if (base_path.is_empty()) {
7173
base_path = p_path.get_base_dir();
7174
}
7175
state->set_base_path(base_path);
7176
err = _parse(p_state, base_path, file);
7177
ERR_FAIL_COND_V(err != OK, err);
7178
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
7179
ERR_CONTINUE(ext.is_null());
7180
err = ext->import_post_parse(p_state);
7181
ERR_FAIL_COND_V(err != OK, err);
7182
}
7183
return OK;
7184
}
7185
7186
Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> p_state) {
7187
ERR_FAIL_COND_V(p_state.is_null(), ERR_PARSE_ERROR);
7188
if (p_state->json.has("extensionsUsed")) {
7189
Vector<String> ext_array = p_state->json["extensionsUsed"];
7190
p_state->extensions_used = ext_array;
7191
}
7192
if (p_state->json.has("extensionsRequired")) {
7193
Vector<String> ext_array = p_state->json["extensionsRequired"];
7194
p_state->extensions_required = ext_array;
7195
}
7196
HashSet<String> supported_extensions = get_supported_gltf_extensions_hashset();
7197
Error ret = OK;
7198
for (int i = 0; i < p_state->extensions_required.size(); i++) {
7199
if (!supported_extensions.has(p_state->extensions_required[i])) {
7200
ERR_PRINT("glTF: Can't import file '" + p_state->filename + "', required extension '" + String(p_state->extensions_required[i]) + "' is not supported. Are you missing a GLTFDocumentExtension plugin?");
7201
ret = ERR_UNAVAILABLE;
7202
}
7203
}
7204
return ret;
7205
}
7206
7207
void GLTFDocument::set_root_node_mode(GLTFDocument::RootNodeMode p_root_node_mode) {
7208
_root_node_mode = p_root_node_mode;
7209
}
7210
7211
GLTFDocument::RootNodeMode GLTFDocument::get_root_node_mode() const {
7212
return _root_node_mode;
7213
}
7214
7215
void GLTFDocument::set_visibility_mode(VisibilityMode p_visibility_mode) {
7216
_visibility_mode = p_visibility_mode;
7217
}
7218
7219
GLTFDocument::VisibilityMode GLTFDocument::get_visibility_mode() const {
7220
return _visibility_mode;
7221
}
7222
7223
String GLTFDocument::_gen_unique_name_static(HashSet<String> &r_unique_names, const String &p_name) {
7224
const String s_name = p_name.validate_node_name();
7225
7226
String u_name;
7227
int index = 1;
7228
while (true) {
7229
u_name = s_name;
7230
7231
if (index > 1) {
7232
u_name += itos(index);
7233
}
7234
if (!r_unique_names.has(u_name)) {
7235
break;
7236
}
7237
index++;
7238
}
7239
7240
r_unique_names.insert(u_name);
7241
7242
return u_name;
7243
}
7244
7245