You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
Merge pull request #107836 from aaronfranke/gltf-without-nodes
GLTF: Allow parsing glTF files without nodes
This commit is contained in:
@@ -566,7 +566,9 @@ String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> p_state, const GLTFSke
|
||||
|
||||
Error GLTFDocument::_parse_scenes(Ref<GLTFState> p_state) {
|
||||
p_state->unique_names.insert("Skeleton3D"); // Reserve skeleton name.
|
||||
ERR_FAIL_COND_V(!p_state->json.has("scenes"), ERR_FILE_CORRUPT);
|
||||
if (!p_state->json.has("scenes")) {
|
||||
return OK; // No scenes.
|
||||
}
|
||||
const Array &scenes = p_state->json["scenes"];
|
||||
int loaded_scene = 0;
|
||||
if (p_state->json.has("scene")) {
|
||||
@@ -578,10 +580,11 @@ Error GLTFDocument::_parse_scenes(Ref<GLTFState> p_state) {
|
||||
if (scenes.size()) {
|
||||
ERR_FAIL_COND_V(loaded_scene >= scenes.size(), ERR_FILE_CORRUPT);
|
||||
const Dictionary &scene_dict = scenes[loaded_scene];
|
||||
ERR_FAIL_COND_V(!scene_dict.has("nodes"), ERR_UNAVAILABLE);
|
||||
const Array &nodes = scene_dict["nodes"];
|
||||
for (int j = 0; j < nodes.size(); j++) {
|
||||
p_state->root_nodes.push_back(nodes[j]);
|
||||
if (scene_dict.has("nodes")) {
|
||||
const Array &nodes = scene_dict["nodes"];
|
||||
for (const Variant &node : nodes) {
|
||||
p_state->root_nodes.push_back(node);
|
||||
}
|
||||
}
|
||||
// Determine what to use for the scene name.
|
||||
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) {
|
||||
}
|
||||
|
||||
Error GLTFDocument::_parse_nodes(Ref<GLTFState> p_state) {
|
||||
ERR_FAIL_COND_V(!p_state->json.has("nodes"), ERR_FILE_CORRUPT);
|
||||
if (!p_state->json.has("nodes")) {
|
||||
return OK; // No nodes to parse.
|
||||
}
|
||||
const Array &nodes = p_state->json["nodes"];
|
||||
for (int i = 0; i < nodes.size(); i++) {
|
||||
Ref<GLTFNode> node;
|
||||
@@ -8687,6 +8692,7 @@ Node *GLTFDocument::_generate_scene_node_tree(Ref<GLTFState> p_state) {
|
||||
// Generate the node tree.
|
||||
Node *single_root;
|
||||
if (p_state->extensions_used.has("GODOT_single_root")) {
|
||||
ERR_FAIL_COND_V_MSG(p_state->nodes.is_empty(), nullptr, "glTF: Single root file has no nodes. This glTF file is invalid.");
|
||||
if (_naming_version < 2) {
|
||||
_generate_scene_node_compat_4pt4(p_state, 0, nullptr, nullptr);
|
||||
} else {
|
||||
@@ -8854,50 +8860,53 @@ Error GLTFDocument::write_to_filesystem(Ref<GLTFState> p_state, const String &p_
|
||||
}
|
||||
|
||||
Node *GLTFDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, bool p_trimming, bool p_remove_immutable_tracks) {
|
||||
Ref<GLTFState> state = p_state;
|
||||
ERR_FAIL_COND_V(state.is_null(), nullptr);
|
||||
ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr);
|
||||
ERR_FAIL_COND_V(p_state.is_null(), nullptr);
|
||||
// The glTF file must have nodes, and have some marked as root nodes, in order to generate a scene.
|
||||
if (p_state->nodes.is_empty()) {
|
||||
WARN_PRINT("glTF: This glTF file has no nodes, the generated Godot scene will be empty.");
|
||||
}
|
||||
// Now that we know that we have glTF nodes, we can begin generating a scene from the parsed glTF data.
|
||||
Error err = OK;
|
||||
p_state->set_bake_fps(p_bake_fps);
|
||||
Node *root = _generate_scene_node_tree(state);
|
||||
ERR_FAIL_NULL_V(root, nullptr);
|
||||
_process_mesh_instances(state, root);
|
||||
if (state->get_create_animations() && state->animations.size()) {
|
||||
AnimationPlayer *ap = memnew(AnimationPlayer);
|
||||
root->add_child(ap, true);
|
||||
ap->set_owner(root);
|
||||
for (int i = 0; i < state->animations.size(); i++) {
|
||||
_import_animation(state, ap, i, p_trimming, p_remove_immutable_tracks);
|
||||
Node *godot_root_node = _generate_scene_node_tree(p_state);
|
||||
ERR_FAIL_NULL_V(godot_root_node, nullptr);
|
||||
_process_mesh_instances(p_state, godot_root_node);
|
||||
if (p_state->get_create_animations() && p_state->animations.size()) {
|
||||
AnimationPlayer *anim_player = memnew(AnimationPlayer);
|
||||
godot_root_node->add_child(anim_player, true);
|
||||
anim_player->set_owner(godot_root_node);
|
||||
for (int i = 0; i < p_state->animations.size(); i++) {
|
||||
_import_animation(p_state, anim_player, i, p_trimming, p_remove_immutable_tracks);
|
||||
}
|
||||
}
|
||||
for (KeyValue<GLTFNodeIndex, Node *> E : state->scene_nodes) {
|
||||
for (KeyValue<GLTFNodeIndex, Node *> E : p_state->scene_nodes) {
|
||||
ERR_CONTINUE(!E.value);
|
||||
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
|
||||
ERR_CONTINUE(ext.is_null());
|
||||
Dictionary node_json;
|
||||
if (state->json.has("nodes")) {
|
||||
Array nodes = state->json["nodes"];
|
||||
if (p_state->json.has("nodes")) {
|
||||
Array nodes = p_state->json["nodes"];
|
||||
if (0 <= E.key && E.key < nodes.size()) {
|
||||
node_json = nodes[E.key];
|
||||
}
|
||||
}
|
||||
Ref<GLTFNode> gltf_node = state->nodes[E.key];
|
||||
Ref<GLTFNode> gltf_node = p_state->nodes[E.key];
|
||||
err = ext->import_node(p_state, gltf_node, node_json, E.value);
|
||||
ERR_CONTINUE(err != OK);
|
||||
}
|
||||
}
|
||||
ImporterMeshInstance3D *root_importer_mesh = Object::cast_to<ImporterMeshInstance3D>(root);
|
||||
ImporterMeshInstance3D *root_importer_mesh = Object::cast_to<ImporterMeshInstance3D>(godot_root_node);
|
||||
if (unlikely(root_importer_mesh)) {
|
||||
root = GLTFDocumentExtensionConvertImporterMesh::convert_importer_mesh_instance_3d(root_importer_mesh);
|
||||
godot_root_node = GLTFDocumentExtensionConvertImporterMesh::convert_importer_mesh_instance_3d(root_importer_mesh);
|
||||
memdelete(root_importer_mesh);
|
||||
}
|
||||
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
|
||||
ERR_CONTINUE(ext.is_null());
|
||||
err = ext->import_post(p_state, root);
|
||||
err = ext->import_post(p_state, godot_root_node);
|
||||
ERR_CONTINUE(err != OK);
|
||||
}
|
||||
ERR_FAIL_NULL_V(root, nullptr);
|
||||
return root;
|
||||
ERR_FAIL_NULL_V(godot_root_node, nullptr);
|
||||
return godot_root_node;
|
||||
}
|
||||
|
||||
Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> p_state, uint32_t p_flags) {
|
||||
|
||||
Reference in New Issue
Block a user