From f82262eecb558accb926628aa95b6e66209dcad3 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Mon, 2 Sep 2024 01:28:07 -0700 Subject: [PATCH] GLTF: Add append_gltf_node to GLTFState --- modules/gltf/doc_classes/GLTFNode.xml | 7 ++++++ modules/gltf/doc_classes/GLTFState.xml | 11 +++++++++ modules/gltf/gltf_document.cpp | 34 ++++++++++---------------- modules/gltf/gltf_document.h | 6 ----- modules/gltf/gltf_state.cpp | 14 +++++++++++ modules/gltf/gltf_state.h | 1 + modules/gltf/structures/gltf_node.cpp | 5 ++++ modules/gltf/structures/gltf_node.h | 1 + 8 files changed, 52 insertions(+), 27 deletions(-) diff --git a/modules/gltf/doc_classes/GLTFNode.xml b/modules/gltf/doc_classes/GLTFNode.xml index 2786c25e9ad..a242a0d1d8b 100644 --- a/modules/gltf/doc_classes/GLTFNode.xml +++ b/modules/gltf/doc_classes/GLTFNode.xml @@ -12,6 +12,13 @@ https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_004_ScenesNodes.md" + + + + + Appends the given child node index to the [member children] array. + + diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml index c049acf557e..de7ec2a4ca5 100644 --- a/modules/gltf/doc_classes/GLTFState.xml +++ b/modules/gltf/doc_classes/GLTFState.xml @@ -28,6 +28,17 @@ Appends the given byte array data to the buffers and creates a [GLTFBufferView] for it. The index of the destination [GLTFBufferView] is returned. If [param deduplication] is true, the buffers will first be searched for duplicate data, otherwise new bytes will always be appended. + + + + + + + Append the given [GLTFNode] to the state, and return its new index. This can be used to export one Godot node as multiple glTF nodes, or inject new glTF nodes at import time. On import, this must be called before [method GLTFDocumentExtension._generate_scene_node] finishes for the parent node. On export, this must be called before [method GLTFDocumentExtension._export_node] runs for the parent node. + The [param godot_scene_node] parameter is the Godot scene node that corresponds to this glTF node. This is highly recommended to be set to a valid node, but may be null if there is no corresponding Godot scene node. One Godot scene node may be used for multiple glTF nodes, so if exporting multiple glTF nodes for one Godot scene node, use the same Godot scene node for each. + The [param parent_node_index] parameter is the index of the parent [GLTFNode] in the state. If [code]-1[/code], the node will be a root node, otherwise the new node will be added to the parent's list of children. The index will also be written to the [member GLTFNode.parent] property of the new node. + + diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 69973a34dd6..acb72c552fa 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -414,7 +414,6 @@ static Vector _xform_to_array(const Transform3D p_transform) { Error GLTFDocument::_serialize_nodes(Ref p_state) { Array nodes; - const int scene_node_count = p_state->scene_nodes.size(); for (int i = 0; i < p_state->nodes.size(); i++) { Dictionary node; Ref gltf_node = p_state->nodes[i]; @@ -465,7 +464,7 @@ Error GLTFDocument::_serialize_nodes(Ref p_state) { } Node *scene_node = nullptr; - if (i < scene_node_count) { + if (i < (int)p_state->scene_nodes.size()) { scene_node = p_state->scene_nodes[i]; } for (Ref ext : document_extensions) { @@ -5264,6 +5263,7 @@ void GLTFDocument::_convert_scene_node(Ref p_state, Node *p_current, gltf_node.instantiate(); gltf_node->set_original_name(p_current->get_name()); gltf_node->set_name(_gen_unique_name(p_state, p_current->get_name())); + gltf_node->merge_meta_from(p_current); if (cast_to(p_current)) { Node3D *spatial = cast_to(p_current); _convert_spatial(p_state, spatial, gltf_node); @@ -5309,14 +5309,18 @@ void GLTFDocument::_convert_scene_node(Ref p_state, Node *p_current, ERR_CONTINUE(ext.is_null()); ext->convert_scene_node(p_state, gltf_node, p_current); } - GLTFNodeIndex current_node_i = p_state->nodes.size(); - GLTFNodeIndex gltf_root = p_gltf_root; - if (gltf_root == -1) { - gltf_root = current_node_i; - p_state->root_nodes.push_back(gltf_root); + GLTFNodeIndex current_node_i; + if (gltf_node->get_parent() == -1) { + current_node_i = p_state->append_gltf_node(gltf_node, p_current, p_gltf_parent); + } else if (gltf_node->get_parent() < -1) { + return; + } else { + current_node_i = p_state->nodes.size() - 1; + while (gltf_node != p_state->nodes[current_node_i]) { + current_node_i--; + } } - gltf_node->merge_meta_from(p_current); - _create_gltf_node(p_state, p_current, current_node_i, p_gltf_parent, gltf_root, gltf_node); + const GLTFNodeIndex gltf_root = (p_gltf_root == -1) ? current_node_i : p_gltf_root; for (int node_i = 0; node_i < p_current->get_child_count(); node_i++) { _convert_scene_node(p_state, p_current->get_child(node_i), current_node_i, gltf_root); } @@ -5377,18 +5381,6 @@ void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeInd } #endif // MODULE_CSG_ENABLED -void GLTFDocument::_create_gltf_node(Ref p_state, Node *p_scene_parent, GLTFNodeIndex p_current_node_i, - GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_gltf_node, Ref p_gltf_node) { - p_state->scene_nodes.insert(p_current_node_i, p_scene_parent); - p_state->nodes.push_back(p_gltf_node); - ERR_FAIL_COND(p_current_node_i == p_parent_node_index); - p_state->nodes.write[p_current_node_i]->parent = p_parent_node_index; - if (p_parent_node_index == -1) { - return; - } - p_state->nodes.write[p_parent_node_index]->children.push_back(p_current_node_i); -} - void GLTFDocument::_convert_animation_player_to_gltf(AnimationPlayer *p_animation_player, Ref p_state, GLTFNodeIndex p_gltf_current, GLTFNodeIndex p_gltf_root_index, Ref p_gltf_node, Node *p_scene_parent) { ERR_FAIL_NULL(p_animation_player); p_state->animation_players.push_back(p_animation_player); diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index b3e6dcf54a6..d347d491029 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -342,12 +342,6 @@ public: void _convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref p_gltf_node, Ref p_state); #endif // MODULE_CSG_ENABLED - void _create_gltf_node(Ref p_state, - Node *p_scene_parent, - GLTFNodeIndex p_current_node_i, - GLTFNodeIndex p_parent_node_index, - GLTFNodeIndex p_root_gltf_node, - Ref p_gltf_node); void _convert_animation_player_to_gltf( AnimationPlayer *p_animation_player, Ref p_state, GLTFNodeIndex p_gltf_current, diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index 73a61ff77f2..7763874d028 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -35,6 +35,7 @@ void GLTFState::_bind_methods() { ClassDB::bind_method(D_METHOD("add_used_extension", "extension_name", "required"), &GLTFState::add_used_extension); ClassDB::bind_method(D_METHOD("append_data_to_buffers", "data", "deduplication"), &GLTFState::append_data_to_buffers); + ClassDB::bind_method(D_METHOD("append_gltf_node", "gltf_node", "godot_scene_node", "parent_node_index"), &GLTFState::append_gltf_node); ClassDB::bind_method(D_METHOD("get_json"), &GLTFState::get_json); ClassDB::bind_method(D_METHOD("set_json", "json"), &GLTFState::set_json); @@ -441,3 +442,16 @@ GLTFBufferViewIndex GLTFState::append_data_to_buffers(const Vector &p_d buffer_views.push_back(buffer_view); return new_index; } + +GLTFNodeIndex GLTFState::append_gltf_node(Ref p_gltf_node, Node *p_godot_scene_node, GLTFNodeIndex p_parent_node_index) { + p_gltf_node->set_parent(p_parent_node_index); + const GLTFNodeIndex new_index = nodes.size(); + nodes.append(p_gltf_node); + scene_nodes.insert(new_index, p_godot_scene_node); + if (p_parent_node_index == -1) { + root_nodes.append(new_index); + } else if (p_parent_node_index < new_index) { + nodes.write[p_parent_node_index]->append_child_index(new_index); + } + return new_index; +} diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index 07efafe13bf..79540491926 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -119,6 +119,7 @@ public: void add_used_extension(const String &p_extension, bool p_required = false); GLTFBufferViewIndex append_data_to_buffers(const Vector &p_data, const bool p_deduplication); + GLTFNodeIndex append_gltf_node(Ref p_gltf_node, Node *p_godot_scene_node, GLTFNodeIndex p_parent_node_index); enum GLTFHandleBinary { HANDLE_BINARY_DISCARD_TEXTURES = 0, diff --git a/modules/gltf/structures/gltf_node.cpp b/modules/gltf/structures/gltf_node.cpp index 2934e4b5ee6..ccee5e8ca43 100644 --- a/modules/gltf/structures/gltf_node.cpp +++ b/modules/gltf/structures/gltf_node.cpp @@ -55,6 +55,7 @@ void GLTFNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_scale", "scale"), &GLTFNode::set_scale); ClassDB::bind_method(D_METHOD("get_children"), &GLTFNode::get_children); ClassDB::bind_method(D_METHOD("set_children", "children"), &GLTFNode::set_children); + ClassDB::bind_method(D_METHOD("append_child_index", "child_index"), &GLTFNode::append_child_index); ClassDB::bind_method(D_METHOD("get_light"), &GLTFNode::get_light); ClassDB::bind_method(D_METHOD("set_light", "light"), &GLTFNode::set_light); ClassDB::bind_method(D_METHOD("get_additional_data", "extension_name"), &GLTFNode::get_additional_data); @@ -170,6 +171,10 @@ void GLTFNode::set_children(Vector p_children) { children = p_children; } +void GLTFNode::append_child_index(int p_child_index) { + children.append(p_child_index); +} + GLTFLightIndex GLTFNode::get_light() { return light; } diff --git a/modules/gltf/structures/gltf_node.h b/modules/gltf/structures/gltf_node.h index 63399fb32bc..f3f6bfa2f16 100644 --- a/modules/gltf/structures/gltf_node.h +++ b/modules/gltf/structures/gltf_node.h @@ -97,6 +97,7 @@ public: Vector get_children(); void set_children(Vector p_children); + void append_child_index(int p_child_index); GLTFLightIndex get_light(); void set_light(GLTFLightIndex p_light);