Skip to content

Commit e825169

Browse files
committed
Merge pull request #107836 from aaronfranke/gltf-without-nodes
GLTF: Allow parsing glTF files without nodes
2 parents 4ae535b + 5d492e1 commit e825169

File tree

1 file changed

+38
-29
lines changed

1 file changed

+38
-29
lines changed

modules/gltf/gltf_document.cpp

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,9 @@ String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> p_state, const GLTFSke
566566

567567
Error GLTFDocument::_parse_scenes(Ref<GLTFState> p_state) {
568568
p_state->unique_names.insert("Skeleton3D"); // Reserve skeleton name.
569-
ERR_FAIL_COND_V(!p_state->json.has("scenes"), ERR_FILE_CORRUPT);
569+
if (!p_state->json.has("scenes")) {
570+
return OK; // No scenes.
571+
}
570572
const Array &scenes = p_state->json["scenes"];
571573
int loaded_scene = 0;
572574
if (p_state->json.has("scene")) {
@@ -578,10 +580,11 @@ Error GLTFDocument::_parse_scenes(Ref<GLTFState> p_state) {
578580
if (scenes.size()) {
579581
ERR_FAIL_COND_V(loaded_scene >= scenes.size(), ERR_FILE_CORRUPT);
580582
const Dictionary &scene_dict = scenes[loaded_scene];
581-
ERR_FAIL_COND_V(!scene_dict.has("nodes"), ERR_UNAVAILABLE);
582-
const Array &nodes = scene_dict["nodes"];
583-
for (int j = 0; j < nodes.size(); j++) {
584-
p_state->root_nodes.push_back(nodes[j]);
583+
if (scene_dict.has("nodes")) {
584+
const Array &nodes = scene_dict["nodes"];
585+
for (const Variant &node : nodes) {
586+
p_state->root_nodes.push_back(node);
587+
}
585588
}
586589
// Determine what to use for the scene name.
587590
if (scene_dict.has("name") && !String(scene_dict["name"]).is_empty() && !((String)scene_dict["name"]).begins_with("Scene")) {
@@ -598,7 +601,9 @@ Error GLTFDocument::_parse_scenes(Ref<GLTFState> p_state) {
598601
}
599602

600603
Error GLTFDocument::_parse_nodes(Ref<GLTFState> p_state) {
601-
ERR_FAIL_COND_V(!p_state->json.has("nodes"), ERR_FILE_CORRUPT);
604+
if (!p_state->json.has("nodes")) {
605+
return OK; // No nodes to parse.
606+
}
602607
const Array &nodes = p_state->json["nodes"];
603608
for (int i = 0; i < nodes.size(); i++) {
604609
Ref<GLTFNode> node;
@@ -8687,6 +8692,7 @@ Node *GLTFDocument::_generate_scene_node_tree(Ref<GLTFState> p_state) {
86878692
// Generate the node tree.
86888693
Node *single_root;
86898694
if (p_state->extensions_used.has("GODOT_single_root")) {
8695+
ERR_FAIL_COND_V_MSG(p_state->nodes.is_empty(), nullptr, "glTF: Single root file has no nodes. This glTF file is invalid.");
86908696
if (_naming_version < 2) {
86918697
_generate_scene_node_compat_4pt4(p_state, 0, nullptr, nullptr);
86928698
} else {
@@ -8854,50 +8860,53 @@ Error GLTFDocument::write_to_filesystem(Ref<GLTFState> p_state, const String &p_
88548860
}
88558861

88568862
Node *GLTFDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, bool p_trimming, bool p_remove_immutable_tracks) {
8857-
Ref<GLTFState> state = p_state;
8858-
ERR_FAIL_COND_V(state.is_null(), nullptr);
8859-
ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr);
8863+
ERR_FAIL_COND_V(p_state.is_null(), nullptr);
8864+
// The glTF file must have nodes, and have some marked as root nodes, in order to generate a scene.
8865+
if (p_state->nodes.is_empty()) {
8866+
WARN_PRINT("glTF: This glTF file has no nodes, the generated Godot scene will be empty.");
8867+
}
8868+
// Now that we know that we have glTF nodes, we can begin generating a scene from the parsed glTF data.
88608869
Error err = OK;
88618870
p_state->set_bake_fps(p_bake_fps);
8862-
Node *root = _generate_scene_node_tree(state);
8863-
ERR_FAIL_NULL_V(root, nullptr);
8864-
_process_mesh_instances(state, root);
8865-
if (state->get_create_animations() && state->animations.size()) {
8866-
AnimationPlayer *ap = memnew(AnimationPlayer);
8867-
root->add_child(ap, true);
8868-
ap->set_owner(root);
8869-
for (int i = 0; i < state->animations.size(); i++) {
8870-
_import_animation(state, ap, i, p_trimming, p_remove_immutable_tracks);
8871-
}
8872-
}
8873-
for (KeyValue<GLTFNodeIndex, Node *> E : state->scene_nodes) {
8871+
Node *godot_root_node = _generate_scene_node_tree(p_state);
8872+
ERR_FAIL_NULL_V(godot_root_node, nullptr);
8873+
_process_mesh_instances(p_state, godot_root_node);
8874+
if (p_state->get_create_animations() && p_state->animations.size()) {
8875+
AnimationPlayer *anim_player = memnew(AnimationPlayer);
8876+
godot_root_node->add_child(anim_player, true);
8877+
anim_player->set_owner(godot_root_node);
8878+
for (int i = 0; i < p_state->animations.size(); i++) {
8879+
_import_animation(p_state, anim_player, i, p_trimming, p_remove_immutable_tracks);
8880+
}
8881+
}
8882+
for (KeyValue<GLTFNodeIndex, Node *> E : p_state->scene_nodes) {
88748883
ERR_CONTINUE(!E.value);
88758884
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
88768885
ERR_CONTINUE(ext.is_null());
88778886
Dictionary node_json;
8878-
if (state->json.has("nodes")) {
8879-
Array nodes = state->json["nodes"];
8887+
if (p_state->json.has("nodes")) {
8888+
Array nodes = p_state->json["nodes"];
88808889
if (0 <= E.key && E.key < nodes.size()) {
88818890
node_json = nodes[E.key];
88828891
}
88838892
}
8884-
Ref<GLTFNode> gltf_node = state->nodes[E.key];
8893+
Ref<GLTFNode> gltf_node = p_state->nodes[E.key];
88858894
err = ext->import_node(p_state, gltf_node, node_json, E.value);
88868895
ERR_CONTINUE(err != OK);
88878896
}
88888897
}
8889-
ImporterMeshInstance3D *root_importer_mesh = Object::cast_to<ImporterMeshInstance3D>(root);
8898+
ImporterMeshInstance3D *root_importer_mesh = Object::cast_to<ImporterMeshInstance3D>(godot_root_node);
88908899
if (unlikely(root_importer_mesh)) {
8891-
root = GLTFDocumentExtensionConvertImporterMesh::convert_importer_mesh_instance_3d(root_importer_mesh);
8900+
godot_root_node = GLTFDocumentExtensionConvertImporterMesh::convert_importer_mesh_instance_3d(root_importer_mesh);
88928901
memdelete(root_importer_mesh);
88938902
}
88948903
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
88958904
ERR_CONTINUE(ext.is_null());
8896-
err = ext->import_post(p_state, root);
8905+
err = ext->import_post(p_state, godot_root_node);
88978906
ERR_CONTINUE(err != OK);
88988907
}
8899-
ERR_FAIL_NULL_V(root, nullptr);
8900-
return root;
8908+
ERR_FAIL_NULL_V(godot_root_node, nullptr);
8909+
return godot_root_node;
89018910
}
89028911

89038912
Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> p_state, uint32_t p_flags) {

0 commit comments

Comments
 (0)