Skip to content

Commit 5d492e1

Browse files
committed
GLTF: Allow parsing glTF files without nodes
1 parent 06827c9 commit 5d492e1

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
@@ -565,7 +565,9 @@ String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> p_state, const GLTFSke
565565

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

599602
Error GLTFDocument::_parse_nodes(Ref<GLTFState> p_state) {
600-
ERR_FAIL_COND_V(!p_state->json.has("nodes"), ERR_FILE_CORRUPT);
603+
if (!p_state->json.has("nodes")) {
604+
return OK; // No nodes to parse.
605+
}
601606
const Array &nodes = p_state->json["nodes"];
602607
for (int i = 0; i < nodes.size(); i++) {
603608
Ref<GLTFNode> node;
@@ -8676,6 +8681,7 @@ Node *GLTFDocument::_generate_scene_node_tree(Ref<GLTFState> p_state) {
86768681
// Generate the node tree.
86778682
Node *single_root;
86788683
if (p_state->extensions_used.has("GODOT_single_root")) {
8684+
ERR_FAIL_COND_V_MSG(p_state->nodes.is_empty(), nullptr, "glTF: Single root file has no nodes. This glTF file is invalid.");
86798685
if (_naming_version < 2) {
86808686
_generate_scene_node_compat_4pt4(p_state, 0, nullptr, nullptr);
86818687
} else {
@@ -8843,50 +8849,53 @@ Error GLTFDocument::write_to_filesystem(Ref<GLTFState> p_state, const String &p_
88438849
}
88448850

88458851
Node *GLTFDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, bool p_trimming, bool p_remove_immutable_tracks) {
8846-
Ref<GLTFState> state = p_state;
8847-
ERR_FAIL_COND_V(state.is_null(), nullptr);
8848-
ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr);
8852+
ERR_FAIL_COND_V(p_state.is_null(), nullptr);
8853+
// The glTF file must have nodes, and have some marked as root nodes, in order to generate a scene.
8854+
if (p_state->nodes.is_empty()) {
8855+
WARN_PRINT("glTF: This glTF file has no nodes, the generated Godot scene will be empty.");
8856+
}
8857+
// Now that we know that we have glTF nodes, we can begin generating a scene from the parsed glTF data.
88498858
Error err = OK;
88508859
p_state->set_bake_fps(p_bake_fps);
8851-
Node *root = _generate_scene_node_tree(state);
8852-
ERR_FAIL_NULL_V(root, nullptr);
8853-
_process_mesh_instances(state, root);
8854-
if (state->get_create_animations() && state->animations.size()) {
8855-
AnimationPlayer *ap = memnew(AnimationPlayer);
8856-
root->add_child(ap, true);
8857-
ap->set_owner(root);
8858-
for (int i = 0; i < state->animations.size(); i++) {
8859-
_import_animation(state, ap, i, p_trimming, p_remove_immutable_tracks);
8860-
}
8861-
}
8862-
for (KeyValue<GLTFNodeIndex, Node *> E : state->scene_nodes) {
8860+
Node *godot_root_node = _generate_scene_node_tree(p_state);
8861+
ERR_FAIL_NULL_V(godot_root_node, nullptr);
8862+
_process_mesh_instances(p_state, godot_root_node);
8863+
if (p_state->get_create_animations() && p_state->animations.size()) {
8864+
AnimationPlayer *anim_player = memnew(AnimationPlayer);
8865+
godot_root_node->add_child(anim_player, true);
8866+
anim_player->set_owner(godot_root_node);
8867+
for (int i = 0; i < p_state->animations.size(); i++) {
8868+
_import_animation(p_state, anim_player, i, p_trimming, p_remove_immutable_tracks);
8869+
}
8870+
}
8871+
for (KeyValue<GLTFNodeIndex, Node *> E : p_state->scene_nodes) {
88638872
ERR_CONTINUE(!E.value);
88648873
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
88658874
ERR_CONTINUE(ext.is_null());
88668875
Dictionary node_json;
8867-
if (state->json.has("nodes")) {
8868-
Array nodes = state->json["nodes"];
8876+
if (p_state->json.has("nodes")) {
8877+
Array nodes = p_state->json["nodes"];
88698878
if (0 <= E.key && E.key < nodes.size()) {
88708879
node_json = nodes[E.key];
88718880
}
88728881
}
8873-
Ref<GLTFNode> gltf_node = state->nodes[E.key];
8882+
Ref<GLTFNode> gltf_node = p_state->nodes[E.key];
88748883
err = ext->import_node(p_state, gltf_node, node_json, E.value);
88758884
ERR_CONTINUE(err != OK);
88768885
}
88778886
}
8878-
ImporterMeshInstance3D *root_importer_mesh = Object::cast_to<ImporterMeshInstance3D>(root);
8887+
ImporterMeshInstance3D *root_importer_mesh = Object::cast_to<ImporterMeshInstance3D>(godot_root_node);
88798888
if (unlikely(root_importer_mesh)) {
8880-
root = GLTFDocumentExtensionConvertImporterMesh::convert_importer_mesh_instance_3d(root_importer_mesh);
8889+
godot_root_node = GLTFDocumentExtensionConvertImporterMesh::convert_importer_mesh_instance_3d(root_importer_mesh);
88818890
memdelete(root_importer_mesh);
88828891
}
88838892
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
88848893
ERR_CONTINUE(ext.is_null());
8885-
err = ext->import_post(p_state, root);
8894+
err = ext->import_post(p_state, godot_root_node);
88868895
ERR_CONTINUE(err != OK);
88878896
}
8888-
ERR_FAIL_NULL_V(root, nullptr);
8889-
return root;
8897+
ERR_FAIL_NULL_V(godot_root_node, nullptr);
8898+
return godot_root_node;
88908899
}
88918900

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

0 commit comments

Comments
 (0)