GLTF: Add append_gltf_node to GLTFState

This commit is contained in:
Aaron Franke 2024-09-02 01:28:07 -07:00
parent 7c383767a2
commit f82262eecb
No known key found for this signature in database
GPG Key ID: 40A1750B977E56BF
8 changed files with 52 additions and 27 deletions

View File

@ -12,6 +12,13 @@
<link title="glTF scene and node spec">https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_004_ScenesNodes.md"</link> <link title="glTF scene and node spec">https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_004_ScenesNodes.md"</link>
</tutorials> </tutorials>
<methods> <methods>
<method name="append_child_index">
<return type="void" />
<param index="0" name="child_index" type="int" />
<description>
Appends the given child node index to the [member children] array.
</description>
</method>
<method name="get_additional_data"> <method name="get_additional_data">
<return type="Variant" /> <return type="Variant" />
<param index="0" name="extension_name" type="StringName" /> <param index="0" name="extension_name" type="StringName" />

View File

@ -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. 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.
</description> </description>
</method> </method>
<method name="append_gltf_node">
<return type="int" />
<param index="0" name="gltf_node" type="GLTFNode" />
<param index="1" name="godot_scene_node" type="Node" />
<param index="2" name="parent_node_index" type="int" />
<description>
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.
</description>
</method>
<method name="get_accessors"> <method name="get_accessors">
<return type="GLTFAccessor[]" /> <return type="GLTFAccessor[]" />
<description> <description>

View File

@ -414,7 +414,6 @@ static Vector<real_t> _xform_to_array(const Transform3D p_transform) {
Error GLTFDocument::_serialize_nodes(Ref<GLTFState> p_state) { Error GLTFDocument::_serialize_nodes(Ref<GLTFState> p_state) {
Array nodes; Array nodes;
const int scene_node_count = p_state->scene_nodes.size();
for (int i = 0; i < p_state->nodes.size(); i++) { for (int i = 0; i < p_state->nodes.size(); i++) {
Dictionary node; Dictionary node;
Ref<GLTFNode> gltf_node = p_state->nodes[i]; Ref<GLTFNode> gltf_node = p_state->nodes[i];
@ -465,7 +464,7 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> p_state) {
} }
Node *scene_node = nullptr; Node *scene_node = nullptr;
if (i < scene_node_count) { if (i < (int)p_state->scene_nodes.size()) {
scene_node = p_state->scene_nodes[i]; scene_node = p_state->scene_nodes[i];
} }
for (Ref<GLTFDocumentExtension> ext : document_extensions) { for (Ref<GLTFDocumentExtension> ext : document_extensions) {
@ -5264,6 +5263,7 @@ void GLTFDocument::_convert_scene_node(Ref<GLTFState> p_state, Node *p_current,
gltf_node.instantiate(); gltf_node.instantiate();
gltf_node->set_original_name(p_current->get_name()); gltf_node->set_original_name(p_current->get_name());
gltf_node->set_name(_gen_unique_name(p_state, 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<Node3D>(p_current)) { if (cast_to<Node3D>(p_current)) {
Node3D *spatial = cast_to<Node3D>(p_current); Node3D *spatial = cast_to<Node3D>(p_current);
_convert_spatial(p_state, spatial, gltf_node); _convert_spatial(p_state, spatial, gltf_node);
@ -5309,14 +5309,18 @@ void GLTFDocument::_convert_scene_node(Ref<GLTFState> p_state, Node *p_current,
ERR_CONTINUE(ext.is_null()); ERR_CONTINUE(ext.is_null());
ext->convert_scene_node(p_state, gltf_node, p_current); ext->convert_scene_node(p_state, gltf_node, p_current);
} }
GLTFNodeIndex current_node_i = p_state->nodes.size(); GLTFNodeIndex current_node_i;
GLTFNodeIndex gltf_root = p_gltf_root; if (gltf_node->get_parent() == -1) {
if (gltf_root == -1) { current_node_i = p_state->append_gltf_node(gltf_node, p_current, p_gltf_parent);
gltf_root = current_node_i; } else if (gltf_node->get_parent() < -1) {
p_state->root_nodes.push_back(gltf_root); 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++) { 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); _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 #endif // MODULE_CSG_ENABLED
void GLTFDocument::_create_gltf_node(Ref<GLTFState> p_state, Node *p_scene_parent, GLTFNodeIndex p_current_node_i,
GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_gltf_node, Ref<GLTFNode> 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<GLTFState> p_state, GLTFNodeIndex p_gltf_current, GLTFNodeIndex p_gltf_root_index, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) { void GLTFDocument::_convert_animation_player_to_gltf(AnimationPlayer *p_animation_player, Ref<GLTFState> p_state, GLTFNodeIndex p_gltf_current, GLTFNodeIndex p_gltf_root_index, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) {
ERR_FAIL_NULL(p_animation_player); ERR_FAIL_NULL(p_animation_player);
p_state->animation_players.push_back(p_animation_player); p_state->animation_players.push_back(p_animation_player);

View File

@ -342,12 +342,6 @@ public:
void _convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state); void _convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state);
#endif // MODULE_CSG_ENABLED #endif // MODULE_CSG_ENABLED
void _create_gltf_node(Ref<GLTFState> p_state,
Node *p_scene_parent,
GLTFNodeIndex p_current_node_i,
GLTFNodeIndex p_parent_node_index,
GLTFNodeIndex p_root_gltf_node,
Ref<GLTFNode> p_gltf_node);
void _convert_animation_player_to_gltf( void _convert_animation_player_to_gltf(
AnimationPlayer *p_animation_player, Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, Ref<GLTFState> p_state,
GLTFNodeIndex p_gltf_current, GLTFNodeIndex p_gltf_current,

View File

@ -35,6 +35,7 @@
void GLTFState::_bind_methods() { void GLTFState::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_used_extension", "extension_name", "required"), &GLTFState::add_used_extension); 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_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("get_json"), &GLTFState::get_json);
ClassDB::bind_method(D_METHOD("set_json", "json"), &GLTFState::set_json); ClassDB::bind_method(D_METHOD("set_json", "json"), &GLTFState::set_json);
@ -441,3 +442,16 @@ GLTFBufferViewIndex GLTFState::append_data_to_buffers(const Vector<uint8_t> &p_d
buffer_views.push_back(buffer_view); buffer_views.push_back(buffer_view);
return new_index; return new_index;
} }
GLTFNodeIndex GLTFState::append_gltf_node(Ref<GLTFNode> 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;
}

View File

@ -119,6 +119,7 @@ public:
void add_used_extension(const String &p_extension, bool p_required = false); void add_used_extension(const String &p_extension, bool p_required = false);
GLTFBufferViewIndex append_data_to_buffers(const Vector<uint8_t> &p_data, const bool p_deduplication); GLTFBufferViewIndex append_data_to_buffers(const Vector<uint8_t> &p_data, const bool p_deduplication);
GLTFNodeIndex append_gltf_node(Ref<GLTFNode> p_gltf_node, Node *p_godot_scene_node, GLTFNodeIndex p_parent_node_index);
enum GLTFHandleBinary { enum GLTFHandleBinary {
HANDLE_BINARY_DISCARD_TEXTURES = 0, HANDLE_BINARY_DISCARD_TEXTURES = 0,

View File

@ -55,6 +55,7 @@ void GLTFNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &GLTFNode::set_scale); 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("get_children"), &GLTFNode::get_children);
ClassDB::bind_method(D_METHOD("set_children", "children"), &GLTFNode::set_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("get_light"), &GLTFNode::get_light);
ClassDB::bind_method(D_METHOD("set_light", "light"), &GLTFNode::set_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); ClassDB::bind_method(D_METHOD("get_additional_data", "extension_name"), &GLTFNode::get_additional_data);
@ -170,6 +171,10 @@ void GLTFNode::set_children(Vector<int> p_children) {
children = p_children; children = p_children;
} }
void GLTFNode::append_child_index(int p_child_index) {
children.append(p_child_index);
}
GLTFLightIndex GLTFNode::get_light() { GLTFLightIndex GLTFNode::get_light() {
return light; return light;
} }

View File

@ -97,6 +97,7 @@ public:
Vector<int> get_children(); Vector<int> get_children();
void set_children(Vector<int> p_children); void set_children(Vector<int> p_children);
void append_child_index(int p_child_index);
GLTFLightIndex get_light(); GLTFLightIndex get_light();
void set_light(GLTFLightIndex p_light); void set_light(GLTFLightIndex p_light);