summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Franke <arnfranke@yahoo.com>2024-01-10 16:08:25 -0600
committerAaron Franke <arnfranke@yahoo.com>2024-01-11 20:33:51 -0600
commitd36a34edb77e93d501fd18fb7a255cc14e246dab (patch)
tree7a5e1605706528742e97ab1a35f98e04fcdb5e28
parent26b1fd0d842fa3c2f090ead47e8ea7cd2d6515e1 (diff)
downloadredot-engine-d36a34edb77e93d501fd18fb7a255cc14e246dab.tar.gz
Misc changes to the GLTF module before audio PR
-rw-r--r--modules/gltf/doc_classes/GLTFAccessor.xml5
-rw-r--r--modules/gltf/doc_classes/GLTFBufferView.xml18
-rw-r--r--modules/gltf/doc_classes/GLTFDocumentExtension.xml4
-rw-r--r--modules/gltf/doc_classes/GLTFState.xml8
-rw-r--r--modules/gltf/extensions/gltf_document_extension.cpp1
-rw-r--r--modules/gltf/gltf_document.cpp20
-rw-r--r--modules/gltf/gltf_state.cpp28
-rw-r--r--modules/gltf/gltf_state.h1
-rw-r--r--modules/gltf/register_types.cpp1
-rw-r--r--modules/gltf/structures/gltf_buffer_view.cpp13
-rw-r--r--modules/gltf/structures/gltf_buffer_view.h3
11 files changed, 91 insertions, 11 deletions
diff --git a/modules/gltf/doc_classes/GLTFAccessor.xml b/modules/gltf/doc_classes/GLTFAccessor.xml
index f678a11319..ba7323b7cd 100644
--- a/modules/gltf/doc_classes/GLTFAccessor.xml
+++ b/modules/gltf/doc_classes/GLTFAccessor.xml
@@ -1,14 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="GLTFAccessor" inherits="Resource" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
+ Represents a GLTF accessor.
</brief_description>
<description>
+ GLTFAccessor is a data structure representing GLTF a [code]accessor[/code] that would be found in the [code]"accessors"[/code] array. A buffer is a blob of binary data. A buffer view is a slice of a buffer. An accessor is a typed interpretation of the data in a buffer view.
+ Most custom data stored in GLTF does not need accessors, only buffer views (see [GLTFBufferView]). Accessors are for more advanced use cases such as interleaved mesh data encoded for the GPU.
</description>
<tutorials>
+ <link title="Buffers, BufferViews, and Accessors in Khronos glTF specification">https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_005_BuffersBufferViewsAccessors.md</link>
<link title="Runtime file loading and saving">$DOCS_URL/tutorials/io/runtime_file_loading_and_saving.html</link>
</tutorials>
<members>
<member name="buffer_view" type="int" setter="set_buffer_view" getter="get_buffer_view" default="-1">
+ The index of the buffer view this accessor is referencing. If [code]-1[/code], this accessor is not referencing any buffer view.
</member>
<member name="byte_offset" type="int" setter="set_byte_offset" getter="get_byte_offset" default="0">
</member>
diff --git a/modules/gltf/doc_classes/GLTFBufferView.xml b/modules/gltf/doc_classes/GLTFBufferView.xml
index d0f76a9af3..11d58bda72 100644
--- a/modules/gltf/doc_classes/GLTFBufferView.xml
+++ b/modules/gltf/doc_classes/GLTFBufferView.xml
@@ -1,22 +1,40 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="GLTFBufferView" inherits="Resource" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
+ Represents a GLTF buffer view.
</brief_description>
<description>
+ GLTFBufferView is a data structure representing GLTF a [code]bufferView[/code] that would be found in the [code]"bufferViews"[/code] array. A buffer is a blob of binary data. A buffer view is a slice of a buffer that can be used to identify and extract data from the buffer.
+ Most custom uses of buffers only need to use the [member buffer], [member byte_length], and [member byte_offset]. The [member byte_stride] and [member indices] properties are for more advanced use cases such as interleaved mesh data encoded for the GPU.
</description>
<tutorials>
+ <link title="Buffers, BufferViews, and Accessors in Khronos glTF specification">https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_005_BuffersBufferViewsAccessors.md</link>
<link title="Runtime file loading and saving">$DOCS_URL/tutorials/io/runtime_file_loading_and_saving.html</link>
</tutorials>
+ <methods>
+ <method name="load_buffer_view_data" qualifiers="const">
+ <return type="PackedByteArray" />
+ <param index="0" name="state" type="GLTFState" />
+ <description>
+ Loads the buffer view data from the buffer referenced by this buffer view in the given [GLTFState]. Interleaved data with a byte stride is not yet supported by this method. The data is returned as a [PackedByteArray].
+ </description>
+ </method>
+ </methods>
<members>
<member name="buffer" type="int" setter="set_buffer" getter="get_buffer" default="-1">
+ The index of the buffer this buffer view is referencing. If [code]-1[/code], this buffer view is not referencing any buffer.
</member>
<member name="byte_length" type="int" setter="set_byte_length" getter="get_byte_length" default="0">
+ The length, in bytes, of this buffer view. If [code]0[/code], this buffer view is empty.
</member>
<member name="byte_offset" type="int" setter="set_byte_offset" getter="get_byte_offset" default="0">
+ The offset, in bytes, from the start of the buffer to the start of this buffer view.
</member>
<member name="byte_stride" type="int" setter="set_byte_stride" getter="get_byte_stride" default="-1">
+ The stride, in bytes, between interleaved data. If [code]-1[/code], this buffer view is not interleaved.
</member>
<member name="indices" type="bool" setter="set_indices" getter="get_indices" default="false">
+ True if the GLTFBufferView's OpenGL GPU buffer type is an [code]ELEMENT_ARRAY_BUFFER[/code] used for vertex indices (integer constant [code]34963[/code]). False if the buffer type is [code]ARRAY_BUFFER[/code] used for vertex attributes (integer constant [code]34962[/code]) or when any other value. See [url=https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_005_BuffersBufferViewsAccessors.md]Buffers, BufferViews, and Accessors[/url] for possible values. This property is set but never used, setting this property will do nothing.
</member>
</members>
</class>
diff --git a/modules/gltf/doc_classes/GLTFDocumentExtension.xml b/modules/gltf/doc_classes/GLTFDocumentExtension.xml
index aaa55e772a..0eabcb5022 100644
--- a/modules/gltf/doc_classes/GLTFDocumentExtension.xml
+++ b/modules/gltf/doc_classes/GLTFDocumentExtension.xml
@@ -30,7 +30,7 @@
<param index="3" name="node" type="Node" />
<description>
Part of the export process. This method is run after [method _get_saveable_image_formats] and before [method _export_post]. If this [GLTFDocumentExtension] is used for exporting images, this runs after [method _serialize_texture_json].
- This method can be used to modify the final JSON of each node.
+ This method can be used to modify the final JSON of each node. Data should be primarily stored in [param gltf_node] prior to serializing the JSON, but the original Godot [param node] is also provided if available. The node may be null if not available, such as when exporting GLTF data not generated from a Godot scene.
</description>
</method>
<method name="_export_post" qualifiers="virtual">
@@ -114,7 +114,7 @@
<param index="0" name="state" type="GLTFState" />
<description>
Part of the import process. This method is run after [method _parse_node_extensions] and before [method _generate_scene_node].
- This method can be used to modify any of the data imported so far, including any scene nodes, before running the final per-node import step.
+ This method can be used to modify any of the data imported so far after parsing, before generating the nodes and then running the final per-node import step.
</description>
</method>
<method name="_import_preflight" qualifiers="virtual">
diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml
index e256041737..100750f400 100644
--- a/modules/gltf/doc_classes/GLTFState.xml
+++ b/modules/gltf/doc_classes/GLTFState.xml
@@ -20,6 +20,14 @@
Appends an extension to the list of extensions used by this GLTF file during serialization. If [param required] is true, the extension will also be added to the list of required extensions. Do not run this in [method GLTFDocumentExtension._export_post], as that stage is too late to add extensions. The final list is sorted alphabetically.
</description>
</method>
+ <method name="append_data_to_buffers">
+ <return type="int" />
+ <param index="0" name="data" type="PackedByteArray" />
+ <param index="1" name="deduplication" type="bool" />
+ <description>
+ 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>
+ </method>
<method name="get_accessors">
<return type="GLTFAccessor[]" />
<description>
diff --git a/modules/gltf/extensions/gltf_document_extension.cpp b/modules/gltf/extensions/gltf_document_extension.cpp
index 582bcf466b..9fdd6034a9 100644
--- a/modules/gltf/extensions/gltf_document_extension.cpp
+++ b/modules/gltf/extensions/gltf_document_extension.cpp
@@ -185,7 +185,6 @@ Error GLTFDocumentExtension::serialize_texture_json(Ref<GLTFState> p_state, Dict
Error GLTFDocumentExtension::export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) {
ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER);
- ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER);
Error err = OK;
GDVIRTUAL_CALL(_export_node, p_state, p_gltf_node, r_dict, p_node, err);
return err;
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 8a60df85cf..c840889f5e 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -405,6 +405,7 @@ static Vector<real_t> _xform_to_array(const Transform3D p_transform) {
Error GLTFDocument::_serialize_nodes(Ref<GLTFState> 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<GLTFNode> gltf_node = p_state->nodes[i];
@@ -452,10 +453,13 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> p_state) {
node["children"] = children;
}
+ Node *scene_node = nullptr;
+ if (i < scene_node_count) {
+ scene_node = p_state->scene_nodes[i];
+ }
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
- ERR_CONTINUE(!p_state->scene_nodes.find(i));
- Error err = ext->export_node(p_state, gltf_node, node, p_state->scene_nodes[i]);
+ Error err = ext->export_node(p_state, gltf_node, node, scene_node);
ERR_CONTINUE(err != OK);
}
@@ -7471,11 +7475,13 @@ Node *GLTFDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, boo
ERR_CONTINUE(!E.value);
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
- ERR_CONTINUE(!p_state->json.has("nodes"));
- Array nodes = p_state->json["nodes"];
- ERR_CONTINUE(E.key >= nodes.size());
- ERR_CONTINUE(E.key < 0);
- Dictionary node_json = nodes[E.key];
+ Dictionary node_json;
+ 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 = p_state->nodes[E.key];
err = ext->import_node(p_state, gltf_node, node_json, E.value);
ERR_CONTINUE(err != OK);
diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp
index 766fe41257..0c47d5777c 100644
--- a/modules/gltf/gltf_state.cpp
+++ b/modules/gltf/gltf_state.cpp
@@ -34,6 +34,8 @@
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("get_json"), &GLTFState::get_json);
ClassDB::bind_method(D_METHOD("set_json", "json"), &GLTFState::set_json);
ClassDB::bind_method(D_METHOD("get_major_version"), &GLTFState::get_major_version);
@@ -399,3 +401,29 @@ Variant GLTFState::get_additional_data(const StringName &p_extension_name) {
void GLTFState::set_additional_data(const StringName &p_extension_name, Variant p_additional_data) {
additional_data[p_extension_name] = p_additional_data;
}
+
+GLTFBufferViewIndex GLTFState::append_data_to_buffers(const Vector<uint8_t> &p_data, const bool p_deduplication = false) {
+ if (p_deduplication) {
+ for (int i = 0; i < buffer_views.size(); i++) {
+ Ref<GLTFBufferView> buffer_view = buffer_views[i];
+ Vector<uint8_t> buffer_view_data = buffer_view->load_buffer_view_data(this);
+ if (buffer_view_data == p_data) {
+ return i;
+ }
+ }
+ }
+ // Append the given data to a buffer and create a buffer view for it.
+ if (unlikely(buffers.is_empty())) {
+ buffers.push_back(Vector<uint8_t>());
+ }
+ Vector<uint8_t> &destination_buffer = buffers.write[0];
+ Ref<GLTFBufferView> buffer_view;
+ buffer_view.instantiate();
+ buffer_view->set_buffer(0);
+ buffer_view->set_byte_offset(destination_buffer.size());
+ buffer_view->set_byte_length(p_data.size());
+ destination_buffer.append_array(p_data);
+ const int new_index = buffer_views.size();
+ buffer_views.push_back(buffer_view);
+ return new_index;
+}
diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h
index 1ed8ce3629..3edf9a722f 100644
--- a/modules/gltf/gltf_state.h
+++ b/modules/gltf/gltf_state.h
@@ -105,6 +105,7 @@ protected:
public:
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);
enum GLTFHandleBinary {
HANDLE_BINARY_DISCARD_TEXTURES = 0,
diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp
index 0bf02cf890..94c9d66f78 100644
--- a/modules/gltf/register_types.cpp
+++ b/modules/gltf/register_types.cpp
@@ -118,6 +118,7 @@ void initialize_gltf_module(ModuleInitializationLevel p_level) {
GDREGISTER_CLASS(GLTFTexture);
GDREGISTER_CLASS(GLTFTextureSampler);
// Register GLTFDocumentExtension classes with GLTFDocument.
+ // Ensure physics is first in this list so that physics nodes are created before other nodes.
GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionPhysics);
GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionTextureKTX);
GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionTextureWebP);
diff --git a/modules/gltf/structures/gltf_buffer_view.cpp b/modules/gltf/structures/gltf_buffer_view.cpp
index 7678f23f57..d40ed69915 100644
--- a/modules/gltf/structures/gltf_buffer_view.cpp
+++ b/modules/gltf/structures/gltf_buffer_view.cpp
@@ -30,7 +30,11 @@
#include "gltf_buffer_view.h"
+#include "../gltf_state.h"
+
void GLTFBufferView::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("load_buffer_view_data", "state"), &GLTFBufferView::load_buffer_view_data);
+
ClassDB::bind_method(D_METHOD("get_buffer"), &GLTFBufferView::get_buffer);
ClassDB::bind_method(D_METHOD("set_buffer", "buffer"), &GLTFBufferView::set_buffer);
ClassDB::bind_method(D_METHOD("get_byte_offset"), &GLTFBufferView::get_byte_offset);
@@ -88,3 +92,12 @@ bool GLTFBufferView::get_indices() {
void GLTFBufferView::set_indices(bool p_indices) {
indices = p_indices;
}
+
+Vector<uint8_t> GLTFBufferView::load_buffer_view_data(const Ref<GLTFState> p_state) const {
+ ERR_FAIL_COND_V_MSG(byte_stride > 0, Vector<uint8_t>(), "Buffer views with byte stride are not yet supported by this method.");
+ const TypedArray<Vector<uint8_t>> &buffers = p_state->get_buffers();
+ ERR_FAIL_INDEX_V(buffer, buffers.size(), Vector<uint8_t>());
+ const PackedByteArray &buffer_data = buffers[buffer];
+ const int64_t byte_end = byte_offset + byte_length;
+ return buffer_data.slice(byte_offset, byte_end);
+}
diff --git a/modules/gltf/structures/gltf_buffer_view.h b/modules/gltf/structures/gltf_buffer_view.h
index 6d138dbf11..e4b7168130 100644
--- a/modules/gltf/structures/gltf_buffer_view.h
+++ b/modules/gltf/structures/gltf_buffer_view.h
@@ -64,7 +64,8 @@ public:
bool get_indices();
void set_indices(bool p_indices);
- // matrices need to be transformed to this
+
+ Vector<uint8_t> load_buffer_view_data(const Ref<GLTFState> p_state) const;
};
#endif // GLTF_BUFFER_VIEW_H