diff options
Diffstat (limited to 'modules/gltf')
-rw-r--r-- | modules/gltf/doc_classes/GLTFState.xml | 5 | ||||
-rw-r--r-- | modules/gltf/editor/editor_scene_importer_blend.cpp | 3 | ||||
-rw-r--r-- | modules/gltf/gltf_document.cpp | 17 | ||||
-rw-r--r-- | modules/gltf/gltf_state.cpp | 11 | ||||
-rw-r--r-- | modules/gltf/gltf_state.h | 4 | ||||
-rw-r--r-- | modules/gltf/skin_tool.cpp | 13 | ||||
-rw-r--r-- | modules/gltf/skin_tool.h | 3 |
7 files changed, 52 insertions, 4 deletions
diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml index 100750f400..6c7c5ee0e6 100644 --- a/modules/gltf/doc_classes/GLTFState.xml +++ b/modules/gltf/doc_classes/GLTFState.xml @@ -289,8 +289,13 @@ The file name associated with this GLTF data. If it ends with [code].gltf[/code], this is text-based GLTF, otherwise this is binary GLB. This will be set during import when appending from a file, and will be set during export when writing to a file. If writing to a buffer, this will be an empty string. </member> <member name="glb_data" type="PackedByteArray" setter="set_glb_data" getter="get_glb_data" default="PackedByteArray()"> + The binary buffer attached to a .glb file. + </member> + <member name="import_as_skeleton_bones" type="bool" setter="set_import_as_skeleton_bones" getter="get_import_as_skeleton_bones" default="false"> + True to force all GLTFNodes in the document to be bones of a single Skeleton3D godot node. </member> <member name="json" type="Dictionary" setter="set_json" getter="get_json" default="{}"> + The original raw JSON document corresponding to this GLTFState. </member> <member name="major_version" type="int" setter="set_major_version" getter="get_major_version" default="0"> </member> diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index a91856c4a1..c6e92de762 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -287,6 +287,9 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ if (p_options.has(SNAME("blender/materials/unpack_enabled")) && p_options[SNAME("blender/materials/unpack_enabled")]) { base_dir = sink.get_base_dir(); } + if (p_options.has(SNAME("nodes/import_as_skeleton_bones")) ? (bool)p_options[SNAME("nodes/import_as_skeleton_bones")] : false) { + state->set_import_as_skeleton_bones(true); + } state->set_scene_name(blend_basename); err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, base_dir); if (err != OK) { diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 740c9a2aa7..0ed2100041 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -2796,7 +2796,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) { Vector<Vector3> normals = array[Mesh::ARRAY_NORMAL]; for (int k = 0; k < vertex_num; k++) { - Vector3 tan = Vector3(0.0, 1.0, 0.0).cross(normals[k]); + Vector3 tan = Vector3(normals[i].z, -normals[i].x, normals[i].y).cross(normals[k].normalized()).normalized(); tangentsw[k * 4 + 0] = tan.x; tangentsw[k * 4 + 1] = tan.y; tangentsw[k * 4 + 2] = tan.z; @@ -2822,6 +2822,19 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) { } array = mesh_surface_tool->commit_to_arrays(); + if ((flags & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && a.has("NORMAL") && (a.has("TANGENT") || generate_tangents)) { + // Compression is enabled, so let's validate that the normals and tangents are correct. + Vector<Vector3> normals = array[Mesh::ARRAY_NORMAL]; + Vector<float> tangents = array[Mesh::ARRAY_TANGENT]; + for (int vert = 0; vert < normals.size(); vert++) { + Vector3 tan = Vector3(tangents[vert * 4 + 0], tangents[vert * 4 + 1], tangents[vert * 4 + 2]); + if (abs(tan.dot(normals[vert])) > 0.0001) { + // Tangent is not perpendicular to the normal, so we can't use compression. + flags &= ~RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES; + } + } + } + Array morphs; //blend shapes if (p.has("targets")) { @@ -6924,7 +6937,7 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> p_state, const String &p_se ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* DETERMINE SKELETONS */ - err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons); + err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons, p_state->get_import_as_skeleton_bones() ? p_state->root_nodes : Vector<GLTFNodeIndex>()); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE MESHES (we have enough info now) */ diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index 0c47d5777c..ed31aadc01 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -90,6 +90,8 @@ void GLTFState::_bind_methods() { ClassDB::bind_method(D_METHOD("set_skeletons", "skeletons"), &GLTFState::set_skeletons); ClassDB::bind_method(D_METHOD("get_create_animations"), &GLTFState::get_create_animations); ClassDB::bind_method(D_METHOD("set_create_animations", "create_animations"), &GLTFState::set_create_animations); + ClassDB::bind_method(D_METHOD("get_import_as_skeleton_bones"), &GLTFState::get_import_as_skeleton_bones); + ClassDB::bind_method(D_METHOD("set_import_as_skeleton_bones", "import_as_skeleton_bones"), &GLTFState::set_import_as_skeleton_bones); ClassDB::bind_method(D_METHOD("get_animations"), &GLTFState::get_animations); ClassDB::bind_method(D_METHOD("set_animations", "animations"), &GLTFState::set_animations); ClassDB::bind_method(D_METHOD("get_scene_node", "idx"), &GLTFState::get_scene_node); @@ -125,6 +127,7 @@ void GLTFState::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_animation_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_animation_names", "get_unique_animation_names"); // Set<String> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skeletons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeletons", "get_skeletons"); // Vector<Ref<GLTFSkeleton>> ADD_PROPERTY(PropertyInfo(Variant::BOOL, "create_animations"), "set_create_animations", "get_create_animations"); // bool + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "import_as_skeleton_bones"), "set_import_as_skeleton_bones", "get_import_as_skeleton_bones"); // bool ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_animations", "get_animations"); // Vector<Ref<GLTFAnimation>> ADD_PROPERTY(PropertyInfo(Variant::INT, "handle_binary_image", PROPERTY_HINT_ENUM, "Discard All Textures,Extract Textures,Embed as Basis Universal,Embed as Uncompressed", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_handle_binary_image", "get_handle_binary_image"); // enum @@ -337,6 +340,14 @@ void GLTFState::set_create_animations(bool p_create_animations) { create_animations = p_create_animations; } +bool GLTFState::get_import_as_skeleton_bones() { + return import_as_skeleton_bones; +} + +void GLTFState::set_import_as_skeleton_bones(bool p_import_as_skeleton_bones) { + import_as_skeleton_bones = p_import_as_skeleton_bones; +} + TypedArray<GLTFAnimation> GLTFState::get_animations() { return GLTFTemplateConvert::to_array(animations); } diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index c7171e0e68..c9efffa3ae 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -64,6 +64,7 @@ protected: bool force_generate_tangents = false; bool create_animations = true; bool force_disable_compression = false; + bool import_as_skeleton_bones = false; int handle_binary_image = HANDLE_BINARY_EXTRACT_TEXTURES; @@ -213,6 +214,9 @@ public: bool get_create_animations(); void set_create_animations(bool p_create_animations); + bool get_import_as_skeleton_bones(); + void set_import_as_skeleton_bones(bool p_import_as_skeleton_bones); + TypedArray<GLTFAnimation> get_animations(); void set_animations(TypedArray<GLTFAnimation> p_animations); diff --git a/modules/gltf/skin_tool.cpp b/modules/gltf/skin_tool.cpp index a008e870e6..2fb55a5f9e 100644 --- a/modules/gltf/skin_tool.cpp +++ b/modules/gltf/skin_tool.cpp @@ -285,7 +285,18 @@ void SkinTool::_recurse_children( Error SkinTool::_determine_skeletons( Vector<Ref<GLTFSkin>> &skins, Vector<Ref<GLTFNode>> &nodes, - Vector<Ref<GLTFSkeleton>> &skeletons) { + Vector<Ref<GLTFSkeleton>> &skeletons, + const Vector<GLTFNodeIndex> &p_single_skeleton_roots) { + if (!p_single_skeleton_roots.is_empty()) { + Ref<GLTFSkin> skin; + skin.instantiate(); + skin->set_name("godot_single_skeleton_root"); + for (GLTFNodeIndex i = 0; i < p_single_skeleton_roots.size(); i++) { + skin->joints.push_back(p_single_skeleton_roots[i]); + } + skins.push_back(skin); + } + // Using a disjoint set, we are going to potentially combine all skins that are actually branches // of a main skeleton, or treat skins defining the same set of nodes as ONE skeleton. // This is another unclear issue caused by the current glTF specification. diff --git a/modules/gltf/skin_tool.h b/modules/gltf/skin_tool.h index 8f7ab011ba..1ba95853f3 100644 --- a/modules/gltf/skin_tool.h +++ b/modules/gltf/skin_tool.h @@ -84,7 +84,8 @@ public: static Error _determine_skeletons( Vector<Ref<GLTFSkin>> &r_skins, Vector<Ref<GLTFNode>> &r_nodes, - Vector<Ref<GLTFSkeleton>> &r_skeletons); + Vector<Ref<GLTFSkeleton>> &r_skeletons, + const Vector<GLTFNodeIndex> &p_single_skeleton_roots); static Error _create_skeletons( HashSet<String> &r_unique_names, Vector<Ref<GLTFSkin>> &r_skins, |