diff options
Diffstat (limited to 'modules/gltf')
-rw-r--r-- | modules/gltf/config.py | 1 | ||||
-rw-r--r-- | modules/gltf/doc_classes/GLTFDocument.xml | 22 | ||||
-rw-r--r-- | modules/gltf/doc_classes/PackedSceneGLTF.xml | 43 | ||||
-rw-r--r-- | modules/gltf/editor_scene_exporter_gltf_plugin.cpp | 11 | ||||
-rw-r--r-- | modules/gltf/editor_scene_exporter_gltf_plugin.h | 1 | ||||
-rw-r--r-- | modules/gltf/editor_scene_importer_gltf.cpp | 117 | ||||
-rw-r--r-- | modules/gltf/editor_scene_importer_gltf.h | 28 | ||||
-rw-r--r-- | modules/gltf/gltf_accessor.h | 3 | ||||
-rw-r--r-- | modules/gltf/gltf_document.cpp | 225 | ||||
-rw-r--r-- | modules/gltf/gltf_document.h | 16 | ||||
-rw-r--r-- | modules/gltf/gltf_node.h | 1 | ||||
-rw-r--r-- | modules/gltf/gltf_state.h | 1 | ||||
-rw-r--r-- | modules/gltf/register_types.cpp | 1 |
13 files changed, 256 insertions, 214 deletions
diff --git a/modules/gltf/config.py b/modules/gltf/config.py index a4ee871eff..52a97c93aa 100644 --- a/modules/gltf/config.py +++ b/modules/gltf/config.py @@ -22,7 +22,6 @@ def get_doc_classes(): "GLTFSpecGloss", "GLTFState", "GLTFTexture", - "PackedSceneGLTF", ] diff --git a/modules/gltf/doc_classes/GLTFDocument.xml b/modules/gltf/doc_classes/GLTFDocument.xml index 04c40dd752..f8e0007684 100644 --- a/modules/gltf/doc_classes/GLTFDocument.xml +++ b/modules/gltf/doc_classes/GLTFDocument.xml @@ -7,6 +7,28 @@ <tutorials> </tutorials> <methods> + <method name="import_scene"> + <return type="Node" /> + <argument index="0" name="path" type="String" /> + <argument index="1" name="flags" type="int" default="0" /> + <argument index="2" name="bake_fps" type="int" default="30" /> + <argument index="3" name="state" type="GLTFState" default="null" /> + <description> + Import a scene from glTF2 ".gltf" or ".glb" file. + </description> + </method> + <method name="save_scene"> + <return type="int" enum="Error" /> + <argument index="0" name="node" type="Node" /> + <argument index="1" name="path" type="String" /> + <argument index="2" name="src_path" type="String" /> + <argument index="3" name="flags" type="int" default="0" /> + <argument index="4" name="bake_fps" type="float" default="30" /> + <argument index="5" name="state" type="GLTFState" default="null" /> + <description> + Save a scene as a glTF2 ".glb" or ".gltf" file. + </description> + </method> </methods> <constants> </constants> diff --git a/modules/gltf/doc_classes/PackedSceneGLTF.xml b/modules/gltf/doc_classes/PackedSceneGLTF.xml deleted file mode 100644 index d0136c6402..0000000000 --- a/modules/gltf/doc_classes/PackedSceneGLTF.xml +++ /dev/null @@ -1,43 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="PackedSceneGLTF" inherits="PackedScene" version="4.0"> - <brief_description> - </brief_description> - <description> - </description> - <tutorials> - </tutorials> - <methods> - <method name="export_gltf"> - <return type="int" enum="Error" /> - <argument index="0" name="node" type="Node" /> - <argument index="1" name="path" type="String" /> - <argument index="2" name="flags" type="int" default="0" /> - <argument index="3" name="bake_fps" type="float" default="1000.0" /> - <description> - </description> - </method> - <method name="import_gltf_scene"> - <return type="Node" /> - <argument index="0" name="path" type="String" /> - <argument index="1" name="flags" type="int" default="0" /> - <argument index="2" name="bake_fps" type="float" default="1000.0" /> - <argument index="3" name="state" type="GLTFState" default="null" /> - <description> - </description> - </method> - <method name="pack_gltf"> - <return type="void" /> - <argument index="0" name="path" type="String" /> - <argument index="1" name="flags" type="int" default="0" /> - <argument index="2" name="bake_fps" type="float" default="1000.0" /> - <argument index="3" name="state" type="GLTFState" default="null" /> - <description> - </description> - </method> - </methods> - <members> - <member name="_bundled" type="Dictionary" setter="_set_bundled_scene" getter="_get_bundled_scene" override="true" default="{"conn_count": 0,"conns": PackedInt32Array(),"editable_instances": [],"names": PackedStringArray(),"node_count": 0,"node_paths": [],"nodes": PackedInt32Array(),"variants": [],"version": 2}" /> - </members> - <constants> - </constants> -</class> diff --git a/modules/gltf/editor_scene_exporter_gltf_plugin.cpp b/modules/gltf/editor_scene_exporter_gltf_plugin.cpp index ae080bcc9a..fd9f758f10 100644 --- a/modules/gltf/editor_scene_exporter_gltf_plugin.cpp +++ b/modules/gltf/editor_scene_exporter_gltf_plugin.cpp @@ -30,9 +30,11 @@ #include "editor_scene_exporter_gltf_plugin.h" #include "core/config/project_settings.h" +#include "core/error/error_list.h" #include "core/object/object.h" #include "core/templates/vector.h" #include "editor/editor_file_system.h" +#include "gltf_document.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/gui/check_box.h" #include "scene/main/node.h" @@ -49,7 +51,6 @@ bool SceneExporterGLTFPlugin::has_main_screen() const { SceneExporterGLTFPlugin::SceneExporterGLTFPlugin(EditorNode *p_node) { editor = p_node; - convert_gltf2.instantiate(); file_export_lib = memnew(EditorFileDialog); editor->get_gui_base()->add_child(file_export_lib); file_export_lib->connect("file_selected", callable_mp(this, &SceneExporterGLTFPlugin::_gltf2_dialog_action)); @@ -71,8 +72,12 @@ void SceneExporterGLTFPlugin::_gltf2_dialog_action(String p_file) { return; } List<String> deps; - convert_gltf2->save_scene(root, p_file, p_file, 0, 1000.0f, &deps); - EditorFileSystem::get_singleton()->scan_changes(); + Ref<GLTFDocument> doc; + doc.instantiate(); + Error err = doc->save_scene(root, p_file, p_file, 0, 30.0f, Ref<GLTFState>()); + if (err != OK) { + ERR_PRINT(vformat("glTF2 save scene error %s.", itos(err))); + } } void SceneExporterGLTFPlugin::convert_scene_to_gltf2() { diff --git a/modules/gltf/editor_scene_exporter_gltf_plugin.h b/modules/gltf/editor_scene_exporter_gltf_plugin.h index d952894c16..c4f277fca2 100644 --- a/modules/gltf/editor_scene_exporter_gltf_plugin.h +++ b/modules/gltf/editor_scene_exporter_gltf_plugin.h @@ -37,7 +37,6 @@ class SceneExporterGLTFPlugin : public EditorPlugin { GDCLASS(SceneExporterGLTFPlugin, EditorPlugin); - Ref<PackedSceneGLTF> convert_gltf2; EditorNode *editor = nullptr; EditorFileDialog *file_export_lib = nullptr; void _gltf2_dialog_action(String p_file); diff --git a/modules/gltf/editor_scene_importer_gltf.cpp b/modules/gltf/editor_scene_importer_gltf.cpp index eca1c85bf3..12796c41d7 100644 --- a/modules/gltf/editor_scene_importer_gltf.cpp +++ b/modules/gltf/editor_scene_importer_gltf.cpp @@ -50,9 +50,9 @@ Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { - Ref<PackedSceneGLTF> importer; - importer.instantiate(); - return importer->import_scene(p_path, p_flags, p_bake_fps, r_missing_deps, r_err, Ref<GLTFState>()); + Ref<GLTFDocument> doc; + doc.instantiate(); + return doc->import_scene_gltf(p_path, p_flags, p_bake_fps, Ref<GLTFState>(), r_missing_deps, r_err); } Ref<Animation> EditorSceneImporterGLTF::import_animation(const String &p_path, @@ -60,114 +60,3 @@ Ref<Animation> EditorSceneImporterGLTF::import_animation(const String &p_path, int p_bake_fps) { return Ref<Animation>(); } - -void PackedSceneGLTF::_bind_methods() { - ClassDB::bind_method( - D_METHOD("export_gltf", "node", "path", "flags", "bake_fps"), - &PackedSceneGLTF::export_gltf, DEFVAL(0), DEFVAL(1000.0f)); - ClassDB::bind_method(D_METHOD("pack_gltf", "path", "flags", "bake_fps", "state"), - &PackedSceneGLTF::pack_gltf, DEFVAL(0), DEFVAL(1000.0f), DEFVAL(Ref<GLTFState>())); - ClassDB::bind_method(D_METHOD("import_gltf_scene", "path", "flags", "bake_fps", "state"), - &PackedSceneGLTF::import_gltf_scene, DEFVAL(0), DEFVAL(1000.0f), DEFVAL(Ref<GLTFState>())); -} -Node *PackedSceneGLTF::import_gltf_scene(const String &p_path, uint32_t p_flags, float p_bake_fps, Ref<GLTFState> r_state) { - Error err = FAILED; - List<String> deps; - return import_scene(p_path, p_flags, p_bake_fps, &deps, &err, r_state); -} - -Node *PackedSceneGLTF::import_scene(const String &p_path, uint32_t p_flags, - int p_bake_fps, - List<String> *r_missing_deps, - Error *r_err, - Ref<GLTFState> r_state) { - if (r_state == Ref<GLTFState>()) { - r_state.instantiate(); - } - r_state->use_named_skin_binds = - p_flags & EditorSceneImporter::IMPORT_USE_NAMED_SKIN_BINDS; - - Ref<GLTFDocument> gltf_document; - gltf_document.instantiate(); - Error err = gltf_document->parse(r_state, p_path); - if (r_err) { - *r_err = err; - } - ERR_FAIL_COND_V(err != Error::OK, nullptr); - - Node3D *root = memnew(Node3D); - for (int32_t root_i = 0; root_i < r_state->root_nodes.size(); root_i++) { - gltf_document->_generate_scene_node(r_state, root, root, r_state->root_nodes[root_i]); - } - gltf_document->_process_mesh_instances(r_state, root); - if (r_state->animations.size()) { - AnimationPlayer *ap = memnew(AnimationPlayer); - root->add_child(ap); - ap->set_owner(root); - for (int i = 0; i < r_state->animations.size(); i++) { - gltf_document->_import_animation(r_state, ap, i, p_bake_fps); - } - } - - return cast_to<Node3D>(root); -} - -void PackedSceneGLTF::pack_gltf(String p_path, int32_t p_flags, - real_t p_bake_fps, Ref<GLTFState> r_state) { - Error err = FAILED; - List<String> deps; - Node *root = import_scene(p_path, p_flags, p_bake_fps, &deps, &err, r_state); - ERR_FAIL_COND(err != OK); - pack(root); -} - -void PackedSceneGLTF::save_scene(Node *p_node, const String &p_path, - const String &p_src_path, uint32_t p_flags, - int p_bake_fps, List<String> *r_missing_deps, - Error *r_err) { - Error err = FAILED; - if (r_err) { - *r_err = err; - } - Ref<GLTFDocument> gltf_document; - gltf_document.instantiate(); - Ref<GLTFState> state; - state.instantiate(); - err = gltf_document->serialize(state, p_node, p_path); - if (r_err) { - *r_err = err; - } -} - -void PackedSceneGLTF::_build_parent_hierachy(Ref<GLTFState> state) { - // build the hierarchy - for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) { - for (int j = 0; j < state->nodes[node_i]->children.size(); j++) { - GLTFNodeIndex child_i = state->nodes[node_i]->children[j]; - ERR_FAIL_INDEX(child_i, state->nodes.size()); - if (state->nodes.write[child_i]->parent != -1) { - continue; - } - state->nodes.write[child_i]->parent = node_i; - } - } -} - -Error PackedSceneGLTF::export_gltf(Node *p_root, String p_path, - int32_t p_flags, - real_t p_bake_fps) { - ERR_FAIL_COND_V(!p_root, FAILED); - List<String> deps; - Error err; - String path = p_path; - int32_t flags = p_flags; - real_t baked_fps = p_bake_fps; - Ref<PackedSceneGLTF> exporter; - exporter.instantiate(); - exporter->save_scene(p_root, path, "", flags, baked_fps, &deps, &err); - int32_t error_code = err; - if (error_code != 0) { - return Error(error_code); - } - return OK; -} diff --git a/modules/gltf/editor_scene_importer_gltf.h b/modules/gltf/editor_scene_importer_gltf.h index 7bc5f594ed..eb8775b137 100644 --- a/modules/gltf/editor_scene_importer_gltf.h +++ b/modules/gltf/editor_scene_importer_gltf.h @@ -46,35 +46,9 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, - int p_bake_fps, - List<String> *r_missing_deps = nullptr, - Error *r_err = nullptr) override; + virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) override; }; #endif - -class PackedSceneGLTF : public PackedScene { - GDCLASS(PackedSceneGLTF, PackedScene); - -protected: - static void _bind_methods(); - -public: - virtual void save_scene(Node *p_node, const String &p_path, const String &p_src_path, - uint32_t p_flags, int p_bake_fps, - List<String> *r_missing_deps, Error *r_err = nullptr); - virtual void _build_parent_hierachy(Ref<GLTFState> state); - virtual Error export_gltf(Node *p_root, String p_path, int32_t p_flags = 0, - real_t p_bake_fps = 1000.0f); - virtual Node *import_scene(const String &p_path, uint32_t p_flags, - int p_bake_fps, - List<String> *r_missing_deps, - Error *r_err, - Ref<GLTFState> r_state); - virtual Node *import_gltf_scene(const String &p_path, uint32_t p_flags, float p_bake_fps, Ref<GLTFState> r_state = Ref<GLTFState>()); - virtual void pack_gltf(String p_path, int32_t p_flags = 0, - real_t p_bake_fps = 1000.0f, Ref<GLTFState> r_state = Ref<GLTFState>()); -}; #endif // EDITOR_SCENE_IMPORTER_GLTF_H diff --git a/modules/gltf/gltf_accessor.h b/modules/gltf/gltf_accessor.h index 949a601730..57aea1026c 100644 --- a/modules/gltf/gltf_accessor.h +++ b/modules/gltf/gltf_accessor.h @@ -44,8 +44,7 @@ private: int component_type = 0; bool normalized = false; int count = 0; - GLTFDocument::GLTFType - type = GLTFDocument::TYPE_SCALAR; + GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR; Vector<double> min; Vector<double> max; int sparse_count = 0; diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index ff0579a11c..db324e23b7 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -48,6 +48,7 @@ #include "core/io/file_access.h" #include "core/io/json.h" #include "core/math/disjoint_set.h" +#include "core/math/vector2.h" #include "core/variant/typed_array.h" #include "core/variant/variant.h" #include "core/version.h" @@ -61,6 +62,7 @@ #include "scene/resources/surface_tool.h" #include "modules/modules_enabled.gen.h" + #ifdef MODULE_CSG_ENABLED #include "modules/csg/csg_shape.h" #endif // MODULE_CSG_ENABLED @@ -70,6 +72,7 @@ #include <stdio.h> #include <stdlib.h> +#include <cstdint> #include <limits> Error GLTFDocument::serialize(Ref<GLTFState> state, Node *p_root, const String &p_path) { @@ -2170,11 +2173,14 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { } Array array = import_mesh->get_surface_arrays(surface_i); + uint32_t format = import_mesh->get_surface_format(surface_i); + int32_t vertex_num = 0; Dictionary attributes; { Vector<Vector3> a = array[Mesh::ARRAY_VERTEX]; ERR_FAIL_COND_V(!a.size(), ERR_INVALID_DATA); attributes["POSITION"] = _encode_accessor_as_vec3(state, a, true); + vertex_num = a.size(); } { Vector<real_t> a = array[Mesh::ARRAY_TANGENT]; @@ -2217,6 +2223,58 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { attributes["TEXCOORD_1"] = _encode_accessor_as_vec2(state, a, true); } } + for (int custom_i = 0; custom_i < 3; custom_i++) { + Vector<float> a = array[Mesh::ARRAY_CUSTOM0 + custom_i]; + if (a.size()) { + int num_channels = 4; + int custom_shift = Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT + custom_i * Mesh::ARRAY_FORMAT_CUSTOM_BITS; + switch ((format >> custom_shift) & Mesh::ARRAY_FORMAT_CUSTOM_MASK) { + case Mesh::ARRAY_CUSTOM_R_FLOAT: + num_channels = 1; + break; + case Mesh::ARRAY_CUSTOM_RG_FLOAT: + num_channels = 2; + break; + case Mesh::ARRAY_CUSTOM_RGB_FLOAT: + num_channels = 3; + break; + case Mesh::ARRAY_CUSTOM_RGBA_FLOAT: + num_channels = 4; + break; + } + int texcoord_i = 2 + 2 * custom_i; + String gltf_texcoord_key; + for (int prev_texcoord_i = 0; prev_texcoord_i < texcoord_i; prev_texcoord_i++) { + gltf_texcoord_key = vformat("TEXCOORD_%d", prev_texcoord_i); + if (!attributes.has(gltf_texcoord_key)) { + Vector<Vector2> empty; + empty.resize(vertex_num); + attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, empty, true); + } + } + + LocalVector<Vector2> first_channel; + first_channel.resize(vertex_num); + LocalVector<Vector2> second_channel; + second_channel.resize(vertex_num); + for (int32_t vert_i = 0; vert_i < vertex_num; vert_i++) { + float u = a[vert_i * num_channels + 0]; + float v = (num_channels == 1 ? 0.0f : a[vert_i * num_channels + 1]); + first_channel[vert_i] = Vector2(u, v); + u = 0; + v = 0; + if (num_channels >= 3) { + u = a[vert_i * num_channels + 2]; + v = (num_channels == 3 ? 0.0f : a[vert_i * num_channels + 3]); + second_channel[vert_i] = Vector2(u, v); + } + } + gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i); + attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, first_channel, true); + gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1); + attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, second_channel, true); + } + } { Vector<Color> a = array[Mesh::ARRAY_COLOR]; if (a.size()) { @@ -2252,13 +2310,12 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { } attributes["JOINTS_0"] = _encode_accessor_as_joints(state, attribs, true); } else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) { - int32_t vertex_count = vertex_array.size(); Vector<Color> joints_0; - joints_0.resize(vertex_count); + joints_0.resize(vertex_num); Vector<Color> joints_1; - joints_1.resize(vertex_count); + joints_1.resize(vertex_num); int32_t weights_8_count = JOINT_GROUP_SIZE * 2; - for (int32_t vertex_i = 0; vertex_i < vertex_count; vertex_i++) { + for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) { Color joint_0; joint_0.r = a[vertex_i * weights_8_count + 0]; joint_0.g = a[vertex_i * weights_8_count + 1]; @@ -2288,13 +2345,12 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { } attributes["WEIGHTS_0"] = _encode_accessor_as_weights(state, attribs, true); } else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) { - int32_t vertex_count = vertex_array.size(); Vector<Color> weights_0; - weights_0.resize(vertex_count); + weights_0.resize(vertex_num); Vector<Color> weights_1; - weights_1.resize(vertex_count); + weights_1.resize(vertex_num); int32_t weights_8_count = JOINT_GROUP_SIZE * 2; - for (int32_t vertex_i = 0; vertex_i < vertex_count; vertex_i++) { + for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) { Color weight_0; weight_0.r = a[vertex_i * weights_8_count + 0]; weight_0.g = a[vertex_i * weights_8_count + 1]; @@ -2458,7 +2514,8 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { ERR_FAIL_COND_V(!d.has("primitives"), ERR_PARSE_ERROR); Array primitives = d["primitives"]; - const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] : Dictionary(); + const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] : + Dictionary(); Ref<EditorSceneImporterMesh> import_mesh; import_mesh.instantiate(); String mesh_name = "mesh"; @@ -2468,6 +2525,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { import_mesh->set_name(_gen_unique_name(state, vformat("%s_%s", state->scene_name, mesh_name))); for (int j = 0; j < primitives.size(); j++) { + uint32_t flags = 0; Dictionary p = primitives[j]; Array array; @@ -2499,8 +2557,11 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { } ERR_FAIL_COND_V(!a.has("POSITION"), ERR_PARSE_ERROR); + int32_t vertex_num = 0; if (a.has("POSITION")) { - array[Mesh::ARRAY_VERTEX] = _decode_accessor_as_vec3(state, a["POSITION"], true); + PackedVector3Array vertices = _decode_accessor_as_vec3(state, a["POSITION"], true); + array[Mesh::ARRAY_VERTEX] = vertices; + vertex_num = vertices.size(); } if (a.has("NORMAL")) { array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(state, a["NORMAL"], true); @@ -2514,6 +2575,60 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { if (a.has("TEXCOORD_1")) { array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(state, a["TEXCOORD_1"], true); } + for (int custom_i = 0; custom_i < 3; custom_i++) { + Vector<float> cur_custom; + Vector<Vector2> texcoord_first; + Vector<Vector2> texcoord_second; + + int texcoord_i = 2 + 2 * custom_i; + String gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i); + int num_channels = 0; + if (a.has(gltf_texcoord_key)) { + texcoord_first = _decode_accessor_as_vec2(state, a[gltf_texcoord_key], true); + num_channels = 2; + } + gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1); + if (a.has(gltf_texcoord_key)) { + texcoord_second = _decode_accessor_as_vec2(state, a[gltf_texcoord_key], true); + num_channels = 4; + } + if (!num_channels) { + break; + } + if (num_channels == 2 || num_channels == 4) { + cur_custom.resize(vertex_num * num_channels); + for (int32_t uv_i = 0; uv_i < texcoord_first.size() && uv_i < vertex_num; uv_i++) { + cur_custom.write[uv_i * num_channels + 0] = texcoord_first[uv_i].x; + cur_custom.write[uv_i * num_channels + 1] = texcoord_first[uv_i].y; + } + // Vector.resize seems to not zero-initialize. Ensure all unused elements are 0: + for (int32_t uv_i = texcoord_first.size(); uv_i < vertex_num; uv_i++) { + cur_custom.write[uv_i * num_channels + 0] = 0; + cur_custom.write[uv_i * num_channels + 1] = 0; + } + } + if (num_channels == 4) { + for (int32_t uv_i = 0; uv_i < texcoord_second.size() && uv_i < vertex_num; uv_i++) { + // num_channels must be 4 + cur_custom.write[uv_i * num_channels + 2] = texcoord_second[uv_i].x; + cur_custom.write[uv_i * num_channels + 3] = texcoord_second[uv_i].y; + } + // Vector.resize seems to not zero-initialize. Ensure all unused elements are 0: + for (int32_t uv_i = texcoord_second.size(); uv_i < vertex_num; uv_i++) { + cur_custom.write[uv_i * num_channels + 2] = 0; + cur_custom.write[uv_i * num_channels + 3] = 0; + } + } + if (cur_custom.size() > 0) { + array[Mesh::ARRAY_CUSTOM0 + custom_i] = cur_custom; + int custom_shift = Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT + custom_i * Mesh::ARRAY_FORMAT_CUSTOM_BITS; + if (num_channels == 2) { + flags |= Mesh::ARRAY_CUSTOM_RG_FLOAT << custom_shift; + } else { + flags |= Mesh::ARRAY_CUSTOM_RGBA_FLOAT << custom_shift; + } + } + } if (a.has("COLOR_0")) { array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(state, a["COLOR_0"], true); has_vertex_color = true; @@ -2525,10 +2640,9 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { PackedInt32Array joints_1 = _decode_accessor_as_ints(state, a["JOINTS_1"], true); ERR_FAIL_COND_V(joints_0.size() != joints_0.size(), ERR_INVALID_DATA); int32_t weight_8_count = JOINT_GROUP_SIZE * 2; - int32_t vertex_count = joints_0.size() / JOINT_GROUP_SIZE; Vector<int> joints; - joints.resize(vertex_count * weight_8_count); - for (int32_t vertex_i = 0; vertex_i < vertex_count; vertex_i++) { + joints.resize(vertex_num * weight_8_count); + for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) { joints.write[vertex_i * weight_8_count + 0] = joints_0[vertex_i * JOINT_GROUP_SIZE + 0]; joints.write[vertex_i * weight_8_count + 1] = joints_0[vertex_i * JOINT_GROUP_SIZE + 1]; joints.write[vertex_i * weight_8_count + 2] = joints_0[vertex_i * JOINT_GROUP_SIZE + 2]; @@ -2567,9 +2681,8 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { Vector<float> weights; ERR_FAIL_COND_V(weights_0.size() != weights_1.size(), ERR_INVALID_DATA); int32_t weight_8_count = JOINT_GROUP_SIZE * 2; - int32_t vertex_count = weights_0.size() / JOINT_GROUP_SIZE; - weights.resize(vertex_count * weight_8_count); - for (int32_t vertex_i = 0; vertex_i < vertex_count; vertex_i++) { + weights.resize(vertex_num * weight_8_count); + for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) { weights.write[vertex_i * weight_8_count + 0] = weights_0[vertex_i * JOINT_GROUP_SIZE + 0]; weights.write[vertex_i * weight_8_count + 1] = weights_0[vertex_i * JOINT_GROUP_SIZE + 1]; weights.write[vertex_i * weight_8_count + 2] = weights_0[vertex_i * JOINT_GROUP_SIZE + 2]; @@ -2797,7 +2910,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { mat = mat3d; } - import_mesh->add_surface(primitive, array, morphs, Dictionary(), mat, mat.is_valid() ? mat->get_name() : String()); + import_mesh->add_surface(primitive, array, morphs, Dictionary(), mat, mat.is_valid() ? mat->get_name() : String(), flags); } Vector<float> blend_weights; @@ -2953,6 +3066,7 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat } } } else { // Relative path to an external image file. + uri = uri.uri_decode(); uri = p_base_path.plus_file(uri).replace("\\", "/"); // Fix for Windows. // ResourceLoader will rely on the file extension to use the relevant loader. // The spec says that if mimeType is defined, it should take precedence (e.g. @@ -4896,7 +5010,7 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_instance(Ref<GLTFState> state, MeshIns if (p_mesh_instance->get_material_override().is_valid()) { mat = p_mesh_instance->get_material_override(); } - import_mesh->add_surface(primitive_type, arrays, blend_shape_arrays, Dictionary(), mat, surface_name); + import_mesh->add_surface(primitive_type, arrays, blend_shape_arrays, Dictionary(), mat, surface_name, godot_mesh->surface_get_format(surface_i)); } for (int32_t blend_i = 0; blend_i < blend_count; blend_i++) { blend_weights.write[blend_i] = 0.0f; @@ -6630,3 +6744,78 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) { } return err; } + +Error GLTFDocument::save_scene(Node *p_node, const String &p_path, + const String &p_src_path, uint32_t p_flags, + float p_bake_fps, Ref<GLTFState> r_state) { + Ref<GLTFDocument> gltf_document; + gltf_document.instantiate(); + if (r_state == Ref<GLTFState>()) { + r_state.instantiate(); + } + return gltf_document->serialize(r_state, p_node, p_path); +} + +Node *GLTFDocument::import_scene_gltf(const String &p_path, uint32_t p_flags, int32_t p_bake_fps, Ref<GLTFState> r_state, List<String> *r_missing_deps, Error *r_err) { + // TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire + if (r_state == Ref<GLTFState>()) { + r_state.instantiate(); + } + r_state->use_named_skin_binds = + p_flags & EditorSceneImporter::IMPORT_USE_NAMED_SKIN_BINDS; + + Ref<GLTFDocument> gltf_document; + gltf_document.instantiate(); + Error err = gltf_document->parse(r_state, p_path); + if (r_err) { + *r_err = err; + } + ERR_FAIL_COND_V(err != Error::OK, nullptr); + + Node3D *root = memnew(Node3D); + for (int32_t root_i = 0; root_i < r_state->root_nodes.size(); root_i++) { + gltf_document->_generate_scene_node(r_state, root, root, r_state->root_nodes[root_i]); + } + gltf_document->_process_mesh_instances(r_state, root); + if (r_state->animations.size()) { + AnimationPlayer *ap = memnew(AnimationPlayer); + root->add_child(ap); + ap->set_owner(root); + for (int i = 0; i < r_state->animations.size(); i++) { + gltf_document->_import_animation(r_state, ap, i, p_bake_fps); + } + } + + return root; +} + +void GLTFDocument::_bind_methods() { + ClassDB::bind_method(D_METHOD("save_scene", "node", "path", "src_path", "flags", "bake_fps", "state"), + &GLTFDocument::save_scene, DEFVAL(0), DEFVAL(30), DEFVAL(Ref<GLTFState>())); + ClassDB::bind_method(D_METHOD("import_scene", "path", "flags", "bake_fps", "state"), + &GLTFDocument::import_scene, DEFVAL(0), DEFVAL(30), DEFVAL(Ref<GLTFState>())); +} + +void GLTFDocument::_build_parent_hierachy(Ref<GLTFState> state) { + // build the hierarchy + for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) { + for (int j = 0; j < state->nodes[node_i]->children.size(); j++) { + GLTFNodeIndex child_i = state->nodes[node_i]->children[j]; + ERR_FAIL_INDEX(child_i, state->nodes.size()); + if (state->nodes.write[child_i]->parent != -1) { + continue; + } + state->nodes.write[child_i]->parent = node_i; + } + } +} + +Node *GLTFDocument::import_scene(const String &p_path, uint32_t p_flags, int32_t p_bake_fps, Ref<GLTFState> r_state) { + Error err = FAILED; + List<String> deps; + Node *node = import_scene_gltf(p_path, p_flags, p_bake_fps, r_state, &deps, &err); + if (err != OK) { + return nullptr; + } + return node; +} diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index 3e8ea19045..fb798a055a 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -44,6 +44,7 @@ #include "scene/resources/texture.h" #include "modules/modules_enabled.gen.h" +#include <cstdint> class GLTFState; class GLTFSkin; @@ -102,6 +103,16 @@ public: COMPONENT_TYPE_FLOAT = 5126, }; +protected: + static void _bind_methods(); + +public: + Node *import_scene(const String &p_path, uint32_t p_flags, int32_t p_bake_fps, Ref<GLTFState> r_state); + Node *import_scene_gltf(const String &p_path, uint32_t p_flags, int32_t p_bake_fps, Ref<GLTFState> r_state, List<String> *r_missing_deps, Error *r_err = nullptr); + Error save_scene(Node *p_node, const String &p_path, + const String &p_src_path, uint32_t p_flags, + float p_bake_fps, Ref<GLTFState> r_state); + private: template <class T> static Array to_array(const Vector<T> &p_inp) { @@ -155,6 +166,7 @@ private: r_out[keys[i]] = p_inp[keys[i]]; } } + void _build_parent_hierachy(Ref<GLTFState> state); double _filter_number(double p_float); String _get_component_type_name(const uint32_t p_component); int _get_component_type_size(const int component_type); @@ -346,8 +358,8 @@ private: Error _serialize_extensions(Ref<GLTFState> state) const; public: - // http://www.itu.int/rec/R-REC-BT.601 - // http://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-7-201103-I!!PDF-E.pdf + // https://www.itu.int/rec/R-REC-BT.601 + // https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-7-201103-I!!PDF-E.pdf static constexpr float R_BRIGHTNESS_COEFF = 0.299f; static constexpr float G_BRIGHTNESS_COEFF = 0.587f; static constexpr float B_BRIGHTNESS_COEFF = 0.114f; diff --git a/modules/gltf/gltf_node.h b/modules/gltf/gltf_node.h index 378b6da8bf..eca3acb239 100644 --- a/modules/gltf/gltf_node.h +++ b/modules/gltf/gltf_node.h @@ -37,7 +37,6 @@ class GLTFNode : public Resource { GDCLASS(GLTFNode, Resource); friend class GLTFDocument; - friend class PackedSceneGLTF; private: // matrices need to be transformed to this diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index d8209523c5..896ea5fc56 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -51,7 +51,6 @@ class GLTFState : public Resource { GDCLASS(GLTFState, Resource); friend class GLTFDocument; - friend class PackedSceneGLTF; String filename; Dictionary json; diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp index 85921490d2..d6020f50f0 100644 --- a/modules/gltf/register_types.cpp +++ b/modules/gltf/register_types.cpp @@ -80,7 +80,6 @@ void register_gltf_types() { GDREGISTER_CLASS(GLTFLight); GDREGISTER_CLASS(GLTFState); GDREGISTER_CLASS(GLTFDocument); - GDREGISTER_CLASS(PackedSceneGLTF); #endif } |