diff --git a/modules/gltf/README.md b/modules/gltf/README.md deleted file mode 100644 index 5d8966b20..000000000 --- a/modules/gltf/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Godot GLTF import and export module - -In a nutshell, the GLTF module works like this: - -* The [`structures/`](structures/) folder contains GLTF structures, the - small pieces that make up a GLTF file, represented as C++ classes. -* The [`extensions/`](extensions/) folder contains GLTF extensions, which - are optional features that build on top of the base GLTF spec. -* [`GLTFState`](gltf_state.h) holds collections of structures and extensions. -* [`GLTFDocument`](gltf_document.h) operates on GLTFState and its elements. -* The [`editor/`](editor/) folder uses GLTFDocument to import and export 3D models. diff --git a/modules/gltf/SCsub b/modules/gltf/SCsub index f3dbc55c4..f23d5675c 100644 --- a/modules/gltf/SCsub +++ b/modules/gltf/SCsub @@ -5,20 +5,5 @@ Import("env_modules") env_gltf = env_modules.Clone() -# Godot source files -env_gltf.add_source_files(env.modules_sources, "register_types.cpp") - -env_gltf.add_source_files(env.modules_sources, "gltf_state.cpp") -env_gltf.add_source_files(env.modules_sources, "gltf_document_extension.cpp") -env_gltf.add_source_files(env.modules_sources, "gltf_document_extension_convert_importer_mesh.cpp") -env_gltf.add_source_files(env.modules_sources, "gltf_document.cpp") - -#env_gltf.add_source_files(env.modules_sources, "*.cpp") - -env_gltf.add_source_files(env.modules_sources, "extensions/*.cpp") -env_gltf.add_source_files(env.modules_sources, "structures/*.cpp") - -if env["tools"]: - env_gltf.add_source_files(env.modules_sources, "editor/editor_scene_importer_gltf.cpp") - env_gltf.add_source_files(env.modules_sources, "editor/editor_scene_importer_fbx.cpp") - #env_gltf.add_source_files(env.modules_sources, "editor/*.cpp") +# Pandemonium's own source files +env_gltf.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/gltf/config.py b/modules/gltf/config.py index 33e9652ae..a4ee871ef 100644 --- a/modules/gltf/config.py +++ b/modules/gltf/config.py @@ -1,8 +1,5 @@ - - def can_build(env, platform): - #return not env["disable_3d"] - return False + return env["tools"] and not env["disable_3d"] def configure(env): @@ -11,16 +8,12 @@ def configure(env): def get_doc_classes(): return [ - "EditorSceneFormatImporterBlend", - "EditorSceneFormatImporterFBX", - "EditorSceneFormatImporterGLTF", + "EditorSceneImporterGLTF", "GLTFAccessor", "GLTFAnimation", "GLTFBufferView", "GLTFCamera", "GLTFDocument", - "GLTFDocumentExtension", - "GLTFDocumentExtensionConvertImporterMesh", "GLTFLight", "GLTFMesh", "GLTFNode", @@ -29,6 +22,7 @@ def get_doc_classes(): "GLTFSpecGloss", "GLTFState", "GLTFTexture", + "PackedSceneGLTF", ] diff --git a/modules/gltf/doc_classes/EditorSceneFormatImporterBlend.xml b/modules/gltf/doc_classes/EditorSceneFormatImporterBlend.xml deleted file mode 100644 index ca8eb9854..000000000 --- a/modules/gltf/doc_classes/EditorSceneFormatImporterBlend.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - Importer for Blender's [code].blend[/code] scene file format. - - - Imports Blender scenes in the [code].blend[/code] file format through the glTF 2.0 3D import pipeline. This importer requires Blender to be installed by the user, so that it can be used to export the scene as glTF 2.0. - The location of the Blender binary is set via the [code]filesystem/import/blender/blender3_path[/code] editor setting. - This importer is only used if [member ProjectSettings.filesystem/import/blender/enabled] is enabled, otherwise [code].blend[/code] files present in the project folder are not imported. - Blend import requires Blender 3.0. - Internally, the EditorSceneFormatImporterBlend uses the Blender glTF "Use Original" mode to reference external textures. - - - - diff --git a/modules/gltf/doc_classes/EditorSceneFormatImporterFBX.xml b/modules/gltf/doc_classes/EditorSceneFormatImporterFBX.xml deleted file mode 100644 index 6754d963f..000000000 --- a/modules/gltf/doc_classes/EditorSceneFormatImporterFBX.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - Importer for the [code].fbx[/code] scene file format. - - - Imports Autodesk FBX 3D scenes by way of converting them to glTF 2.0 using the FBX2glTF command line tool. - The location of the FBX2glTF binary is set via the [code]filesystem/import/fbx/fbx2gltf_path[/code] editor setting. - This importer is only used if [member ProjectSettings.filesystem/import/fbx/enabled] is enabled, otherwise [code].fbx[/code] files present in the project folder are not imported. - - - - diff --git a/modules/gltf/doc_classes/EditorSceneFormatImporterGLTF.xml b/modules/gltf/doc_classes/EditorSceneFormatImporterGLTF.xml deleted file mode 100644 index 5a6a2f52d..000000000 --- a/modules/gltf/doc_classes/EditorSceneFormatImporterGLTF.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/modules/gltf/doc_classes/EditorSceneImporterGLTF.xml b/modules/gltf/doc_classes/EditorSceneImporterGLTF.xml new file mode 100644 index 000000000..60853edc1 --- /dev/null +++ b/modules/gltf/doc_classes/EditorSceneImporterGLTF.xml @@ -0,0 +1,14 @@ + + + + + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [EditorSceneImporterGLTF] within a script will cause an error in an exported project. + + + + + + + + diff --git a/modules/gltf/doc_classes/GLTFAccessor.xml b/modules/gltf/doc_classes/GLTFAccessor.xml index b73a4f8c5..2052ec2ec 100644 --- a/modules/gltf/doc_classes/GLTFAccessor.xml +++ b/modules/gltf/doc_classes/GLTFAccessor.xml @@ -1,11 +1,14 @@ - + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [GLTFAccessor] within a script will cause an error in an exported project. + + @@ -15,9 +18,9 @@ - + - + @@ -36,4 +39,6 @@ + + diff --git a/modules/gltf/doc_classes/GLTFAnimation.xml b/modules/gltf/doc_classes/GLTFAnimation.xml index e2991170a..032794dd8 100644 --- a/modules/gltf/doc_classes/GLTFAnimation.xml +++ b/modules/gltf/doc_classes/GLTFAnimation.xml @@ -1,13 +1,18 @@ - + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [GLTFAnimation] within a script will cause an error in an exported project. + + + + diff --git a/modules/gltf/doc_classes/GLTFBufferView.xml b/modules/gltf/doc_classes/GLTFBufferView.xml index 00b6ccbe7..7ebdc463d 100644 --- a/modules/gltf/doc_classes/GLTFBufferView.xml +++ b/modules/gltf/doc_classes/GLTFBufferView.xml @@ -1,11 +1,14 @@ - + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [GLTFBufferView] within a script will cause an error in an exported project. + + @@ -18,4 +21,6 @@ + + diff --git a/modules/gltf/doc_classes/GLTFCamera.xml b/modules/gltf/doc_classes/GLTFCamera.xml index 9b9eff614..3c8b0a776 100644 --- a/modules/gltf/doc_classes/GLTFCamera.xml +++ b/modules/gltf/doc_classes/GLTFCamera.xml @@ -1,19 +1,24 @@ - + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [GLTFCamera] within a script will cause an error in an exported project. + + - - - - + + + + + + diff --git a/modules/gltf/doc_classes/GLTFDocument.xml b/modules/gltf/doc_classes/GLTFDocument.xml index a79fbd6be..bde28758a 100644 --- a/modules/gltf/doc_classes/GLTFDocument.xml +++ b/modules/gltf/doc_classes/GLTFDocument.xml @@ -1,65 +1,14 @@ - + - Append a glTF2 3d format from a file, buffer or scene and then write to the filesystem, buffer or scene. + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [GLTFDocument] within a script will cause an error in an exported project. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/modules/gltf/doc_classes/GLTFDocumentExtension.xml b/modules/gltf/doc_classes/GLTFDocumentExtension.xml deleted file mode 100644 index 3c28546ad..000000000 --- a/modules/gltf/doc_classes/GLTFDocumentExtension.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/modules/gltf/doc_classes/GLTFDocumentExtensionConvertImporterMesh.xml b/modules/gltf/doc_classes/GLTFDocumentExtensionConvertImporterMesh.xml deleted file mode 100644 index 70268fc0c..000000000 --- a/modules/gltf/doc_classes/GLTFDocumentExtensionConvertImporterMesh.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/modules/gltf/doc_classes/GLTFLight.xml b/modules/gltf/doc_classes/GLTFLight.xml index c8cda9301..7f9f7307d 100644 --- a/modules/gltf/doc_classes/GLTFLight.xml +++ b/modules/gltf/doc_classes/GLTFLight.xml @@ -1,31 +1,36 @@ - + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [GLTFLight] within a script will cause an error in an exported project. + + - + The [Color] of the light. Defaults to white. A black color causes the light to have no effect. The inner angle of the cone in a spotlight. Must be less than or equal to the outer cone angle. - Within this angle, the light is at full brightness. Between the inner and outer cone angles, there is a transition from full brightness to zero brightness. When creating a Godot [SpotLight], the ratio between the inner and outer cone angles is used to calculate the attenuation of the light. + Within this angle, the light is at full brightness. Between the inner and outer cone angles, there is a transition from full brightness to zero brightness. When creating a Pandemonium [SpotLight], the ratio between the inner and outer cone angles is used to calculate the attenuation of the light. - The intensity of the light. This is expressed in candelas (lumens per steradian) for point and spot lights, and lux (lumens per m²) for directional lights. When creating a Godot light, this value is converted to a unitless multiplier. - - - The type of the light. The values accepted by Godot are "point", "spot", and "directional", which correspond to Godot's [OmniLight], [SpotLight], and [DirectionalLight] respectively. + The intensity of the light. This is expressed in candelas (lumens per steradian) for point and spot lights, and lux (lumens per m²) for directional lights. When creating a Pandemonium light, this value is converted to a unitless multiplier. The outer angle of the cone in a spotlight. Must be greater than or equal to the inner angle. - At this angle, the light drops off to zero brightness. Between the inner and outer cone angles, there is a transition from full brightness to zero brightness. If this angle is a half turn, then the spotlight emits in all directions. When creating a Godot [SpotLight], the outer cone angle is used as the angle of the spotlight. + At this angle, the light drops off to zero brightness. Between the inner and outer cone angles, there is a transition from full brightness to zero brightness. If this angle is a half turn, then the spotlight emits in all directions. When creating a Pandemonium [SpotLight], the outer cone angle is used as the angle of the spotlight. - The range of the light, beyond which the light has no effect. GLTF lights with no range defined behave like physical lights (which have infinite range). When creating a Godot light, the range is clamped to 4096. + The range of the light, beyond which the light has no effect. GLTF lights with no range defined behave like physical lights (which have infinite range). When creating a Pandemonium light, the range is clamped to 4096. + + + The type of the light. The values accepted by Pandemonium are "point", "spot", and "directional", which correspond to Pandemonium's [OmniLight], [SpotLight], and [DirectionalLight] respectively. + + diff --git a/modules/gltf/doc_classes/GLTFMesh.xml b/modules/gltf/doc_classes/GLTFMesh.xml index bac351cc2..a39cf88af 100644 --- a/modules/gltf/doc_classes/GLTFMesh.xml +++ b/modules/gltf/doc_classes/GLTFMesh.xml @@ -1,17 +1,22 @@ - + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [GLTFMesh] within a script will cause an error in an exported project. + + - + - + - + + + diff --git a/modules/gltf/doc_classes/GLTFNode.xml b/modules/gltf/doc_classes/GLTFNode.xml index a974315c1..dd73b9dc0 100644 --- a/modules/gltf/doc_classes/GLTFNode.xml +++ b/modules/gltf/doc_classes/GLTFNode.xml @@ -1,15 +1,18 @@ - + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [GLTFNode] within a script will cause an error in an exported project. + + - + @@ -21,17 +24,19 @@ - + - - - + - + + + + + diff --git a/modules/gltf/doc_classes/GLTFSkeleton.xml b/modules/gltf/doc_classes/GLTFSkeleton.xml index 10b9d4830..83b3fd48b 100644 --- a/modules/gltf/doc_classes/GLTFSkeleton.xml +++ b/modules/gltf/doc_classes/GLTFSkeleton.xml @@ -1,8 +1,9 @@ - + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [GLTFSkeleton] within a script will cause an error in an exported project. @@ -18,12 +19,12 @@ - + - + @@ -33,9 +34,9 @@ - + - + @@ -47,9 +48,11 @@ - + - + + + diff --git a/modules/gltf/doc_classes/GLTFSkin.xml b/modules/gltf/doc_classes/GLTFSkin.xml index b6a2bdb95..2c5bc9a1f 100644 --- a/modules/gltf/doc_classes/GLTFSkin.xml +++ b/modules/gltf/doc_classes/GLTFSkin.xml @@ -1,5 +1,5 @@ - + @@ -42,19 +42,21 @@ - + - + - + - + - + + + diff --git a/modules/gltf/doc_classes/GLTFSpecGloss.xml b/modules/gltf/doc_classes/GLTFSpecGloss.xml index 8433cf8dd..96c69193b 100644 --- a/modules/gltf/doc_classes/GLTFSpecGloss.xml +++ b/modules/gltf/doc_classes/GLTFSpecGloss.xml @@ -1,13 +1,16 @@ - + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [GLTFSpecGloss] within a script will cause an error in an exported project. + + - + @@ -15,7 +18,9 @@ - + + + diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml index ac1d85745..6e917672a 100644 --- a/modules/gltf/doc_classes/GLTFState.xml +++ b/modules/gltf/doc_classes/GLTFState.xml @@ -1,8 +1,9 @@ - + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [GLTFState] within a script will cause an error in an exported project. @@ -192,11 +193,9 @@ - + - - - + @@ -204,11 +203,13 @@ - + + + diff --git a/modules/gltf/doc_classes/GLTFTexture.xml b/modules/gltf/doc_classes/GLTFTexture.xml index c0bc42416..c81406119 100644 --- a/modules/gltf/doc_classes/GLTFTexture.xml +++ b/modules/gltf/doc_classes/GLTFTexture.xml @@ -1,13 +1,18 @@ - + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [GLTFTexture] within a script will cause an error in an exported project. + + + + diff --git a/modules/gltf/doc_classes/PackedSceneGLTF.xml b/modules/gltf/doc_classes/PackedSceneGLTF.xml new file mode 100644 index 000000000..d618160c0 --- /dev/null +++ b/modules/gltf/doc_classes/PackedSceneGLTF.xml @@ -0,0 +1,46 @@ + + + + + + [b]Note:[/b] This class is only compiled in editor builds. Run-time glTF loading and saving is [i]not[/i] available in exported projects. References to [PackedSceneGLTF] within a script will cause an error in an exported project. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp deleted file mode 100644 index 8002c185c..000000000 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ /dev/null @@ -1,575 +0,0 @@ -/*************************************************************************/ -/* editor_scene_importer_blend.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "editor_scene_importer_blend.h" - -#ifdef TOOLS_ENABLED - -#include "../gltf_document.h" -#include "../gltf_state.h" - -#include "core/config/project_settings.h" -#include "editor/editor_file_dialog.h" -#include "editor/editor_node.h" -#include "editor/editor_scale.h" -#include "editor/editor_settings.h" -#include "main/main.h" -#include "scene/main/node.h" -#include "scene/resources/animation.h" - -#ifdef WINDOWS_ENABLED -// Code by Pedro Estebanez (https://github.com/godotengine/godot/pull/59766) -#include -#endif - -uint32_t EditorSceneFormatImporterBlend::get_import_flags() const { - return ImportFlags::IMPORT_SCENE | ImportFlags::IMPORT_ANIMATION; -} - -void EditorSceneFormatImporterBlend::get_extensions(List *r_extensions) const { - r_extensions->push_back("blend"); -} - -Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_t p_flags, - const HashMap &p_options, int p_bake_fps, - List *r_missing_deps, Error *r_err) { - // Get global paths for source and sink. - - // Escape paths to be valid Python strings to embed in the script. - const String source_global = ProjectSettings::get_singleton()->globalize_path(p_path).c_escape(); - const String sink = ProjectSettings::get_singleton()->get_imported_files_path().plus_file( - vformat("%s-%s.gltf", p_path.get_file().get_basename(), p_path.md5_text())); - const String sink_global = ProjectSettings::get_singleton()->globalize_path(sink).c_escape(); - - // Handle configuration options. - - String parameters_arg; - - if (p_options.has(SNAME("blender/nodes/custom_properties")) && p_options[SNAME("blender/nodes/custom_properties")]) { - parameters_arg += "export_extras=True,"; - } else { - parameters_arg += "export_extras=False,"; - } - if (p_options.has(SNAME("blender/meshes/skins")) && p_options[SNAME("blender/meshes/skins")]) { - int32_t skins = p_options["blender/meshes/skins"]; - if (skins == BLEND_BONE_INFLUENCES_NONE) { - parameters_arg += "export_all_influences=False,"; - } else if (skins == BLEND_BONE_INFLUENCES_COMPATIBLE) { - parameters_arg += "export_all_influences=False,"; - } else if (skins == BLEND_BONE_INFLUENCES_ALL) { - parameters_arg += "export_all_influences=True,"; - } - parameters_arg += "export_skins=True,"; - } else { - parameters_arg += "export_skins=False,"; - } - if (p_options.has(SNAME("blender/materials/export_materials")) && p_options[SNAME("blender/materials/export_materials")]) { - int32_t exports = p_options["blender/materials/export_materials"]; - if (exports == BLEND_MATERIAL_EXPORT_PLACEHOLDER) { - parameters_arg += "export_materials='PLACEHOLDER',"; - } else if (exports == BLEND_MATERIAL_EXPORT_EXPORT) { - parameters_arg += "export_materials='EXPORT',"; - } - } else { - parameters_arg += "export_materials='PLACEHOLDER',"; - } - if (p_options.has(SNAME("blender/nodes/cameras")) && p_options[SNAME("blender/nodes/cameras")]) { - parameters_arg += "export_cameras=True,"; - } else { - parameters_arg += "export_cameras=False,"; - } - if (p_options.has(SNAME("blender/nodes/punctual_lights")) && p_options[SNAME("blender/nodes/punctual_lights")]) { - parameters_arg += "export_lights=True,"; - } else { - parameters_arg += "export_lights=False,"; - } - if (p_options.has(SNAME("blender/meshes/colors")) && p_options[SNAME("blender/meshes/colors")]) { - parameters_arg += "export_colors=True,"; - } else { - parameters_arg += "export_colors=False,"; - } - if (p_options.has(SNAME("blender/nodes/visible")) && p_options[SNAME("blender/nodes/visible")]) { - int32_t visible = p_options["blender/nodes/visible"]; - if (visible == BLEND_VISIBLE_VISIBLE_ONLY) { - parameters_arg += "use_visible=True,"; - } else if (visible == BLEND_VISIBLE_RENDERABLE) { - parameters_arg += "use_renderable=True,"; - } else if (visible == BLEND_VISIBLE_ALL) { - parameters_arg += "use_visible=False,use_renderable=False,"; - } - } else { - parameters_arg += "use_visible=False,use_renderable=False,"; - } - - if (p_options.has(SNAME("blender/meshes/uvs")) && p_options[SNAME("blender/meshes/uvs")]) { - parameters_arg += "export_texcoords=True,"; - } else { - parameters_arg += "export_texcoords=False,"; - } - if (p_options.has(SNAME("blender/meshes/normals")) && p_options[SNAME("blender/meshes/normals")]) { - parameters_arg += "export_normals=True,"; - } else { - parameters_arg += "export_normals=False,"; - } - if (p_options.has(SNAME("blender/meshes/tangents")) && p_options[SNAME("blender/meshes/tangents")]) { - parameters_arg += "export_tangents=True,"; - } else { - parameters_arg += "export_tangents=False,"; - } - if (p_options.has(SNAME("blender/animation/group_tracks")) && p_options[SNAME("blender/animation/group_tracks")]) { - parameters_arg += "export_nla_strips=True,"; - } else { - parameters_arg += "export_nla_strips=False,"; - } - if (p_options.has(SNAME("blender/animation/limit_playback")) && p_options[SNAME("blender/animation/limit_playback")]) { - parameters_arg += "export_frame_range=True,"; - } else { - parameters_arg += "export_frame_range=False,"; - } - if (p_options.has(SNAME("blender/animation/always_sample")) && p_options[SNAME("blender/animation/always_sample")]) { - parameters_arg += "export_force_sampling=True,"; - } else { - parameters_arg += "export_force_sampling=False,"; - } - if (p_options.has(SNAME("blender/meshes/export_bones_deforming_mesh_only")) && p_options[SNAME("blender/meshes/export_bones_deforming_mesh_only")]) { - parameters_arg += "export_def_bones=True,"; - } else { - parameters_arg += "export_def_bones=False,"; - } - if (p_options.has(SNAME("blender/nodes/modifiers")) && p_options[SNAME("blender/nodes/modifiers")]) { - parameters_arg += "export_apply=True"; - } else { - parameters_arg += "export_apply=False"; - } - - String unpack_all; - if (p_options.has(SNAME("blender/materials/unpack_enabled")) && p_options[SNAME("blender/materials/unpack_enabled")]) { - unpack_all = "bpy.ops.file.unpack_all(method='USE_LOCAL');"; - } - - // Prepare Blender export script. - - String common_args = vformat("filepath='%s',", sink_global) + - "export_format='GLTF_SEPARATE'," - "export_yup=True," + - parameters_arg; - String script = - String("import bpy, sys;") + - "print('Blender 3.0 or higher is required.', file=sys.stderr) if bpy.app.version < (3, 0, 0) else None;" + - vformat("bpy.ops.wm.open_mainfile(filepath='%s');", source_global) + - unpack_all + - vformat("bpy.ops.export_scene.gltf(export_keep_originals=True,%s);", common_args); - print_verbose(script); - - // Run script with configured Blender binary. - - String blender_path = EDITOR_GET("filesystem/import/blender/blender3_path"); - -#ifdef WINDOWS_ENABLED - blender_path = blender_path.plus_file("blender.exe"); -#else - blender_path = blender_path.plus_file("blender"); -#endif - - List args; - args.push_back("--background"); - args.push_back("--python-expr"); - args.push_back(script); - - String standard_out; - int ret; - OS::get_singleton()->execute(blender_path, args, &standard_out, &ret, true); - print_verbose(blender_path); - print_verbose(standard_out); - - if (ret != 0) { - if (r_err) { - *r_err = ERR_SCRIPT_FAILED; - } - ERR_PRINT(vformat("Blend export to glTF failed with error: %d.", ret)); - return nullptr; - } - - // Import the generated glTF. - - // Use GLTFDocument instead of glTF importer to keep image references. - Ref gltf; - gltf.instantiate(); - Ref state; - state.instantiate(); - String base_dir; - if (p_options.has(SNAME("blender/materials/unpack_enabled")) && p_options[SNAME("blender/materials/unpack_enabled")]) { - base_dir = sink.get_base_dir(); - } - Error err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, p_bake_fps, base_dir); - if (err != OK) { - if (r_err) { - *r_err = FAILED; - } - return nullptr; - } - return gltf->generate_scene(state, p_bake_fps); -} - -Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, - const HashMap &p_options) { - if (p_path.get_extension().to_lower() != "blend") { - return true; - } - - if (p_option.begins_with("animation/")) { - if (p_option != "animation/import" && !bool(p_options["animation/import"])) { - return false; - } - } - return true; -} - -void EditorSceneFormatImporterBlend::get_import_options(const String &p_path, List *r_options) { - if (p_path.get_extension().to_lower() != "blend") { - return; - } -#define ADD_OPTION_BOOL(PATH, VALUE) \ - r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, SNAME(PATH)), VALUE)); -#define ADD_OPTION_ENUM(PATH, ENUM_HINT, VALUE) \ - r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, SNAME(PATH), PROPERTY_HINT_ENUM, ENUM_HINT), VALUE)); - - ADD_OPTION_ENUM("blender/nodes/visible", "Visible Only,Renderable,All", BLEND_VISIBLE_ALL); - ADD_OPTION_BOOL("blender/nodes/punctual_lights", true); - ADD_OPTION_BOOL("blender/nodes/cameras", true); - ADD_OPTION_BOOL("blender/nodes/custom_properties", true); - ADD_OPTION_ENUM("blender/nodes/modifiers", "No Modifiers,All Modifiers", BLEND_MODIFIERS_ALL); - ADD_OPTION_BOOL("blender/meshes/colors", false); - ADD_OPTION_BOOL("blender/meshes/uvs", true); - ADD_OPTION_BOOL("blender/meshes/normals", true); - ADD_OPTION_BOOL("blender/meshes/tangents", true); - ADD_OPTION_ENUM("blender/meshes/skins", "None,4 Influences (Compatible),All Influences", BLEND_BONE_INFLUENCES_ALL); - ADD_OPTION_BOOL("blender/meshes/export_bones_deforming_mesh_only", false); - ADD_OPTION_BOOL("blender/materials/unpack_enabled", true); - ADD_OPTION_ENUM("blender/materials/export_materials", "Placeholder,Export", BLEND_MATERIAL_EXPORT_EXPORT); - ADD_OPTION_BOOL("blender/animation/limit_playback", true); - ADD_OPTION_BOOL("blender/animation/always_sample", true); - ADD_OPTION_BOOL("blender/animation/group_tracks", true); - -#undef ADD_OPTION_BOOL -#undef ADD_OPTION_ENUM -} - -/////////////////////////// - -static bool _test_blender_path(const String &p_path, String *r_err = nullptr) { - String path = p_path; -#ifdef WINDOWS_ENABLED - path = path.plus_file("blender.exe"); -#else - path = path.plus_file("blender"); -#endif - -#if defined(MACOS_ENABLED) - if (!FileAccess::exists(path)) { - path = path.plus_file("Blender"); - } -#endif - - if (!FileAccess::exists(path)) { - if (r_err) { - *r_err = TTR("Path does not contain a Blender installation."); - } - return false; - } - List args; - args.push_back("--version"); - String pipe; - Error err = OS::get_singleton()->execute(path, args, &pipe); - if (err != OK) { - if (r_err) { - *r_err = TTR("Can't execute Blender binary."); - } - return false; - } - - if (pipe.find("Blender ") != 0) { - if (r_err) { - *r_err = vformat(TTR("Unexpected --version output from Blender binary at: %s"), path); - } - return false; - } - pipe = pipe.replace_first("Blender ", ""); - int pp = pipe.find("."); - if (pp == -1) { - if (r_err) { - *r_err = TTR("Path supplied lacks a Blender binary."); - } - return false; - } - String v = pipe.substr(0, pp); - int version = v.to_int(); - if (version < 3) { - if (r_err) { - *r_err = TTR("This Blender installation is too old for this importer (not 3.0+)."); - } - return false; - } - if (version > 3) { - if (r_err) { - *r_err = TTR("This Blender installation is too new for this importer (not 3.x)."); - } - return false; - } - - return true; -} - -bool EditorFileSystemImportFormatSupportQueryBlend::is_active() const { - bool blend_enabled = GLOBAL_GET("filesystem/import/blender/enabled"); - - String blender_path = EDITOR_GET("filesystem/import/blender/blender3_path"); - - if (blend_enabled && !_test_blender_path(blender_path)) { - // Intending to import Blender, but blend not configured. - return true; - } - - return false; -} -Vector EditorFileSystemImportFormatSupportQueryBlend::get_file_extensions() const { - Vector ret; - ret.push_back("blend"); - return ret; -} - -void EditorFileSystemImportFormatSupportQueryBlend::_validate_path(String p_path) { - String error; - bool success = false; - if (p_path == "") { - error = TTR("Path is empty."); - } else { - if (_test_blender_path(p_path, &error)) { - success = true; - if (auto_detected_path == p_path) { - error = TTR("Path to Blender installation is valid (Autodetected)."); - } else { - error = TTR("Path to Blender installation is valid."); - } - } - } - - path_status->set_text(error); - - if (success) { - path_status->add_theme_color_override("font_color", path_status->get_theme_color(SNAME("success_color"), SNAME("Editor"))); - configure_blender_dialog->get_ok_button()->set_disabled(false); - } else { - path_status->add_theme_color_override("font_color", path_status->get_theme_color(SNAME("error_color"), SNAME("Editor"))); - configure_blender_dialog->get_ok_button()->set_disabled(true); - } -} - -bool EditorFileSystemImportFormatSupportQueryBlend::_autodetect_path(String p_path) { - if (_test_blender_path(p_path)) { - auto_detected_path = p_path; - return true; - } - return false; -} - -void EditorFileSystemImportFormatSupportQueryBlend::_path_confirmed() { - confirmed = true; -} - -void EditorFileSystemImportFormatSupportQueryBlend::_select_install(String p_path) { - blender_path->set_text(p_path); - _validate_path(p_path); -} -void EditorFileSystemImportFormatSupportQueryBlend::_browse_install() { - if (blender_path->get_text() != String()) { - browse_dialog->set_current_dir(blender_path->get_text()); - } - - browse_dialog->popup_centered_ratio(); -} - -bool EditorFileSystemImportFormatSupportQueryBlend::query() { - if (!configure_blender_dialog) { - configure_blender_dialog = memnew(ConfirmationDialog); - configure_blender_dialog->set_title(TTR("Configure Blender Importer")); - configure_blender_dialog->set_flag(Window::FLAG_BORDERLESS, true); // Avoid closing accidentally . - configure_blender_dialog->set_close_on_escape(false); - - VBoxContainer *vb = memnew(VBoxContainer); - vb->add_child(memnew(Label(TTR("Blender 3.0+ is required to import '.blend' files.\nPlease provide a valid path to a Blender installation:")))); - - HBoxContainer *hb = memnew(HBoxContainer); - - blender_path = memnew(LineEdit); - blender_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); - hb->add_child(blender_path); - blender_path_browse = memnew(Button); - hb->add_child(blender_path_browse); - blender_path_browse->set_text(TTR("Browse")); - blender_path_browse->connect("pressed", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_browse_install)); - hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); - hb->set_custom_minimum_size(Size2(400 * EDSCALE, 0)); - - vb->add_child(hb); - - path_status = memnew(Label); - vb->add_child(path_status); - - configure_blender_dialog->add_child(vb); - - blender_path->connect("text_changed", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_validate_path)); - - EditorNode::get_singleton()->get_gui_base()->add_child(configure_blender_dialog); - - configure_blender_dialog->set_ok_button_text(TTR("Confirm Path")); - configure_blender_dialog->set_cancel_button_text(TTR("Disable '.blend' Import")); - configure_blender_dialog->get_cancel_button()->set_tooltip(TTR("Disables Blender '.blend' files import for this project. Can be re-enabled in Project Settings.")); - configure_blender_dialog->connect("confirmed", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_path_confirmed)); - - browse_dialog = memnew(EditorFileDialog); - browse_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - browse_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR); - browse_dialog->connect("dir_selected", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_select_install)); - - EditorNode::get_singleton()->get_gui_base()->add_child(browse_dialog); - } - - String path = EDITOR_GET("filesystem/import/blender/blender3_path"); - - if (path == "") { - // Autodetect - auto_detected_path = ""; - -#if defined(MACOS_ENABLED) - - { - Vector mdfind_paths; - { - List mdfind_args; - mdfind_args.push_back("kMDItemCFBundleIdentifier=org.blenderfoundation.blender"); - - String output; - Error err = OS::get_singleton()->execute("mdfind", mdfind_args, &output); - if (err == OK) { - mdfind_paths = output.split("\n"); - } - } - - bool found = false; - for (const String &path : mdfind_paths) { - found = _autodetect_path(path.plus_file("Contents/MacOS")); - if (found) { - break; - } - } - if (!found) { - found = _autodetect_path("/opt/homebrew/bin"); - } - if (!found) { - found = _autodetect_path("/opt/local/bin"); - } - if (!found) { - found = _autodetect_path("/usr/local/bin"); - } - if (!found) { - found = _autodetect_path("/usr/local/opt"); - } - if (!found) { - found = _autodetect_path("/Applications/Blender.app/Contents/MacOS"); - } - } -#elif defined(WINDOWS_ENABLED) - { - char blender_opener_path[MAX_PATH]; - DWORD path_len = MAX_PATH; - HRESULT res = AssocQueryString(0, ASSOCSTR_EXECUTABLE, ".blend", "open", blender_opener_path, &path_len); - if (res == S_OK && _autodetect_path(String(blender_opener_path).get_base_dir())) { - // Good. - } else if (_autodetect_path("C:\\Program Files\\Blender Foundation")) { - // Good. - } else { - _autodetect_path("C:\\Program Files (x86)\\Blender Foundation"); - } - } - -#elif defined(UNIX_ENABLED) - if (_autodetect_path("/usr/bin")) { - // Good. - } else if (_autodetect_path("/usr/local/bin")) { - // Good - } else { - _autodetect_path("/opt/blender/bin"); - } -#endif - if (auto_detected_path != "") { - path = auto_detected_path; - } - } - - blender_path->set_text(path); - - _validate_path(path); - - configure_blender_dialog->popup_centered(); - confirmed = false; - - while (true) { - OS::get_singleton()->delay_usec(1); - DisplayServer::get_singleton()->process_events(); - Main::iteration(); - if (!configure_blender_dialog->is_visible() || confirmed) { - break; - } - } - - if (confirmed) { - // Can only confirm a valid path. - EditorSettings::get_singleton()->set("filesystem/import/blender/blender3_path", blender_path->get_text()); - EditorSettings::get_singleton()->save(); - } else { - // Disable Blender import - ProjectSettings::get_singleton()->set("filesystem/import/blender/enabled", false); - ProjectSettings::get_singleton()->save(); - - if (EditorNode::immediate_confirmation_dialog(TTR("Disabling '.blend' file import requires restarting the editor."), TTR("Save & Restart"), TTR("Restart"))) { - EditorNode::get_singleton()->save_all_scenes(); - } - EditorNode::get_singleton()->restart_editor(); - return true; - } - - return false; -} - -EditorFileSystemImportFormatSupportQueryBlend::EditorFileSystemImportFormatSupportQueryBlend() { -} - -#endif // TOOLS_ENABLED diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h deleted file mode 100644 index 3121ed5e6..000000000 --- a/modules/gltf/editor/editor_scene_importer_blend.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef EDITOR_SCENE_IMPORTER_BLEND_H -#define EDITOR_SCENE_IMPORTER_BLEND_H - -/*************************************************************************/ -/* editor_scene_importer_blend.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef TOOLS_ENABLED - -#include "editor/editor_file_system.h" -#include "editor/import/resource_importer_scene.h" - -class Animation; -class Node; -class ConfirmationDialog; - -class EditorSceneFormatImporterBlend : public EditorSceneFormatImporter { - GDCLASS(EditorSceneFormatImporterBlend, EditorSceneFormatImporter); - -public: - enum { - BLEND_VISIBLE_VISIBLE_ONLY, - BLEND_VISIBLE_RENDERABLE, - BLEND_VISIBLE_ALL - }; - enum { - BLEND_BONE_INFLUENCES_NONE, - BLEND_BONE_INFLUENCES_COMPATIBLE, - BLEND_BONE_INFLUENCES_ALL - }; - enum { - BLEND_MATERIAL_EXPORT_PLACEHOLDER, - BLEND_MATERIAL_EXPORT_EXPORT - }; - enum { - BLEND_MODIFIERS_NONE, - BLEND_MODIFIERS_ALL - }; - - virtual uint32_t get_import_flags() const override; - virtual void get_extensions(List *r_extensions) const override; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, - const HashMap &p_options, int p_bake_fps, - List *r_missing_deps, Error *r_err = nullptr) override; - virtual void get_import_options(const String &p_path, - List *r_options) override; - virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, - const HashMap &p_options) override; -}; - -class LineEdit; -class Button; -class EditorFileDialog; -class Label; - -class EditorFileSystemImportFormatSupportQueryBlend : public EditorFileSystemImportFormatSupportQuery { - GDCLASS(EditorFileSystemImportFormatSupportQueryBlend, EditorFileSystemImportFormatSupportQuery); - - ConfirmationDialog *configure_blender_dialog = nullptr; - LineEdit *blender_path = nullptr; - Button *blender_path_browse = nullptr; - EditorFileDialog *browse_dialog = nullptr; - Label *path_status = nullptr; - bool confirmed = false; - - String auto_detected_path; - void _validate_path(String p_path); - - bool _autodetect_path(String p_path); - - void _path_confirmed(); - - void _select_install(String p_path); - void _browse_install(); - -public: - virtual bool is_active() const override; - virtual Vector get_file_extensions() const override; - virtual bool query() override; - - EditorFileSystemImportFormatSupportQueryBlend(); -}; - -#endif // TOOLS_ENABLED - -#endif // EDITOR_SCENE_IMPORTER_BLEND_H diff --git a/modules/gltf/editor/editor_scene_importer_fbx.cpp b/modules/gltf/editor/editor_scene_importer_fbx.cpp deleted file mode 100644 index 0b54a3c25..000000000 --- a/modules/gltf/editor/editor_scene_importer_fbx.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/*************************************************************************/ -/* editor_scene_importer_fbx.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "editor_scene_importer_fbx.h" - -#ifdef TOOLS_ENABLED - -#include "../gltf_document.h" -#include "../gltf_state.h" - -#include "core/os/os.h" -#include "core/project_settings.h" -#include "editor/editor_settings.h" -#include "scene/main/node.h" -#include "scene/resources/animation.h" - -uint32_t EditorSceneFormatImporterFBX::get_import_flags() const { - return ImportFlags::IMPORT_SCENE | ImportFlags::IMPORT_ANIMATION; -} - -void EditorSceneFormatImporterFBX::get_extensions(List *r_extensions) const { - r_extensions->push_back("fbx"); -} - -Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, uint32_t p_compress_flags, List *r_missing_deps, Error *r_err) { - // Get global paths for source and sink. - - // Don't use `c_escape()` as it can generate broken paths. These paths will be - // enclosed in double quotes by OS::execute(), so we only need to escape those. - // `c_escape_multiline()` seems to do this (escapes `\` and `"` only). - const String source_global = ProjectSettings::get_singleton()->globalize_path(p_path).c_escape_multiline(); - const String sink = ProjectSettings::get_singleton()->get_project_data_path().plus_file( - vformat("%s-%s.glb", p_path.get_file().get_basename(), p_path.md5_text())); - const String sink_global = ProjectSettings::get_singleton()->globalize_path(sink).c_escape_multiline(); - - // Run fbx2gltf. - - String fbx2gltf_path = EDITOR_GET("filesystem/import/fbx/fbx2gltf_path"); - - List args; - args.push_back("--pbr-metallic-roughness"); - args.push_back("--input"); - args.push_back(source_global); - args.push_back("--output"); - args.push_back(sink_global); - args.push_back("--binary"); - - String standard_out; - int ret; - OS::get_singleton()->execute(fbx2gltf_path, args, true, nullptr, &standard_out, &ret, true); - - print_verbose(fbx2gltf_path); - print_verbose(standard_out); - - if (ret != 0) { - if (r_err) { - *r_err = ERR_SCRIPT_FAILED; - } - ERR_PRINT(vformat("FBX conversion to glTF failed with error: %d.", ret)); - return nullptr; - } - - // Import the generated glTF. - - // Use GLTFDocument instead of glTF importer to keep image references. - Ref gltf; - gltf.instance(); - Ref state; - state.instance(); - - print_verbose(vformat("glTF path: %s", sink)); - Error err = gltf->append_from_file(sink, state, p_flags, p_bake_fps); - - if (err != OK) { - if (r_err) { - *r_err = FAILED; - } - return nullptr; - } - - return gltf->generate_scene(state, p_bake_fps); -} - -bool EditorSceneFormatImporterFBX::get_option_visibility(const String &p_option, const Map &p_options) const { - return true; -} - -void EditorSceneFormatImporterFBX::get_import_options(List *r_options, int p_preset) const { -} - -EditorSceneFormatImporterFBX::EditorSceneFormatImporterFBX() { -} -EditorSceneFormatImporterFBX::~EditorSceneFormatImporterFBX() { -} - -#endif // TOOLS_ENABLED diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp b/modules/gltf/editor_scene_exporter_gltf_plugin.cpp similarity index 61% rename from modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp rename to modules/gltf/editor_scene_exporter_gltf_plugin.cpp index 95db1c096..841687186 100644 --- a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp +++ b/modules/gltf/editor_scene_exporter_gltf_plugin.cpp @@ -32,18 +32,9 @@ #include "editor_scene_exporter_gltf_plugin.h" -#include "../gltf_document.h" -#include "../gltf_state.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_dialog.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" -#include "scene/3d/mesh_instance_3d.h" -#include "scene/gui/check_box.h" #include "scene/main/node.h" String SceneExporterGLTFPlugin::get_name() const { @@ -54,58 +45,50 @@ bool SceneExporterGLTFPlugin::has_main_screen() const { return false; } -SceneExporterGLTFPlugin::SceneExporterGLTFPlugin() { +SceneExporterGLTFPlugin::SceneExporterGLTFPlugin(EditorNode *p_node) { + editor = p_node; + convert_gltf2.instance(); file_export_lib = memnew(EditorFileDialog); - EditorNode::get_singleton()->get_gui_base()->add_child(file_export_lib); - file_export_lib->connect("file_selected", callable_mp(this, &SceneExporterGLTFPlugin::_gltf2_dialog_action)); + editor->get_gui_base()->add_child(file_export_lib); + file_export_lib->connect("file_selected", this, "_gltf2_dialog_action"); file_export_lib->set_title(TTR("Export Library")); - file_export_lib->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); + file_export_lib->set_mode(EditorFileDialog::MODE_SAVE_FILE); file_export_lib->set_access(EditorFileDialog::ACCESS_FILESYSTEM); file_export_lib->clear_filters(); file_export_lib->add_filter("*.glb"); file_export_lib->add_filter("*.gltf"); - file_export_lib->set_title(TTR("Export Scene to glTF 2.0 File")); - - PopupMenu *menu = get_export_as_menu(); - int idx = menu->get_item_count(); - menu->add_item(TTR("glTF 2.0 Scene...")); - menu->set_item_metadata(idx, callable_mp(this, &SceneExporterGLTFPlugin::convert_scene_to_gltf2)); + file_export_lib->set_title(TTR("Export Mesh GLTF2")); + String gltf_scene_name = TTR("Export GLTF..."); + add_tool_menu_item(gltf_scene_name, this, "convert_scene_to_gltf2", DEFVAL(Variant())); } void SceneExporterGLTFPlugin::_gltf2_dialog_action(String p_file) { - Node *root = EditorNode::get_singleton()->get_tree()->get_edited_scene_root(); + Node *root = editor->get_tree()->get_edited_scene_root(); if (!root) { - EditorNode::get_singleton()->show_accept(TTR("This operation can't be done without a scene."), TTR("OK")); + editor->show_accept(TTR("This operation can't be done without a scene."), TTR("OK")); return; } List deps; - Ref doc; - doc.instantiate(); - Ref state; - state.instantiate(); - int32_t flags = 0; - flags |= EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS; - Error err = doc->append_from_scene(root, state, flags, 30.0f); - if (err != OK) { - ERR_PRINT(vformat("glTF2 save scene error %s.", itos(err))); - } - err = doc->write_to_filesystem(state, p_file); - if (err != OK) { - ERR_PRINT(vformat("glTF2 save scene error %s.", itos(err))); - } + convert_gltf2->save_scene(root, p_file, p_file, 0, 1000.0f, &deps); + EditorFileSystem::get_singleton()->scan_changes(); } -void SceneExporterGLTFPlugin::convert_scene_to_gltf2() { - Node *root = EditorNode::get_singleton()->get_tree()->get_edited_scene_root(); +void SceneExporterGLTFPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("convert_scene_to_gltf2"), &SceneExporterGLTFPlugin::convert_scene_to_gltf2); + ClassDB::bind_method(D_METHOD("_gltf2_dialog_action", "file"), &SceneExporterGLTFPlugin::_gltf2_dialog_action); +} + +void SceneExporterGLTFPlugin::convert_scene_to_gltf2(Variant p_null) { + Node *root = editor->get_tree()->get_edited_scene_root(); if (!root) { - EditorNode::get_singleton()->show_accept(TTR("This operation can't be done without a scene."), TTR("OK")); + editor->show_accept(TTR("This operation can't be done without a scene."), TTR("OK")); return; } - String filename = String(root->get_scene_file_path().get_file().get_basename()); - if (filename.is_empty()) { + String filename = String(root->get_filename().get_file().get_basename()); + if (filename.empty()) { filename = root->get_name(); } - file_export_lib->set_current_file(filename + String(".gltf")); + file_export_lib->set_current_file(filename + ".gltf"); file_export_lib->popup_centered_ratio(); } diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h b/modules/gltf/editor_scene_exporter_gltf_plugin.h similarity index 88% rename from modules/gltf/editor/editor_scene_exporter_gltf_plugin.h rename to modules/gltf/editor_scene_exporter_gltf_plugin.h index d19137d41..97dc17982 100644 --- a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h +++ b/modules/gltf/editor_scene_exporter_gltf_plugin.h @@ -1,6 +1,5 @@ #ifndef EDITOR_SCENE_EXPORTER_GLTF_PLUGIN_H #define EDITOR_SCENE_EXPORTER_GLTF_PLUGIN_H - /*************************************************************************/ /* editor_scene_exporter_gltf_plugin.h */ /*************************************************************************/ @@ -31,24 +30,27 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef TOOLS_ENABLED - +#include "editor/editor_file_dialog.h" #include "editor/editor_plugin.h" -#include "editor_scene_importer_gltf.h" + +#include "packed_scene_gltf.h" class SceneExporterGLTFPlugin : public EditorPlugin { GDCLASS(SceneExporterGLTFPlugin, EditorPlugin); + Ref convert_gltf2; + EditorNode *editor = nullptr; EditorFileDialog *file_export_lib = nullptr; void _gltf2_dialog_action(String p_file); - void convert_scene_to_gltf2(); + void convert_scene_to_gltf2(Variant p_null); + +protected: + static void _bind_methods(); public: - virtual String get_name() const override; - bool has_main_screen() const override; - SceneExporterGLTFPlugin(); + virtual String get_name() const; + bool has_main_screen() const; + SceneExporterGLTFPlugin(class EditorNode *p_node); }; -#endif // TOOLS_ENABLED - #endif // EDITOR_SCENE_EXPORTER_GLTF_PLUGIN_H diff --git a/modules/gltf/editor/editor_scene_importer_gltf.cpp b/modules/gltf/editor_scene_importer_gltf.cpp similarity index 75% rename from modules/gltf/editor/editor_scene_importer_gltf.cpp rename to modules/gltf/editor_scene_importer_gltf.cpp index 9277f17a7..af4bc9261 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.cpp +++ b/modules/gltf/editor_scene_importer_gltf.cpp @@ -31,42 +31,33 @@ #ifdef TOOLS_ENABLED #include "editor_scene_importer_gltf.h" - -#include "../gltf_document.h" -#include "../gltf_state.h" - #include "scene/resources/animation.h" +#include "scene/resources/skin.h" -uint32_t EditorSceneFormatImporterGLTF::get_import_flags() const { +#include "gltf_state.h" +#include "packed_scene_gltf.h" + +uint32_t EditorSceneImporterGLTF::get_import_flags() const { return ImportFlags::IMPORT_SCENE | ImportFlags::IMPORT_ANIMATION; } -void EditorSceneFormatImporterGLTF::get_extensions(List *r_extensions) const { +void EditorSceneImporterGLTF::get_extensions(List *r_extensions) const { r_extensions->push_back("gltf"); r_extensions->push_back("glb"); } -Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t p_flags, - int p_bake_fps, uint32_t p_compress_flags, List *r_missing_deps, Error *r_err) { - - Ref doc; - doc.instance(); - Ref state; - state.instance(); - - Error err = doc->append_from_file(p_path, state, p_flags, p_bake_fps); - - if (err != OK) { - if (r_err) { - *r_err = err; - } - return nullptr; - } - - return doc->generate_scene(state, p_bake_fps); +Node *EditorSceneImporterGLTF::import_scene(const String &p_path, + uint32_t p_flags, int p_bake_fps, uint32_t p_compress_flags, + List *r_missing_deps, + Error *r_err) { + Ref importer; + importer.instance(); + return importer->import_scene(p_path, p_flags, p_bake_fps, p_compress_flags, r_missing_deps, r_err, Ref()); } -Ref EditorSceneFormatImporterGLTF::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { +Ref EditorSceneImporterGLTF::import_animation(const String &p_path, + uint32_t p_flags, + int p_bake_fps) { return Ref(); } diff --git a/modules/gltf/editor/editor_scene_importer_gltf.h b/modules/gltf/editor_scene_importer_gltf.h similarity index 85% rename from modules/gltf/editor/editor_scene_importer_gltf.h rename to modules/gltf/editor_scene_importer_gltf.h index b0cf10d12..dc222cc84 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.h +++ b/modules/gltf/editor_scene_importer_gltf.h @@ -1,6 +1,5 @@ #ifndef EDITOR_SCENE_IMPORTER_GLTF_H #define EDITOR_SCENE_IMPORTER_GLTF_H - /*************************************************************************/ /* editor_scene_importer_gltf.h */ /*************************************************************************/ @@ -33,25 +32,25 @@ #ifdef TOOLS_ENABLED -#include "../gltf_document_extension.h" -#include "../gltf_state.h" - #include "editor/import/resource_importer_scene.h" -class Animation; -class Node; +#include "gltf_document.h" +#include "gltf_state.h" -class EditorSceneFormatImporterGLTF : public EditorSceneImporter { - GDCLASS(EditorSceneFormatImporterGLTF, EditorSceneImporter); +class EditorSceneImporterGLTF : public EditorSceneImporter { + GDCLASS(EditorSceneImporterGLTF, EditorSceneImporter); public: virtual uint32_t get_import_flags() const; virtual void get_extensions(List *r_extensions) const; - - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, uint32_t p_compress_flags, List *r_missing_deps = nullptr, Error *r_err = nullptr); - virtual Ref import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps); + virtual Node *import_scene(const String &p_path, uint32_t p_flags, + int p_bake_fps, uint32_t p_compress_flags, + List *r_missing_deps = nullptr, + Error *r_err = nullptr); + virtual Ref import_animation(const String &p_path, + uint32_t p_flags, int p_bake_fps); }; -#endif // TOOLS_ENABLED - #endif // EDITOR_SCENE_IMPORTER_GLTF_H + +#endif // TOOLS_ENABLED diff --git a/modules/gltf/structures/gltf_accessor.cpp b/modules/gltf/gltf_accessor.cpp similarity index 96% rename from modules/gltf/structures/gltf_accessor.cpp rename to modules/gltf/gltf_accessor.cpp index 03955edee..fd29ac2e8 100644 --- a/modules/gltf/structures/gltf_accessor.cpp +++ b/modules/gltf/gltf_accessor.cpp @@ -65,7 +65,7 @@ void GLTFAccessor::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "component_type"), "set_component_type", "get_component_type"); // int ADD_PROPERTY(PropertyInfo(Variant::BOOL, "normalized"), "set_normalized", "get_normalized"); // bool ADD_PROPERTY(PropertyInfo(Variant::INT, "count"), "set_count", "get_count"); // int - ADD_PROPERTY(PropertyInfo(Variant::INT, "type"), "set_type", "get_type"); // GLTFType + ADD_PROPERTY(PropertyInfo(Variant::INT, "type"), "set_type", "get_type"); // GLTFDocument::GLTFType ADD_PROPERTY(PropertyInfo(Variant::POOL_REAL_ARRAY, "min"), "set_min", "get_min"); // Vector ADD_PROPERTY(PropertyInfo(Variant::POOL_REAL_ARRAY, "max"), "set_max", "get_max"); // Vector ADD_PROPERTY(PropertyInfo(Variant::INT, "sparse_count"), "set_sparse_count", "get_sparse_count"); // int @@ -121,22 +121,22 @@ int GLTFAccessor::get_type() { } void GLTFAccessor::set_type(int p_type) { - type = (GLTFType)p_type; // TODO: Register enum + type = (GLTFDocument::GLTFType)p_type; // TODO: Register enum } -PoolRealArray GLTFAccessor::get_min() { +PoolVector GLTFAccessor::get_min() { return min; } -void GLTFAccessor::set_min(const PoolRealArray &p_min) { +void GLTFAccessor::set_min(PoolVector p_min) { min = p_min; } -PoolRealArray GLTFAccessor::get_max() { +PoolVector GLTFAccessor::get_max() { return max; } -void GLTFAccessor::set_max(const PoolRealArray &p_max) { +void GLTFAccessor::set_max(PoolVector p_max) { max = p_max; } diff --git a/modules/gltf/structures/gltf_accessor.h b/modules/gltf/gltf_accessor.h similarity index 93% rename from modules/gltf/structures/gltf_accessor.h rename to modules/gltf/gltf_accessor.h index 991fda6f3..6e6a6007b 100644 --- a/modules/gltf/structures/gltf_accessor.h +++ b/modules/gltf/gltf_accessor.h @@ -1,6 +1,5 @@ #ifndef GLTF_ACCESSOR_H #define GLTF_ACCESSOR_H - /*************************************************************************/ /* gltf_accessor.h */ /*************************************************************************/ @@ -33,7 +32,7 @@ #include "core/resource.h" -#include "../gltf_defines.h" +#include "gltf_document.h" struct GLTFAccessor : public Resource { GDCLASS(GLTFAccessor, Resource); @@ -45,9 +44,9 @@ private: int component_type = 0; bool normalized = false; int count = 0; - GLTFType type = GLTFType::TYPE_SCALAR; - PoolRealArray min; - PoolRealArray max; + GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR; + PoolVector min; + PoolVector max; int sparse_count = 0; int sparse_indices_buffer_view = 0; int sparse_indices_byte_offset = 0; @@ -77,11 +76,11 @@ public: int get_type(); void set_type(int p_type); - PoolRealArray get_min(); - void set_min(const PoolRealArray &p_min); + PoolVector get_min(); + void set_min(PoolVector p_min); - PoolRealArray get_max(); - void set_max(const PoolRealArray &p_max); + PoolVector get_max(); + void set_max(PoolVector p_max); int get_sparse_count(); void set_sparse_count(int p_sparse_count); diff --git a/modules/gltf/structures/gltf_animation.cpp b/modules/gltf/gltf_animation.cpp similarity index 97% rename from modules/gltf/structures/gltf_animation.cpp rename to modules/gltf/gltf_animation.cpp index e598c870a..c857be4b2 100644 --- a/modules/gltf/structures/gltf_animation.cpp +++ b/modules/gltf/gltf_animation.cpp @@ -45,7 +45,7 @@ void GLTFAnimation::set_loop(bool p_val) { loop = p_val; } -HashMap &GLTFAnimation::get_tracks() { +Map &GLTFAnimation::get_tracks() { return tracks; } diff --git a/modules/gltf/structures/gltf_animation.h b/modules/gltf/gltf_animation.h similarity index 93% rename from modules/gltf/structures/gltf_animation.h rename to modules/gltf/gltf_animation.h index 7c17e0afc..008782ae7 100644 --- a/modules/gltf/structures/gltf_animation.h +++ b/modules/gltf/gltf_animation.h @@ -1,6 +1,5 @@ #ifndef GLTF_ANIMATION_H #define GLTF_ANIMATION_H - /*************************************************************************/ /* gltf_animation.h */ /*************************************************************************/ @@ -50,26 +49,26 @@ public: template struct Channel { Interpolation interpolation; - PoolRealArray times; - PoolVector values; + Vector times; + Vector values; }; struct Track { - Channel position_track; + Channel translation_track; Channel rotation_track; Channel scale_track; - Vector> weight_tracks; + Vector> weight_tracks; }; public: bool get_loop() const; void set_loop(bool p_val); - HashMap &get_tracks(); + Map &get_tracks(); GLTFAnimation(); private: bool loop = false; - HashMap tracks; + Map tracks; }; #endif // GLTF_ANIMATION_H diff --git a/modules/gltf/structures/gltf_buffer_view.cpp b/modules/gltf/gltf_buffer_view.cpp similarity index 100% rename from modules/gltf/structures/gltf_buffer_view.cpp rename to modules/gltf/gltf_buffer_view.cpp diff --git a/modules/gltf/structures/gltf_buffer_view.h b/modules/gltf/gltf_buffer_view.h similarity index 99% rename from modules/gltf/structures/gltf_buffer_view.h rename to modules/gltf/gltf_buffer_view.h index 9a0d5dd4d..e148a65c0 100644 --- a/modules/gltf/structures/gltf_buffer_view.h +++ b/modules/gltf/gltf_buffer_view.h @@ -1,6 +1,5 @@ #ifndef GLTF_BUFFER_VIEW_H #define GLTF_BUFFER_VIEW_H - /*************************************************************************/ /* gltf_buffer_view.h */ /*************************************************************************/ @@ -31,9 +30,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "../gltf_defines.h" #include "core/resource.h" +#include "gltf_document.h" + class GLTFBufferView : public Resource { GDCLASS(GLTFBufferView, Resource); friend class GLTFDocument; diff --git a/modules/gltf/structures/gltf_camera.cpp b/modules/gltf/gltf_camera.cpp similarity index 83% rename from modules/gltf/structures/gltf_camera.cpp rename to modules/gltf/gltf_camera.cpp index cf89a066d..0efdfb06f 100644 --- a/modules/gltf/structures/gltf_camera.cpp +++ b/modules/gltf/gltf_camera.cpp @@ -35,13 +35,13 @@ void GLTFCamera::_bind_methods() { ClassDB::bind_method(D_METHOD("set_perspective", "perspective"), &GLTFCamera::set_perspective); ClassDB::bind_method(D_METHOD("get_fov_size"), &GLTFCamera::get_fov_size); ClassDB::bind_method(D_METHOD("set_fov_size", "fov_size"), &GLTFCamera::set_fov_size); - ClassDB::bind_method(D_METHOD("get_depth_far"), &GLTFCamera::get_depth_far); - ClassDB::bind_method(D_METHOD("set_depth_far", "zdepth_far"), &GLTFCamera::set_depth_far); - ClassDB::bind_method(D_METHOD("get_depth_near"), &GLTFCamera::get_depth_near); - ClassDB::bind_method(D_METHOD("set_depth_near", "zdepth_near"), &GLTFCamera::set_depth_near); + ClassDB::bind_method(D_METHOD("get_zfar"), &GLTFCamera::get_zfar); + ClassDB::bind_method(D_METHOD("set_zfar", "zfar"), &GLTFCamera::set_zfar); + ClassDB::bind_method(D_METHOD("get_znear"), &GLTFCamera::get_znear); + ClassDB::bind_method(D_METHOD("set_znear", "znear"), &GLTFCamera::set_znear); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "perspective"), "set_perspective", "get_perspective"); // bool ADD_PROPERTY(PropertyInfo(Variant::REAL, "fov_size"), "set_fov_size", "get_fov_size"); // float - ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth_far"), "set_depth_far", "get_depth_far"); // float - ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth_near"), "set_depth_near", "get_depth_near"); // float + ADD_PROPERTY(PropertyInfo(Variant::REAL, "zfar"), "set_zfar", "get_zfar"); // float + ADD_PROPERTY(PropertyInfo(Variant::REAL, "znear"), "set_znear", "get_znear"); // float } diff --git a/modules/gltf/structures/gltf_camera.h b/modules/gltf/gltf_camera.h similarity index 90% rename from modules/gltf/structures/gltf_camera.h rename to modules/gltf/gltf_camera.h index afbec0ba7..207dff64e 100644 --- a/modules/gltf/structures/gltf_camera.h +++ b/modules/gltf/gltf_camera.h @@ -1,6 +1,5 @@ #ifndef GLTF_CAMERA_H #define GLTF_CAMERA_H - /*************************************************************************/ /* gltf_camera.h */ /*************************************************************************/ @@ -39,8 +38,8 @@ class GLTFCamera : public Resource { private: bool perspective = true; float fov_size = 75.0; - float depth_far = 4000.0; - float depth_near = 0.05; + float zfar = 4000.0; + float znear = 0.05; protected: static void _bind_methods(); @@ -50,10 +49,10 @@ public: void set_perspective(bool p_val) { perspective = p_val; } float get_fov_size() const { return fov_size; } void set_fov_size(float p_val) { fov_size = p_val; } - float get_depth_far() const { return depth_far; } - void set_depth_far(float p_val) { depth_far = p_val; } - float get_depth_near() const { return depth_near; } - void set_depth_near(float p_val) { depth_near = p_val; } + float get_zfar() const { return zfar; } + void set_zfar(float p_val) { zfar = p_val; } + float get_znear() const { return znear; } + void set_znear(float p_val) { znear = p_val; } }; #endif // GLTF_CAMERA_H diff --git a/modules/gltf/gltf_defines.h b/modules/gltf/gltf_defines.h deleted file mode 100644 index abb86ef46..000000000 --- a/modules/gltf/gltf_defines.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef GLTF_DEFINES_H -#define GLTF_DEFINES_H - -/*************************************************************************/ -/* gltf_defines.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -// This file should only be included by other headers. - -// Godot classes used by GLTF headers. -class BoneAttachment; -class DirectionalLight; -class Light; -class MultiMeshInstance; -class Skeleton; -class Skin; - -// GLTF classes. -struct GLTFAccessor; -class GLTFAnimation; -class GLTFBufferView; -class GLTFCamera; -class GLTFDocument; -class GLTFDocumentExtension; -class GLTFLight; -class GLTFMesh; -class GLTFNode; -class GLTFSkeleton; -class GLTFSkin; -class GLTFSpecGloss; -class GLTFState; -class GLTFTexture; - -// GLTF index aliases. -using GLTFAccessorIndex = int; -using GLTFAnimationIndex = int; -using GLTFBufferIndex = int; -using GLTFBufferViewIndex = int; -using GLTFCameraIndex = int; -using GLTFImageIndex = int; -using GLTFMaterialIndex = int; -using GLTFMeshIndex = int; -using GLTFLightIndex = int; -using GLTFNodeIndex = int; -using GLTFSkeletonIndex = int; -using GLTFSkinIndex = int; -using GLTFTextureIndex = int; - -enum GLTFType { - TYPE_SCALAR, - TYPE_VEC2, - TYPE_VEC3, - TYPE_VEC4, - TYPE_MAT2, - TYPE_MAT3, - TYPE_MAT4, -}; - -#endif // GLTF_DEFINES_H diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 8318f0d7f..edcda55b1 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -30,93 +30,81 @@ #include "gltf_document.h" -#include "extensions/gltf_spec_gloss.h" -#include "gltf_document_extension.h" -#include "gltf_document_extension_convert_importer_mesh.h" +#include "gltf_accessor.h" +#include "gltf_animation.h" +#include "gltf_camera.h" +#include "gltf_light.h" +#include "gltf_mesh.h" +#include "gltf_node.h" +#include "gltf_skeleton.h" +#include "gltf_skin.h" +#include "gltf_spec_gloss.h" #include "gltf_state.h" +#include "gltf_texture.h" -#include "core/array.h" +#include "core/bind/core_bind.h" // FIXME: Shouldn't use _Directory but DirAccess. #include "core/crypto/crypto_core.h" -#include "core/dictionary.h" -#include "core/error_macros.h" -#include "core/io/file_access_memory.h" #include "core/io/json.h" -#include "core/io/stream_peer.h" #include "core/math/disjoint_set.h" -#include "core/math/vector2.h" -#include "core/os/dir_access.h" #include "core/os/file_access.h" #include "core/variant.h" #include "core/version.h" #include "drivers/png/png_driver_common.h" #include "scene/2d/node_2d.h" -#include "scene/3d/camera.h" +#include "scene/3d/bone_attachment.h" #include "scene/3d/mesh_instance.h" #include "scene/3d/multimesh_instance.h" #include "scene/3d/spatial.h" #include "scene/animation/animation_player.h" +#include "scene/main/node.h" #include "scene/resources/animation.h" -#include "scene/resources/importer_mesh.h" -#include "scene/resources/material.h" -#include "scene/resources/mesh.h" #include "scene/resources/multimesh.h" +#include "scene/resources/skin.h" #include "scene/resources/surface_tool.h" -#include "modules/modules_enabled.gen.h" // For csg, gridmap. +#include "modules/modules_enabled.gen.h" // For csg, gridmap, regex. -// FIXME: Hardcoded to avoid editor dependency. -#define GLTF_IMPORT_USE_NAMED_SKIN_BINDS 16 -#define GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS 32 - -#include -#include -#include -#include - -static Ref _mesh_to_importer_mesh(Ref p_mesh) { - Ref importer_mesh; - importer_mesh.instance(); - if (p_mesh.is_null()) { - return importer_mesh; - } +#ifdef MODULE_REGEX_ENABLED +#include "modules/regex/regex.h" +#endif // MODULE_REGEX_ENABLED +Ref _mesh_to_array_mesh(Ref p_mesh) { Ref array_mesh = p_mesh; - if (p_mesh->get_blend_shape_count()) { - ArrayMesh::BlendShapeMode shape_mode = ArrayMesh::BLEND_SHAPE_MODE_NORMALIZED; - if (array_mesh.is_valid()) { - shape_mode = array_mesh->get_blend_shape_mode(); - } - importer_mesh->set_blend_shape_mode(shape_mode); - for (int morph_i = 0; morph_i < p_mesh->get_blend_shape_count(); morph_i++) { - importer_mesh->add_blend_shape(p_mesh->get_blend_shape_name(morph_i)); - } + if (array_mesh.is_valid()) { + return array_mesh; } + array_mesh.instance(); + if (p_mesh.is_null()) { + return array_mesh; + } + for (int32_t surface_i = 0; surface_i < p_mesh->get_surface_count(); surface_i++) { - Array array = p_mesh->surface_get_arrays(surface_i); + Mesh::PrimitiveType primitive_type = p_mesh->surface_get_primitive_type(surface_i); + Array arrays = p_mesh->surface_get_arrays(surface_i); Ref mat = p_mesh->surface_get_material(surface_i); - String mat_name; - if (mat.is_valid()) { - mat_name = mat->get_name(); - } else { - // Assign default material when no material is assigned. - mat = Ref(memnew(SpatialMaterial)); - } - importer_mesh->add_surface(p_mesh->surface_get_primitive_type(surface_i), - array, p_mesh->surface_get_blend_shape_arrays(surface_i), Dictionary(), mat, - mat_name, p_mesh->surface_get_format(surface_i)); + int32_t mat_idx = array_mesh->get_surface_count(); + array_mesh->add_surface_from_arrays(primitive_type, arrays); + array_mesh->surface_set_material(mat_idx, mat); } - return importer_mesh; + + return array_mesh; } -Error GLTFDocument::_serialize(Ref state, const String &p_path) { +Error GLTFDocument::serialize(Ref state, Node *p_root, const String &p_path) { + uint64_t begin_time = OS::get_singleton()->get_ticks_usec(); + + state->skeleton3d_to_gltf_skeleton.clear(); + state->skin_and_skeleton3d_to_gltf_skin.clear(); + + _convert_scene_node(state, p_root, -1, -1); if (!state->buffers.size()) { state->buffers.push_back(Vector()); } - /* STEP CONVERT MESH INSTANCES */ + /* STEP 1 CONVERT MESH INSTANCES */ _convert_mesh_instances(state); - /* STEP SERIALIZE CAMERAS */ + /* STEP 2 SERIALIZE CAMERAS */ Error err = _serialize_cameras(state); if (err != OK) { return Error::FAILED; @@ -128,37 +116,37 @@ Error GLTFDocument::_serialize(Ref state, const String &p_path) { return Error::FAILED; } - /* STEP SERIALIZE MESHES (we have enough info now) */ + /* STEP 5 SERIALIZE MESHES (we have enough info now) */ err = _serialize_meshes(state); if (err != OK) { return Error::FAILED; } - /* STEP SERIALIZE TEXTURES */ + /* STEP 6 SERIALIZE TEXTURES */ err = _serialize_materials(state); if (err != OK) { return Error::FAILED; } - /* STEP SERIALIZE ANIMATIONS */ + /* STEP 7 SERIALIZE ANIMATIONS */ err = _serialize_animations(state); if (err != OK) { return Error::FAILED; } - /* STEP SERIALIZE ACCESSORS */ + /* STEP 8 SERIALIZE ACCESSORS */ err = _encode_accessors(state); if (err != OK) { return Error::FAILED; } - /* STEP SERIALIZE IMAGES */ + /* STEP 9 SERIALIZE IMAGES */ err = _serialize_images(state, p_path); if (err != OK) { return Error::FAILED; } - /* STEP SERIALIZE TEXTURES */ + /* STEP 10 SERIALIZE TEXTURES */ err = _serialize_textures(state); if (err != OK) { return Error::FAILED; @@ -168,68 +156,65 @@ Error GLTFDocument::_serialize(Ref state, const String &p_path) { state->buffer_views.write[i]->buffer = 0; } - /* STEP SERIALIZE BUFFER VIEWS */ + /* STEP 11 SERIALIZE BUFFER VIEWS */ err = _encode_buffer_views(state); if (err != OK) { return Error::FAILED; } - /* STEP SERIALIZE NODES */ + /* STEP 12 SERIALIZE NODES */ err = _serialize_nodes(state); if (err != OK) { return Error::FAILED; } - /* STEP SERIALIZE SCENE */ + /* STEP 13 SERIALIZE SCENE */ err = _serialize_scenes(state); if (err != OK) { return Error::FAILED; } - /* STEP SERIALIZE SCENE */ + /* STEP 14 SERIALIZE SCENE */ err = _serialize_lights(state); if (err != OK) { return Error::FAILED; } - /* STEP SERIALIZE EXTENSIONS */ + /* STEP 15 SERIALIZE EXTENSIONS */ err = _serialize_extensions(state); if (err != OK) { return Error::FAILED; } - /* STEP SERIALIZE VERSION */ + /* STEP 16 SERIALIZE VERSION */ err = _serialize_version(state); if (err != OK) { return Error::FAILED; } - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref ext = document_extensions[ext_i]; - ERR_CONTINUE(ext.is_null()); - err = ext->export_post(state); - ERR_FAIL_COND_V(err != OK, err); + /* STEP 17 SERIALIZE FILE */ + err = _serialize_file(state, p_path); + if (err != OK) { + return Error::FAILED; } + uint64_t elapsed = OS::get_singleton()->get_ticks_usec() - begin_time; + float elapsed_sec = double(elapsed) / 1000000.0; + elapsed_sec = Math::stepify(elapsed_sec, 0.01f); + print_line("glTF: Export time elapsed seconds " + rtos(elapsed_sec).pad_decimals(2)); return OK; } Error GLTFDocument::_serialize_extensions(Ref state) const { + const String texture_transform = "KHR_texture_transform"; + const String punctual_lights = "KHR_lights_punctual"; Array extensions_used; + extensions_used.push_back(punctual_lights); + extensions_used.push_back(texture_transform); + state->json["extensionsUsed"] = extensions_used; Array extensions_required; - if (!state->lights.empty()) { - extensions_used.push_back("KHR_lights_punctual"); - } - if (state->use_khr_texture_transform) { - extensions_used.push_back("KHR_texture_transform"); - extensions_required.push_back("KHR_texture_transform"); - } - if (!extensions_used.empty()) { - state->json["extensionsUsed"] = extensions_used; - } - if (!extensions_required.empty()) { - state->json["extensionsRequired"] = extensions_required; - } + extensions_required.push_back(texture_transform); + state->json["extensionsRequired"] = extensions_required; return OK; } @@ -257,8 +242,7 @@ Error GLTFDocument::_serialize_scenes(Ref state) { Error GLTFDocument::_parse_json(const String &p_path, Ref state) { Error err; FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err); - - if (f.is_null()) { + if (!f) { return err; } @@ -268,29 +252,31 @@ Error GLTFDocument::_parse_json(const String &p_path, Ref state) { String text; text.parse_utf8((const char *)array.ptr(), array.size()); - JSON json; - Variant data; - String err_str; + String err_txt; int err_line; - err = json.parse(text, data, err_str, err_line); - + Variant v; + err = JSON::parse(text, v, err_txt, err_line); if (err != OK) { - _err_print_error("", p_path.utf8().get_data(), err_line, err_str.utf8().get_data(), ERR_HANDLER_SCRIPT); + _err_print_error("", p_path.utf8().get_data(), err_line, err_txt.utf8().get_data(), ERR_HANDLER_SCRIPT); return err; } - state->json = data; + state->json = v; return OK; } -Error GLTFDocument::_parse_glb(FileAccess *f, Ref state) { - ERR_FAIL_NULL_V(f, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(state.is_null(), ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(f->get_position() != 0, ERR_FILE_CANT_READ); +Error GLTFDocument::_parse_glb(const String &p_path, Ref state) { + Error err; + FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err); + if (!f) { + return err; + } + uint32_t magic = f->get_32(); ERR_FAIL_COND_V(magic != 0x46546C67, ERR_FILE_UNRECOGNIZED); //glTF f->get_32(); // version f->get_32(); // length + uint32_t chunk_length = f->get_32(); uint32_t chunk_type = f->get_32(); @@ -303,17 +289,16 @@ Error GLTFDocument::_parse_glb(FileAccess *f, Ref state) { String text; text.parse_utf8((const char *)json_data.ptr(), json_data.size()); - JSON json; - Variant data; - String err_str; + String err_txt; int err_line; - Error err = json.parse(text, data, err_str, err_line); - + Variant v; + err = JSON::parse(text, v, err_txt, err_line); if (err != OK) { - _err_print_error("", "", err_line, err_str.utf8().get_data(), ERR_HANDLER_SCRIPT); + _err_print_error("", p_path.utf8().get_data(), err_line, err_txt.utf8().get_data(), ERR_HANDLER_SCRIPT); return err; } - state->json = data; + + state->json = v; //data? @@ -347,17 +332,17 @@ static Vector3 _arr_to_vec3(const Array &p_array) { return Vector3(p_array[0], p_array[1], p_array[2]); } -static Array _quaternion_to_array(const Quat &p_quaternion) { +static Array _quat_to_array(const Quat &p_quat) { Array array; array.resize(4); - array[0] = p_quaternion.x; - array[1] = p_quaternion.y; - array[2] = p_quaternion.z; - array[3] = p_quaternion.w; + array[0] = p_quat.x; + array[1] = p_quat.y; + array[2] = p_quat.z; + array[3] = p_quat.w; return array; } -static Quat _arr_to_quaternion(const Array &p_array) { +static Quat _arr_to_quat(const Array &p_array) { ERR_FAIL_COND_V(p_array.size() != 4, Quat()); return Quat(p_array[0], p_array[1], p_array[2], p_array[3]); } @@ -366,9 +351,9 @@ static Transform _arr_to_xform(const Array &p_array) { ERR_FAIL_COND_V(p_array.size() != 16, Transform()); Transform xform; - xform.basis.set_column(Vector3::AXIS_X, Vector3(p_array[0], p_array[1], p_array[2])); - xform.basis.set_column(Vector3::AXIS_Y, Vector3(p_array[4], p_array[5], p_array[6])); - xform.basis.set_column(Vector3::AXIS_Z, Vector3(p_array[8], p_array[9], p_array[10])); + xform.basis.set_axis(Vector3::AXIS_X, Vector3(p_array[0], p_array[1], p_array[2])); + xform.basis.set_axis(Vector3::AXIS_Y, Vector3(p_array[4], p_array[5], p_array[6])); + xform.basis.set_axis(Vector3::AXIS_Z, Vector3(p_array[8], p_array[9], p_array[10])); xform.set_origin(Vector3(p_array[12], p_array[13], p_array[14])); return xform; @@ -377,17 +362,17 @@ static Transform _arr_to_xform(const Array &p_array) { static Vector _xform_to_array(const Transform p_transform) { Vector array; array.resize(16); - Vector3 axis_x = p_transform.get_basis().get_column(Vector3::AXIS_X); + Vector3 axis_x = p_transform.get_basis().get_axis(Vector3::AXIS_X); array.write[0] = axis_x.x; array.write[1] = axis_x.y; array.write[2] = axis_x.z; array.write[3] = 0.0f; - Vector3 axis_y = p_transform.get_basis().get_column(Vector3::AXIS_Y); + Vector3 axis_y = p_transform.get_basis().get_axis(Vector3::AXIS_Y); array.write[4] = axis_y.x; array.write[5] = axis_y.y; array.write[6] = axis_y.z; array.write[7] = 0.0f; - Vector3 axis_z = p_transform.get_basis().get_column(Vector3::AXIS_Z); + Vector3 axis_z = p_transform.get_basis().get_axis(Vector3::AXIS_Z); array.write[8] = axis_z.x; array.write[9] = axis_z.y; array.write[10] = axis_z.z; @@ -431,15 +416,15 @@ Error GLTFDocument::_serialize_nodes(Ref state) { } if (!n->rotation.is_equal_approx(Quat())) { - node["rotation"] = _quaternion_to_array(n->rotation); + node["rotation"] = _quat_to_array(n->rotation); } if (!n->scale.is_equal_approx(Vector3(1.0f, 1.0f, 1.0f))) { node["scale"] = _vec3_to_arr(n->scale); } - if (!n->position.is_equal_approx(Vector3())) { - node["translation"] = _vec3_to_arr(n->position); + if (!n->translation.is_equal_approx(Vector3())) { + node["translation"] = _vec3_to_arr(n->translation); } if (n->children.size()) { Array children; @@ -448,27 +433,37 @@ Error GLTFDocument::_serialize_nodes(Ref state) { } node["children"] = children; } - - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref ext = document_extensions[ext_i]; - ERR_CONTINUE(ext.is_null()); - - Node **scene_node = state->scene_nodes.getptr(i); - - ERR_CONTINUE(!scene_node); - - Error err = ext->export_node(state, n, state->json, *scene_node); - ERR_CONTINUE(err != OK); - } - nodes.push_back(node); } state->json["nodes"] = nodes; return OK; } +String GLTFDocument::_sanitize_scene_name(Ref state, const String &p_name) { + if (state->use_legacy_names) { +#ifdef MODULE_REGEX_ENABLED + RegEx regex("([^a-zA-Z0-9_ -]+)"); + String s_name = regex.sub(p_name, "", true); + return s_name; +#else + WARN_PRINT("GLTF: Legacy scene names are not supported without the RegEx module. Falling back to new names."); +#endif // MODULE_REGEX_ENABLED + } + return p_name.validate_node_name(); +} + +String GLTFDocument::_legacy_validate_node_name(const String &p_name) { + String invalid_character = ". : @ / \""; + String name = p_name; + Vector chars = invalid_character.split(" "); + for (int i = 0; i < chars.size(); i++) { + name = name.replace(chars[i], ""); + } + return name; +} + String GLTFDocument::_gen_unique_name(Ref state, const String &p_name) { - const String s_name = p_name.validate_node_name(); + const String s_name = _sanitize_scene_name(state, p_name); String name; int index = 1; @@ -476,6 +471,9 @@ String GLTFDocument::_gen_unique_name(Ref state, const String &p_name name = s_name; if (index > 1) { + if (state->use_legacy_names) { + name += " "; + } name += itos(index); } if (!state->unique_names.has(name)) { @@ -522,18 +520,39 @@ String GLTFDocument::_gen_unique_animation_name(Ref state, const Stri return name; } -String GLTFDocument::_sanitize_bone_name(const String &p_name) { +String GLTFDocument::_sanitize_bone_name(Ref state, const String &p_name) { + if (state->use_legacy_names) { +#ifdef MODULE_REGEX_ENABLED + String name = p_name.camelcase_to_underscore(true); + RegEx pattern_del("([^a-zA-Z0-9_ ])+"); + + name = pattern_del.sub(name, "", true); + + RegEx pattern_nospace(" +"); + name = pattern_nospace.sub(name, "_", true); + + RegEx pattern_multiple("_+"); + name = pattern_multiple.sub(name, "_", true); + + RegEx pattern_padded("0+(\\d+)"); + name = pattern_padded.sub(name, "$1", true); + + return name; +#else + WARN_PRINT("GLTF: Legacy bone names are not supported without the RegEx module. Falling back to new names."); +#endif // MODULE_REGEX_ENABLED + } String name = p_name; name = name.replace(":", "_"); name = name.replace("/", "_"); + if (name.empty()) { + name = "bone"; + } return name; } String GLTFDocument::_gen_unique_bone_name(Ref state, const GLTFSkeletonIndex skel_i, const String &p_name) { - String s_name = _sanitize_bone_name(p_name); - if (s_name.empty()) { - s_name = "bone"; - } + String s_name = _sanitize_bone_name(state, p_name); String name; int index = 1; while (true) { @@ -573,9 +592,9 @@ Error GLTFDocument::_parse_scenes(Ref state) { } if (s.has("name") && !String(s["name"]).empty() && !((String)s["name"]).begins_with("Scene")) { - state->scene_name = _gen_unique_name(state, s["name"]); + state->scene_name = s["name"]; } else { - state->scene_name = _gen_unique_name(state, state->filename); + state->scene_name = state->filename; } } @@ -606,17 +625,17 @@ Error GLTFDocument::_parse_nodes(Ref state) { node->xform = _arr_to_xform(n["matrix"]); } else { if (n.has("translation")) { - node->position = _arr_to_vec3(n["translation"]); + node->translation = _arr_to_vec3(n["translation"]); } if (n.has("rotation")) { - node->rotation = _arr_to_quaternion(n["rotation"]); + node->rotation = _arr_to_quat(n["rotation"]); } if (n.has("scale")) { node->scale = _arr_to_vec3(n["scale"]); } node->xform.basis.set_quat_scale(node->rotation, node->scale); - node->xform.origin = node->position; + node->xform.origin = node->translation; } if (n.has("extensions")) { @@ -682,7 +701,7 @@ static Vector _parse_base64_uri(const String &uri) { int start = uri.find(","); ERR_FAIL_COND_V(start == -1, Vector()); - CharString substr = uri.substr(start + 1).ascii(); + CharString substr = uri.right(start + 1).ascii(); int strlen = substr.length(); @@ -718,7 +737,7 @@ Error GLTFDocument::_encode_buffer_glb(Ref state, const String &p_pat String path = p_path.get_base_dir() + "/" + filename; Error err; FileAccessRef f = FileAccess::open(path, FileAccess::WRITE, &err); - if (f.is_null()) { + if (!f) { return err; } if (buffer_data.size() == 0) { @@ -726,10 +745,14 @@ Error GLTFDocument::_encode_buffer_glb(Ref state, const String &p_pat } f->create(FileAccess::ACCESS_RESOURCES); f->store_buffer(buffer_data.ptr(), buffer_data.size()); + f->close(); gltf_buffer["uri"] = filename; gltf_buffer["byteLength"] = buffer_data.size(); buffers.push_back(gltf_buffer); } + if (!buffers.size()) { + return OK; + } state->json["buffers"] = buffers; return OK; @@ -750,7 +773,7 @@ Error GLTFDocument::_encode_buffer_bins(Ref state, const String &p_pa String path = p_path.get_base_dir() + "/" + filename; Error err; FileAccessRef f = FileAccess::open(path, FileAccess::WRITE, &err); - if (f.is_null()) { + if (!f) { return err; } if (buffer_data.size() == 0) { @@ -758,6 +781,7 @@ Error GLTFDocument::_encode_buffer_bins(Ref state, const String &p_pa } f->create(FileAccess::ACCESS_RESOURCES); f->store_buffer(buffer_data.ptr(), buffer_data.size()); + f->close(); gltf_buffer["uri"] = filename; gltf_buffer["byteLength"] = buffer_data.size(); buffers.push_back(gltf_buffer); @@ -791,8 +815,7 @@ Error GLTFDocument::_parse_buffers(Ref state, const String &p_base_pa } buffer_data = _parse_base64_uri(uri); } else { // Relative path to an external image file. - ERR_FAIL_COND_V(p_base_path.empty(), ERR_INVALID_PARAMETER); - uri = uri.uri_decode(); + uri = uri.http_unescape(); uri = p_base_path.plus_file(uri).replace("\\", "/"); // Fix for Windows. buffer_data = FileAccess::get_file_as_array(uri); ERR_FAIL_COND_V_MSG(buffer.size() == 0, ERR_PARSE_ERROR, "glTF: Couldn't load binary file as an array: " + uri); @@ -890,8 +913,18 @@ Error GLTFDocument::_encode_accessors(Ref state) { d["type"] = _get_accessor_type_name(accessor->type); d["byteOffset"] = accessor->byte_offset; d["normalized"] = accessor->normalized; - d["max"] = accessor->max; - d["min"] = accessor->min; + Array max; + max.resize(accessor->max.size()); + for (int32_t max_i = 0; max_i < max.size(); max_i++) { + max[max_i] = accessor->max[max_i]; + } + d["max"] = max; + Array min; + min.resize(accessor->min.size()); + for (int32_t min_i = 0; min_i < min.size(); min_i++) { + min[min_i] = accessor->min[min_i]; + } + d["min"] = min; d["bufferView"] = accessor->buffer_view; //optional because it may be sparse... // Dictionary s; @@ -937,58 +970,58 @@ Error GLTFDocument::_encode_accessors(Ref state) { return OK; } -String GLTFDocument::_get_accessor_type_name(const GLTFType p_type) { - if (p_type == GLTFType::TYPE_SCALAR) { +String GLTFDocument::_get_accessor_type_name(const GLTFDocument::GLTFType p_type) { + if (p_type == GLTFDocument::TYPE_SCALAR) { return "SCALAR"; } - if (p_type == GLTFType::TYPE_VEC2) { + if (p_type == GLTFDocument::TYPE_VEC2) { return "VEC2"; } - if (p_type == GLTFType::TYPE_VEC3) { + if (p_type == GLTFDocument::TYPE_VEC3) { return "VEC3"; } - if (p_type == GLTFType::TYPE_VEC4) { + if (p_type == GLTFDocument::TYPE_VEC4) { return "VEC4"; } - if (p_type == GLTFType::TYPE_MAT2) { + if (p_type == GLTFDocument::TYPE_MAT2) { return "MAT2"; } - if (p_type == GLTFType::TYPE_MAT3) { + if (p_type == GLTFDocument::TYPE_MAT3) { return "MAT3"; } - if (p_type == GLTFType::TYPE_MAT4) { + if (p_type == GLTFDocument::TYPE_MAT4) { return "MAT4"; } ERR_FAIL_V("SCALAR"); } -GLTFType GLTFDocument::_get_type_from_str(const String &p_string) { +GLTFDocument::GLTFType GLTFDocument::_get_type_from_str(const String &p_string) { if (p_string == "SCALAR") { - return GLTFType::TYPE_SCALAR; + return GLTFDocument::TYPE_SCALAR; } if (p_string == "VEC2") { - return GLTFType::TYPE_VEC2; + return GLTFDocument::TYPE_VEC2; } if (p_string == "VEC3") { - return GLTFType::TYPE_VEC3; + return GLTFDocument::TYPE_VEC3; } if (p_string == "VEC4") { - return GLTFType::TYPE_VEC4; + return GLTFDocument::TYPE_VEC4; } if (p_string == "MAT2") { - return GLTFType::TYPE_MAT2; + return GLTFDocument::TYPE_MAT2; } if (p_string == "MAT3") { - return GLTFType::TYPE_MAT3; + return GLTFDocument::TYPE_MAT3; } if (p_string == "MAT4") { - return GLTFType::TYPE_MAT4; + return GLTFDocument::TYPE_MAT4; } - ERR_FAIL_V(GLTFType::TYPE_SCALAR); + ERR_FAIL_V(GLTFDocument::TYPE_SCALAR); } Error GLTFDocument::_parse_accessors(Ref state) { @@ -1022,11 +1055,21 @@ Error GLTFDocument::_parse_accessors(Ref state) { } if (d.has("max")) { - accessor->max = d["max"]; + Array max = d["max"]; + accessor->max.resize(max.size()); + PoolVector::Write max_write = accessor->max.write(); + for (int32_t max_i = 0; max_i < accessor->max.size(); max_i++) { + max_write[max_i] = max[max_i]; + } } if (d.has("min")) { - accessor->min = d["min"]; + Array min = d["min"]; + accessor->min.resize(min.size()); + PoolVector::Write min_write = accessor->min.write(); + for (int32_t min_i = 0; min_i < accessor->min.size(); min_i++) { + min_write[min_i] = min[min_i]; + } } if (d.has("sparse")) { @@ -1106,7 +1149,7 @@ String GLTFDocument::_get_type_name(const GLTFType p_component) { return names[p_component]; } -Error GLTFDocument::_encode_buffer_view(Ref state, const float *src, const int count, const GLTFType type, const int component_type, const bool normalized, const int byte_offset, const bool for_vertex, GLTFBufferViewIndex &r_accessor) { +Error GLTFDocument::_encode_buffer_view(Ref state, const double *src, const int count, const GLTFType type, const int component_type, const bool normalized, const int byte_offset, const bool for_vertex, GLTFBufferViewIndex &r_accessor) { const int component_count_for_type[7] = { 1, 2, 3, 4, 4, 9, 16 }; @@ -1511,25 +1554,25 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref state, c } const int element_count = 1; const int ret_size = p_attribs.size(); - PoolRealArray attribs; + Vector attribs; attribs.resize(ret_size); - PoolRealArray type_max; + Vector type_max; type_max.resize(element_count); - PoolRealArray type_min; + Vector type_min; type_min.resize(element_count); for (int i = 0; i < p_attribs.size(); i++) { - attribs.set(i, Math::stepify(p_attribs[i], 1.0)); + attribs.write[i] = Math::stepify(p_attribs[i], 1.0); if (i == 0) { for (int32_t type_i = 0; type_i < element_count; type_i++) { - type_max.set(type_i, attribs[(i * element_count) + type_i]); - type_min.set(type_i, attribs[(i * element_count) + type_i]); + type_max.write[type_i] = attribs[(i * element_count) + type_i]; + type_min.write[type_i] = attribs[(i * element_count) + type_i]; } } for (int32_t type_i = 0; type_i < element_count; type_i++) { - type_max.set(type_i, MAX(attribs[(i * element_count) + type_i], type_max[type_i])); - type_min.set(type_i, MIN(attribs[(i * element_count) + type_i], type_min[type_i])); - type_max.set(type_i, _filter_number(type_max[type_i])); - type_min.set(type_i, _filter_number(type_min[type_i])); + type_max.write[type_i] = MAX(attribs[(i * element_count) + type_i], type_max[type_i]); + type_min.write[type_i] = MIN(attribs[(i * element_count) + type_i], type_min[type_i]); + type_max.write[type_i] = _filter_number(type_max.write[type_i]); + type_min.write[type_i] = _filter_number(type_min.write[type_i]); } } @@ -1539,19 +1582,29 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref state, c accessor.instance(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFType type = GLTFType::TYPE_SCALAR; + const GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR; const int component_type = GLTFDocument::COMPONENT_TYPE_INT; - accessor->max = type_max; - accessor->min = type_min; + PoolVector max; + max.resize(type_max.size()); + PoolVector::Write write_max = max.write(); + for (int32_t max_i = 0; max_i < max.size(); max_i++) { + write_max[max_i] = type_max[max_i]; + } + accessor->max = max; + PoolVector min; + min.resize(type_min.size()); + PoolVector::Write write_min = min.write(); + for (int32_t min_i = 0; min_i < min.size(); min_i++) { + write_min[min_i] = type_min[min_i]; + } + accessor->min = min; accessor->normalized = false; accessor->count = ret_size; accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - - PoolRealArray::Read attrr = attribs.read(); - Error err = _encode_buffer_view(state, attrr.ptr(), attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(state, attribs.ptr(), attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } @@ -1560,9 +1613,9 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref state, c return state->accessors.size() - 1; } -PoolIntArray GLTFDocument::_decode_accessor_as_ints(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { +Vector GLTFDocument::_decode_accessor_as_ints(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { const Vector attribs = _decode_accessor(state, p_accessor, p_for_vertex); - PoolIntArray ret; + Vector ret; if (attribs.size() == 0) { return ret; @@ -1571,18 +1624,17 @@ PoolIntArray GLTFDocument::_decode_accessor_as_ints(Ref state, const const double *attribs_ptr = attribs.ptr(); const int ret_size = attribs.size(); ret.resize(ret_size); - PoolIntArray::Write w = ret.write(); { for (int i = 0; i < ret_size; i++) { - w[i] = int(attribs_ptr[i]); + ret.write[i] = int(attribs_ptr[i]); } } return ret; } -PoolVector GLTFDocument::_decode_accessor_as_floats(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { +Vector GLTFDocument::_decode_accessor_as_floats(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { const Vector attribs = _decode_accessor(state, p_accessor, p_for_vertex); - PoolVector ret; + Vector ret; if (attribs.size() == 0) { return ret; @@ -1593,7 +1645,7 @@ PoolVector GLTFDocument::_decode_accessor_as_floats(Ref state, ret.resize(ret_size); { for (int i = 0; i < ret_size; i++) { - ret.set(i, float(attribs_ptr[i])); + ret.write[i] = float(attribs_ptr[i]); } } return ret; @@ -1606,17 +1658,17 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref state, c const int element_count = 2; const int ret_size = p_attribs.size() * element_count; - PoolRealArray attribs; + Vector attribs; attribs.resize(ret_size); - PoolRealArray type_max; + Vector type_max; type_max.resize(element_count); - PoolRealArray type_min; + Vector type_min; type_min.resize(element_count); for (int i = 0; i < p_attribs.size(); i++) { Vector2 attrib = p_attribs[i]; - attribs.set((i * element_count) + 0, Math::stepify(attrib.x, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 1, Math::stepify(attrib.y, CMP_NORMALIZE_TOLERANCE)); + attribs.write[(i * element_count) + 0] = Math::stepify(attrib.x, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 1] = Math::stepify(attrib.y, CMP_NORMALIZE_TOLERANCE); _calc_accessor_min_max(i, element_count, type_max, attribs, type_min); } @@ -1626,19 +1678,29 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref state, c accessor.instance(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFType type = GLTFType::TYPE_VEC2; + const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC2; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; - accessor->max = type_max; - accessor->min = type_min; + PoolVector max; + max.resize(type_max.size()); + PoolVector::Write write_max = max.write(); + for (int32_t max_i = 0; max_i < max.size(); max_i++) { + write_max[max_i] = type_max[max_i]; + } + accessor->max = max; + PoolVector min; + min.resize(type_min.size()); + PoolVector::Write write_min = min.write(); + for (int32_t min_i = 0; min_i < min.size(); min_i++) { + write_min[min_i] = type_min[min_i]; + } + accessor->min = min; accessor->normalized = false; accessor->count = p_attribs.size(); accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - - PoolRealArray::Read attribsr = attribs.read(); - Error err = _encode_buffer_view(state, attribsr.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } @@ -1653,20 +1715,20 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref state, } const int ret_size = p_attribs.size() * 4; - PoolRealArray attribs; + Vector attribs; attribs.resize(ret_size); const int element_count = 4; - PoolRealArray type_max; + Vector type_max; type_max.resize(element_count); - PoolRealArray type_min; + Vector type_min; type_min.resize(element_count); for (int i = 0; i < p_attribs.size(); i++) { Color attrib = p_attribs[i]; - attribs.set((i * element_count) + 0, Math::stepify(attrib.r, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 1, Math::stepify(attrib.g, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 2, Math::stepify(attrib.b, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 3, Math::stepify(attrib.a, CMP_NORMALIZE_TOLERANCE)); + attribs.write[(i * element_count) + 0] = Math::stepify(attrib.r, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 1] = Math::stepify(attrib.g, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 2] = Math::stepify(attrib.b, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 3] = Math::stepify(attrib.a, CMP_NORMALIZE_TOLERANCE); _calc_accessor_min_max(i, element_count, type_max, attribs, type_min); } @@ -1677,19 +1739,28 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref state, accessor.instance(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFType type = GLTFType::TYPE_VEC4; + const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; - - accessor->max = type_max; - accessor->min = type_min; + PoolVector max; + max.resize(type_max.size()); + PoolVector::Write write_max = max.write(); + for (int32_t max_i = 0; max_i < max.size(); max_i++) { + write_max[max_i] = type_max[max_i]; + } + accessor->max = max; + PoolVector min; + min.resize(type_min.size()); + PoolVector::Write write_min = min.write(); + for (int32_t min_i = 0; min_i < min.size(); min_i++) { + write_min[min_i] = type_min[min_i]; + } + accessor->min = min; accessor->normalized = false; accessor->count = p_attribs.size(); accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - - PoolRealArray::Read attribsr = attribs.read(); - Error err = _encode_buffer_view(state, attribsr.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } @@ -1698,18 +1769,18 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref state, return state->accessors.size() - 1; } -void GLTFDocument::_calc_accessor_min_max(int i, const int element_count, PoolRealArray &type_max, PoolRealArray attribs, PoolRealArray &type_min) { +void GLTFDocument::_calc_accessor_min_max(int i, const int element_count, Vector &type_max, Vector attribs, Vector &type_min) { if (i == 0) { for (int32_t type_i = 0; type_i < element_count; type_i++) { - type_max.set(type_i, attribs[(i * element_count) + type_i]); - type_min.set(type_i, attribs[(i * element_count) + type_i]); + type_max.write[type_i] = attribs[(i * element_count) + type_i]; + type_min.write[type_i] = attribs[(i * element_count) + type_i]; } } for (int32_t type_i = 0; type_i < element_count; type_i++) { - type_max.set(type_i, MAX(attribs[(i * element_count) + type_i], type_max[type_i])); - type_min.set(type_i, MIN(attribs[(i * element_count) + type_i], type_min[type_i])); - type_max.set(type_i, _filter_number(type_max[type_i])); - type_min.set(type_i, _filter_number(type_min[type_i])); + type_max.write[type_i] = MAX(attribs[(i * element_count) + type_i], type_max[type_i]); + type_min.write[type_i] = MIN(attribs[(i * element_count) + type_i], type_min[type_i]); + type_max.write[type_i] = _filter_number(type_max.write[type_i]); + type_min.write[type_i] = _filter_number(type_min.write[type_i]); } } @@ -1719,21 +1790,21 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref state } const int ret_size = p_attribs.size() * 4; - PoolRealArray attribs; + Vector attribs; attribs.resize(ret_size); const int element_count = 4; - PoolRealArray type_max; + Vector type_max; type_max.resize(element_count); - PoolRealArray type_min; + Vector type_min; type_min.resize(element_count); for (int i = 0; i < p_attribs.size(); i++) { Color attrib = p_attribs[i]; - attribs.set((i * element_count) + 0, Math::stepify(attrib.r, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 1, Math::stepify(attrib.g, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 2, Math::stepify(attrib.b, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 3, Math::stepify(attrib.a, CMP_NORMALIZE_TOLERANCE)); + attribs.write[(i * element_count) + 0] = Math::stepify(attrib.r, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 1] = Math::stepify(attrib.g, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 2] = Math::stepify(attrib.b, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 3] = Math::stepify(attrib.a, CMP_NORMALIZE_TOLERANCE); _calc_accessor_min_max(i, element_count, type_max, attribs, type_min); } @@ -1744,18 +1815,29 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref state accessor.instance(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFType type = GLTFType::TYPE_VEC4; + const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; - accessor->max = type_max; - accessor->min = type_min; + PoolVector max; + max.resize(type_max.size()); + PoolVector::Write write_max = max.write(); + for (int32_t max_i = 0; max_i < max.size(); max_i++) { + write_max[max_i] = type_max[max_i]; + } + accessor->max = max; + PoolVector min; + min.resize(type_min.size()); + PoolVector::Write write_min = min.write(); + for (int32_t min_i = 0; min_i < min.size(); min_i++) { + write_min[min_i] = type_min[min_i]; + } + accessor->min = min; accessor->normalized = false; accessor->count = p_attribs.size(); accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - PoolRealArray::Read attribsr = attribs.read(); - Error err = _encode_buffer_view(state, attribsr.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } @@ -1771,20 +1853,19 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref state, const int element_count = 4; const int ret_size = p_attribs.size() * element_count; - PoolRealArray attribs; + Vector attribs; attribs.resize(ret_size); - PoolRealArray type_max; + Vector type_max; type_max.resize(element_count); - PoolRealArray type_min; + Vector type_min; type_min.resize(element_count); for (int i = 0; i < p_attribs.size(); i++) { Color attrib = p_attribs[i]; - attribs.set((i * element_count) + 0, Math::stepify(attrib.r, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 1, Math::stepify(attrib.g, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 2, Math::stepify(attrib.b, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 3, Math::stepify(attrib.a, CMP_NORMALIZE_TOLERANCE)); - + attribs.write[(i * element_count) + 0] = Math::stepify(attrib.r, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 1] = Math::stepify(attrib.g, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 2] = Math::stepify(attrib.b, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 3] = Math::stepify(attrib.a, CMP_NORMALIZE_TOLERANCE); _calc_accessor_min_max(i, element_count, type_max, attribs, type_min); } ERR_FAIL_COND_V(attribs.size() % element_count != 0, -1); @@ -1793,19 +1874,29 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref state, accessor.instance(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFType type = GLTFType::TYPE_VEC4; + const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT; - accessor->max = type_max; - accessor->min = type_min; + PoolVector max; + max.resize(type_max.size()); + PoolVector::Write write_max = max.write(); + for (int32_t max_i = 0; max_i < max.size(); max_i++) { + write_max[max_i] = type_max[max_i]; + } + accessor->max = max; + PoolVector min; + min.resize(type_min.size()); + PoolVector::Write write_min = min.write(); + for (int32_t min_i = 0; min_i < min.size(); min_i++) { + write_min[min_i] = type_min[min_i]; + } + accessor->min = min; accessor->normalized = false; accessor->count = p_attribs.size(); accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - - PoolRealArray::Read attribsr = attribs.read(); - Error err = _encode_buffer_view(state, attribsr.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } @@ -1814,26 +1905,26 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref state, return state->accessors.size() - 1; } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref state, const PoolVector p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quats(Ref state, const Vector p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } const int element_count = 4; const int ret_size = p_attribs.size() * element_count; - PoolRealArray attribs; + Vector attribs; attribs.resize(ret_size); - PoolRealArray type_max; + Vector type_max; type_max.resize(element_count); - PoolRealArray type_min; + Vector type_min; type_min.resize(element_count); for (int i = 0; i < p_attribs.size(); i++) { - Quat quaternion = p_attribs[i]; - attribs.set((i * element_count) + 0, Math::stepify(quaternion.x, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 1, Math::stepify(quaternion.y, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 2, Math::stepify(quaternion.z, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 3, Math::stepify(quaternion.w, CMP_NORMALIZE_TOLERANCE)); + Quat quat = p_attribs[i]; + attribs.write[(i * element_count) + 0] = Math::stepify(quat.x, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 1] = Math::stepify(quat.y, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 2] = Math::stepify(quat.z, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 3] = Math::stepify(quat.w, CMP_NORMALIZE_TOLERANCE); _calc_accessor_min_max(i, element_count, type_max, attribs, type_min); } @@ -1844,19 +1935,29 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref s accessor.instance(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFType type = GLTFType::TYPE_VEC4; + const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; - accessor->max = type_max; - accessor->min = type_min; + PoolVector max; + max.resize(type_max.size()); + PoolVector::Write write_max = max.write(); + for (int32_t max_i = 0; max_i < max.size(); max_i++) { + write_max[max_i] = type_max[max_i]; + } + accessor->max = max; + PoolVector min; + min.resize(type_min.size()); + PoolVector::Write write_min = min.write(); + for (int32_t min_i = 0; min_i < min.size(); min_i++) { + write_min[min_i] = type_min[min_i]; + } + accessor->min = min; accessor->normalized = false; accessor->count = p_attribs.size(); accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - - PoolRealArray::Read attribsr = attribs.read(); - Error err = _encode_buffer_view(state, attribsr.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } @@ -1885,22 +1986,22 @@ Vector GLTFDocument::_decode_accessor_as_vec2(Ref state, con return ret; } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref state, const PoolRealArray p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref state, const Vector p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } const int element_count = 1; const int ret_size = p_attribs.size(); - PoolRealArray attribs; + Vector attribs; attribs.resize(ret_size); - PoolRealArray type_max; + Vector type_max; type_max.resize(element_count); - PoolRealArray type_min; + Vector type_min; type_min.resize(element_count); for (int i = 0; i < p_attribs.size(); i++) { - attribs.set(i, Math::stepify(p_attribs[i], CMP_NORMALIZE_TOLERANCE)); + attribs.write[i] = Math::stepify(p_attribs[i], CMP_NORMALIZE_TOLERANCE); _calc_accessor_min_max(i, element_count, type_max, attribs, type_min); } @@ -1911,19 +2012,29 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref state, accessor.instance(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFType type = GLTFType::TYPE_SCALAR; + const GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; - accessor->max = type_max; - accessor->min = type_min; + PoolVector max; + max.resize(type_max.size()); + PoolVector::Write write_max = max.write(); + for (int32_t max_i = 0; max_i < max.size(); max_i++) { + write_max[max_i] = type_max[max_i]; + } + accessor->max = max; + PoolVector min; + min.resize(type_min.size()); + PoolVector::Write write_min = min.write(); + for (int32_t min_i = 0; min_i < min.size(); min_i++) { + write_min[min_i] = type_min[min_i]; + } + accessor->min = min; accessor->normalized = false; accessor->count = ret_size; accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - - PoolRealArray::Read attribsr = attribs.read(); - Error err = _encode_buffer_view(state, attribsr.ptr(), attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(state, attribs.ptr(), attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } @@ -1932,24 +2043,24 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref state, return state->accessors.size() - 1; } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref state, const PoolVector p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref state, const Vector p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } const int element_count = 3; const int ret_size = p_attribs.size() * element_count; - PoolRealArray attribs; + Vector attribs; attribs.resize(ret_size); - PoolRealArray type_max; + Vector type_max; type_max.resize(element_count); - PoolRealArray type_min; + Vector type_min; type_min.resize(element_count); for (int i = 0; i < p_attribs.size(); i++) { Vector3 attrib = p_attribs[i]; - attribs.set((i * element_count) + 0, Math::stepify(attrib.x, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 1, Math::stepify(attrib.y, CMP_NORMALIZE_TOLERANCE)); - attribs.set((i * element_count) + 2, Math::stepify(attrib.z, CMP_NORMALIZE_TOLERANCE)); + attribs.write[(i * element_count) + 0] = Math::stepify(attrib.x, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 1] = Math::stepify(attrib.y, CMP_NORMALIZE_TOLERANCE); + attribs.write[(i * element_count) + 2] = Math::stepify(attrib.z, CMP_NORMALIZE_TOLERANCE); _calc_accessor_min_max(i, element_count, type_max, attribs, type_min); } @@ -1959,19 +2070,29 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref state, c accessor.instance(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFType type = GLTFType::TYPE_VEC3; + const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC3; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; - accessor->max = type_max; - accessor->min = type_min; + PoolVector max; + max.resize(type_max.size()); + PoolVector::Write write_max = max.write(); + for (int32_t max_i = 0; max_i < max.size(); max_i++) { + write_max[max_i] = type_max[max_i]; + } + accessor->max = max; + PoolVector min; + min.resize(type_min.size()); + PoolVector::Write write_min = min.write(); + for (int32_t min_i = 0; min_i < min.size(); min_i++) { + write_min[min_i] = type_min[min_i]; + } + accessor->min = min; accessor->normalized = false; accessor->count = p_attribs.size(); accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - - PoolRealArray::Read attribsr = attribs.read(); - Error err = _encode_buffer_view(state, attribsr.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } @@ -1986,40 +2107,40 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref state, } const int element_count = 16; const int ret_size = p_attribs.size() * element_count; - PoolRealArray attribs; + Vector attribs; attribs.resize(ret_size); - PoolRealArray type_max; + Vector type_max; type_max.resize(element_count); - PoolRealArray type_min; + Vector type_min; type_min.resize(element_count); for (int i = 0; i < p_attribs.size(); i++) { Transform attrib = p_attribs[i]; Basis basis = attrib.get_basis(); - Vector3 axis_0 = basis.get_column(Vector3::AXIS_X); + Vector3 axis_0 = basis.get_axis(Vector3::AXIS_X); - attribs.set(i * element_count + 0, Math::stepify(axis_0.x, CMP_NORMALIZE_TOLERANCE)); - attribs.set(i * element_count + 1, Math::stepify(axis_0.y, CMP_NORMALIZE_TOLERANCE)); - attribs.set(i * element_count + 2, Math::stepify(axis_0.z, CMP_NORMALIZE_TOLERANCE)); - attribs.set(i * element_count + 3, 0.0); + attribs.write[i * element_count + 0] = Math::stepify(axis_0.x, CMP_NORMALIZE_TOLERANCE); + attribs.write[i * element_count + 1] = Math::stepify(axis_0.y, CMP_NORMALIZE_TOLERANCE); + attribs.write[i * element_count + 2] = Math::stepify(axis_0.z, CMP_NORMALIZE_TOLERANCE); + attribs.write[i * element_count + 3] = 0.0; - Vector3 axis_1 = basis.get_column(Vector3::AXIS_Y); - attribs.set(i * element_count + 4, Math::stepify(axis_1.x, CMP_NORMALIZE_TOLERANCE)); - attribs.set(i * element_count + 5, Math::stepify(axis_1.y, CMP_NORMALIZE_TOLERANCE)); - attribs.set(i * element_count + 6, Math::stepify(axis_1.z, CMP_NORMALIZE_TOLERANCE)); - attribs.set(i * element_count + 7, 0.0); + Vector3 axis_1 = basis.get_axis(Vector3::AXIS_Y); + attribs.write[i * element_count + 4] = Math::stepify(axis_1.x, CMP_NORMALIZE_TOLERANCE); + attribs.write[i * element_count + 5] = Math::stepify(axis_1.y, CMP_NORMALIZE_TOLERANCE); + attribs.write[i * element_count + 6] = Math::stepify(axis_1.z, CMP_NORMALIZE_TOLERANCE); + attribs.write[i * element_count + 7] = 0.0; - Vector3 axis_2 = basis.get_column(Vector3::AXIS_Z); - attribs.set(i * element_count + 8, Math::stepify(axis_2.x, CMP_NORMALIZE_TOLERANCE)); - attribs.set(i * element_count + 9, Math::stepify(axis_2.y, CMP_NORMALIZE_TOLERANCE)); - attribs.set(i * element_count + 10, Math::stepify(axis_2.z, CMP_NORMALIZE_TOLERANCE)); - attribs.set(i * element_count + 11, 0.0); + Vector3 axis_2 = basis.get_axis(Vector3::AXIS_Z); + attribs.write[i * element_count + 8] = Math::stepify(axis_2.x, CMP_NORMALIZE_TOLERANCE); + attribs.write[i * element_count + 9] = Math::stepify(axis_2.y, CMP_NORMALIZE_TOLERANCE); + attribs.write[i * element_count + 10] = Math::stepify(axis_2.z, CMP_NORMALIZE_TOLERANCE); + attribs.write[i * element_count + 11] = 0.0; Vector3 origin = attrib.get_origin(); - attribs.set(i * element_count + 12, Math::stepify(origin.x, CMP_NORMALIZE_TOLERANCE)); - attribs.set(i * element_count + 13, Math::stepify(origin.y, CMP_NORMALIZE_TOLERANCE)); - attribs.set(i * element_count + 14, Math::stepify(origin.z, CMP_NORMALIZE_TOLERANCE)); - attribs.set(i * element_count + 15, 1.0); + attribs.write[i * element_count + 12] = Math::stepify(origin.x, CMP_NORMALIZE_TOLERANCE); + attribs.write[i * element_count + 13] = Math::stepify(origin.y, CMP_NORMALIZE_TOLERANCE); + attribs.write[i * element_count + 14] = Math::stepify(origin.z, CMP_NORMALIZE_TOLERANCE); + attribs.write[i * element_count + 15] = 1.0; _calc_accessor_min_max(i, element_count, type_max, attribs, type_min); } @@ -2029,19 +2150,29 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref state, accessor.instance(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFType type = GLTFType::TYPE_MAT4; + const GLTFDocument::GLTFType type = GLTFDocument::TYPE_MAT4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; - accessor->max = type_max; - accessor->min = type_min; + PoolVector max; + max.resize(type_max.size()); + PoolVector::Write write_max = max.write(); + for (int32_t max_i = 0; max_i < max.size(); max_i++) { + write_max[max_i] = type_max[max_i]; + } + accessor->max = max; + PoolVector min; + min.resize(type_min.size()); + PoolVector::Write write_min = min.write(); + for (int32_t min_i = 0; min_i < min.size(); min_i++) { + write_min[min_i] = type_min[min_i]; + } + accessor->min = min; accessor->normalized = false; accessor->count = p_attribs.size(); accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - - PoolRealArray::Read attribsr = attribs.read(); - Error err = _encode_buffer_view(state, attribsr.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } @@ -2050,9 +2181,9 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref state, return state->accessors.size() - 1; } -PoolVector3Array GLTFDocument::_decode_accessor_as_vec3(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { +Vector GLTFDocument::_decode_accessor_as_vec3(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { const Vector attribs = _decode_accessor(state, p_accessor, p_for_vertex); - PoolVector3Array ret; + Vector ret; if (attribs.size() == 0) { return ret; @@ -2062,10 +2193,9 @@ PoolVector3Array GLTFDocument::_decode_accessor_as_vec3(Ref state, co const double *attribs_ptr = attribs.ptr(); const int ret_size = attribs.size() / 3; ret.resize(ret_size); - PoolVector3Array::Write w = ret.write(); { for (int i = 0; i < ret_size; i++) { - w[i] = Vector3(attribs_ptr[i * 3 + 0], attribs_ptr[i * 3 + 1], attribs_ptr[i * 3 + 2]); + ret.write[i] = Vector3(attribs_ptr[i * 3 + 0], attribs_ptr[i * 3 + 1], attribs_ptr[i * 3 + 2]); } } return ret; @@ -2097,9 +2227,9 @@ Vector GLTFDocument::_decode_accessor_as_color(Ref state, cons } return ret; } -PoolVector GLTFDocument::_decode_accessor_as_quaternion(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { +Vector GLTFDocument::_decode_accessor_as_quat(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { const Vector attribs = _decode_accessor(state, p_accessor, p_for_vertex); - PoolVector ret; + Vector ret; if (attribs.size() == 0) { return ret; @@ -2111,7 +2241,7 @@ PoolVector GLTFDocument::_decode_accessor_as_quaternion(Ref sta ret.resize(ret_size); { for (int i = 0; i < ret_size; i++) { - ret.set(i, Quat(attribs_ptr[i * 4 + 0], attribs_ptr[i * 4 + 1], attribs_ptr[i * 4 + 2], attribs_ptr[i * 4 + 3]).normalized()); + ret.write[i] = Quat(attribs_ptr[i * 4 + 0], attribs_ptr[i * 4 + 1], attribs_ptr[i * 4 + 2], attribs_ptr[i * 4 + 3]).normalized(); } } return ret; @@ -2144,9 +2274,9 @@ Vector GLTFDocument::_decode_accessor_as_basis(Ref state, cons ERR_FAIL_COND_V(attribs.size() % 9 != 0, ret); ret.resize(attribs.size() / 9); for (int i = 0; i < ret.size(); i++) { - ret.write[i].set_column(0, Vector3(attribs[i * 9 + 0], attribs[i * 9 + 1], attribs[i * 9 + 2])); - ret.write[i].set_column(1, Vector3(attribs[i * 9 + 3], attribs[i * 9 + 4], attribs[i * 9 + 5])); - ret.write[i].set_column(2, Vector3(attribs[i * 9 + 6], attribs[i * 9 + 7], attribs[i * 9 + 8])); + ret.write[i].set_axis(0, Vector3(attribs[i * 9 + 0], attribs[i * 9 + 1], attribs[i * 9 + 2])); + ret.write[i].set_axis(1, Vector3(attribs[i * 9 + 3], attribs[i * 9 + 4], attribs[i * 9 + 5])); + ret.write[i].set_axis(2, Vector3(attribs[i * 9 + 6], attribs[i * 9 + 7], attribs[i * 9 + 8])); } return ret; } @@ -2162,9 +2292,9 @@ Vector GLTFDocument::_decode_accessor_as_xform(Ref state, ERR_FAIL_COND_V(attribs.size() % 16 != 0, ret); ret.resize(attribs.size() / 16); for (int i = 0; i < ret.size(); i++) { - ret.write[i].basis.set_column(0, Vector3(attribs[i * 16 + 0], attribs[i * 16 + 1], attribs[i * 16 + 2])); - ret.write[i].basis.set_column(1, Vector3(attribs[i * 16 + 4], attribs[i * 16 + 5], attribs[i * 16 + 6])); - ret.write[i].basis.set_column(2, Vector3(attribs[i * 16 + 8], attribs[i * 16 + 9], attribs[i * 16 + 10])); + ret.write[i].basis.set_axis(0, Vector3(attribs[i * 16 + 0], attribs[i * 16 + 1], attribs[i * 16 + 2])); + ret.write[i].basis.set_axis(1, Vector3(attribs[i * 16 + 4], attribs[i * 16 + 5], attribs[i * 16 + 6])); + ret.write[i].basis.set_axis(2, Vector3(attribs[i * 16 + 8], attribs[i * 16 + 9], attribs[i * 16 + 10])); ret.write[i].set_origin(Vector3(attribs[i * 16 + 12], attribs[i * 16 + 13], attribs[i * 16 + 14])); } return ret; @@ -2174,7 +2304,7 @@ Error GLTFDocument::_serialize_meshes(Ref state) { Array meshes; for (GLTFMeshIndex gltf_mesh_i = 0; gltf_mesh_i < state->meshes.size(); gltf_mesh_i++) { print_verbose("glTF: Serializing mesh: " + itos(gltf_mesh_i)); - Ref import_mesh = state->meshes.write[gltf_mesh_i]->get_mesh(); + Ref import_mesh = state->meshes.write[gltf_mesh_i]->get_mesh(); if (import_mesh.is_null()) { continue; } @@ -2189,7 +2319,7 @@ Error GLTFDocument::_serialize_meshes(Ref state) { for (int surface_i = 0; surface_i < import_mesh->get_surface_count(); surface_i++) { Array targets; Dictionary primitive; - Mesh::PrimitiveType primitive_type = import_mesh->get_surface_primitive_type(surface_i); + Mesh::PrimitiveType primitive_type = import_mesh->surface_get_primitive_type(surface_i); switch (primitive_type) { case Mesh::PRIMITIVE_POINTS: { primitive["mode"] = 0; @@ -2224,15 +2354,12 @@ Error GLTFDocument::_serialize_meshes(Ref 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; + Array array = import_mesh->surface_get_arrays(surface_i); Dictionary attributes; { - PoolVector a = array[Mesh::ARRAY_VERTEX]; + Vector 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 a = array[Mesh::ARRAY_TANGENT]; @@ -2255,10 +2382,10 @@ Error GLTFDocument::_serialize_meshes(Ref state) { Vector a = array[Mesh::ARRAY_NORMAL]; if (a.size()) { const int ret_size = a.size(); - PoolVector attribs; + Vector attribs; attribs.resize(ret_size); for (int i = 0; i < ret_size; i++) { - attribs.set(i, Vector3(a[i]).normalized()); + attribs.write[i] = Vector3(a[i]).normalized(); } attributes["NORMAL"] = _encode_accessor_as_vec3(state, attribs, true); } @@ -2275,67 +2402,13 @@ Error GLTFDocument::_serialize_meshes(Ref state) { attributes["TEXCOORD_1"] = _encode_accessor_as_vec2(state, a, true); } } - /* - for (int custom_i = 0; custom_i < 3; custom_i++) { - Vector 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 empty; - empty.resize(vertex_num); - attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, empty, true); - } - } - - LocalVector first_channel; - first_channel.resize(vertex_num); - LocalVector 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 a = array[Mesh::ARRAY_COLOR]; if (a.size()) { attributes["COLOR_0"] = _encode_accessor_as_color(state, a, true); } } - HashMap joint_i_to_bone_i; + Map joint_i_to_bone_i; for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) { GLTFSkinIndex skin_i = -1; if (state->nodes[node_i]->mesh == gltf_mesh_i) { @@ -2363,29 +2436,8 @@ Error GLTFDocument::_serialize_meshes(Ref state) { } } attributes["JOINTS_0"] = _encode_accessor_as_joints(state, attribs, true); - } else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) { - Vector joints_0; - joints_0.resize(vertex_num); - Vector joints_1; - joints_1.resize(vertex_num); - int32_t weights_8_count = JOINT_GROUP_SIZE * 2; - 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]; - joint_0.b = a[vertex_i * weights_8_count + 2]; - joint_0.a = a[vertex_i * weights_8_count + 3]; - joints_0.write[vertex_i] = joint_0; - Color joint_1; - joint_1.r = a[vertex_i * weights_8_count + 4]; - joint_1.g = a[vertex_i * weights_8_count + 5]; - joint_1.b = a[vertex_i * weights_8_count + 6]; - joint_1.a = a[vertex_i * weights_8_count + 7]; - joints_1.write[vertex_i] = joint_1; - } - attributes["JOINTS_0"] = _encode_accessor_as_joints(state, joints_0, true); - attributes["JOINTS_1"] = _encode_accessor_as_joints(state, joints_1, true); } + ERR_FAIL_COND_V((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size(), FAILED); } { const Array &a = array[Mesh::ARRAY_WEIGHTS]; @@ -2399,12 +2451,13 @@ Error GLTFDocument::_serialize_meshes(Ref 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 weights_0; - weights_0.resize(vertex_num); + weights_0.resize(vertex_count); Vector weights_1; - weights_1.resize(vertex_num); + weights_1.resize(vertex_count); int32_t weights_8_count = JOINT_GROUP_SIZE * 2; - for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) { + for (int32_t vertex_i = 0; vertex_i < vertex_count; 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]; @@ -2462,32 +2515,32 @@ Error GLTFDocument::_serialize_meshes(Ref state) { print_verbose("glTF: Mesh has targets"); if (import_mesh->get_blend_shape_count()) { ArrayMesh::BlendShapeMode shape_mode = import_mesh->get_blend_shape_mode(); - for (int morph_i = 0; morph_i < import_mesh->get_blend_shape_count(); morph_i++) { - Array array_morph = import_mesh->get_surface_blend_shape_arrays(surface_i, morph_i); + Array array_morphs = import_mesh->surface_get_blend_shape_arrays(surface_i); + for (int morph_i = 0; morph_i < array_morphs.size(); morph_i++) { + Array array_morph = array_morphs[morph_i]; Dictionary t; - PoolVector varr = array_morph[Mesh::ARRAY_VERTEX]; - Array mesh_arrays = import_mesh->get_surface_arrays(surface_i); + Vector varr = array_morph[Mesh::ARRAY_VERTEX]; + Array mesh_arrays = import_mesh->surface_get_arrays(surface_i); if (varr.size()) { - PoolVector src_varr = array[Mesh::ARRAY_VERTEX]; + Vector src_varr = array[Mesh::ARRAY_VERTEX]; if (shape_mode == ArrayMesh::BlendShapeMode::BLEND_SHAPE_MODE_NORMALIZED) { const int max_idx = src_varr.size(); for (int blend_i = 0; blend_i < max_idx; blend_i++) { - varr.set(blend_i, Vector3(varr[blend_i]) - src_varr[blend_i]); + varr.write[blend_i] = Vector3(varr[blend_i]) - src_varr[blend_i]; } } t["POSITION"] = _encode_accessor_as_vec3(state, varr, true); } - PoolVector narr = array_morph[Mesh::ARRAY_NORMAL]; + Vector narr = array_morph[Mesh::ARRAY_NORMAL]; if (narr.size()) { t["NORMAL"] = _encode_accessor_as_vec3(state, narr, true); } - - PoolRealArray tarr = array_morph[Mesh::ARRAY_TANGENT]; + Vector tarr = array_morph[Mesh::ARRAY_TANGENT]; if (tarr.size()) { const int ret_size = tarr.size() / 4; - PoolVector attribs; + Vector attribs; attribs.resize(ret_size); for (int i = 0; i < ret_size; i++) { Vector3 vec3; @@ -2500,25 +2553,23 @@ Error GLTFDocument::_serialize_meshes(Ref state) { targets.push_back(t); } } - Variant v; if (surface_i < instance_materials.size()) { v = instance_materials.get(surface_i); } Ref mat = v; if (!mat.is_valid()) { - mat = import_mesh->get_surface_material(surface_i); + mat = import_mesh->surface_get_material(surface_i); } if (mat.is_valid()) { - GLTFMaterialIndex *material_cache_i = state->material_cache.getptr(mat); - - if (material_cache_i && (*material_cache_i) != -1) { - primitive["material"] = (*material_cache_i); + Map, GLTFMaterialIndex>::Element *material_cache_i = state->material_cache.find(mat); + if (material_cache_i && material_cache_i->get() != -1) { + primitive["material"] = material_cache_i->get(); } else { GLTFMaterialIndex mat_i = state->materials.size(); state->materials.push_back(mat); primitive["material"] = mat_i; - state->material_cache.set(mat, mat_i); + state->material_cache.insert(mat, mat_i); } } @@ -2567,6 +2618,7 @@ Error GLTFDocument::_parse_meshes(Ref state) { return OK; } + bool has_warned = false; Array meshes = state->json["meshes"]; for (GLTFMeshIndex i = 0; i < meshes.size(); i++) { print_verbose("glTF: Parsing mesh: " + itos(i)); @@ -2580,7 +2632,7 @@ Error GLTFDocument::_parse_meshes(Ref state) { Array primitives = d["primitives"]; const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] : Dictionary(); - Ref import_mesh; + Ref import_mesh; import_mesh.instance(); String mesh_name = "mesh"; if (d.has("name") && !String(d["name"]).empty()) { @@ -2589,7 +2641,6 @@ Error GLTFDocument::_parse_meshes(Ref 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; @@ -2603,19 +2654,17 @@ Error GLTFDocument::_parse_meshes(Ref state) { if (p.has("mode")) { const int mode = p["mode"]; ERR_FAIL_INDEX_V(mode, 7, ERR_FILE_CORRUPT); - // Convert mesh.primitive.mode to Godot Mesh enum. See: - // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_mesh_primitive_mode static const Mesh::PrimitiveType primitives2[7] = { - Mesh::PRIMITIVE_POINTS, // 0 POINTS - Mesh::PRIMITIVE_LINES, // 1 LINES - Mesh::PRIMITIVE_LINES, // 2 LINE_LOOP; loop not supported, should be converted - Mesh::PRIMITIVE_LINE_STRIP, // 3 LINE_STRIP - Mesh::PRIMITIVE_TRIANGLES, // 4 TRIANGLES - Mesh::PRIMITIVE_TRIANGLE_STRIP, // 5 TRIANGLE_STRIP - Mesh::PRIMITIVE_TRIANGLES, // 6 TRIANGLE_FAN fan not supported, should be converted - //#ifndef _MSC_VER - //#warning line loop and triangle fan are not supported and need to be converted to lines and triangles - //#endif + Mesh::PRIMITIVE_POINTS, + Mesh::PRIMITIVE_LINES, + Mesh::PRIMITIVE_LINES, //loop not supported, should ce converted + Mesh::PRIMITIVE_LINES, + Mesh::PRIMITIVE_TRIANGLES, + Mesh::PRIMITIVE_TRIANGLE_STRIP, + Mesh::PRIMITIVE_TRIANGLES, //fan not supported, should be converted +#ifndef _MSC_VER +// #warning line loop and triangle fan are not supported and need to be converted to lines and triangles +#endif }; @@ -2623,11 +2672,8 @@ Error GLTFDocument::_parse_meshes(Ref state) { } ERR_FAIL_COND_V(!a.has("POSITION"), ERR_PARSE_ERROR); - int32_t vertex_num = 0; if (a.has("POSITION")) { - PoolVector3Array vertices = _decode_accessor_as_vec3(state, a["POSITION"], true); - array[Mesh::ARRAY_VERTEX] = vertices; - vertex_num = vertices.size(); + array[Mesh::ARRAY_VERTEX] = _decode_accessor_as_vec3(state, a["POSITION"], true); } if (a.has("NORMAL")) { array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(state, a["NORMAL"], true); @@ -2641,93 +2687,24 @@ Error GLTFDocument::_parse_meshes(Ref 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 cur_custom; - Vector texcoord_first; - Vector 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; } - if (a.has("JOINTS_0") && !a.has("JOINTS_1")) { + if (a.has("JOINTS_0")) { array[Mesh::ARRAY_BONES] = _decode_accessor_as_ints(state, a["JOINTS_0"], true); - } else if (a.has("JOINTS_0") && a.has("JOINTS_1")) { - PoolIntArray joints_0 = _decode_accessor_as_ints(state, a["JOINTS_0"], true); - PoolIntArray 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; - Vector joints; - 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]; - joints.write[vertex_i * weight_8_count + 3] = joints_0[vertex_i * JOINT_GROUP_SIZE + 3]; - joints.write[vertex_i * weight_8_count + 4] = joints_1[vertex_i * JOINT_GROUP_SIZE + 0]; - joints.write[vertex_i * weight_8_count + 5] = joints_1[vertex_i * JOINT_GROUP_SIZE + 1]; - joints.write[vertex_i * weight_8_count + 6] = joints_1[vertex_i * JOINT_GROUP_SIZE + 2]; - joints.write[vertex_i * weight_8_count + 7] = joints_1[vertex_i * JOINT_GROUP_SIZE + 3]; - } - array[Mesh::ARRAY_BONES] = joints; } - if (a.has("WEIGHTS_0") && !a.has("WEIGHTS_1")) { - PoolVector weights = _decode_accessor_as_floats(state, a["WEIGHTS_0"], true); + if (a.has("WEIGHTS_1") && a.has("JOINTS_1")) { + if (!has_warned) { + WARN_PRINT("glTF: Meshes use more than 4 bone joints"); + has_warned = true; + } + } + if (a.has("WEIGHTS_0")) { + Vector weights = _decode_accessor_as_floats(state, a["WEIGHTS_0"], true); { //gltf does not seem to normalize the weights for some reason.. int wc = weights.size(); - PoolVector::Write weights_write = weights.write(); - float *w = weights_write.ptr(); + float *w = weights.ptrw(); for (int k = 0; k < wc; k += 4) { float total = 0.0; @@ -2744,61 +2721,16 @@ Error GLTFDocument::_parse_meshes(Ref state) { } } array[Mesh::ARRAY_WEIGHTS] = weights; - } else if (a.has("WEIGHTS_0") && a.has("WEIGHTS_1")) { - PoolVector weights_0 = _decode_accessor_as_floats(state, a["WEIGHTS_0"], true); - PoolVector weights_1 = _decode_accessor_as_floats(state, a["WEIGHTS_1"], true); - Vector weights; - ERR_FAIL_COND_V(weights_0.size() != weights_1.size(), ERR_INVALID_DATA); - int32_t weight_8_count = JOINT_GROUP_SIZE * 2; - 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]; - weights.write[vertex_i * weight_8_count + 3] = weights_0[vertex_i * JOINT_GROUP_SIZE + 3]; - weights.write[vertex_i * weight_8_count + 4] = weights_1[vertex_i * JOINT_GROUP_SIZE + 0]; - weights.write[vertex_i * weight_8_count + 5] = weights_1[vertex_i * JOINT_GROUP_SIZE + 1]; - weights.write[vertex_i * weight_8_count + 6] = weights_1[vertex_i * JOINT_GROUP_SIZE + 2]; - weights.write[vertex_i * weight_8_count + 7] = weights_1[vertex_i * JOINT_GROUP_SIZE + 3]; - } - { //gltf does not seem to normalize the weights for some reason.. - int wc = weights.size(); - float *w = weights.ptrw(); - - for (int k = 0; k < wc; k += weight_8_count) { - float total = 0.0; - total += w[k + 0]; - total += w[k + 1]; - total += w[k + 2]; - total += w[k + 3]; - total += w[k + 4]; - total += w[k + 5]; - total += w[k + 6]; - total += w[k + 7]; - if (total > 0.0) { - w[k + 0] /= total; - w[k + 1] /= total; - w[k + 2] /= total; - w[k + 3] /= total; - w[k + 4] /= total; - w[k + 5] /= total; - w[k + 6] /= total; - w[k + 7] /= total; - } - } - } - array[Mesh::ARRAY_WEIGHTS] = weights; } if (p.has("indices")) { - PoolIntArray indices = _decode_accessor_as_ints(state, p["indices"], false); + Vector indices = _decode_accessor_as_ints(state, p["indices"], false); if (primitive == Mesh::PRIMITIVE_TRIANGLES) { //swap around indices, convert ccw to cw for front face const int is = indices.size(); - PoolIntArray::Write iw = indices.write(); - int *w = iw.ptr(); + int *w = indices.ptrw(); for (int k = 0; k < is; k += 3) { SWAP(w[k + 1], w[k + 2]); } @@ -2809,12 +2741,11 @@ Error GLTFDocument::_parse_meshes(Ref state) { //generate indices because they need to be swapped for CW/CCW const Vector &vertices = array[Mesh::ARRAY_VERTEX]; ERR_FAIL_COND_V(vertices.size() == 0, ERR_PARSE_ERROR); - PoolIntArray indices; + Vector indices; const int vs = vertices.size(); indices.resize(vs); - PoolIntArray::Write iw = indices.write(); { - int *w = iw.ptr(); + int *w = indices.ptrw(); for (int k = 0; k < vs; k += 3) { w[k] = k; w[k + 1] = k + 2; @@ -2826,21 +2757,14 @@ Error GLTFDocument::_parse_meshes(Ref state) { bool generate_tangents = (primitive == Mesh::PRIMITIVE_TRIANGLES && !a.has("TANGENT") && a.has("TEXCOORD_0") && a.has("NORMAL")); - Ref mesh_surface_tool; - mesh_surface_tool.instance(); - mesh_surface_tool->create_from_triangle_arrays(array); - /* - if (a.has("JOINTS_0") && a.has("JOINTS_1")) { - mesh_surface_tool->set_skin_weight_count(SurfaceTool::SKIN_8_WEIGHTS); - } - */ - - mesh_surface_tool->index(); if (generate_tangents) { //must generate mikktspace tangents.. ergh.. - mesh_surface_tool->generate_tangents(); + Ref st; + st.instance(); + st->create_from_triangle_arrays(array); + st->generate_tangents(); + array = st->commit_to_arrays(); } - array = mesh_surface_tool->commit_to_arrays(); Array morphs; //blend shapes @@ -2870,21 +2794,20 @@ Error GLTFDocument::_parse_meshes(Ref state) { array_copy[l] = array[l]; } + array_copy[Mesh::ARRAY_INDEX] = Variant(); + if (t.has("POSITION")) { - PoolVector3Array varr = _decode_accessor_as_vec3(state, t["POSITION"], true); - const PoolVector3Array src_varr = array[Mesh::ARRAY_VERTEX]; + Vector varr = _decode_accessor_as_vec3(state, t["POSITION"], true); + const Vector src_varr = array[Mesh::ARRAY_VERTEX]; const int size = src_varr.size(); ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR); { const int max_idx = varr.size(); varr.resize(size); - PoolVector3Array::Write varr_write = varr.write(); - PoolVector3Array::Read src_varr_read = src_varr.read(); - - Vector3 *w_varr = varr_write.ptr(); - const Vector3 *r_varr = varr_write.ptr(); - const Vector3 *r_src_varr = src_varr_read.ptr(); + Vector3 *w_varr = varr.ptrw(); + const Vector3 *r_varr = varr.ptr(); + const Vector3 *r_src_varr = src_varr.ptr(); for (int l = 0; l < size; l++) { if (l < max_idx) { w_varr[l] = r_varr[l] + r_src_varr[l]; @@ -2893,25 +2816,20 @@ Error GLTFDocument::_parse_meshes(Ref state) { } } } - array_copy[Mesh::ARRAY_VERTEX] = varr; } if (t.has("NORMAL")) { - PoolVector3Array narr = _decode_accessor_as_vec3(state, t["NORMAL"], true); - const PoolVector3Array src_narr = array[Mesh::ARRAY_NORMAL]; + Vector narr = _decode_accessor_as_vec3(state, t["NORMAL"], true); + const Vector src_narr = array[Mesh::ARRAY_NORMAL]; int size = src_narr.size(); ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR); { int max_idx = narr.size(); narr.resize(size); - PoolVector3Array::Write narr_write = narr.write(); - PoolVector3Array::Read src_narr_read = src_narr.read(); - - Vector3 *w_narr = narr_write.ptr(); - const Vector3 *r_narr = narr_write.ptr(); - const Vector3 *r_src_narr = src_narr_read.ptr(); - + Vector3 *w_narr = narr.ptrw(); + const Vector3 *r_narr = narr.ptr(); + const Vector3 *r_src_narr = src_narr.ptr(); for (int l = 0; l < size; l++) { if (l < max_idx) { w_narr[l] = r_narr[l] + r_src_narr[l]; @@ -2920,29 +2838,24 @@ Error GLTFDocument::_parse_meshes(Ref state) { } } } - array_copy[Mesh::ARRAY_NORMAL] = narr; } if (t.has("TANGENT")) { - const PoolVector3Array tangents_v3 = _decode_accessor_as_vec3(state, t["TANGENT"], true); - const PoolRealArray src_tangents = array[Mesh::ARRAY_TANGENT]; + const Vector tangents_v3 = _decode_accessor_as_vec3(state, t["TANGENT"], true); + const Vector src_tangents = array[Mesh::ARRAY_TANGENT]; ERR_FAIL_COND_V(src_tangents.size() == 0, ERR_PARSE_ERROR); - PoolRealArray tangents_v4; + Vector tangents_v4; { int max_idx = tangents_v3.size(); int size4 = src_tangents.size(); tangents_v4.resize(size4); - PoolRealArray::Write tangents_v4_write = tangents_v4.write(); - float *w4 = tangents_v4_write.ptr(); + float *w4 = tangents_v4.ptrw(); - PoolVector3Array::Read r3_read = tangents_v3.read(); - const Vector3 *r3 = r3_read.ptr(); - - PoolRealArray::Read src_tangents_read = src_tangents.read(); - const float *r4 = src_tangents_read.ptr(); + const Vector3 *r3 = tangents_v3.ptr(); + const float *r4 = src_tangents.ptr(); for (int l = 0; l < size4 / 4; l++) { if (l < max_idx) { @@ -2954,7 +2867,6 @@ Error GLTFDocument::_parse_meshes(Ref state) { w4[l * 4 + 1] = r4[l * 4 + 1]; w4[l * 4 + 2] = r4[l * 4 + 2]; } - w4[l * 4 + 3] = r4[l * 4 + 3]; //copy flip value } } @@ -2962,63 +2874,40 @@ Error GLTFDocument::_parse_meshes(Ref state) { array_copy[Mesh::ARRAY_TANGENT] = tangents_v4; } - Ref blend_surface_tool; - blend_surface_tool.instance(); - blend_surface_tool->create_from_triangle_arrays(array_copy); - /* - if (a.has("JOINTS_0") && a.has("JOINTS_1")) { - blend_surface_tool->set_skin_weight_count(SurfaceTool::SKIN_8_WEIGHTS); - } - */ - - blend_surface_tool->index(); if (generate_tangents) { - blend_surface_tool->generate_tangents(); + Ref st; + st.instance(); + st->create_from_triangle_arrays(array_copy); + st->deindex(); + st->generate_tangents(); + array_copy = st->commit_to_arrays(); } - array_copy = blend_surface_tool->commit_to_arrays(); - - // Enforce blend shape mask array format - /* - for (int l = 0; l < Mesh::ARRAY_MAX; l++) { - if (!(Mesh::ARRAY_FORMAT_BLEND_SHAPE_MASK & (1 << l))) { - array_copy[l] = Variant(); - } - } - */ morphs.push_back(array_copy); } } + //just add it + Ref mat; - String mat_name; - if (!state->discard_meshes_and_materials) { - if (p.has("material")) { - const int material = p["material"]; - ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT); - Ref mat3d = state->materials[material]; - ERR_FAIL_COND_V(mat3d.is_null(), ERR_FILE_CORRUPT); - - if (has_vertex_color) { - mat3d->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - } - - mat = mat3d; - - } else { - Ref mat3d; - mat3d.instance(); - if (has_vertex_color) { - mat3d->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - } - mat = mat3d; + if (p.has("material")) { + const int material = p["material"]; + ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT); + Ref mat3d = state->materials[material]; + if (has_vertex_color) { + mat3d->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); } + mat = mat3d; - ERR_FAIL_NULL_V(mat.is_null(), ERR_FILE_CORRUPT); - mat_name = mat->get_name(); + } else if (has_vertex_color) { + Ref mat3d; + mat3d.instance(); + mat3d->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + mat = mat3d; } - import_mesh->add_surface(primitive, array, morphs, - Dictionary(), mat, mat_name, flags); + int32_t mat_idx = import_mesh->get_surface_count(); + import_mesh->add_surface_from_arrays(primitive, array, morphs, state->compress_flags); + import_mesh->surface_set_material(mat_idx, mat); } Vector blend_weights; @@ -3057,7 +2946,7 @@ Error GLTFDocument::_serialize_images(Ref state, const String &p_path Ref image = state->images[i]->get_data(); ERR_CONTINUE(image.is_null()); - if (p_path.to_lower().ends_with("glb") || p_path.empty()) { + if (p_path.to_lower().ends_with("glb")) { GLTFBufferViewIndex bvi; Ref bv; @@ -3068,7 +2957,7 @@ Error GLTFDocument::_serialize_images(Ref state, const String &p_path bv->byte_offset = state->buffers[bi].size(); ERR_FAIL_INDEX_V(bi, state->buffers.size(), ERR_PARAMETER_RANGE_ERROR); - PoolByteArray buffer; + PoolVector buffer; Ref img_tex = image; if (img_tex.is_valid()) { image = img_tex->get_data(); @@ -3078,9 +2967,7 @@ Error GLTFDocument::_serialize_images(Ref state, const String &p_path bv->byte_length = buffer.size(); state->buffers.write[bi].resize(state->buffers[bi].size() + bv->byte_length); - - PoolByteArray::Write buffer_write = buffer.write(); - memcpy(&state->buffers.write[bi].write[bv->byte_offset], buffer_write.ptr(), buffer.size()); + memcpy(&state->buffers.write[bi].write[bv->byte_offset], buffer.read().ptr(), buffer.size()); ERR_FAIL_COND_V(bv->byte_offset + bv->byte_length > state->buffers[bi].size(), ERR_FILE_CORRUPT); state->buffer_views.push_back(bv); @@ -3088,27 +2975,23 @@ Error GLTFDocument::_serialize_images(Ref state, const String &p_path d["bufferView"] = bvi; d["mimeType"] = "image/png"; } else { - ERR_FAIL_COND_V(p_path.empty(), ERR_INVALID_PARAMETER); String name = state->images[i]->get_name(); if (name.empty()) { name = itos(i); } name = _gen_unique_name(state, name); - name = name.pad_zeros(3) + ".png"; + name = name.pad_zeros(3); + Ref<_Directory> dir; + dir.instance(); String texture_dir = "textures"; - String path = p_path.get_base_dir(); - String new_texture_dir = path + "/" + texture_dir; - - DirAccess *da = DirAccess::open(path); - - if (!da->dir_exists(new_texture_dir)) { - da->make_dir(new_texture_dir); + String new_texture_dir = p_path.get_base_dir() + "/" + texture_dir; + dir->open(p_path.get_base_dir()); + if (!dir->dir_exists(new_texture_dir)) { + dir->make_dir(new_texture_dir); } - - memdelete(da); - + name = name + ".png"; image->save_png(new_texture_dir.plus_file(name)); - d["uri"] = texture_dir.plus_file(name).uri_encode(); + d["uri"] = texture_dir.plus_file(name); } images.push_back(d); } @@ -3124,7 +3007,6 @@ Error GLTFDocument::_serialize_images(Ref state, const String &p_path } Error GLTFDocument::_parse_images(Ref state, const String &p_base_path) { - ERR_FAIL_COND_V(state.is_null(), ERR_INVALID_PARAMETER); if (!state->json.has("images")) { return OK; } @@ -3140,7 +3022,7 @@ Error GLTFDocument::_parse_images(Ref state, const String &p_base_pat // - a URI with embedded base64-encoded data, or // - a reference to a bufferView; in that case mimeType must be defined." // Since mimeType is optional for external files and base64 data, we'll have to - // fall back on letting Godot parse the data to figure out if it's PNG or JPEG. + // fall back on letting Pandemonium parse the data to figure out if it's PNG or JPEG. // We'll assume that we use either URI or bufferView, so let's warn the user // if their image somehow uses both. And fail if it has neither. @@ -3184,13 +3066,12 @@ Error GLTFDocument::_parse_images(Ref state, const String &p_base_pat } } } else { // Relative path to an external image file. - ERR_FAIL_COND_V(p_base_path.empty(), ERR_INVALID_PARAMETER); - uri = uri.uri_decode(); + uri = uri.http_unescape(); 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. // there could be a `.png` image which is actually JPEG), but there's no easy - // API for that in Godot, so we'd have to load as a buffer (i.e. embedded in + // API for that in Pandemonium, so we'd have to load as a buffer (i.e. embedded in // the material), so we do this only as fallback. Ref texture = ResourceLoader::load(uri); if (texture.is_valid()) { @@ -3267,10 +3148,11 @@ Error GLTFDocument::_parse_images(Ref state, const String &p_base_pat continue; } - Ref imgtex; - imgtex.instance(); - imgtex->create_from_image(img); - state->images.push_back(imgtex); + Ref t; + t.instance(); + t->create_from_image(img); + + state->images.push_back(t); } print_verbose("glTF: Total images: " + itos(state->images.size())); @@ -3373,11 +3255,7 @@ Error GLTFDocument::_serialize_materials(Ref state) { } if (gltf_texture_index != -1) { bct["index"] = gltf_texture_index; - Dictionary extensions = _serialize_texture_transform_uv1(material); - if (!extensions.empty()) { - bct["extensions"] = extensions; - state->use_khr_texture_transform = true; - } + bct["extensions"] = _serialize_texture_transform_uv1(material); mr["baseColorTexture"] = bct; } } @@ -3401,7 +3279,6 @@ Error GLTFDocument::_serialize_materials(Ref state) { orm_image.instance(); int32_t height = 0; int32_t width = 0; - Ref ao_image; if (has_ao) { height = ao_texture->get_height(); @@ -3415,7 +3292,6 @@ Error GLTFDocument::_serialize_materials(Ref state) { ao_image->decompress(); } } - Ref roughness_image; if (has_roughness) { height = roughness_texture->get_height(); @@ -3429,7 +3305,6 @@ Error GLTFDocument::_serialize_materials(Ref state) { roughness_image->decompress(); } } - Ref metallness_image; if (has_metalness) { height = metallic_texture->get_height(); @@ -3448,24 +3323,22 @@ Error GLTFDocument::_serialize_materials(Ref state) { height = albedo_texture->get_height(); width = albedo_texture->get_width(); } - orm_image->create(width, height, false, Image::FORMAT_RGBA8); if (ao_image.is_valid() && ao_image->get_size() != Vector2(width, height)) { ao_image->resize(width, height, Image::INTERPOLATE_LANCZOS); } - if (roughness_image.is_valid() && roughness_image->get_size() != Vector2(width, height)) { roughness_image->resize(width, height, Image::INTERPOLATE_LANCZOS); } - if (metallness_image.is_valid() && metallness_image->get_size() != Vector2(width, height)) { metallness_image->resize(width, height, Image::INTERPOLATE_LANCZOS); } - + orm_image->lock(); for (int32_t h = 0; h < height; h++) { for (int32_t w = 0; w < width; w++) { Color c = Color(1.0f, 1.0f, 1.0f); if (has_ao) { + ao_image->lock(); if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_RED == ao_channel) { c.r = ao_image->get_pixel(w, h).r; } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_GREEN == ao_channel) { @@ -3475,8 +3348,10 @@ Error GLTFDocument::_serialize_materials(Ref state) { } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_ALPHA == ao_channel) { c.r = ao_image->get_pixel(w, h).a; } + ao_image->lock(); } if (has_roughness) { + roughness_image->lock(); if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_RED == roughness_channel) { c.g = roughness_image->get_pixel(w, h).r; } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_GREEN == roughness_channel) { @@ -3486,8 +3361,10 @@ Error GLTFDocument::_serialize_materials(Ref state) { } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_ALPHA == roughness_channel) { c.g = roughness_image->get_pixel(w, h).a; } + roughness_image->unlock(); } if (has_metalness) { + metallness_image->lock(); if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_RED == metalness_channel) { c.b = metallness_image->get_pixel(w, h).r; } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_GREEN == metalness_channel) { @@ -3497,33 +3374,27 @@ Error GLTFDocument::_serialize_materials(Ref state) { } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_ALPHA == metalness_channel) { c.b = metallness_image->get_pixel(w, h).a; } + metallness_image->unlock(); } orm_image->set_pixel(w, h, c); } } - + orm_image->unlock(); orm_image->generate_mipmaps(); - orm_texture->set_data(orm_image); + orm_texture->create_from_image(orm_image); GLTFTextureIndex orm_texture_index = -1; if (has_ao || has_roughness || has_metalness) { orm_texture->set_name(material->get_name() + "_orm"); orm_texture_index = _set_texture(state, orm_texture); } - if (has_ao) { - Dictionary occt; - occt["index"] = orm_texture_index; - d["occlusionTexture"] = occt; + Dictionary ot; + ot["index"] = orm_texture_index; + d["occlusionTexture"] = ot; } - if (has_roughness || has_metalness) { mrt["index"] = orm_texture_index; - Dictionary extensions = _serialize_texture_transform_uv1(material); - if (!extensions.empty()) { - mrt["extensions"] = extensions; - state->use_khr_texture_transform = true; - } - + mrt["extensions"] = _serialize_texture_transform_uv1(material); mr["metallicRoughnessTexture"] = mrt; } } @@ -3534,7 +3405,6 @@ Error GLTFDocument::_serialize_materials(Ref state) { Dictionary nt; Ref tex; tex.instance(); - { Ref normal_texture = material->get_texture(SpatialMaterial::TEXTURE_NORMAL); if (normal_texture.is_valid()) { @@ -3547,7 +3417,7 @@ Error GLTFDocument::_serialize_materials(Ref state) { } img->decompress(); img->convert(Image::FORMAT_RGBA8); - img->convert_ra_rgba8_to_rg(); + img->lock(); for (int32_t y = 0; y < img->get_height(); y++) { for (int32_t x = 0; x < img->get_width(); x++) { Color c = img->get_pixel(x, y); @@ -3559,17 +3429,16 @@ Error GLTFDocument::_serialize_materials(Ref state) { img->set_pixel(x, y, c); } } - tex->set_data(img); + img->unlock(); + tex->create_from_image(img); } } } - GLTFTextureIndex gltf_texture_index = -1; if (tex.is_valid() && tex->get_data().is_valid()) { tex->set_name(material->get_name() + "_normal"); gltf_texture_index = _set_texture(state, tex); } - nt["scale"] = material->get_normal_scale(); if (gltf_texture_index != -1) { nt["index"] = gltf_texture_index; @@ -3585,7 +3454,6 @@ Error GLTFDocument::_serialize_materials(Ref state) { arr.push_back(c.b); d["emissiveFactor"] = arr; } - if (material->get_feature(SpatialMaterial::FEATURE_EMISSION)) { Dictionary et; Ref emission_texture = material->get_texture(SpatialMaterial::TEXTURE_EMISSION); @@ -3600,12 +3468,10 @@ Error GLTFDocument::_serialize_materials(Ref state) { d["emissiveTexture"] = et; } } - const bool ds = material->get_cull_mode() == SpatialMaterial::CULL_DISABLED; if (ds) { d["doubleSided"] = ds; } - if (material->get_feature(SpatialMaterial::FEATURE_TRANSPARENT)) { if (material->get_flag(SpatialMaterial::FLAG_USE_ALPHA_SCISSOR)) { d["alphaMode"] = "MASK"; @@ -3614,14 +3480,11 @@ Error GLTFDocument::_serialize_materials(Ref state) { d["alphaMode"] = "BLEND"; } } - materials.push_back(d); } - if (!materials.size()) { return OK; } - state->json["materials"] = materials; print_verbose("Total materials: " + itos(state->materials.size())); @@ -3644,6 +3507,7 @@ Error GLTFDocument::_parse_materials(Ref state) { } else { material->set_name(vformat("material_%s", itos(i))); } + material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); Dictionary pbr_spec_gloss_extensions; if (d.has("extensions")) { @@ -3787,13 +3651,14 @@ Error GLTFDocument::_parse_materials(Ref state) { material->set_cull_mode(SpatialMaterial::CULL_DISABLED); } } + if (d.has("alphaMode")) { const String &am = d["alphaMode"]; if (am == "BLEND") { + material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); material->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS); } else if (am == "MASK") { material->set_flag(SpatialMaterial::FLAG_USE_ALPHA_SCISSOR, true); - if (d.has("alphaCutoff")) { material->set_alpha_scissor_threshold(d["alphaCutoff"]); } else { @@ -3843,6 +3708,7 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref r_spec_gloss, Re p_material->set_roughness(1.0f); p_material->set_metallic(1.0f); rm_img->create(r_spec_gloss->spec_gloss_img->get_width(), r_spec_gloss->spec_gloss_img->get_height(), false, Image::FORMAT_RGBA8); + rm_img->lock(); r_spec_gloss->spec_gloss_img->decompress(); if (r_spec_gloss->diffuse_img.is_valid()) { r_spec_gloss->diffuse_img->decompress(); @@ -3855,6 +3721,7 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref r_spec_gloss, Re Color specular = Color(specular_pixel.r, specular_pixel.g, specular_pixel.b); specular *= r_spec_gloss->specular_factor; Color diffuse = Color(1.0f, 1.0f, 1.0f); + r_spec_gloss->diffuse_img->lock(); diffuse *= r_spec_gloss->diffuse_img->get_pixel(x, y).to_linear(); float metallic = 0.0f; Color base_color; @@ -3865,29 +3732,26 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref r_spec_gloss, Re if (!Math::is_equal_approx(mr.g, 1.0f)) { has_roughness = true; } - if (!Math::is_zero_approx(mr.b)) { + if (!Math::is_equal_approx(mr.b, 0.0f)) { has_metal = true; } mr.g *= r_spec_gloss->gloss_factor; mr.g = 1.0f - mr.g; rm_img->set_pixel(x, y, mr); - if (r_spec_gloss->diffuse_img.is_valid()) { - r_spec_gloss->diffuse_img->set_pixel(x, y, base_color.to_srgb()); - } + r_spec_gloss->diffuse_img->set_pixel(x, y, base_color.to_srgb()); + r_spec_gloss->diffuse_img->unlock(); } } + rm_img->unlock(); rm_img->generate_mipmaps(); r_spec_gloss->diffuse_img->generate_mipmaps(); - - Ref ita; - ita.instance(); - ita->create_from_image(r_spec_gloss->diffuse_img); - - p_material->set_texture(SpatialMaterial::TEXTURE_ALBEDO, ita); + Ref diffuse_image_texture; + diffuse_image_texture.instance(); + diffuse_image_texture->create_from_image(r_spec_gloss->diffuse_img); + p_material->set_texture(SpatialMaterial::TEXTURE_ALBEDO, diffuse_image_texture); Ref rm_image_texture; rm_image_texture.instance(); rm_image_texture->create_from_image(rm_img); - if (has_roughness) { p_material->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, rm_image_texture); p_material->set_roughness_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_GREEN); @@ -3914,7 +3778,10 @@ void GLTFDocument::spec_gloss_to_metal_base_color(const Color &p_specular_factor r_base_color.g = Math::lerp(base_color_from_diffuse.g, base_color_from_specular.g, r_metallic * r_metallic); r_base_color.b = Math::lerp(base_color_from_diffuse.b, base_color_from_specular.b, r_metallic * r_metallic); r_base_color.a = p_diffuse.a; - r_base_color = r_base_color.clamp(); + r_base_color.r = CLAMP(r_base_color.r, 0.0f, 1.0f); + r_base_color.g = CLAMP(r_base_color.g, 0.0f, 1.0f); + r_base_color.b = CLAMP(r_base_color.b, 0.0f, 1.0f); + r_base_color.a = CLAMP(r_base_color.a, 0.0f, 1.0f); } GLTFNodeIndex GLTFDocument::_find_highest_node(Ref state, const Vector &subset) { @@ -3989,7 +3856,7 @@ void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref state, Ref } // Go up the tree till all of the multiple roots of the skin are at the same hierarchy level. - // This sucks, but 99% of all game engines (not just Godot) would have this same issue. + // This sucks, but 99% of all game engines (not just Pandemonium) would have this same issue. for (int i = 0; i < roots.size(); ++i) { GLTFNodeIndex current_node = roots[i]; while (state->nodes[current_node]->height > maxHeight) { @@ -4416,8 +4283,13 @@ Error GLTFDocument::_determine_skeleton_roots(Ref state, const GLTFSk } roots.sort(); - - skeleton->roots = roots; + PoolVector roots_array; + roots_array.resize(roots.size()); + PoolVector::Write write_roots = roots_array.write(); + for (int32_t root_i = 0; root_i < roots_array.size(); root_i++) { + write_roots[root_i] = roots[root_i]; + } + skeleton->roots = roots_array; if (roots.size() == 0) { return FAILED; @@ -4441,7 +4313,7 @@ Error GLTFDocument::_create_skeletons(Ref state) { Ref gltf_skeleton = state->skeletons.write[skel_i]; Skeleton *skeleton = memnew(Skeleton); - gltf_skeleton->godot_skeleton = skeleton; + gltf_skeleton->pandemonium_skeleton = skeleton; state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()] = skel_i; // Make a unique name, no gltf node represents this skeleton @@ -4491,18 +4363,13 @@ Error GLTFDocument::_create_skeletons(Ref state) { skeleton->add_bone(node->get_name()); skeleton->set_bone_rest(bone_index, node->xform); - //TODO UNCOMMENT - //skeleton->set_bone_pose_position(bone_index, node->position); - //skeleton->set_bone_pose_rotation(bone_index, node->rotation.normalized()); - //skeleton->set_bone_pose_scale(bone_index, node->scale); - if (node->parent >= 0 && state->nodes[node->parent]->skeleton == skel_i) { const int bone_parent = skeleton->find_bone(state->nodes[node->parent]->get_name()); ERR_FAIL_COND_V(bone_parent < 0, FAILED); skeleton->set_bone_parent(bone_index, skeleton->find_bone(state->nodes[node->parent]->get_name())); } - state->scene_nodes.set(node_i, skeleton); + state->scene_nodes.insert(node_i, skeleton); } } @@ -4521,10 +4388,10 @@ Error GLTFDocument::_map_skin_joints_indices_to_skeleton_bone_indices(Refjoints_original[joint_index]; const Ref node = state->nodes[node_i]; - const int bone_index = skeleton->godot_skeleton->find_bone(node->get_name()); + const int bone_index = skeleton->pandemonium_skeleton->find_bone(node->get_name()); ERR_FAIL_COND_V(bone_index < 0, FAILED); - skin->joint_i_to_bone_i.set(joint_index, bone_index); + skin->joint_i_to_bone_i.insert(joint_index, bone_index); } } @@ -4577,7 +4444,7 @@ Error GLTFDocument::_create_skins(Ref state) { } } - gltf_skin->godot_skin = skin; + gltf_skin->pandemonium_skin = skin; } // Purge the duplicates! @@ -4585,7 +4452,7 @@ Error GLTFDocument::_create_skins(Ref state) { // Create unique names now, after removing duplicates for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) { - Ref skin = state->skins.write[skin_i]->godot_skin; + Ref skin = state->skins.write[skin_i]->pandemonium_skin; if (skin->get_name().empty()) { // Make a unique name, no gltf node represents this skin skin->set_name(_gen_unique_name(state, "Skin")); @@ -4622,21 +4489,18 @@ bool GLTFDocument::_skins_are_same(const Ref skin_a, const Ref skin_ void GLTFDocument::_remove_duplicate_skins(Ref state) { for (int i = 0; i < state->skins.size(); ++i) { for (int j = i + 1; j < state->skins.size(); ++j) { - const Ref skin_i = state->skins[i]->godot_skin; - const Ref skin_j = state->skins[j]->godot_skin; + const Ref skin_i = state->skins[i]->pandemonium_skin; + const Ref skin_j = state->skins[j]->pandemonium_skin; if (_skins_are_same(skin_i, skin_j)) { // replace it and delete the old - state->skins.write[j]->godot_skin = skin_i; + state->skins.write[j]->pandemonium_skin = skin_i; } } } } Error GLTFDocument::_serialize_lights(Ref state) { - if (state->lights.empty()) { - return OK; - } Array lights; for (GLTFLightIndex i = 0; i < state->lights.size(); i++) { Dictionary d; @@ -4647,8 +4511,8 @@ Error GLTFDocument::_serialize_lights(Ref state) { color[1] = light->color.g; color[2] = light->color.b; d["color"] = color; - d["type"] = light->light_type; - if (light->light_type == "spot") { + d["type"] = light->type; + if (light->type == "spot") { Dictionary s; float inner_cone_angle = light->inner_cone_angle; s["innerConeAngle"] = inner_cone_angle; @@ -4663,6 +4527,10 @@ Error GLTFDocument::_serialize_lights(Ref state) { lights.push_back(d); } + if (!state->lights.size()) { + return OK; + } + Dictionary extensions; if (state->json.has("extensions")) { extensions = state->json["extensions"]; @@ -4690,16 +4558,16 @@ Error GLTFDocument::_serialize_cameras(Ref state) { Dictionary og; og["ymag"] = Math::deg2rad(camera->get_fov_size()); og["xmag"] = Math::deg2rad(camera->get_fov_size()); - og["zfar"] = camera->get_depth_far(); - og["znear"] = camera->get_depth_near(); + og["zfar"] = camera->get_zfar(); + og["znear"] = camera->get_znear(); d["orthographic"] = og; d["type"] = "orthographic"; } else if (camera->get_perspective()) { Dictionary ppt; - // GLTF spec is in radians, Godot's camera is in degrees. + // GLTF spec is in radians, Pandemonium's camera is in degrees. ppt["yfov"] = Math::deg2rad(camera->get_fov_size()); - ppt["zfar"] = camera->get_depth_far(); - ppt["znear"] = camera->get_depth_near(); + ppt["zfar"] = camera->get_zfar(); + ppt["znear"] = camera->get_znear(); d["perspective"] = ppt; d["type"] = "perspective"; } @@ -4739,7 +4607,7 @@ Error GLTFDocument::_parse_lights(Ref state) { light.instance(); ERR_FAIL_COND_V(!d.has("type"), ERR_PARSE_ERROR); const String &type = d["type"]; - light->light_type = type; + light->type = type; if (d.has("color")) { const Array &arr = d["color"]; @@ -4788,10 +4656,10 @@ Error GLTFDocument::_parse_cameras(Ref state) { camera->set_perspective(false); if (d.has("orthographic")) { const Dictionary &og = d["orthographic"]; - // GLTF spec is in radians, Godot's camera is in degrees. + // GLTF spec is in radians, Pandemonium's camera is in degrees. camera->set_fov_size(Math::rad2deg(real_t(og["ymag"]))); - camera->set_depth_far(og["zfar"]); - camera->set_depth_near(og["znear"]); + camera->set_zfar(og["zfar"]); + camera->set_znear(og["znear"]); } else { camera->set_fov_size(10); } @@ -4799,10 +4667,10 @@ Error GLTFDocument::_parse_cameras(Ref state) { camera->set_perspective(true); if (d.has("perspective")) { const Dictionary &ppt = d["perspective"]; - // GLTF spec is in radians, Godot's camera is in degrees. + // GLTF spec is in radians, Pandemonium's camera is in degrees. camera->set_fov_size(Math::rad2deg(real_t(ppt["yfov"]))); - camera->set_depth_far(ppt["zfar"]); - camera->set_depth_near(ppt["znear"]); + camera->set_zfar(ppt["zfar"]); + camera->set_znear(ppt["znear"]); } else { camera->set_fov_size(10); } @@ -4861,74 +4729,68 @@ Error GLTFDocument::_serialize_animations(Ref state) { Array channels; Array samplers; - const int *gltf_animation_key = NULL; - while ((gltf_animation_key = gltf_animation->get_tracks().next(gltf_animation_key))) { - int track_i_key = *gltf_animation_key; - GLTFAnimation::Track track = gltf_animation->get_tracks()[track_i_key]; - - if (track.position_track.times.size()) { + for (Map::Element *track_i = gltf_animation->get_tracks().front(); track_i; track_i = track_i->next()) { + GLTFAnimation::Track track = track_i->get(); + if (track.translation_track.times.size()) { Dictionary t; t["sampler"] = samplers.size(); Dictionary s; - s["interpolation"] = interpolation_to_string(track.position_track.interpolation); - PoolRealArray times = Variant(track.position_track.times); + s["interpolation"] = interpolation_to_string(track.translation_track.interpolation); + Vector times = Variant(track.translation_track.times); s["input"] = _encode_accessor_as_floats(state, times, false); - PoolVector3Array values = Variant(track.position_track.values); + Vector values = Variant(track.translation_track.values); s["output"] = _encode_accessor_as_vec3(state, values, false); samplers.push_back(s); Dictionary target; target["path"] = "translation"; - target["node"] = track_i_key; + target["node"] = track_i->key(); t["target"] = target; channels.push_back(t); } - if (track.rotation_track.times.size()) { Dictionary t; t["sampler"] = samplers.size(); Dictionary s; s["interpolation"] = interpolation_to_string(track.rotation_track.interpolation); - PoolRealArray times = Variant(track.rotation_track.times); + Vector times = Variant(track.rotation_track.times); s["input"] = _encode_accessor_as_floats(state, times, false); - PoolVector values = track.rotation_track.values; - s["output"] = _encode_accessor_as_quaternions(state, values, false); + Vector values = track.rotation_track.values; + s["output"] = _encode_accessor_as_quats(state, values, false); samplers.push_back(s); Dictionary target; target["path"] = "rotation"; - target["node"] = track_i_key; + target["node"] = track_i->key(); t["target"] = target; channels.push_back(t); } - if (track.scale_track.times.size()) { Dictionary t; t["sampler"] = samplers.size(); Dictionary s; s["interpolation"] = interpolation_to_string(track.scale_track.interpolation); - PoolRealArray times = Variant(track.scale_track.times); + Vector times = Variant(track.scale_track.times); s["input"] = _encode_accessor_as_floats(state, times, false); - PoolVector values = Variant(track.scale_track.values); + Vector values = Variant(track.scale_track.values); s["output"] = _encode_accessor_as_vec3(state, values, false); samplers.push_back(s); Dictionary target; target["path"] = "scale"; - target["node"] = track_i_key; + target["node"] = track_i->key(); t["target"] = target; channels.push_back(t); } - if (track.weight_tracks.size()) { double length = 0.0f; @@ -4940,7 +4802,7 @@ Error GLTFDocument::_serialize_animations(Ref state) { Dictionary t; t["sampler"] = samplers.size(); Dictionary s; - PoolRealArray times; + Vector times; const double increment = 1.0 / BAKE_FPS; { double time = 0.0; @@ -4961,9 +4823,9 @@ Error GLTFDocument::_serialize_animations(Ref state) { for (int32_t track_idx = 0; track_idx < track.weight_tracks.size(); track_idx++) { double time = 0.0; bool last = false; - PoolRealArray weight_track; + Vector weight_track; while (true) { - float weight = _interpolate_track(track.weight_tracks[track_idx].times, + float weight = _interpolate_track(track.weight_tracks[track_idx].times, track.weight_tracks[track_idx].values, time, track.weight_tracks[track_idx].interpolation); @@ -4981,17 +4843,17 @@ Error GLTFDocument::_serialize_animations(Ref state) { track.weight_tracks.write[track_idx].values = weight_track; } - PoolRealArray all_track_times = times; - PoolRealArray all_track_values; + Vector all_track_times = times; + Vector all_track_values; int32_t values_size = track.weight_tracks[0].values.size(); int32_t weight_tracks_size = track.weight_tracks.size(); all_track_values.resize(weight_tracks_size * values_size); for (int k = 0; k < track.weight_tracks.size(); k++) { - PoolRealArray wdata = track.weight_tracks[k].values; + Vector wdata = track.weight_tracks[k].values; for (int l = 0; l < wdata.size(); l++) { int32_t index = l * weight_tracks_size + k; ERR_BREAK(index >= all_track_values.size()); - all_track_values.set(index, wdata[l]); + all_track_values.write[index] = wdata.write[l]; } } @@ -5003,7 +4865,7 @@ Error GLTFDocument::_serialize_animations(Ref state) { Dictionary target; target["path"] = "weights"; - target["node"] = track_i_key; + target["node"] = track_i->key(); t["target"] = target; channels.push_back(t); @@ -5048,11 +4910,14 @@ Error GLTFDocument::_parse_animations(Ref state) { if (d.has("name")) { const String name = d["name"]; - const String name_lower = name.to_lower(); - if (name_lower.begins_with("loop") || name_lower.ends_with("loop") || name_lower.begins_with("cycle") || name_lower.ends_with("cycle")) { + if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) { animation->set_loop(true); } - animation->set_name(_gen_unique_animation_name(state, name)); + if (state->use_legacy_names) { + animation->set_name(_sanitize_scene_name(state, name)); + } else { + animation->set_name(_gen_unique_animation_name(state, name)); + } } for (int j = 0; j < channels.size(); j++) { @@ -5108,24 +4973,24 @@ Error GLTFDocument::_parse_animations(Ref state) { } } - const PoolVector times = _decode_accessor_as_floats(state, input, false); + const Vector times = _decode_accessor_as_floats(state, input, false); if (path == "translation") { - const PoolVector positions = _decode_accessor_as_vec3(state, output, false); - track->position_track.interpolation = interp; - track->position_track.times = Variant(times); //convert via variant - track->position_track.values = Variant(positions); //convert via variant + const Vector translations = _decode_accessor_as_vec3(state, output, false); + track->translation_track.interpolation = interp; + track->translation_track.times = Variant(times); //convert via variant + track->translation_track.values = Variant(translations); //convert via variant } else if (path == "rotation") { - const PoolVector rotations = _decode_accessor_as_quaternion(state, output, false); + const Vector rotations = _decode_accessor_as_quat(state, output, false); track->rotation_track.interpolation = interp; track->rotation_track.times = Variant(times); //convert via variant track->rotation_track.values = rotations; } else if (path == "scale") { - const PoolVector scales = _decode_accessor_as_vec3(state, output, false); + const Vector scales = _decode_accessor_as_vec3(state, output, false); track->scale_track.interpolation = interp; track->scale_track.times = Variant(times); //convert via variant track->scale_track.values = Variant(scales); //convert via variant } else if (path == "weights") { - const PoolVector weights = _decode_accessor_as_floats(state, output, false); + const Vector weights = _decode_accessor_as_floats(state, output, false); ERR_FAIL_INDEX_V(state->nodes[node]->mesh, state->meshes.size(), ERR_PARSE_ERROR); Ref mesh = state->meshes[state->nodes[node]->mesh]; @@ -5139,13 +5004,13 @@ Error GLTFDocument::_parse_animations(Ref state) { const int wlen = weights.size() / wc; for (int k = 0; k < wc; k++) { //separate tracks, having them together is not such a good idea - GLTFAnimation::Channel cf; + GLTFAnimation::Channel cf; cf.interpolation = interp; cf.times = Variant(times); - PoolRealArray wdata; + Vector wdata; wdata.resize(wlen); for (int l = 0; l < wlen; l++) { - wdata.set(l, weights[l * wc + k]); + wdata.write[l] = weights[l * wc + k]; } cf.values = wdata; @@ -5185,11 +5050,15 @@ void GLTFDocument::_assign_scene_names(Ref state) { n->set_name(_gen_unique_name(state, n->get_name())); } + + // Assign a unique name to the scene last to avoid naming conflicts with the root + state->scene_name = _gen_unique_name(state, state->scene_name); } BoneAttachment *GLTFDocument::_generate_bone_attachment(Ref state, Skeleton *skeleton, const GLTFNodeIndex node_index, const GLTFNodeIndex bone_index) { Ref gltf_node = state->nodes[node_index]; Ref bone_node = state->nodes[bone_index]; + BoneAttachment *bone_attachment = memnew(BoneAttachment); print_verbose("glTF: Creating bone attachment for: " + gltf_node->get_name()); @@ -5205,57 +5074,82 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref state, MeshInst if (p_mesh_instance->get_mesh().is_null()) { return -1; } - - Ref import_mesh = p_mesh_instance->get_mesh(); - Ref current_mesh = _mesh_to_importer_mesh(import_mesh); + Ref import_mesh; + import_mesh.instance(); + Ref pandemonium_mesh = p_mesh_instance->get_mesh(); + if (pandemonium_mesh.is_null()) { + return -1; + } + int32_t blend_count = pandemonium_mesh->get_blend_shape_count(); Vector blend_weights; - int32_t blend_count = import_mesh->get_blend_shape_count(); blend_weights.resize(blend_count); + Ref am = pandemonium_mesh; + if (am != nullptr) { + import_mesh = am; + } else { + for (int32_t surface_i = 0; surface_i < pandemonium_mesh->get_surface_count(); surface_i++) { + Mesh::PrimitiveType primitive_type = pandemonium_mesh->surface_get_primitive_type(surface_i); + Array arrays = pandemonium_mesh->surface_get_arrays(surface_i); + Ref mat = pandemonium_mesh->surface_get_material(surface_i); + if (p_mesh_instance->get_surface_material(surface_i).is_valid()) { + mat = p_mesh_instance->get_surface_material(surface_i); + } + if (p_mesh_instance->get_material_override().is_valid()) { + mat = p_mesh_instance->get_material_override(); + } + int32_t mat_idx = import_mesh->get_surface_count(); + import_mesh->add_surface_from_arrays(primitive_type, arrays); + import_mesh->surface_set_material(mat_idx, mat); + } + } for (int32_t blend_i = 0; blend_i < blend_count; blend_i++) { blend_weights.write[blend_i] = 0.0f; } - Ref gltf_mesh; gltf_mesh.instance(); Array instance_materials; - for (int32_t surface_i = 0; surface_i < current_mesh->get_surface_count(); surface_i++) { - Ref mat = current_mesh->get_surface_material(surface_i); - + for (int32_t surface_i = 0; surface_i < import_mesh->get_surface_count(); surface_i++) { + Ref mat = import_mesh->surface_get_material(surface_i); + if (p_mesh_instance->get_surface_material(surface_i).is_valid()) { + mat = p_mesh_instance->get_surface_material(surface_i); + } if (p_mesh_instance->get_material_override().is_valid()) { mat = p_mesh_instance->get_material_override(); } - instance_materials.append(mat); } gltf_mesh->set_instance_materials(instance_materials); - gltf_mesh->set_mesh(current_mesh); + gltf_mesh->set_mesh(import_mesh); gltf_mesh->set_blend_weights(blend_weights); GLTFMeshIndex mesh_i = state->meshes.size(); state->meshes.push_back(gltf_mesh); return mesh_i; } -ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref state, const GLTFNodeIndex node_index) { +Spatial *GLTFDocument::_generate_mesh_instance(Ref state, Node *scene_parent, const GLTFNodeIndex node_index) { Ref gltf_node = state->nodes[node_index]; ERR_FAIL_INDEX_V(gltf_node->mesh, state->meshes.size(), nullptr); - ImporterMeshInstance3D *mi = memnew(ImporterMeshInstance3D); + MeshInstance *mi = memnew(MeshInstance); print_verbose("glTF: Creating mesh for: " + gltf_node->get_name()); Ref mesh = state->meshes.write[gltf_node->mesh]; if (mesh.is_null()) { return mi; } - Ref import_mesh = mesh->get_mesh(); + Ref import_mesh = mesh->get_mesh(); if (import_mesh.is_null()) { return mi; } mi->set_mesh(import_mesh); + for (int i = 0; i < mesh->get_blend_weights().size(); i++) { + mi->set("blend_shapes/" + mesh->get_mesh()->get_blend_shape_name(i), mesh->get_blend_weights()[i]); + } return mi; } -Spatial *GLTFDocument::_generate_light(Ref state, const GLTFNodeIndex node_index) { +Spatial *GLTFDocument::_generate_light(Ref state, Node *scene_parent, const GLTFNodeIndex node_index) { Ref gltf_node = state->nodes[node_index]; ERR_FAIL_INDEX_V(gltf_node->light, state->lights.size(), nullptr); @@ -5272,7 +5166,7 @@ Spatial *GLTFDocument::_generate_light(Ref state, const GLTFNodeIndex intensity /= 100; } - if (l->light_type == "directional") { + if (l->type == "directional") { DirectionalLight *light = memnew(DirectionalLight); light->set_param(Light::PARAM_ENERGY, intensity); light->set_color(l->color); @@ -5280,14 +5174,14 @@ Spatial *GLTFDocument::_generate_light(Ref state, const GLTFNodeIndex } const float range = CLAMP(l->range, 0, 4096); - if (l->light_type == "point") { + if (l->type == "point") { OmniLight *light = memnew(OmniLight); light->set_param(OmniLight::PARAM_ENERGY, intensity); light->set_param(OmniLight::PARAM_RANGE, range); light->set_color(l->color); return light; } - if (l->light_type == "spot") { + if (l->type == "spot") { SpotLight *light = memnew(SpotLight); light->set_param(SpotLight::PARAM_ENERGY, intensity); light->set_param(SpotLight::PARAM_RANGE, range); @@ -5304,7 +5198,7 @@ Spatial *GLTFDocument::_generate_light(Ref state, const GLTFNodeIndex return memnew(Spatial); } -Camera *GLTFDocument::_generate_camera(Ref state, const GLTFNodeIndex node_index) { +Camera *GLTFDocument::_generate_camera(Ref state, Node *scene_parent, const GLTFNodeIndex node_index) { Ref gltf_node = state->nodes[node_index]; ERR_FAIL_INDEX_V(gltf_node->camera, state->cameras.size(), nullptr); @@ -5314,9 +5208,9 @@ Camera *GLTFDocument::_generate_camera(Ref state, const GLTFNodeIndex Ref c = state->cameras[gltf_node->camera]; if (c->get_perspective()) { - camera->set_perspective(c->get_fov_size(), c->get_depth_near(), c->get_depth_far()); + camera->set_perspective(c->get_fov_size(), c->get_znear(), c->get_zfar()); } else { - camera->set_orthogonal(c->get_fov_size(), c->get_depth_near(), c->get_depth_far()); + camera->set_orthogonal(c->get_fov_size(), c->get_znear(), c->get_zfar()); } return camera; @@ -5328,14 +5222,16 @@ GLTFCameraIndex GLTFDocument::_convert_camera(Ref state, Camera *p_ca Ref c; c.instance(); - if (p_camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { + if (p_camera->get_projection() == Camera::Projection::PROJECTION_PERSPECTIVE) { c->set_perspective(true); + c->set_fov_size(p_camera->get_fov()); + c->set_zfar(p_camera->get_zfar()); + c->set_znear(p_camera->get_znear()); + } else { + c->set_fov_size(p_camera->get_fov()); + c->set_zfar(p_camera->get_zfar()); + c->set_znear(p_camera->get_znear()); } - - c->set_fov_size(p_camera->get_fov()); - c->set_depth_far(p_camera->get_zfar()); - c->set_depth_near(p_camera->get_znear()); - GLTFCameraIndex camera_index = state->cameras.size(); state->cameras.push_back(c); return camera_index; @@ -5348,17 +5244,17 @@ GLTFLightIndex GLTFDocument::_convert_light(Ref state, Light *p_light l.instance(); l->color = p_light->get_color(); if (cast_to(p_light)) { - l->light_type = "directional"; + l->type = "directional"; DirectionalLight *light = cast_to(p_light); l->intensity = light->get_param(DirectionalLight::PARAM_ENERGY); - l->range = FLT_MAX; // Range for directional lights is infinite in Godot. + l->range = FLT_MAX; // Range for directional lights is infinite in Pandemonium. } else if (cast_to(p_light)) { - l->light_type = "point"; + l->type = "point"; OmniLight *light = cast_to(p_light); l->range = light->get_param(OmniLight::PARAM_RANGE); l->intensity = light->get_param(OmniLight::PARAM_ENERGY); } else if (cast_to(p_light)) { - l->light_type = "spot"; + l->type = "spot"; SpotLight *light = cast_to(p_light); l->range = light->get_param(SpotLight::PARAM_RANGE); l->intensity = light->get_param(SpotLight::PARAM_ENERGY); @@ -5379,10 +5275,10 @@ void GLTFDocument::_convert_spatial(Ref state, Spatial *p_spatial, Re Transform xform = p_spatial->get_transform(); p_node->scale = xform.basis.get_scale(); p_node->rotation = xform.basis.get_rotation_quat(); - p_node->position = xform.origin; + p_node->translation = xform.origin; } -Spatial *GLTFDocument::_generate_spatial(Ref state, const GLTFNodeIndex node_index) { +Spatial *GLTFDocument::_generate_spatial(Ref state, Node *scene_parent, const GLTFNodeIndex node_index) { Ref gltf_node = state->nodes[node_index]; Spatial *spatial = memnew(Spatial); @@ -5393,11 +5289,9 @@ Spatial *GLTFDocument::_generate_spatial(Ref state, const GLTFNodeInd void GLTFDocument::_convert_scene_node(Ref state, Node *p_current, const GLTFNodeIndex p_gltf_parent, const GLTFNodeIndex p_gltf_root) { bool retflag = true; _check_visibility(p_current, retflag); - if (retflag) { return; } - Ref gltf_node; gltf_node.instance(); gltf_node->set_name(_gen_unique_name(state, p_current->get_name())); @@ -5415,11 +5309,11 @@ void GLTFDocument::_convert_scene_node(Ref state, Node *p_current, co } else if (cast_to(p_current)) { Skeleton *skel = cast_to(p_current); _convert_skeleton_to_gltf(skel, state, p_gltf_parent, p_gltf_root, gltf_node); - // We ignore the Godot Engine node that is the skeleton. + // We ignore the Pandemonium Engine node that is the skeleton. return; } else if (cast_to(p_current)) { MultiMeshInstance *multi = cast_to(p_current); - _convert_multi_mesh_instance_to_gltf(multi, p_gltf_parent, p_gltf_root, gltf_node, state); + _convert_mult_mesh_instance_to_gltf(multi, p_gltf_parent, p_gltf_root, gltf_node, state); } else if (cast_to(p_current)) { Camera *camera = Object::cast_to(p_current); _convert_camera_to_gltf(camera, state, gltf_node); @@ -5430,9 +5324,6 @@ void GLTFDocument::_convert_scene_node(Ref state, Node *p_current, co AnimationPlayer *animation_player = Object::cast_to(p_current); _convert_animation_player_to_gltf(animation_player, state, p_gltf_parent, p_gltf_root, gltf_node, p_current); } - //TODO ADD SUPPORT FOR MESH DATA INSTANCE -> it can be converted to MeshInstance trivially - //TODO ADD SUPPORT FOR PROP INSTACE -> They can be coverted to scenes already - GLTFNodeIndex current_node_i = state->nodes.size(); GLTFNodeIndex gltf_root = p_gltf_root; if (gltf_root == -1) { @@ -5449,7 +5340,7 @@ void GLTFDocument::_convert_scene_node(Ref state, Node *p_current, co void GLTFDocument::_create_gltf_node(Ref state, Node *p_scene_parent, GLTFNodeIndex current_node_i, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_gltf_node, Ref gltf_node) { - state->scene_nodes.set(current_node_i, p_scene_parent); + state->scene_nodes.insert(current_node_i, p_scene_parent); state->nodes.push_back(gltf_node); ERR_FAIL_COND(current_node_i == p_parent_node_index); state->nodes.write[current_node_i]->parent = p_parent_node_index; @@ -5494,73 +5385,49 @@ void GLTFDocument::_convert_light_to_gltf(Light *light, Ref state, Re } } -void GLTFDocument::_convert_multi_mesh_instance_to_gltf( - MultiMeshInstance *p_multi_mesh_instance, - GLTFNodeIndex p_parent_node_index, - GLTFNodeIndex p_root_node_index, - Ref gltf_node, Ref state) { - ERR_FAIL_COND(!p_multi_mesh_instance); +void GLTFDocument::_convert_mult_mesh_instance_to_gltf(MultiMeshInstance *p_multi_mesh_instance, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref gltf_node, Ref state) { Ref multi_mesh = p_multi_mesh_instance->get_multimesh(); - if (multi_mesh.is_null()) { - return; - } - Ref gltf_mesh; - gltf_mesh.instance(); - Ref mesh = multi_mesh->get_mesh(); - if (mesh.is_null()) { - return; - } - gltf_mesh->set_name(multi_mesh->get_name()); - Ref importer_mesh; - importer_mesh.instance(); - Ref array_mesh = multi_mesh->get_mesh(); - if (array_mesh.is_valid()) { - importer_mesh->set_blend_shape_mode(array_mesh->get_blend_shape_mode()); - for (int32_t blend_i = 0; blend_i < array_mesh->get_blend_shape_count(); blend_i++) { - importer_mesh->add_blend_shape(array_mesh->get_blend_shape_name(blend_i)); + if (multi_mesh.is_valid()) { + for (int32_t instance_i = 0; instance_i < multi_mesh->get_instance_count(); + instance_i++) { + GLTFNode *new_gltf_node = memnew(GLTFNode); + Transform transform; + if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_2D) { + Transform2D xform_2d = multi_mesh->get_instance_transform_2d(instance_i); + transform.origin = + Vector3(xform_2d.get_origin().x, 0, xform_2d.get_origin().y); + real_t rotation = xform_2d.get_rotation(); + Quat quat(Vector3(0, 1, 0), rotation); + Size2 scale = xform_2d.get_scale(); + transform.basis.set_quat_scale(quat, + Vector3(scale.x, 0, scale.y)); + transform = + p_multi_mesh_instance->get_transform() * transform; + } else if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_3D) { + transform = p_multi_mesh_instance->get_transform() * + multi_mesh->get_instance_transform(instance_i); + } + Ref mm = multi_mesh->get_mesh(); + if (mm.is_valid()) { + Ref mesh; + mesh.instance(); + for (int32_t surface_i = 0; surface_i < mm->get_surface_count(); surface_i++) { + Array surface = mm->surface_get_arrays(surface_i); + mesh->add_surface_from_arrays(mm->surface_get_primitive_type(surface_i), surface); + } + Ref gltf_mesh; + gltf_mesh.instance(); + gltf_mesh->set_name(multi_mesh->get_name()); + gltf_mesh->set_mesh(mesh); + new_gltf_node->mesh = state->meshes.size(); + state->meshes.push_back(gltf_mesh); + } + new_gltf_node->xform = transform; + new_gltf_node->set_name(_gen_unique_name(state, p_multi_mesh_instance->get_name())); + gltf_node->children.push_back(state->nodes.size()); + state->nodes.push_back(new_gltf_node); } } - for (int32_t surface_i = 0; surface_i < mesh->get_surface_count(); surface_i++) { - Ref mat = mesh->surface_get_material(surface_i); - String material_name; - if (mat.is_valid()) { - material_name = mat->get_name(); - } - Array blend_arrays; - if (array_mesh.is_valid()) { - blend_arrays = array_mesh->surface_get_blend_shape_arrays(surface_i); - } - importer_mesh->add_surface(mesh->surface_get_primitive_type(surface_i), mesh->surface_get_arrays(surface_i), - blend_arrays, Dictionary(), mat, material_name, mesh->surface_get_format(surface_i)); - } - gltf_mesh->set_mesh(importer_mesh); - GLTFMeshIndex mesh_index = state->meshes.size(); - state->meshes.push_back(gltf_mesh); - for (int32_t instance_i = 0; instance_i < multi_mesh->get_instance_count(); - instance_i++) { - Transform transform; - if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_2D) { - Transform2D xform_2d = multi_mesh->get_instance_transform_2d(instance_i); - transform.origin = - Vector3(xform_2d.get_origin().x, 0, xform_2d.get_origin().y); - real_t rotation = xform_2d.get_rotation(); - Quat quaternion(Vector3(0, 1, 0), rotation); - Size2 scale = xform_2d.get_scale(); - transform.basis.set_quat_scale(quaternion, - Vector3(scale.x, 0, scale.y)); - transform = p_multi_mesh_instance->get_transform() * transform; - } else if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_3D) { - transform = p_multi_mesh_instance->get_transform() * - multi_mesh->get_instance_transform(instance_i); - } - Ref new_gltf_node; - new_gltf_node.instance(); - new_gltf_node->mesh = mesh_index; - new_gltf_node->xform = transform; - new_gltf_node->set_name(_gen_unique_name(state, p_multi_mesh_instance->get_name())); - gltf_node->children.push_back(state->nodes.size()); - state->nodes.push_back(new_gltf_node); - } } void GLTFDocument::_convert_skeleton_to_gltf(Skeleton *p_skeleton3d, Ref state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref gltf_node) { @@ -5569,7 +5436,7 @@ void GLTFDocument::_convert_skeleton_to_gltf(Skeleton *p_skeleton3d, Refgodot_skeleton = skeleton; + gltf_skeleton->pandemonium_skeleton = skeleton; GLTFSkeletonIndex skeleton_i = state->skeletons.size(); state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()] = skeleton_i; state->skeletons.push_back(gltf_skeleton); @@ -5581,24 +5448,23 @@ void GLTFDocument::_convert_skeleton_to_gltf(Skeleton *p_skeleton3d, Refset_name(_gen_unique_name(state, skeleton->get_bone_name(bone_i))); - Transform xform = skeleton->get_bone_pose(bone_i); + Transform xform = skeleton->get_bone_rest(bone_i) * skeleton->get_bone_pose(bone_i); joint_node->scale = xform.basis.get_scale(); joint_node->rotation = xform.basis.get_rotation_quat(); - joint_node->position = xform.origin; + joint_node->translation = xform.origin; joint_node->joint = true; GLTFNodeIndex current_node_i = state->nodes.size(); - state->scene_nodes.set(current_node_i, skeleton); + state->scene_nodes.insert(current_node_i, skeleton); state->nodes.push_back(joint_node); gltf_skeleton->joints.push_back(current_node_i); if (skeleton->get_bone_parent(bone_i) == -1) { gltf_skeleton->roots.push_back(current_node_i); } - - gltf_skeleton->godot_bone_node.set(bone_i, current_node_i); + gltf_skeleton->pandemonium_bone_node.insert(bone_i, current_node_i); } for (BoneId bone_i = 0; bone_i < bone_count; bone_i++) { - GLTFNodeIndex current_node_i = gltf_skeleton->godot_bone_node[bone_i]; + GLTFNodeIndex current_node_i = gltf_skeleton->pandemonium_bone_node[bone_i]; BoneId parent_bone_id = skeleton->get_bone_parent(bone_i); if (parent_bone_id == -1) { if (p_parent_node_index != -1) { @@ -5606,7 +5472,7 @@ void GLTFDocument::_convert_skeleton_to_gltf(Skeleton *p_skeleton3d, Refnodes.write[p_parent_node_index]->children.push_back(current_node_i); } } else { - GLTFNodeIndex parent_node_i = gltf_skeleton->godot_bone_node[parent_bone_id]; + GLTFNodeIndex parent_node_i = gltf_skeleton->pandemonium_bone_node[parent_bone_id]; state->nodes.write[current_node_i]->parent = parent_node_i; state->nodes.write[parent_node_i]->children.push_back(current_node_i); } @@ -5621,21 +5487,14 @@ void GLTFDocument::_convert_skeleton_to_gltf(Skeleton *p_skeleton3d, Ref state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref gltf_node) { Skeleton *skeleton; // Note that relative transforms to external skeletons and pose overrides are not supported. - if (p_bone_attachment->get_use_external_skeleton()) { - skeleton = cast_to(p_bone_attachment->get_node_or_null(p_bone_attachment->get_external_skeleton())); - } else { - skeleton = cast_to(p_bone_attachment->get_parent()); - } + skeleton = cast_to(p_bone_attachment->get_parent()); GLTFSkeletonIndex skel_gltf_i = -1; if (skeleton != nullptr && state->skeleton3d_to_gltf_skeleton.has(skeleton->get_instance_id())) { skel_gltf_i = state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()]; } int bone_idx = -1; if (skeleton != nullptr) { - bone_idx = p_bone_attachment->get_bone_idx(); - if (bone_idx == -1) { - bone_idx = skeleton->find_bone(p_bone_attachment->get_bone_name()); - } + bone_idx = skeleton->find_bone(p_bone_attachment->get_bone_name()); } GLTFNodeIndex par_node_index = p_parent_node_index; if (skeleton != nullptr && bone_idx != -1 && skel_gltf_i != -1) { @@ -5671,12 +5530,12 @@ void GLTFDocument::_generate_scene_node(Ref state, Node *scene_parent const bool non_bone_parented_to_skeleton = active_skeleton; - // skinned meshes must not be placed in a bone attachment. + // If we have an active skeleton, and the node is node skinned, we need to create a bone attachment if (non_bone_parented_to_skeleton && gltf_node->skin < 0) { // Bone Attachment - Parent Case BoneAttachment *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, gltf_node->parent); - scene_parent->add_child(bone_attachment, true); + scene_parent->add_child(bone_attachment); bone_attachment->set_owner(scene_root); // There is no gltf_node that represent this, so just directly create a unique name @@ -5687,25 +5546,26 @@ void GLTFDocument::_generate_scene_node(Ref state, Node *scene_parent scene_parent = bone_attachment; } if (gltf_node->mesh >= 0) { - current_node = _generate_mesh_instance(state, node_index); + current_node = _generate_mesh_instance(state, scene_parent, node_index); } else if (gltf_node->camera >= 0) { - current_node = _generate_camera(state, node_index); + current_node = _generate_camera(state, scene_parent, node_index); } else if (gltf_node->light >= 0) { - current_node = _generate_light(state, node_index); + current_node = _generate_light(state, scene_parent, node_index); } // We still have not managed to make a node. if (!current_node) { - current_node = _generate_spatial(state, node_index); + current_node = _generate_spatial(state, scene_parent, node_index); } - scene_parent->add_child(current_node, true); + + scene_parent->add_child(current_node); if (current_node != scene_root) { current_node->set_owner(scene_root); } current_node->set_transform(gltf_node->xform); current_node->set_name(gltf_node->get_name()); - state->scene_nodes.set(node_index, current_node); + state->scene_nodes.insert(node_index, current_node); for (int i = 0; i < gltf_node->children.size(); ++i) { _generate_scene_node(state, current_node, scene_root, gltf_node->children[i]); @@ -5717,7 +5577,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref state, Node *scen Spatial *current_node = nullptr; - Skeleton *skeleton = state->skeletons[gltf_node->skeleton]->godot_skeleton; + Skeleton *skeleton = state->skeletons[gltf_node->skeleton]->pandemonium_skeleton; // In this case, this node is already a bone in skeleton. const bool is_skinned_mesh = (gltf_node->skin >= 0 && gltf_node->mesh >= 0); const bool requires_extra_node = (gltf_node->mesh >= 0 || gltf_node->camera >= 0 || gltf_node->light >= 0); @@ -5728,7 +5588,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref state, Node *scen // Bone Attachment - Direct Parented Skeleton Case BoneAttachment *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, gltf_node->parent); - scene_parent->add_child(bone_attachment, true); + scene_parent->add_child(bone_attachment); bone_attachment->set_owner(scene_root); // There is no gltf_node that represent this, so just directly create a unique name @@ -5742,7 +5602,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref state, Node *scen // Add it to the scene if it has not already been added if (skeleton->get_parent() == nullptr) { - scene_parent->add_child(skeleton, true); + scene_parent->add_child(skeleton); skeleton->set_owner(scene_root); } } @@ -5756,7 +5616,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref state, Node *scen // Bone Attachment - Same Node Case BoneAttachment *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, node_index); - scene_parent->add_child(bone_attachment, true); + scene_parent->add_child(bone_attachment); bone_attachment->set_owner(scene_root); // There is no gltf_node that represent this, so just directly create a unique name @@ -5769,22 +5629,26 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref state, Node *scen // We still have not managed to make a node if (gltf_node->mesh >= 0) { - current_node = _generate_mesh_instance(state, node_index); + current_node = _generate_mesh_instance(state, scene_parent, node_index); } else if (gltf_node->camera >= 0) { - current_node = _generate_camera(state, node_index); + current_node = _generate_camera(state, scene_parent, node_index); } else if (gltf_node->light >= 0) { - current_node = _generate_light(state, node_index); + current_node = _generate_light(state, scene_parent, node_index); } - scene_parent->add_child(current_node, true); + scene_parent->add_child(current_node); if (current_node != scene_root) { current_node->set_owner(scene_root); } // Do not set transform here. Transform is already applied to our bone. - current_node->set_name(gltf_node->get_name()); + if (state->use_legacy_names) { + current_node->set_name(_legacy_validate_node_name(gltf_node->get_name())); + } else { + current_node->set_name(gltf_node->get_name()); + } } - state->scene_nodes.set(node_index, current_node); + state->scene_nodes.insert(node_index, current_node); for (int i = 0; i < gltf_node->children.size(); ++i) { _generate_scene_node(state, active_skeleton, scene_root, gltf_node->children[i]); @@ -5792,7 +5656,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref state, Node *scen } template -struct SceneFormatImporterGLTFInterpolate { +struct EditorSceneImporterGLTFInterpolate { T lerp(const T &a, const T &b, float c) const { return a + (b - a) * c; } @@ -5818,7 +5682,7 @@ struct SceneFormatImporterGLTFInterpolate { // thank you for existing, partial specialization template <> -struct SceneFormatImporterGLTFInterpolate { +struct EditorSceneImporterGLTFInterpolate { Quat lerp(const Quat &a, const Quat &b, const float c) const { ERR_FAIL_COND_V_MSG(!a.is_normalized(), Quat(), "The quaternion \"a\" must be normalized."); ERR_FAIL_COND_V_MSG(!b.is_normalized(), Quat(), "The quaternion \"b\" must be normalized."); @@ -5842,11 +5706,9 @@ struct SceneFormatImporterGLTFInterpolate { }; template -T GLTFDocument::_interpolate_track(const PoolRealArray &p_times, const PoolVector &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp) { +T GLTFDocument::_interpolate_track(const Vector &p_times, const Vector &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp) { ERR_FAIL_COND_V(!p_values.size(), T()); - if (p_times.size() != p_values.size()) { - //TODO UNDO THIS: - //if (p_times.size() != (p_values.size() / (p_interp == GLTFAnimation::INTERP_CUBIC_SPLINE ? 3 : 1))) { + if (p_times.size() != (p_values.size() / (p_interp == GLTFAnimation::INTERP_CUBIC_SPLINE ? 3 : 1))) { ERR_PRINT_ONCE("The interpolated values are not corresponding to its times."); return p_values[0]; } @@ -5859,7 +5721,7 @@ T GLTFDocument::_interpolate_track(const PoolRealArray &p_times, const PoolVecto idx++; } - SceneFormatImporterGLTFInterpolate interp; + EditorSceneImporterGLTFInterpolate interp; switch (p_interp) { case GLTFAnimation::INTERP_LINEAR: { @@ -5928,38 +5790,30 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, animation->set_name(name); if (anim->get_loop()) { - //animation->set_loop_mode(Animation::LOOP_LINEAR); animation->set_loop(true); } float length = 0.0; - HashMap &anims = anim->get_tracks(); - const int *anims_key = NULL; - - while ((anims_key = anims.next(anims_key))) { - int track_i_key = *anims_key; - const GLTFAnimation::Track &track = anims[track_i_key]; + for (Map::Element *track_i = anim->get_tracks().front(); track_i; track_i = track_i->next()) { + const GLTFAnimation::Track &track = track_i->get(); //need to find the path: for skeletons, weight tracks will affect the mesh NodePath node_path; //for skeletons, transform tracks always affect bones NodePath transform_node_path; - GLTFNodeIndex node_index = track_i_key; + GLTFNodeIndex node_index = track_i->key(); - const Ref gltf_node = state->nodes[track_i_key]; + const Ref gltf_node = state->nodes[track_i->key()]; Node *root = ap->get_parent(); ERR_FAIL_COND(root == nullptr); - - HashMap scene_nodes; - Node **node_element = state->scene_nodes.getptr(node_index); - ERR_CONTINUE_MSG(!node_element, vformat("Unable to find node %d for animation", node_index)); - Node *node_element_value = *node_element; - node_path = root->get_path_to(node_element_value); + Map::Element *node_element = state->scene_nodes.find(node_index); + ERR_CONTINUE_MSG(node_element == nullptr, vformat("Unable to find node %d for animation", node_index)); + node_path = root->get_path_to(node_element->get()); if (gltf_node->skeleton >= 0) { - const Skeleton *sk = state->skeletons[gltf_node->skeleton]->godot_skeleton; + const Skeleton *sk = state->skeletons[gltf_node->skeleton]->pandemonium_skeleton; ERR_FAIL_COND(sk == nullptr); const String path = ap->get_parent()->get_path_to(sk); @@ -5972,8 +5826,8 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, for (int i = 0; i < track.rotation_track.times.size(); i++) { length = MAX(length, track.rotation_track.times[i]); } - for (int i = 0; i < track.position_track.times.size(); i++) { - length = MAX(length, track.position_track.times[i]); + for (int i = 0; i < track.translation_track.times.size(); i++) { + length = MAX(length, track.translation_track.times[i]); } for (int i = 0; i < track.scale_track.times.size(); i++) { length = MAX(length, track.scale_track.times[i]); @@ -5987,78 +5841,11 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, // Animated TRS properties will not affect a skinned mesh. const bool transform_affects_skinned_mesh_instance = gltf_node->skeleton < 0 && gltf_node->skin >= 0; - if ((track.rotation_track.values.size() || track.position_track.values.size() || track.scale_track.values.size()) && !transform_affects_skinned_mesh_instance) { + if ((track.rotation_track.values.size() || track.translation_track.values.size() || track.scale_track.values.size()) && !transform_affects_skinned_mesh_instance) { //make transform track - - //TODO REMOVE THIS: int track_idx = animation->get_track_count(); animation->add_track(Animation::TYPE_TRANSFORM); animation->track_set_path(track_idx, transform_node_path); - - //TODO UNCOMMENT: - /* - int base_idx = animation->get_track_count(); - int position_idx = -1; - int rotation_idx = -1; - int scale_idx = -1; - - if (track.position_track.values.size()) { - Vector3 base_pos = state->nodes[track_i.key]->position; - bool not_default = false; //discard the track if all it contains is default values - for (int i = 0; i < track.position_track.times.size(); i++) { - Vector3 value = track.position_track.values[track.position_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i]; - if (!value.is_equal_approx(base_pos)) { - not_default = true; - break; - } - } - if (not_default) { - position_idx = base_idx; - animation->add_track(Animation::TYPE_POSITION_3D); - animation->track_set_path(position_idx, transform_node_path); - animation->track_set_imported(position_idx, true); //helps merging later - - base_idx++; - } - } - if (track.rotation_track.values.size()) { - Quat base_rot = state->nodes[track_i.key]->rotation.normalized(); - bool not_default = false; //discard the track if all it contains is default values - for (int i = 0; i < track.rotation_track.times.size(); i++) { - Quat value = track.rotation_track.values[track.rotation_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i].normalized(); - if (!value.is_equal_approx(base_rot)) { - not_default = true; - break; - } - } - if (not_default) { - rotation_idx = base_idx; - animation->add_track(Animation::TYPE_ROTATION_3D); - animation->track_set_path(rotation_idx, transform_node_path); - animation->track_set_imported(rotation_idx, true); //helps merging later - base_idx++; - } - } - if (track.scale_track.values.size()) { - Vector3 base_scale = state->nodes[track_i.key]->scale; - bool not_default = false; //discard the track if all it contains is default values - for (int i = 0; i < track.scale_track.times.size(); i++) { - Vector3 value = track.scale_track.values[track.scale_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i]; - if (!value.is_equal_approx(base_scale)) { - not_default = true; - break; - } - } - if (not_default) { - scale_idx = base_idx; - animation->add_track(Animation::TYPE_SCALE_3D); - animation->track_set_path(scale_idx, transform_node_path); - animation->track_set_imported(scale_idx, true); //helps merging later - base_idx++; - } - } - */ - //first determine animation length const double increment = 1.0 / bake_fps; @@ -6068,43 +5855,26 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, Quat base_rot; Vector3 base_scale = Vector3(1, 1, 1); - //TODO REMOVE: if (!track.rotation_track.values.size()) { - base_rot = state->nodes[track_i_key]->rotation.normalized(); + base_rot = state->nodes[track_i->key()]->rotation.normalized(); } - if (!track.position_track.values.size()) { - base_pos = state->nodes[track_i_key]->position; + if (!track.translation_track.values.size()) { + base_pos = state->nodes[track_i->key()]->translation; } if (!track.scale_track.values.size()) { - base_scale = state->nodes[track_i_key]->scale; + base_scale = state->nodes[track_i->key()]->scale; } - //TODO UNCOMMENT - /* - if (rotation_idx == -1) { - base_rot = state->nodes[track_i_key]->rotation.normalized(); - } - - if (position_idx == -1) { - base_pos = state->nodes[track_i_key]->position; - } - - if (scale_idx == -1) { - base_scale = state->nodes[track_i_key]->scale; - } - */ - bool last = false; while (true) { Vector3 pos = base_pos; Quat rot = base_rot; Vector3 scale = base_scale; - //TODO DELETE - if (track.position_track.times.size()) { - pos = _interpolate_track(track.position_track.times, track.position_track.values, time, track.position_track.interpolation); + if (track.translation_track.times.size()) { + pos = _interpolate_track(track.translation_track.times, track.translation_track.values, time, track.translation_track.interpolation); } if (track.rotation_track.times.size()) { @@ -6115,23 +5885,22 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, scale = _interpolate_track(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation); } - //TODO UNCOMMENT - /* - if (position_idx >= 0) { - pos = _interpolate_track(track.position_track.times, track.position_track.values, time, track.position_track.interpolation); - animation->position_track_insert_key(position_idx, time, pos); + if (gltf_node->skeleton >= 0) { + Transform xform; + xform.basis.set_quat_scale(rot, scale); + xform.origin = pos; + + const Skeleton *skeleton = state->skeletons[gltf_node->skeleton]->pandemonium_skeleton; + const int bone_idx = skeleton->find_bone(gltf_node->get_name()); + xform = skeleton->get_bone_rest(bone_idx).affine_inverse() * xform; + + rot = xform.basis.get_rotation_quat(); + rot.normalize(); + scale = xform.basis.get_scale(); + pos = xform.origin; } - if (rotation_idx >= 0) { - rot = _interpolate_track(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation); - animation->rotation_track_insert_key(rotation_idx, time, rot); - } - - if (scale_idx >= 0) { - scale = _interpolate_track(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation); - animation->scale_track_insert_key(scale_idx, time, scale); - } - */ + animation->transform_track_insert_key(track_idx, time, pos, rot, scale); if (last) { break; @@ -6144,21 +5913,20 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, } } - /* for (int i = 0; i < track.weight_tracks.size(); i++) { ERR_CONTINUE(gltf_node->mesh < 0 || gltf_node->mesh >= state->meshes.size()); Ref mesh = state->meshes[gltf_node->mesh]; ERR_CONTINUE(mesh.is_null()); ERR_CONTINUE(mesh->get_mesh().is_null()); - ERR_CONTINUE(mesh->get_mesh()->get_mesh().is_null()); + const String prop = "blend_shapes/" + mesh->get_mesh()->get_blend_shape_name(i); - const String blend_path = String(node_path) + ":" + String(mesh->get_mesh()->get_blend_shape_name(i)); + const String blend_path = String(node_path) + ":" + prop; const int track_idx = animation->get_track_count(); - animation->add_track(Animation::TYPE_BLEND_SHAPE); + animation->add_track(Animation::TYPE_VALUE); animation->track_set_path(track_idx, blend_path); - // Only LINEAR and STEP (NEAREST) can be supported out of the box by Godot's Animation, + // Only LINEAR and STEP (NEAREST) can be supported out of the box by Pandemonium's Animation, // the other modes have to be baked. GLTFAnimation::Interpolation gltf_interp = track.weight_tracks[i].interpolation; if (gltf_interp == GLTFAnimation::INTERP_LINEAR || gltf_interp == GLTFAnimation::INTERP_STEP) { @@ -6166,7 +5934,7 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, for (int j = 0; j < track.weight_tracks[i].times.size(); j++) { const float t = track.weight_tracks[i].times[j]; const float attribs = track.weight_tracks[i].values[j]; - animation->blend_shape_track_insert_key(track_idx, t, attribs); + animation->track_insert_key(track_idx, t, attribs); } } else { // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. @@ -6174,8 +5942,7 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, double time = 0.0; bool last = false; while (true) { - real_t blend = _interpolate_track(track.weight_tracks[i].times, track.weight_tracks[i].values, time, gltf_interp); - animation->blend_shape_track_insert_key(track_idx, time, blend); + _interpolate_track(track.weight_tracks[i].times, track.weight_tracks[i].values, time, gltf_interp); if (last) { break; } @@ -6187,22 +5954,10 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, } } } - */ } animation->set_length(length); - /* - Ref library; - if (!ap->has_animation_library("")) { - library.instance(); - ap->add_animation_library("", library); - } else { - library = ap->get_animation_library(""); - } - library->add_animation(name, animation); - */ - ap->add_animation(name, animation); } @@ -6213,23 +5968,16 @@ void GLTFDocument::_convert_mesh_instances(Ref state) { if (node->mesh < 0) { continue; } - - Node **mi_element = state->scene_nodes.getptr(mi_node_i); + Map::Element *mi_element = state->scene_nodes.find(mi_node_i); if (!mi_element) { continue; } - - Node *mi_element_value = *mi_element; - - MeshInstance *mi = Object::cast_to(mi_element_value); - if (!mi) { - continue; - } - + MeshInstance *mi = Object::cast_to(mi_element->get()); + ERR_CONTINUE(!mi); Transform mi_xform = mi->get_transform(); node->scale = mi_xform.basis.get_scale(); node->rotation = mi_xform.basis.get_rotation_quat(); - node->position = mi_xform.origin; + node->translation = mi_xform.origin; Skeleton *skeleton = Object::cast_to(mi->get_node(mi->get_skeleton_path())); if (!skeleton) { @@ -6245,22 +5993,22 @@ void GLTFDocument::_convert_mesh_instances(Ref state) { NodePath skeleton_path = mi->get_skeleton_path(); Node *skel_node = mi->get_node_or_null(skeleton_path); - Skeleton *godot_skeleton = nullptr; + Skeleton *pandemonium_skeleton = nullptr; if (skel_node != nullptr) { - godot_skeleton = cast_to(skel_node); + pandemonium_skeleton = cast_to(skel_node); } - if (godot_skeleton != nullptr && state->skeleton3d_to_gltf_skeleton.has(godot_skeleton->get_instance_id())) { + if (pandemonium_skeleton != nullptr && state->skeleton3d_to_gltf_skeleton.has(pandemonium_skeleton->get_instance_id())) { // This is a skinned mesh. If the mesh has no ARRAY_WEIGHTS or ARRAY_BONES, it will be invisible. - const GLTFSkeletonIndex skeleton_gltf_i = state->skeleton3d_to_gltf_skeleton[godot_skeleton->get_instance_id()]; + const GLTFSkeletonIndex skeleton_gltf_i = state->skeleton3d_to_gltf_skeleton[pandemonium_skeleton->get_instance_id()]; Ref gltf_skeleton = state->skeletons[skeleton_gltf_i]; int bone_cnt = skeleton->get_bone_count(); ERR_FAIL_COND(bone_cnt != gltf_skeleton->joints.size()); - ObjectID gltf_skin_key; + ObjectID gltf_skin_key = 0; if (skin.is_valid()) { gltf_skin_key = skin->get_instance_id(); } - ObjectID gltf_skel_key = godot_skeleton->get_instance_id(); + ObjectID gltf_skel_key = pandemonium_skeleton->get_instance_id(); GLTFSkinIndex skin_gltf_i = -1; GLTFNodeIndex root_gltf_i = -1; if (!gltf_skeleton->roots.empty()) { @@ -6271,49 +6019,39 @@ void GLTFDocument::_convert_mesh_instances(Ref state) { } else { if (skin.is_null()) { // Note that gltf_skin_key should remain null, so these can share a reference. - skin = skeleton->create_skin_from_rest_transforms(); + skin = skeleton->register_skin(nullptr)->get_skin(); } - gltf_skin.instance(); - gltf_skin->godot_skin = skin; + gltf_skin->pandemonium_skin = skin; gltf_skin->set_name(skin->get_name()); gltf_skin->skeleton = skeleton_gltf_i; gltf_skin->skin_root = root_gltf_i; - //gltf_state->godot_to_gltf_node[skel_node] - + //gltf_state->pandemonium_to_gltf_node[skel_node] HashMap bone_name_to_idx; for (int bone_i = 0; bone_i < bone_cnt; bone_i++) { bone_name_to_idx[skeleton->get_bone_name(bone_i)] = bone_i; } - for (int bind_i = 0, cnt = skin->get_bind_count(); bind_i < cnt; bind_i++) { int bone_i = skin->get_bind_bone(bind_i); Transform bind_pose = skin->get_bind_pose(bind_i); StringName bind_name = skin->get_bind_name(bind_i); - if (bind_name != StringName()) { bone_i = bone_name_to_idx[bind_name]; } - ERR_CONTINUE(bone_i < 0 || bone_i >= bone_cnt); - if (bind_name == StringName()) { bind_name = skeleton->get_bone_name(bone_i); } - GLTFNodeIndex skeleton_bone_i = gltf_skeleton->joints[bone_i]; gltf_skin->joints_original.push_back(skeleton_bone_i); gltf_skin->joints.push_back(skeleton_bone_i); gltf_skin->inverse_binds.push_back(bind_pose); - if (skeleton->get_bone_parent(bone_i) == -1) { gltf_skin->roots.push_back(skeleton_bone_i); } - gltf_skin->joint_i_to_bone_i[bind_i] = bone_i; gltf_skin->joint_i_to_name[bind_i] = bind_name; } - skin_gltf_i = state->skins.size(); state->skins.push_back(gltf_skin); state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key][gltf_skel_key] = skin_gltf_i; @@ -6362,30 +6100,28 @@ void GLTFDocument::_process_mesh_instances(Ref state, Node *scene_roo if (node->skin >= 0 && node->mesh >= 0) { const GLTFSkinIndex skin_i = node->skin; - Node **mi_element = state->scene_nodes.getptr(node_i); - ERR_CONTINUE_MSG(!mi_element, vformat("Unable to find node %d", node_i)); - Node *mi_element_value = *mi_element; + Map::Element *mi_element = state->scene_nodes.find(node_i); + ERR_CONTINUE_MSG(mi_element == nullptr, vformat("Unable to find node %d", node_i)); - ImporterMeshInstance3D *mi = Object::cast_to(mi_element_value); - ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to ImporterMeshInstance3D", node_i, mi_element_value->get_class_name())); + MeshInstance *mi = Object::cast_to(mi_element->get()); + ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to MeshInstance", node_i, mi_element->get()->get_class_name())); const GLTFSkeletonIndex skel_i = state->skins.write[node->skin]->skeleton; Ref gltf_skeleton = state->skeletons.write[skel_i]; - Skeleton *skeleton = gltf_skeleton->godot_skeleton; + Skeleton *skeleton = gltf_skeleton->pandemonium_skeleton; ERR_CONTINUE_MSG(skeleton == nullptr, vformat("Unable to find Skeleton for node %d skin %d", node_i, skin_i)); mi->get_parent()->remove_child(mi); - skeleton->add_child(mi, true); + skeleton->add_child(mi); mi->set_owner(skeleton->get_owner()); - mi->set_skin(state->skins.write[skin_i]->godot_skin); + mi->set_skin(state->skins.write[skin_i]->pandemonium_skin); mi->set_skeleton_path(mi->get_path_to(skeleton)); mi->set_transform(Transform()); } } } -//TODO DELETE GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref state, GLTFAnimation::Track p_track, Ref p_animation, Transform p_bone_rest, int32_t p_track_i, GLTFNodeIndex p_node_i) { Animation::InterpolationType interpolation = p_animation->track_get_interpolation_type(p_track_i); @@ -6399,16 +6135,15 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref state } Animation::TrackType track_type = p_animation->track_get_type(p_track_i); int32_t key_count = p_animation->track_get_key_count(p_track_i); - PoolVector times; + Vector times; times.resize(key_count); String path = p_animation->track_get_path(p_track_i); for (int32_t key_i = 0; key_i < key_count; key_i++) { - times.set(key_i, p_animation->track_get_key_time(p_track_i, key_i)); + times.write[key_i] = p_animation->track_get_key_time(p_track_i, key_i); } - if (track_type == Animation::TYPE_TRANSFORM) { - p_track.position_track.times = times; - p_track.position_track.interpolation = gltf_interpolation; + p_track.translation_track.times = times; + p_track.translation_track.interpolation = gltf_interpolation; p_track.rotation_track.times = times; p_track.rotation_track.interpolation = gltf_interpolation; p_track.scale_track.times = times; @@ -6416,27 +6151,27 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref state p_track.scale_track.values.resize(key_count); p_track.scale_track.interpolation = gltf_interpolation; - p_track.position_track.values.resize(key_count); - p_track.position_track.interpolation = gltf_interpolation; + p_track.translation_track.values.resize(key_count); + p_track.translation_track.interpolation = gltf_interpolation; p_track.rotation_track.values.resize(key_count); p_track.rotation_track.interpolation = gltf_interpolation; for (int32_t key_i = 0; key_i < key_count; key_i++) { - Vector3 position; + Vector3 translation; Quat rotation; Vector3 scale; - Error err = p_animation->transform_track_get_key(p_track_i, key_i, &position, &rotation, &scale); + Error err = p_animation->transform_track_get_key(p_track_i, key_i, &translation, &rotation, &scale); ERR_CONTINUE(err != OK); Transform xform; xform.basis.set_quat_scale(rotation, scale); - xform.origin = position; + xform.origin = translation; xform = p_bone_rest * xform; - p_track.position_track.values.set(key_i, xform.get_origin()); - p_track.rotation_track.values.set(key_i, xform.basis.get_rotation_quat()); - p_track.scale_track.values.set(key_i, xform.basis.get_scale()); + p_track.translation_track.values.write[key_i] = xform.get_origin(); + p_track.rotation_track.values.write[key_i] = xform.basis.get_rotation_quat(); + p_track.scale_track.values.write[key_i] = xform.basis.get_scale(); } } else if (path.find(":transform") != -1) { - p_track.position_track.times = times; - p_track.position_track.interpolation = gltf_interpolation; + p_track.translation_track.times = times; + p_track.translation_track.interpolation = gltf_interpolation; p_track.rotation_track.times = times; p_track.rotation_track.interpolation = gltf_interpolation; p_track.scale_track.times = times; @@ -6444,15 +6179,15 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref state p_track.scale_track.values.resize(key_count); p_track.scale_track.interpolation = gltf_interpolation; - p_track.position_track.values.resize(key_count); - p_track.position_track.interpolation = gltf_interpolation; + p_track.translation_track.values.resize(key_count); + p_track.translation_track.interpolation = gltf_interpolation; p_track.rotation_track.values.resize(key_count); p_track.rotation_track.interpolation = gltf_interpolation; for (int32_t key_i = 0; key_i < key_count; key_i++) { Transform xform = p_animation->track_get_key_value(p_track_i, key_i); - p_track.position_track.values.set(key_i, xform.get_origin()); - p_track.rotation_track.values.set(key_i, xform.basis.get_rotation_quat()); - p_track.scale_track.values.set(key_i, xform.basis.get_scale()); + p_track.translation_track.values.write[key_i] = xform.get_origin(); + p_track.rotation_track.values.write[key_i] = xform.basis.get_rotation_quat(); + p_track.scale_track.values.write[key_i] = xform.basis.get_scale(); } } else if (track_type == Animation::TYPE_VALUE) { if (path.find("/rotation_quat") != -1) { @@ -6464,20 +6199,20 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref state for (int32_t key_i = 0; key_i < key_count; key_i++) { Quat rotation_track = p_animation->track_get_key_value(p_track_i, key_i); - p_track.rotation_track.values.set(key_i, rotation_track); + p_track.rotation_track.values.write[key_i] = rotation_track; } - } else if (path.find(":position") != -1) { - p_track.position_track.times = times; - p_track.position_track.interpolation = gltf_interpolation; + } else if (path.find(":translation") != -1) { + p_track.translation_track.times = times; + p_track.translation_track.interpolation = gltf_interpolation; - p_track.position_track.values.resize(key_count); - p_track.position_track.interpolation = gltf_interpolation; + p_track.translation_track.values.resize(key_count); + p_track.translation_track.interpolation = gltf_interpolation; for (int32_t key_i = 0; key_i < key_count; key_i++) { - Vector3 position = p_animation->track_get_key_value(p_track_i, key_i); - p_track.position_track.values.set(key_i, position); + Vector3 translation = p_animation->track_get_key_value(p_track_i, key_i); + p_track.translation_track.values.write[key_i] = translation; } - } else if (path.find(":rotation") != -1) { + } else if (path.find(":rotation_degrees") != -1) { p_track.rotation_track.times = times; p_track.rotation_track.interpolation = gltf_interpolation; @@ -6485,165 +6220,14 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref state p_track.rotation_track.interpolation = gltf_interpolation; for (int32_t key_i = 0; key_i < key_count; key_i++) { - Vector3 rotation_radian = p_animation->track_get_key_value(p_track_i, key_i); - p_track.rotation_track.values.set(key_i, Quat(rotation_radian)); - } - } else if (path.find(":scale") != -1) { - p_track.scale_track.times = times; - p_track.scale_track.interpolation = gltf_interpolation; - - p_track.scale_track.values.resize(key_count); - p_track.scale_track.interpolation = gltf_interpolation; - - for (int32_t key_i = 0; key_i < key_count; key_i++) { - Vector3 scale_track = p_animation->track_get_key_value(p_track_i, key_i); - p_track.scale_track.values.set(key_i, scale_track); - } - } - } else if (track_type == Animation::TYPE_BEZIER) { - if (path.find("/scale") != -1) { - const int32_t keys = p_animation->track_get_key_time(p_track_i, key_count - 1) * BAKE_FPS; - if (!p_track.scale_track.times.size()) { - PoolVector new_times; - new_times.resize(keys); - for (int32_t key_i = 0; key_i < keys; key_i++) { - new_times.set(key_i, key_i / BAKE_FPS); - } - p_track.scale_track.times = new_times; - p_track.scale_track.interpolation = gltf_interpolation; - - p_track.scale_track.values.resize(keys); - - for (int32_t key_i = 0; key_i < keys; key_i++) { - p_track.scale_track.values.set(key_i, Vector3(1.0f, 1.0f, 1.0f)); - } - p_track.scale_track.interpolation = gltf_interpolation; - } - - for (int32_t key_i = 0; key_i < keys; key_i++) { - Vector3 bezier_track = p_track.scale_track.values[key_i]; - if (path.find("/scale:x") != -1) { - bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); - bezier_track.x = p_bone_rest.affine_inverse().basis.get_scale().x * bezier_track.x; - } else if (path.find("/scale:y") != -1) { - bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); - bezier_track.y = p_bone_rest.affine_inverse().basis.get_scale().y * bezier_track.y; - } else if (path.find("/scale:z") != -1) { - bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); - bezier_track.z = p_bone_rest.affine_inverse().basis.get_scale().z * bezier_track.z; - } - p_track.scale_track.values.set(key_i, bezier_track); - } - } else if (path.find("/position") != -1) { - const int32_t keys = p_animation->track_get_key_time(p_track_i, key_count - 1) * BAKE_FPS; - if (!p_track.position_track.times.size()) { - PoolVector new_times; - new_times.resize(keys); - for (int32_t key_i = 0; key_i < keys; key_i++) { - new_times.set(key_i, key_i / BAKE_FPS); - } - p_track.position_track.times = new_times; - p_track.position_track.interpolation = gltf_interpolation; - - p_track.position_track.values.resize(keys); - p_track.position_track.interpolation = gltf_interpolation; - } - - for (int32_t key_i = 0; key_i < keys; key_i++) { - Vector3 bezier_track = p_track.position_track.values[key_i]; - if (path.find("/position:x") != -1) { - bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); - bezier_track.x = p_bone_rest.affine_inverse().origin.x * bezier_track.x; - } else if (path.find("/position:y") != -1) { - bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); - bezier_track.y = p_bone_rest.affine_inverse().origin.y * bezier_track.y; - } else if (path.find("/position:z") != -1) { - bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); - bezier_track.z = p_bone_rest.affine_inverse().origin.z * bezier_track.z; - } - p_track.position_track.values.set(key_i, bezier_track); - } - } - } - - return p_track; -} - -//TODO UNCOMMENT -/* -GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref state, GLTFAnimation::Track p_track, Ref p_animation, int32_t p_track_i, GLTFNodeIndex p_node_i) { - Animation::InterpolationType interpolation = p_animation->track_get_interpolation_type(p_track_i); - - GLTFAnimation::Interpolation gltf_interpolation = GLTFAnimation::INTERP_LINEAR; - if (interpolation == Animation::InterpolationType::INTERPOLATION_LINEAR) { - gltf_interpolation = GLTFAnimation::INTERP_LINEAR; - } else if (interpolation == Animation::InterpolationType::INTERPOLATION_NEAREST) { - gltf_interpolation = GLTFAnimation::INTERP_STEP; - } else if (interpolation == Animation::InterpolationType::INTERPOLATION_CUBIC) { - gltf_interpolation = GLTFAnimation::INTERP_CUBIC_SPLINE; - } - Animation::TrackType track_type = p_animation->track_get_type(p_track_i); - int32_t key_count = p_animation->track_get_key_count(p_track_i); - Vector times; - times.resize(key_count); - String path = p_animation->track_get_path(p_track_i); - for (int32_t key_i = 0; key_i < key_count; key_i++) { - times.write[key_i] = p_animation->track_get_key_time(p_track_i, key_i); - } - if (track_type == Animation::TYPE_SCALE_3D) { - p_track.scale_track.times = times; - p_track.scale_track.interpolation = gltf_interpolation; - p_track.scale_track.values.resize(key_count); - for (int32_t key_i = 0; key_i < key_count; key_i++) { - Vector3 scale; - Error err = p_animation->scale_track_get_key(p_track_i, key_i, &scale); - ERR_CONTINUE(err != OK); - p_track.scale_track.values.write[key_i] = scale; - } - } else if (track_type == Animation::TYPE_POSITION_3D) { - p_track.position_track.times = times; - p_track.position_track.values.resize(key_count); - p_track.position_track.interpolation = gltf_interpolation; - for (int32_t key_i = 0; key_i < key_count; key_i++) { - Vector3 position; - Error err = p_animation->position_track_get_key(p_track_i, key_i, &position); - ERR_CONTINUE(err != OK); - p_track.position_track.values.write[key_i] = position; - } - } else if (track_type == Animation::TYPE_ROTATION_3D) { - p_track.rotation_track.times = times; - p_track.rotation_track.interpolation = gltf_interpolation; - p_track.rotation_track.values.resize(key_count); - for (int32_t key_i = 0; key_i < key_count; key_i++) { - Quat rotation; - Error err = p_animation->rotation_track_get_key(p_track_i, key_i, &rotation); - ERR_CONTINUE(err != OK); - p_track.rotation_track.values.write[key_i] = rotation; - } - } else if (track_type == Animation::TYPE_VALUE) { - if (path.contains(":position")) { - p_track.position_track.times = times; - p_track.position_track.interpolation = gltf_interpolation; - - p_track.position_track.values.resize(key_count); - p_track.position_track.interpolation = gltf_interpolation; - - for (int32_t key_i = 0; key_i < key_count; key_i++) { - Vector3 position = p_animation->track_get_key_value(p_track_i, key_i); - p_track.position_track.values.write[key_i] = position; - } - } else if (path.contains(":rotation")) { - p_track.rotation_track.times = times; - p_track.rotation_track.interpolation = gltf_interpolation; - - p_track.rotation_track.values.resize(key_count); - p_track.rotation_track.interpolation = gltf_interpolation; - - for (int32_t key_i = 0; key_i < key_count; key_i++) { - Vector3 rotation_radian = p_animation->track_get_key_value(p_track_i, key_i); + Vector3 rotation_degrees = p_animation->track_get_key_value(p_track_i, key_i); + Vector3 rotation_radian; + rotation_radian.x = Math::deg2rad(rotation_degrees.x); + rotation_radian.y = Math::deg2rad(rotation_degrees.y); + rotation_radian.z = Math::deg2rad(rotation_degrees.z); p_track.rotation_track.values.write[key_i] = Quat(rotation_radian); } - } else if (path.contains(":scale")) { + } else if (path.find(":scale") != -1) { p_track.scale_track.times = times; p_track.scale_track.interpolation = gltf_interpolation; @@ -6656,10 +6240,10 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref state } } } else if (track_type == Animation::TYPE_BEZIER) { - if (path.contains("/scale")) { + if (path.find("/scale") != -1) { const int32_t keys = p_animation->track_get_key_time(p_track_i, key_count - 1) * BAKE_FPS; if (!p_track.scale_track.times.size()) { - Vector new_times; + Vector new_times; new_times.resize(keys); for (int32_t key_i = 0; key_i < keys; key_i++) { new_times.write[key_i] = key_i / BAKE_FPS; @@ -6677,46 +6261,52 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref state for (int32_t key_i = 0; key_i < keys; key_i++) { Vector3 bezier_track = p_track.scale_track.values[key_i]; - if (path.contains("/scale:x")) { + if (path.find("/scale:x") != -1) { bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); - } else if (path.contains("/scale:y")) { + bezier_track.x = p_bone_rest.affine_inverse().basis.get_scale().x * bezier_track.x; + } else if (path.find("/scale:y") != -1) { bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); - } else if (path.contains("/scale:z")) { + bezier_track.y = p_bone_rest.affine_inverse().basis.get_scale().y * bezier_track.y; + } else if (path.find("/scale:z") != -1) { bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); + bezier_track.z = p_bone_rest.affine_inverse().basis.get_scale().z * bezier_track.z; } p_track.scale_track.values.write[key_i] = bezier_track; } - } else if (path.contains("/position")) { + } else if (path.find("/translation") != -1) { const int32_t keys = p_animation->track_get_key_time(p_track_i, key_count - 1) * BAKE_FPS; - if (!p_track.position_track.times.size()) { - Vector new_times; + if (!p_track.translation_track.times.size()) { + Vector new_times; new_times.resize(keys); for (int32_t key_i = 0; key_i < keys; key_i++) { new_times.write[key_i] = key_i / BAKE_FPS; } - p_track.position_track.times = new_times; - p_track.position_track.interpolation = gltf_interpolation; + p_track.translation_track.times = new_times; + p_track.translation_track.interpolation = gltf_interpolation; - p_track.position_track.values.resize(keys); - p_track.position_track.interpolation = gltf_interpolation; + p_track.translation_track.values.resize(keys); + p_track.translation_track.interpolation = gltf_interpolation; } for (int32_t key_i = 0; key_i < keys; key_i++) { - Vector3 bezier_track = p_track.position_track.values[key_i]; - if (path.contains("/position:x")) { + Vector3 bezier_track = p_track.translation_track.values[key_i]; + if (path.find("/translation:x") != -1) { bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); - } else if (path.contains("/position:y")) { + bezier_track.x = p_bone_rest.affine_inverse().origin.x * bezier_track.x; + } else if (path.find("/translation:y") != -1) { bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); - } else if (path.contains("/position:z")) { + bezier_track.y = p_bone_rest.affine_inverse().origin.y * bezier_track.y; + } else if (path.find("/translation:z") != -1) { bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); + bezier_track.z = p_bone_rest.affine_inverse().origin.z * bezier_track.z; } - p_track.position_track.values.write[key_i] = bezier_track; + p_track.translation_track.values.write[key_i] = bezier_track; } } } + return p_track; } -*/ void GLTFDocument::_convert_animation(Ref state, AnimationPlayer *ap, String p_animation_track_name) { Ref animation = ap->get_animation(p_animation_track_name); @@ -6728,127 +6318,90 @@ void GLTFDocument::_convert_animation(Ref state, AnimationPlayer *ap, if (!animation->track_is_enabled(track_i)) { continue; } - String orig_track_path = animation->track_get_path(track_i); - if (String(orig_track_path).contains(":position")) { - const Vector node_suffix = String(orig_track_path).split(":position"); + if (String(orig_track_path).find(":translation") != -1) { + const Vector node_suffix = String(orig_track_path).split(":translation"); const NodePath path = node_suffix[0]; const Node *node = ap->get_parent()->get_node_or_null(path); - - const GLTFNodeIndex *position_scene_node_val_ptr = NULL; - while ((position_scene_node_val_ptr = state->scene_nodes.next(position_scene_node_val_ptr))) { - GLTFNodeIndex position_scene_node_i_key = *position_scene_node_val_ptr; - Node *position_scene_node_i_value = state->scene_nodes[position_scene_node_i_key]; - - if (position_scene_node_i_value == node) { - GLTFNodeIndex node_index = position_scene_node_i_key; - GLTFAnimation::Track *position_track_i = gltf_animation->get_tracks().getptr(node_index); - + for (Map::Element *translation_scene_node_i = state->scene_nodes.front(); translation_scene_node_i; translation_scene_node_i = translation_scene_node_i->next()) { + if (translation_scene_node_i->get() == node) { + GLTFNodeIndex node_index = translation_scene_node_i->key(); + Map::Element *translation_track_i = gltf_animation->get_tracks().find(node_index); GLTFAnimation::Track track; - - if (position_track_i) { - track = *position_track_i; + if (translation_track_i) { + track = translation_track_i->get(); } - track = _convert_animation_track(state, track, animation, Transform(), track_i, node_index); - gltf_animation->get_tracks().set(node_index, track); + gltf_animation->get_tracks().insert(node_index, track); } } - } else if (String(orig_track_path).contains(":rotation_degrees")) { + } else if (String(orig_track_path).find(":rotation_degrees") != -1) { const Vector node_suffix = String(orig_track_path).split(":rotation_degrees"); const NodePath path = node_suffix[0]; const Node *node = ap->get_parent()->get_node_or_null(path); - - const GLTFNodeIndex *rotation_degree_scene_node_ptr = NULL; - while ((rotation_degree_scene_node_ptr = state->scene_nodes.next(rotation_degree_scene_node_ptr))) { - GLTFNodeIndex rotation_degree_scene_node_i_key = *rotation_degree_scene_node_ptr; - Node *rotation_degree_scene_node_i_value = state->scene_nodes.get(rotation_degree_scene_node_i_key); - - if (rotation_degree_scene_node_i_value == node) { - GLTFNodeIndex node_index = rotation_degree_scene_node_i_key; - GLTFAnimation::Track *rotation_degree_track_i = gltf_animation->get_tracks().getptr(node_index); - + for (Map::Element *rotation_degree_scene_node_i = state->scene_nodes.front(); rotation_degree_scene_node_i; rotation_degree_scene_node_i = rotation_degree_scene_node_i->next()) { + if (rotation_degree_scene_node_i->get() == node) { + GLTFNodeIndex node_index = rotation_degree_scene_node_i->key(); + Map::Element *rotation_degree_track_i = gltf_animation->get_tracks().find(node_index); GLTFAnimation::Track track; - if (rotation_degree_track_i) { - track = *rotation_degree_track_i; + track = rotation_degree_track_i->get(); } - track = _convert_animation_track(state, track, animation, Transform(), track_i, node_index); - gltf_animation->get_tracks().set(node_index, track); + gltf_animation->get_tracks().insert(node_index, track); } } - } else if (String(orig_track_path).contains(":scale")) { + } else if (String(orig_track_path).find(":scale") != -1) { const Vector node_suffix = String(orig_track_path).split(":scale"); const NodePath path = node_suffix[0]; const Node *node = ap->get_parent()->get_node_or_null(path); - - const GLTFNodeIndex *scale_scene_node_i_ptr = NULL; - while ((scale_scene_node_i_ptr = state->scene_nodes.next(scale_scene_node_i_ptr))) { - GLTFNodeIndex scale_scene_node_i_key = *scale_scene_node_i_ptr; - Node *scale_scene_node_i_value = state->scene_nodes.get(scale_scene_node_i_key); - - if (scale_scene_node_i_value == node) { - GLTFNodeIndex node_index = scale_scene_node_i_key; - GLTFAnimation::Track *scale_track_i = gltf_animation->get_tracks().getptr(node_index); - + for (Map::Element *scale_scene_node_i = state->scene_nodes.front(); scale_scene_node_i; scale_scene_node_i = scale_scene_node_i->next()) { + if (scale_scene_node_i->get() == node) { + GLTFNodeIndex node_index = scale_scene_node_i->key(); + Map::Element *scale_track_i = gltf_animation->get_tracks().find(node_index); GLTFAnimation::Track track; - if (scale_track_i) { - track = *scale_track_i; + track = scale_track_i->get(); } - track = _convert_animation_track(state, track, animation, Transform(), track_i, node_index); - gltf_animation->get_tracks().set(node_index, track); + gltf_animation->get_tracks().insert(node_index, track); } } - } else if (String(orig_track_path).contains(":transform")) { + } else if (String(orig_track_path).find(":transform") != -1) { const Vector node_suffix = String(orig_track_path).split(":transform"); const NodePath path = node_suffix[0]; const Node *node = ap->get_parent()->get_node_or_null(path); - - const GLTFNodeIndex *transform_track_i_ptr = NULL; - while ((transform_track_i_ptr = state->scene_nodes.next(transform_track_i_ptr))) { - GLTFNodeIndex transform_track_i_key = *transform_track_i_ptr; - Node *transform_track_i_value = state->scene_nodes.get(transform_track_i_key); - - if (transform_track_i_value == node) { + for (Map::Element *transform_track_i = state->scene_nodes.front(); transform_track_i; transform_track_i = transform_track_i->next()) { + if (transform_track_i->get() == node) { GLTFAnimation::Track track; - track = _convert_animation_track(state, track, animation, Transform(), track_i, transform_track_i_key); - gltf_animation->get_tracks().set(transform_track_i_key, track); + track = _convert_animation_track(state, track, animation, Transform(), track_i, transform_track_i->key()); + gltf_animation->get_tracks().insert(transform_track_i->key(), track); } } } else if (String(orig_track_path).find(":blend_shapes/") != -1) { - //TODO - } - /* - else if (String(orig_track_path).contains(":") && animation->track_get_type(track_i) == Animation::TYPE_BLEND_SHAPE) { - const Vector node_suffix = String(orig_track_path).split(":"); + const Vector node_suffix = String(orig_track_path).split(":blend_shapes/"); const NodePath path = node_suffix[0]; const String suffix = node_suffix[1]; Node *node = ap->get_parent()->get_node_or_null(path); - MeshInstance3D *mi = cast_to(node); + MeshInstance *mi = cast_to(node); Ref mesh = mi->get_mesh(); ERR_CONTINUE(mesh.is_null()); int32_t mesh_index = -1; - - for (const KeyValue &mesh_track_i : state->scene_nodes) { - if (mesh_track_i.value == node) { - mesh_index = mesh_track_i.key; + for (Map::Element *mesh_track_i = state->scene_nodes.front(); mesh_track_i; mesh_track_i = mesh_track_i->next()) { + if (mesh_track_i->get() == node) { + mesh_index = mesh_track_i->key(); } } - ERR_CONTINUE(mesh_index == -1); - HashMap &tracks = gltf_animation->get_tracks(); + Map &tracks = gltf_animation->get_tracks(); GLTFAnimation::Track track = gltf_animation->get_tracks().has(mesh_index) ? gltf_animation->get_tracks()[mesh_index] : GLTFAnimation::Track(); if (!tracks.has(mesh_index)) { for (int32_t shape_i = 0; shape_i < mesh->get_blend_shape_count(); shape_i++) { String shape_name = mesh->get_blend_shape_name(shape_i); - NodePath shape_path = String(path) + ":" + shape_name; - int32_t shape_track_i = animation->find_track(shape_path, Animation::TYPE_BLEND_SHAPE); - + NodePath shape_path = String(path) + ":blend_shapes/" + shape_name; + int32_t shape_track_i = animation->find_track(shape_path); if (shape_track_i == -1) { - GLTFAnimation::Channel weight; + GLTFAnimation::Channel weight; weight.interpolation = GLTFAnimation::INTERP_LINEAR; weight.times.push_back(0.0f); weight.times.push_back(0.0f); @@ -6857,7 +6410,6 @@ void GLTFDocument::_convert_animation(Ref state, AnimationPlayer *ap, track.weight_tracks.push_back(weight); continue; } - Animation::InterpolationType interpolation = animation->track_get_interpolation_type(track_i); GLTFAnimation::Interpolation gltf_interpolation = GLTFAnimation::INTERP_LINEAR; if (interpolation == Animation::InterpolationType::INTERPOLATION_LINEAR) { @@ -6867,202 +6419,263 @@ void GLTFDocument::_convert_animation(Ref state, AnimationPlayer *ap, } else if (interpolation == Animation::InterpolationType::INTERPOLATION_CUBIC) { gltf_interpolation = GLTFAnimation::INTERP_CUBIC_SPLINE; } - int32_t key_count = animation->track_get_key_count(shape_track_i); - GLTFAnimation::Channel weight; + GLTFAnimation::Channel weight; weight.interpolation = gltf_interpolation; weight.times.resize(key_count); - for (int32_t time_i = 0; time_i < key_count; time_i++) { weight.times.write[time_i] = animation->track_get_key_time(shape_track_i, time_i); } - weight.values.resize(key_count); for (int32_t value_i = 0; value_i < key_count; value_i++) { weight.values.write[value_i] = animation->track_get_key_value(shape_track_i, value_i); } - track.weight_tracks.push_back(weight); } tracks[mesh_index] = track; } - } - */ - else if (String(orig_track_path).contains(":")) { + } else if (String(orig_track_path).find(":") != -1) { //Process skeleton const Vector node_suffix = String(orig_track_path).split(":"); const String node = node_suffix[0]; const NodePath node_path = node; const String suffix = node_suffix[1]; - Node *godot_node = ap->get_parent()->get_node_or_null(node_path); + Node *pandemonium_node = ap->get_parent()->get_node_or_null(node_path); Skeleton *skeleton = nullptr; GLTFSkeletonIndex skeleton_gltf_i = -1; - for (GLTFSkeletonIndex skeleton_i = 0; skeleton_i < state->skeletons.size(); skeleton_i++) { - if (state->skeletons[skeleton_i]->godot_skeleton == cast_to(godot_node)) { - skeleton = state->skeletons[skeleton_i]->godot_skeleton; + if (state->skeletons[skeleton_i]->pandemonium_skeleton == cast_to(pandemonium_node)) { + skeleton = state->skeletons[skeleton_i]->pandemonium_skeleton; skeleton_gltf_i = skeleton_i; ERR_CONTINUE(!skeleton); Ref skeleton_gltf = state->skeletons[skeleton_gltf_i]; int32_t bone = skeleton->find_bone(suffix); ERR_CONTINUE(bone == -1); - - if (!skeleton_gltf->godot_bone_node.has(bone)) { + Transform xform = skeleton->get_bone_rest(bone); + if (!skeleton_gltf->pandemonium_bone_node.has(bone)) { continue; } - - //TODO REMOVE - Transform xform = skeleton->get_bone_rest(bone); - - GLTFNodeIndex node_i = skeleton_gltf->godot_bone_node[bone]; - GLTFAnimation::Track *property_track_i = gltf_animation->get_tracks().getptr(node_i); + GLTFNodeIndex node_i = skeleton_gltf->pandemonium_bone_node[bone]; + Map::Element *property_track_i = gltf_animation->get_tracks().find(node_i); GLTFAnimation::Track track; - if (property_track_i) { - track = *property_track_i; + track = property_track_i->get(); } - track = _convert_animation_track(state, track, animation, xform, track_i, node_i); gltf_animation->get_tracks()[node_i] = track; } } - } else if (!String(orig_track_path).contains(":")) { + } else if (String(orig_track_path).find(":") == -1) { ERR_CONTINUE(!ap->get_parent()); - Node *godot_node = ap->get_parent()->get_node_or_null(orig_track_path); - - const GLTFNodeIndex *scene_node_i_ptr = NULL; - while ((scene_node_i_ptr = state->scene_nodes.next(scene_node_i_ptr))) { - GLTFNodeIndex scene_node_i_key = *scene_node_i_ptr; - Node *scene_node_i_value = state->scene_nodes.get(scene_node_i_key); - - //for (const KeyValue &scene_node_i : state->scene_nodes) { - if (scene_node_i_value == godot_node) { - GLTFNodeIndex node_i = scene_node_i_key; - GLTFAnimation::Track *node_track_i = gltf_animation->get_tracks().getptr(node_i); - - GLTFAnimation::Track track; - - if (node_track_i) { - track = *node_track_i; + for (int32_t node_i = 0; node_i < ap->get_parent()->get_child_count(); node_i++) { + const Node *child = ap->get_parent()->get_child(node_i); + const Node *node = child->get_node_or_null(orig_track_path); + for (Map::Element *scene_node_i = state->scene_nodes.front(); scene_node_i; scene_node_i = scene_node_i->next()) { + if (scene_node_i->get() == node) { + GLTFNodeIndex node_index = scene_node_i->key(); + Map::Element *node_track_i = gltf_animation->get_tracks().find(node_index); + GLTFAnimation::Track track; + if (node_track_i) { + track = node_track_i->get(); + } + track = _convert_animation_track(state, track, animation, Transform(), track_i, node_index); + gltf_animation->get_tracks().insert(node_index, track); + break; } - - track = _convert_animation_track(state, track, animation, Transform(), track_i, node_i); - gltf_animation->get_tracks()[node_i] = track; - break; } } } } - if (gltf_animation->get_tracks().size()) { state->animations.push_back(gltf_animation); } } -Error GLTFDocument::_parse(Ref state, String p_path, FileAccess *f, int p_bake_fps) { +Error GLTFDocument::parse(Ref state, String p_path, bool p_read_binary) { Error err; - + FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err); if (!f) { - return FAILED; + return err; } - - f->seek(0); uint32_t magic = f->get_32(); if (magic == 0x46546C67) { //binary file //text file - f->seek(0); - err = _parse_glb(f, state); - if (err != OK) { - return err; + err = _parse_glb(p_path, state); + if (err) { + return FAILED; } } else { - f->seek(0); - String text = f->get_as_utf8_string(); - - JSON json; - Variant data; - String err_str; - int err_line; - Error err = json.parse(text, data, err_str, err_line); - - if (err != OK) { - _err_print_error("", "", err_line, err_str.utf8().get_data(), ERR_HANDLER_SCRIPT); - return err; + //text file + err = _parse_json(p_path, state); + if (err) { + return FAILED; } - - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - state->json = data; } + f->close(); - if (!state->json.has("asset")) { - return ERR_PARSE_ERROR; - } + // get file's name, use for scene name if none + state->filename = p_path.get_file().get_slice(".", 0); + + ERR_FAIL_COND_V(!state->json.has("asset"), Error::FAILED); Dictionary asset = state->json["asset"]; - if (!asset.has("version")) { - return ERR_PARSE_ERROR; - } + ERR_FAIL_COND_V(!asset.has("version"), Error::FAILED); String version = asset["version"]; state->major_version = version.get_slice(".", 0).to_int(); state->minor_version = version.get_slice(".", 1).to_int(); - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref ext = document_extensions[ext_i]; - ERR_CONTINUE(ext.is_null()); - err = ext->import_preflight(state); - ERR_FAIL_COND_V(err != OK, err); + /* PARSE EXTENSIONS */ + + err = _parse_gltf_extensions(state); + if (err != OK) { + return Error::FAILED; } - err = _parse_gltf_state(state, p_path, p_bake_fps); - ERR_FAIL_COND_V(err != OK, err); + + /* PARSE SCENE */ + err = _parse_scenes(state); + if (err != OK) { + return Error::FAILED; + } + + /* PARSE NODES */ + err = _parse_nodes(state); + if (err != OK) { + return Error::FAILED; + } + + /* PARSE BUFFERS */ + err = _parse_buffers(state, p_path.get_base_dir()); + if (err != OK) { + return Error::FAILED; + } + + /* PARSE BUFFER VIEWS */ + err = _parse_buffer_views(state); + if (err != OK) { + return Error::FAILED; + } + + /* PARSE ACCESSORS */ + err = _parse_accessors(state); + if (err != OK) { + return Error::FAILED; + } + + /* PARSE IMAGES */ + err = _parse_images(state, p_path.get_base_dir()); + if (err != OK) { + return Error::FAILED; + } + + /* PARSE TEXTURES */ + err = _parse_textures(state); + if (err != OK) { + return Error::FAILED; + } + + /* PARSE TEXTURES */ + err = _parse_materials(state); + if (err != OK) { + return Error::FAILED; + } + + /* PARSE SKINS */ + err = _parse_skins(state); + if (err != OK) { + return Error::FAILED; + } + + /* DETERMINE SKELETONS */ + err = _determine_skeletons(state); + if (err != OK) { + return Error::FAILED; + } + + /* CREATE SKELETONS */ + err = _create_skeletons(state); + if (err != OK) { + return Error::FAILED; + } + + /* CREATE SKINS */ + err = _create_skins(state); + if (err != OK) { + return Error::FAILED; + } + + /* PARSE MESHES (we have enough info now) */ + err = _parse_meshes(state); + if (err != OK) { + return Error::FAILED; + } + + /* PARSE LIGHTS */ + err = _parse_lights(state); + if (err != OK) { + return Error::FAILED; + } + + /* PARSE CAMERAS */ + err = _parse_cameras(state); + if (err != OK) { + return Error::FAILED; + } + + /* PARSE ANIMATIONS */ + err = _parse_animations(state); + if (err != OK) { + return Error::FAILED; + } + + /* ASSIGN SCENE NAMES */ + _assign_scene_names(state); + return OK; } -Dictionary _serialize_texture_transform_uv(Vector2 p_offset, Vector2 p_scale) { - Dictionary texture_transform; - bool is_offset = p_offset != Vector2(0.0, 0.0); - if (is_offset) { +Dictionary GLTFDocument::_serialize_texture_transform_uv2(Ref p_material) { + Dictionary extension; + Ref mat = p_material; + if (mat.is_valid()) { + Dictionary texture_transform; Array offset; offset.resize(2); - offset[0] = p_offset.x; - offset[1] = p_offset.y; + offset[0] = mat->get_uv2_offset().x; + offset[1] = mat->get_uv2_offset().y; texture_transform["offset"] = offset; - } - bool is_scaled = p_scale != Vector2(1.0, 1.0); - if (is_scaled) { Array scale; scale.resize(2); - scale[0] = p_scale.x; - scale[1] = p_scale.y; + scale[0] = mat->get_uv2_scale().x; + scale[1] = mat->get_uv2_scale().y; texture_transform["scale"] = scale; - } - Dictionary extension; - // Note: Godot doesn't support texture rotation. - if (is_offset || is_scaled) { + // Pandemonium doesn't support texture rotation extension["KHR_texture_transform"] = texture_transform; } return extension; } Dictionary GLTFDocument::_serialize_texture_transform_uv1(Ref p_material) { + Dictionary extension; if (p_material.is_valid()) { - Vector3 offset = p_material->get_uv1_offset(); - Vector3 scale = p_material->get_uv1_scale(); - return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y)); + Dictionary texture_transform; + Array offset; + offset.resize(2); + offset[0] = p_material->get_uv1_offset().x; + offset[1] = p_material->get_uv1_offset().y; + texture_transform["offset"] = offset; + Array scale; + scale.resize(2); + scale[0] = p_material->get_uv1_scale().x; + scale[1] = p_material->get_uv1_scale().y; + texture_transform["scale"] = scale; + // Pandemonium doesn't support texture rotation + extension["KHR_texture_transform"] = texture_transform; } - return Dictionary(); -} - -Dictionary GLTFDocument::_serialize_texture_transform_uv2(Ref p_material) { - if (p_material.is_valid()) { - Vector3 offset = p_material->get_uv2_offset(); - Vector3 scale = p_material->get_uv2_scale(); - return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y)); - } - return Dictionary(); + return extension; } Error GLTFDocument::_serialize_version(Ref state) { @@ -7086,9 +6699,8 @@ Error GLTFDocument::_serialize_file(Ref state, const String p_path) { err = _encode_buffer_glb(state, p_path); ERR_FAIL_COND_V(err != OK, err); FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE, &err); - ERR_FAIL_COND_V(f.is_null(), FAILED); + ERR_FAIL_COND_V(!f, FAILED); - //String json = Variant(state->json).to_json_string(); String json = JSON::print(state->json); const uint32_t magic = 0x46546C67; // GLTF @@ -7124,376 +6736,24 @@ Error GLTFDocument::_serialize_file(Ref state, const String p_path) { for (uint32_t pad_i = binary_data_length; pad_i < binary_chunk_length; pad_i++) { f->store_8(0); } + + f->close(); } else { err = _encode_buffer_bins(state, p_path); ERR_FAIL_COND_V(err != OK, err); FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE, &err); - ERR_FAIL_COND_V(f.is_null(), FAILED); + ERR_FAIL_COND_V(!f, FAILED); f->create(FileAccess::ACCESS_RESOURCES); - //String json = Variant(state->json).to_json_string(); String json = JSON::print(state->json); f->store_string(json); + f->close(); } return err; } -void GLTFDocument::_bind_methods() { - ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "bake_fps", "base_path"), &GLTFDocument::append_from_file, 0, 30, String()); - ClassDB::bind_method(D_METHOD("append_from_buffer", "bytes", "base_path", "state", "flags", "bake_fps"), &GLTFDocument::append_from_buffer, 0, 30); - ClassDB::bind_method(D_METHOD("append_from_scene", "node", "state", "flags", "bake_fps"), &GLTFDocument::append_from_scene, 0, 30); - ClassDB::bind_method(D_METHOD("generate_scene", "state", "bake_fps"), &GLTFDocument::generate_scene, 30); - ClassDB::bind_method(D_METHOD("generate_buffer", "state"), &GLTFDocument::generate_buffer); - ClassDB::bind_method(D_METHOD("write_to_filesystem", "state", "path"), &GLTFDocument::write_to_filesystem); - ClassDB::bind_method(D_METHOD("set_extensions", "extensions"), &GLTFDocument::set_extensions); - ClassDB::bind_method(D_METHOD("get_extensions"), &GLTFDocument::get_extensions); - - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "extensions", PROPERTY_HINT_RESOURCE_TYPE, "20/19:GLTFDocumentExtension", PROPERTY_USAGE_DEFAULT, "GLTFDocumentExtension"), "set_extensions", "get_extensions"); -} - -void GLTFDocument::_build_parent_hierachy(Ref 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; - } - } -} - -void GLTFDocument::set_extensionsv(const Vector> &p_extensions) { - document_extensions = p_extensions; -} - -Vector> GLTFDocument::get_extensionsv() const { - return document_extensions; -} - -void GLTFDocument::set_extensions(const Vector &p_extensions) { - document_extensions.clear(); - - for (int i = 0; i < p_extensions.size(); i++) { - Ref extension = Ref(p_extensions[i]); - - document_extensions.push_back(extension); - } -} - -Vector GLTFDocument::get_extensions() const { - Vector r; - for (int i = 0; i < document_extensions.size(); i++) { - r.push_back(document_extensions[i].get_ref_ptr()); - } - return r; -} - -GLTFDocument::GLTFDocument() { - bool is_editor = ::Engine::get_singleton()->is_editor_hint(); - if (is_editor) { - return; - } - Ref extension_editor; - extension_editor.instance(); - document_extensions.push_back(extension_editor); -} - -GLTFDocument::~GLTFDocument() { -} - -PoolByteArray GLTFDocument::_serialize_glb_buffer(Ref state, Error *r_err) { - Error err = _encode_buffer_glb(state, ""); - if (r_err) { - *r_err = err; - } - ERR_FAIL_COND_V(err != OK, PoolByteArray()); - //String json = Variant(state->json).to_json_string(); - String json = JSON::print(state->json); - - const uint32_t magic = 0x46546C67; // GLTF - const int32_t header_size = 12; - const int32_t chunk_header_size = 8; - - for (int32_t pad_i = 0; pad_i < (chunk_header_size + json.utf8().length()) % 4; pad_i++) { - json += " "; - } - CharString cs = json.utf8(); - const uint32_t text_chunk_length = cs.length(); - - const uint32_t text_chunk_type = 0x4E4F534A; //JSON - int32_t binary_data_length = 0; - if (state->buffers.size()) { - binary_data_length = state->buffers[0].size(); - } - const int32_t binary_chunk_length = binary_data_length; - const int32_t binary_chunk_type = 0x004E4942; //BIN - - Ref buffer; - buffer.instance(); - buffer->put_32(magic); - buffer->put_32(state->major_version); // version - buffer->put_32(header_size + chunk_header_size + text_chunk_length + chunk_header_size + binary_data_length); // length - buffer->put_32(text_chunk_length); - buffer->put_32(text_chunk_type); - buffer->put_data((uint8_t *)&cs[0], cs.length()); - if (binary_chunk_length) { - buffer->put_32(binary_chunk_length); - buffer->put_32(binary_chunk_type); - buffer->put_data(state->buffers[0].ptr(), binary_data_length); - } - return buffer->get_data_array(); -} - -PoolByteArray GLTFDocument::generate_buffer(Ref state) { - ERR_FAIL_COND_V(state.is_null(), PoolByteArray()); - Error err = _serialize(state, ""); - ERR_FAIL_COND_V(err != OK, PoolByteArray()); - PoolByteArray bytes = _serialize_glb_buffer(state, &err); - return bytes; -} - -Error GLTFDocument::write_to_filesystem(Ref state, const String &p_path) { - ERR_FAIL_COND_V(state.is_null(), ERR_INVALID_PARAMETER); - - Error err = _serialize(state, p_path); - - if (err != OK) { - return err; - } - - err = _serialize_file(state, p_path); - if (err != OK) { - return Error::FAILED; - } - - return OK; -} - -Node *GLTFDocument::generate_scene(Ref state, int32_t p_bake_fps) { - ERR_FAIL_COND_V(state.is_null(), nullptr); - ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr); - - Error err = OK; - GLTFNodeIndex gltf_root = state->root_nodes.write[0]; - Node *gltf_root_node = state->get_scene_node(gltf_root); - Node *root = gltf_root_node->get_parent(); - ERR_FAIL_COND_V(root, nullptr); - - _process_mesh_instances(state, root); - - if (state->animations.size()) { - AnimationPlayer *ap = memnew(AnimationPlayer); - root->add_child(ap, true); - ap->set_owner(root); - for (int i = 0; i < state->animations.size(); i++) { - _import_animation(state, ap, i, p_bake_fps); - } - } - - const GLTFNodeIndex *scene_nodes_ptr = NULL; - while ((scene_nodes_ptr = state->scene_nodes.next(scene_nodes_ptr))) { - //for (KeyValue E : state->scene_nodes) { - GLTFNodeIndex E_key = *scene_nodes_ptr; - Node **E_value = state->scene_nodes.getptr(E_key); - - ERR_CONTINUE(!E_value); - - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref ext = document_extensions[ext_i]; - ERR_CONTINUE(ext.is_null()); - ERR_CONTINUE(!state->json.has("nodes")); - Array nodes = state->json["nodes"]; - ERR_CONTINUE(E_key >= nodes.size()); - ERR_CONTINUE(E_key < 0); - Dictionary node_json = nodes[E_key]; - Ref gltf_node = state->nodes[E_key]; - err = ext->import_node(state, gltf_node, node_json, *E_value); - ERR_CONTINUE(err != OK); - } - } - - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref ext = document_extensions[ext_i]; - ERR_CONTINUE(ext.is_null()); - err = ext->import_post(state, root); - ERR_CONTINUE(err != OK); - } - - ERR_FAIL_NULL_V(root, nullptr); - return root; -} - -Error GLTFDocument::append_from_scene(Node *p_node, Ref state, uint32_t p_flags, int32_t p_bake_fps) { - ERR_FAIL_COND_V(state.is_null(), FAILED); - state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; - state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; - - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref ext = document_extensions[ext_i]; - ERR_CONTINUE(ext.is_null()); - Error err = ext->export_preflight(p_node); - ERR_FAIL_COND_V(err != OK, FAILED); - } - - _convert_scene_node(state, p_node, -1, -1); - - if (!state->buffers.size()) { - state->buffers.push_back(Vector()); - } - - return OK; -} - -Error GLTFDocument::append_from_buffer(PoolByteArray p_bytes, String p_base_path, Ref state, uint32_t p_flags, int32_t p_bake_fps) { - ERR_FAIL_COND_V(state.is_null(), FAILED); - // TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire - Error err = FAILED; - state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; - state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; - - FileAccessMemory *fam = memnew(FileAccessMemory); - PoolByteArray::Read p_bytes_read = p_bytes.read(); - fam->open_custom(p_bytes_read.ptr(), p_bytes.size()); - p_bytes_read.release(); - FileAccessRef file_access = fam; - - state->base_path = p_base_path.get_base_dir(); - err = _parse(state, state->base_path, file_access.f, p_bake_fps); - ERR_FAIL_COND_V(err != OK, err); - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref ext = document_extensions[ext_i]; - ERR_CONTINUE(ext.is_null()); - err = ext->import_post_parse(state); - ERR_FAIL_COND_V(err != OK, err); - } - - return OK; -} - -Error GLTFDocument::_parse_gltf_state(Ref state, const String &p_search_path, float p_bake_fps) { - Error err; - - /* PARSE EXTENSIONS */ - err = _parse_gltf_extensions(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* PARSE SCENE */ - err = _parse_scenes(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* PARSE NODES */ - err = _parse_nodes(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* PARSE BUFFERS */ - err = _parse_buffers(state, p_search_path); - - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* PARSE BUFFER VIEWS */ - err = _parse_buffer_views(state); - - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* PARSE ACCESSORS */ - err = _parse_accessors(state); - - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - if (!state->discard_meshes_and_materials) { - /* PARSE IMAGES */ - err = _parse_images(state, p_search_path); - - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* PARSE TEXTURES */ - err = _parse_textures(state); - - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* PARSE TEXTURES */ - err = _parse_materials(state); - - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - } - - /* PARSE SKINS */ - err = _parse_skins(state); - - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* DETERMINE SKELETONS */ - err = _determine_skeletons(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* CREATE SKELETONS */ - err = _create_skeletons(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* CREATE SKINS */ - err = _create_skins(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* PARSE MESHES (we have enough info now) */ - err = _parse_meshes(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* PARSE LIGHTS */ - err = _parse_lights(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* PARSE CAMERAS */ - err = _parse_cameras(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* PARSE ANIMATIONS */ - err = _parse_animations(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - - /* ASSIGN SCENE NAMES */ - _assign_scene_names(state); - - Spatial *root = memnew(Spatial); - for (int32_t root_i = 0; root_i < state->root_nodes.size(); root_i++) { - _generate_scene_node(state, root, root, state->root_nodes[root_i]); - } - - return OK; -} - -Error GLTFDocument::append_from_file(String p_path, Ref r_state, uint32_t p_flags, int32_t p_bake_fps, String p_base_path) { - // TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire - if (r_state == Ref()) { - r_state.instance(); - } - r_state->filename = p_path.get_file().get_basename(); - r_state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; - r_state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; - Error err; - FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err); - ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN); - ERR_FAIL_NULL_V(f, ERR_FILE_CANT_OPEN); - String base_path = p_base_path; - if (base_path.empty()) { - base_path = p_path.get_base_dir(); - } - r_state->base_path = base_path; - err = _parse(r_state, base_path, f.f, p_bake_fps); - ERR_FAIL_COND_V(err != OK, err); - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref ext = document_extensions[ext_i]; - ERR_CONTINUE(ext.is_null()); - err = ext->import_post_parse(r_state); - ERR_FAIL_COND_V(err != OK, err); - } - return OK; -} - Error GLTFDocument::_parse_gltf_extensions(Ref state) { - ERR_FAIL_COND_V(state.is_null(), ERR_PARSE_ERROR); + ERR_FAIL_COND_V(!state.is_valid(), ERR_PARSE_ERROR); if (state->json.has("extensionsRequired") && state->json["extensionsRequired"].get_type() == Variant::ARRAY) { Array extensions_required = state->json["extensionsRequired"]; if (extensions_required.find("KHR_draco_mesh_compression") != -1) { diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index 2d1417dbb..07e0ff2b7 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -1,6 +1,5 @@ #ifndef GLTF_DOCUMENT_H #define GLTF_DOCUMENT_H - /*************************************************************************/ /* gltf_document.h */ /*************************************************************************/ @@ -31,24 +30,61 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "gltf_defines.h" -#include "structures/gltf_animation.h" - -#include "core/os/file_access.h" #include "scene/3d/bone_attachment.h" -#include "scene/3d/importer_mesh_instance_3d.h" +#include "scene/3d/camera.h" +#include "scene/3d/light.h" #include "scene/3d/mesh_instance.h" +#include "scene/3d/skeleton.h" +#include "scene/3d/spatial.h" #include "scene/animation/animation_player.h" #include "scene/resources/material.h" +#include "scene/resources/texture.h" -class Camera; -class GLTFDocumentExtension; +#include "gltf_animation.h" + +#include "modules/modules_enabled.gen.h" // For csg, gridmap. + +class GLTFState; +class GLTFSkin; +class GLTFNode; +class GLTFSpecGloss; +class GLTFSkeleton; +class MultiMeshInstance; + +using GLTFAccessorIndex = int; +using GLTFAnimationIndex = int; +using GLTFBufferIndex = int; +using GLTFBufferViewIndex = int; +using GLTFCameraIndex = int; +using GLTFImageIndex = int; +using GLTFMaterialIndex = int; +using GLTFMeshIndex = int; +using GLTFLightIndex = int; +using GLTFNodeIndex = int; +using GLTFSkeletonIndex = int; +using GLTFSkinIndex = int; +using GLTFTextureIndex = int; class GLTFDocument : public Resource { GDCLASS(GLTFDocument, Resource); + friend class GLTFState; + friend class GLTFSkin; + friend class GLTFSkeleton; + +private: + const float BAKE_FPS = 30.0f; public: const int32_t JOINT_GROUP_SIZE = 4; + enum GLTFType { + TYPE_SCALAR, + TYPE_VEC2, + TYPE_VEC3, + TYPE_VEC4, + TYPE_MAT2, + TYPE_MAT3, + TYPE_MAT4, + }; enum { ARRAY_BUFFER = 34962, @@ -69,26 +105,70 @@ public: COMPONENT_TYPE_FLOAT = 5126, }; -public: - void set_extensionsv(const Vector> &p_extensions); - Vector> get_extensionsv() const; - - void set_extensions(const Vector &p_extensions); - Vector get_extensions() const; - private: - void _build_parent_hierachy(Ref state); + template + static Array to_array(const Vector &p_inp) { + Array ret; + for (int i = 0; i < p_inp.size(); i++) { + ret.push_back(p_inp[i]); + } + return ret; + } + + template + static Array to_array(const Set &p_inp) { + Array ret; + typename Set::Element *elem = p_inp.front(); + while (elem) { + ret.push_back(elem->get()); + elem = elem->next(); + } + return ret; + } + + template + static void set_from_array(Vector &r_out, const Array &p_inp) { + r_out.clear(); + for (int i = 0; i < p_inp.size(); i++) { + r_out.push_back(p_inp[i]); + } + } + + template + static void set_from_array(Set &r_out, const Array &p_inp) { + r_out.clear(); + for (int i = 0; i < p_inp.size(); i++) { + r_out.insert(p_inp[i]); + } + } + template + static Dictionary to_dict(const Map &p_inp) { + Dictionary ret; + for (typename Map::Element *E = p_inp.front(); E; E = E->next()) { + ret[E->key()] = E->value(); + } + return ret; + } + + template + static void set_from_dict(Map &r_out, const Dictionary &p_inp) { + r_out.clear(); + Array keys = p_inp.keys(); + for (int i = 0; i < keys.size(); i++) { + r_out[keys[i]] = p_inp[keys[i]]; + } + } 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); Error _parse_scenes(Ref state); Error _parse_nodes(Ref state); String _get_type_name(const GLTFType p_component); - String _get_accessor_type_name(const GLTFType p_type); + String _get_accessor_type_name(const GLTFDocument::GLTFType p_type); String _gen_unique_name(Ref state, const String &p_name); String _sanitize_animation_name(const String &name); String _gen_unique_animation_name(Ref state, const String &p_name); - String _sanitize_bone_name(const String &name); + String _sanitize_bone_name(Ref state, const String &name); String _gen_unique_bone_name(Ref state, const GLTFSkeletonIndex skel_i, const String &p_name); @@ -96,7 +176,7 @@ private: Ref _get_texture(Ref state, const GLTFTextureIndex p_texture); Error _parse_json(const String &p_path, Ref state); - Error _parse_glb(FileAccess *f, Ref state); + Error _parse_glb(const String &p_path, Ref state); void _compute_node_heights(Ref state); Error _parse_buffers(Ref state, const String &p_base_path); Error _parse_buffer_views(Ref state); @@ -113,22 +193,22 @@ private: Vector _decode_accessor(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - PoolVector _decode_accessor_as_floats(Ref state, + Vector _decode_accessor_as_floats(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - PoolIntArray _decode_accessor_as_ints(Ref state, + Vector _decode_accessor_as_ints(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); Vector _decode_accessor_as_vec2(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - PoolVector3Array _decode_accessor_as_vec3(Ref state, + Vector _decode_accessor_as_vec3(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); Vector _decode_accessor_as_color(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - PoolVector _decode_accessor_as_quaternion(Ref state, + Vector _decode_accessor_as_quat(Ref state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); Vector _decode_accessor_as_xform2d(Ref state, @@ -183,17 +263,19 @@ private: Skeleton *skeleton, const GLTFNodeIndex node_index, const GLTFNodeIndex bone_index); - ImporterMeshInstance3D *_generate_mesh_instance(Ref state, const GLTFNodeIndex node_index); - Camera *_generate_camera(Ref state, const GLTFNodeIndex node_index); - Spatial *_generate_light(Ref state, const GLTFNodeIndex node_index); - Spatial *_generate_spatial(Ref state, const GLTFNodeIndex node_index); + Spatial *_generate_mesh_instance(Ref state, Node *scene_parent, const GLTFNodeIndex node_index); + Camera *_generate_camera(Ref state, Node *scene_parent, + const GLTFNodeIndex node_index); + Spatial *_generate_light(Ref state, Node *scene_parent, const GLTFNodeIndex node_index); + Spatial *_generate_spatial(Ref state, Node *scene_parent, + const GLTFNodeIndex node_index); void _assign_scene_names(Ref state); template - T _interpolate_track(const PoolRealArray &p_times, const PoolVector &p_values, + T _interpolate_track(const Vector &p_times, const Vector &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp); - GLTFAccessorIndex _encode_accessor_as_quaternions(Ref state, - const PoolVector p_attribs, + GLTFAccessorIndex _encode_accessor_as_quats(Ref state, + const Vector p_attribs, const bool p_for_vertex); GLTFAccessorIndex _encode_accessor_as_weights(Ref state, const Vector p_attribs, @@ -202,35 +284,35 @@ private: const Vector p_attribs, const bool p_for_vertex); GLTFAccessorIndex _encode_accessor_as_floats(Ref state, - const PoolRealArray p_attribs, + const Vector p_attribs, const bool p_for_vertex); GLTFAccessorIndex _encode_accessor_as_vec2(Ref state, const Vector p_attribs, const bool p_for_vertex); - void _calc_accessor_vec2_min_max(int i, const int element_count, PoolRealArray &type_max, Vector2 attribs, PoolRealArray &type_min) { + void _calc_accessor_vec2_min_max(int i, const int element_count, Vector &type_max, Vector2 attribs, Vector &type_min) { if (i == 0) { for (int32_t type_i = 0; type_i < element_count; type_i++) { - type_max.set(type_i, attribs[(i * element_count) + type_i]); - type_min.set(type_i, attribs[(i * element_count) + type_i]); + type_max.write[type_i] = attribs[(i * element_count) + type_i]; + type_min.write[type_i] = attribs[(i * element_count) + type_i]; } } for (int32_t type_i = 0; type_i < element_count; type_i++) { - type_max.set(type_i, MAX(attribs[(i * element_count) + type_i], type_max[type_i])); - type_min.set(type_i, MIN(attribs[(i * element_count) + type_i], type_min[type_i])); - type_max.set(type_i, _filter_number(type_max[type_i])); - type_min.set(type_i, _filter_number(type_min[type_i])); + type_max.write[type_i] = MAX(attribs[(i * element_count) + type_i], type_max[type_i]); + type_min.write[type_i] = MIN(attribs[(i * element_count) + type_i], type_min[type_i]); + type_max.write[type_i] = _filter_number(type_max.write[type_i]); + type_min.write[type_i] = _filter_number(type_min.write[type_i]); } } GLTFAccessorIndex _encode_accessor_as_vec3(Ref state, - const PoolVector p_attribs, + const Vector p_attribs, const bool p_for_vertex); GLTFAccessorIndex _encode_accessor_as_color(Ref state, const Vector p_attribs, const bool p_for_vertex); - void _calc_accessor_min_max(int p_i, const int p_element_count, PoolRealArray &p_type_max, PoolRealArray p_attribs, PoolRealArray &p_type_min); + void _calc_accessor_min_max(int p_i, const int p_element_count, Vector &p_type_max, Vector p_attribs, Vector &p_type_min); GLTFAccessorIndex _encode_accessor_as_ints(Ref state, const Vector p_attribs, @@ -238,7 +320,7 @@ private: GLTFAccessorIndex _encode_accessor_as_xform(Ref state, const Vector p_attribs, const bool p_for_vertex); - Error _encode_buffer_view(Ref state, const float *src, + Error _encode_buffer_view(Ref state, const double *src, const int count, const GLTFType type, const int component_type, const bool normalized, const int byte_offset, const bool for_vertex, @@ -250,22 +332,13 @@ private: Error _serialize_nodes(Ref state); Error _serialize_scenes(Ref state); String interpolation_to_string(const GLTFAnimation::Interpolation p_interp); - - //TODO UNCOMMENT - /* GLTFAnimation::Track _convert_animation_track(Ref state, GLTFAnimation::Track p_track, - Ref p_animation, + Ref p_animation, Transform p_bone_rest, int32_t p_track_i, GLTFNodeIndex p_node_i); - */ - - //TODO DELETE - GLTFAnimation::Track _convert_animation_track(Ref state, GLTFAnimation::Track p_track, Ref p_animation, Transform p_bone_rest, int32_t p_track_i, GLTFNodeIndex p_node_i); - Error _encode_buffer_bins(Ref state, const String &p_path); Error _encode_buffer_glb(Ref state, const String &p_path); - PoolByteArray _serialize_glb_buffer(Ref state, Error *r_err); Dictionary _serialize_texture_transform_uv1(Ref p_material); Dictionary _serialize_texture_transform_uv2(Ref p_material); Error _serialize_version(Ref state); @@ -273,8 +346,8 @@ private: Error _serialize_extensions(Ref state) const; public: - // 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 + // 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 static constexpr float R_BRIGHTNESS_COEFF = 0.299f; static constexpr float G_BRIGHTNESS_COEFF = 0.587f; static constexpr float B_BRIGHTNESS_COEFF = 0.114f; @@ -289,18 +362,11 @@ private: static float get_max_component(const Color &p_color); public: - Error append_from_file(String p_path, Ref r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30, String p_base_path = String()); - Error append_from_buffer(PoolByteArray p_bytes, String p_base_path, Ref r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30); - Error append_from_scene(Node *p_node, Ref r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30); + String _sanitize_scene_name(Ref state, const String &p_name); + String _legacy_validate_node_name(const String &p_name); -public: - Node *generate_scene(Ref state, int32_t p_bake_fps = 30.0f); - PoolByteArray generate_buffer(Ref state); - Error write_to_filesystem(Ref state, const String &p_path); - -public: - Error _parse_gltf_state(Ref state, const String &p_search_path, float p_bake_fps); Error _parse_gltf_extensions(Ref state); + void _process_mesh_instances(Ref state, Node *scene_root); void _generate_scene_node(Ref state, Node *scene_parent, Spatial *scene_root, @@ -331,8 +397,8 @@ public: void _check_visibility(Node *p_node, bool &retflag); void _convert_camera_to_gltf(Camera *camera, Ref state, Ref gltf_node); - void _convert_multi_mesh_instance_to_gltf( - MultiMeshInstance *p_multi_mesh_instance, + void _convert_mult_mesh_instance_to_gltf( + MultiMeshInstance *p_scene_parent, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref gltf_node, Ref state); @@ -353,19 +419,8 @@ public: MeshInstance *p_mesh_instance); void _convert_animation(Ref state, AnimationPlayer *ap, String p_animation_track_name); - Error _serialize(Ref state, const String &p_path); - Error _parse(Ref state, String p_path, FileAccess *f, int p_bake_fps); - - GLTFDocument(); - ~GLTFDocument(); - -protected: - static void _bind_methods(); - -private: - const float BAKE_FPS = 30.0f; - - Vector> document_extensions; + Error serialize(Ref state, Node *p_root, const String &p_path); + Error parse(Ref state, String p_paths, bool p_read_binary = false); }; #endif // GLTF_DOCUMENT_H diff --git a/modules/gltf/gltf_document_extension.cpp b/modules/gltf/gltf_document_extension.cpp deleted file mode 100644 index 729bb13eb..000000000 --- a/modules/gltf/gltf_document_extension.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/*************************************************************************/ -/* gltf_document_extension.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "gltf_document_extension.h" - -#include "gltf_state.h" -#include "structures/gltf_node.h" - -Error GLTFDocumentExtension::import_post(Ref p_state, Node *p_root) { - ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER); - - int err = call("_import_post", p_state, p_root); - return static_cast(err); -} - -Error GLTFDocumentExtension::import_preflight(Ref p_state) { - ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER); - - int err = call("_import_preflight", p_state); - return static_cast(err); -} - -Error GLTFDocumentExtension::import_post_parse(Ref p_state) { - ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER); - - int err = call("_import_post_parse", p_state); - return static_cast(err); -} - -Error GLTFDocumentExtension::export_post(Ref p_state) { - ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER); - - int err = call("_export_post", p_state); - return static_cast(err); -} -Error GLTFDocumentExtension::export_preflight(Node *p_root) { - ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER); - - int err = call("_export_preflight", p_root); - return static_cast(err); -} - -Error GLTFDocumentExtension::import_node(Ref p_state, Ref p_gltf_node, const Dictionary &r_dict, Node *p_node) { - ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(p_gltf_node.is_null(), ERR_INVALID_PARAMETER); - ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER); - - int err = call("_import_node", p_state, p_gltf_node, r_dict, p_node); - return static_cast(err); -} - -Error GLTFDocumentExtension::export_node(Ref p_state, Ref p_gltf_node, const Dictionary &r_dict, Node *p_node) { - ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(p_gltf_node.is_null(), ERR_INVALID_PARAMETER); - ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER); - - int err = call("_export_node", p_state, p_gltf_node, r_dict, p_node); - return static_cast(err); -} - -int GLTFDocumentExtension::_import_preflight(Ref p_state) { - return OK; -} -int GLTFDocumentExtension::_import_post_parse(Ref p_state) { - return OK; -} -int GLTFDocumentExtension::_export_post(Ref p_state) { - return OK; -} -int GLTFDocumentExtension::_import_post(Ref p_state, Node *p_node) { - return OK; -} -int GLTFDocumentExtension::_export_preflight(Node *p_state) { - return OK; -} -int GLTFDocumentExtension::_import_node(Ref p_state, Ref p_gltf_node, const Dictionary &r_json, Node *p_node) { - return OK; -} -int GLTFDocumentExtension::_export_node(Ref p_state, Ref p_gltf_node, const Dictionary &r_json, Node *p_node) { - return OK; -} - -GLTFDocumentExtension::GLTFDocumentExtension() { -} -GLTFDocumentExtension::~GLTFDocumentExtension() { -} - -void GLTFDocumentExtension::_bind_methods() { - BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::INT, "ret"), - "_import_preflight", - PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "GLTFState"))); - - BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::INT, "ret"), - "_import_post_parse", - PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "GLTFState"))); - - BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::INT, "ret"), - "_import_node", - PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "GLTFState"), - PropertyInfo(Variant::OBJECT, "gltf_node", PROPERTY_HINT_RESOURCE_TYPE, "GLTFNode"), - PropertyInfo(Variant::DICTIONARY, "json"), - PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - - BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::INT, "ret"), - "_import_post", - PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "GLTFState"), - PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - - BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::INT, "ret"), - "_export_preflight", - PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - - BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::INT, "ret"), - "_export_node", - PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "GLTFState"), - PropertyInfo(Variant::OBJECT, "gltf_node", PROPERTY_HINT_RESOURCE_TYPE, "GLTFNode"), - PropertyInfo(Variant::DICTIONARY, "json"), - PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - - BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::INT, "ret"), - "_export_post", - PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "GLTFState"))); - - ClassDB::bind_method(D_METHOD("_import_preflight", "p_state"), &GLTFDocumentExtension::_import_preflight); - ClassDB::bind_method(D_METHOD("_import_post_parse", "p_state"), &GLTFDocumentExtension::_import_post_parse); - ClassDB::bind_method(D_METHOD("_export_post", "p_state"), &GLTFDocumentExtension::_export_post); - ClassDB::bind_method(D_METHOD("_import_post", "p_state", "p_node"), &GLTFDocumentExtension::_import_post); - ClassDB::bind_method(D_METHOD("_export_preflight", "p_state"), &GLTFDocumentExtension::_export_preflight); - ClassDB::bind_method(D_METHOD("_import_node", "p_state", "p_gltf_node", "r_json", "p_node"), &GLTFDocumentExtension::_import_node); - ClassDB::bind_method(D_METHOD("_export_node", "p_state", "p_gltf_node", "r_json", "p_node"), &GLTFDocumentExtension::_export_node); -} diff --git a/modules/gltf/gltf_document_extension.h b/modules/gltf/gltf_document_extension.h deleted file mode 100644 index edcde3b5f..000000000 --- a/modules/gltf/gltf_document_extension.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef GLTF_DOCUMENT_EXTENSION_H -#define GLTF_DOCUMENT_EXTENSION_H - -/*************************************************************************/ -/* gltf_document_extension.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "core/reference.h" - -#include "core/resource.h" - -class GLTFNode; -class GLTFState; - -class GLTFDocumentExtension : public Resource { - GDCLASS(GLTFDocumentExtension, Resource); - -public: - Error import_preflight(Ref p_state); - Error import_post_parse(Ref p_state); - Error export_post(Ref p_state); - Error import_post(Ref p_state, Node *p_node); - Error export_preflight(Node *p_state); - Error import_node(Ref p_state, Ref p_gltf_node, const Dictionary &r_json, Node *p_node); - Error export_node(Ref p_state, Ref p_gltf_node, const Dictionary &r_json, Node *p_node); - - virtual int _import_preflight(Ref p_state); - virtual int _import_post_parse(Ref p_state); - virtual int _export_post(Ref p_state); - virtual int _import_post(Ref p_state, Node *p_node); - virtual int _export_preflight(Node *p_state); - virtual int _import_node(Ref p_state, Ref p_gltf_node, const Dictionary &r_json, Node *p_node); - virtual int _export_node(Ref p_state, Ref p_gltf_node, const Dictionary &r_json, Node *p_node); - - GLTFDocumentExtension(); - ~GLTFDocumentExtension(); - -protected: - static void _bind_methods(); -}; - -#endif // GLTF_DOCUMENT_EXTENSION_H diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp b/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp deleted file mode 100644 index 6f328be81..000000000 --- a/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/*************************************************************************/ -/* gltf_document_extension_convert_importer_mesh.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "gltf_document_extension_convert_importer_mesh.h" - -#include "gltf_state.h" - -#include "core/error_macros.h" -#include "scene/3d/mesh_instance.h" -#include "scene/resources/importer_mesh.h" -#include "scene/3d/importer_mesh_instance_3d.h" -#include "scene/3d/mesh_instance.h" -#include "scene/main/node.h" - -void GLTFDocumentExtensionConvertImporterMesh::_bind_methods() { -} - -int GLTFDocumentExtensionConvertImporterMesh::_import_post(Ref p_state, Node *p_root) { - ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER); - - List queue; - queue.push_back(p_root); - List delete_queue; - while (!queue.empty()) { - List::Element *E = queue.front(); - Node *node = E->get(); - ImporterMeshInstance3D *mesh_3d = cast_to(node); - if (mesh_3d) { - MeshInstance *mesh_instance_node_3d = memnew(MeshInstance); - Ref mesh = mesh_3d->get_mesh(); - if (mesh.is_valid()) { - Ref array_mesh = mesh->get_mesh(); - mesh_instance_node_3d->set_name(node->get_name()); - mesh_instance_node_3d->set_transform(mesh_3d->get_transform()); - mesh_instance_node_3d->set_mesh(array_mesh); - mesh_instance_node_3d->set_skin(mesh_3d->get_skin()); - mesh_instance_node_3d->set_skeleton_path(mesh_3d->get_skeleton_path()); - node->replace_by(mesh_instance_node_3d); - delete_queue.push_back(node); - } else { - memdelete(mesh_instance_node_3d); - } - } - int child_count = node->get_child_count(); - for (int i = 0; i < child_count; i++) { - queue.push_back(node->get_child(i)); - } - queue.pop_front(); - } - - while (!queue.empty()) { - List::Element *E = delete_queue.front(); - Node *node = E->get(); - memdelete(node); - delete_queue.pop_front(); - } - - return OK; -} diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.h b/modules/gltf/gltf_document_extension_convert_importer_mesh.h deleted file mode 100644 index 97d60ad2d..000000000 --- a/modules/gltf/gltf_document_extension_convert_importer_mesh.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef GLTF_DOCUMENT_EXTENSION_CONVERT_IMPORTER_MESH_H -#define GLTF_DOCUMENT_EXTENSION_CONVERT_IMPORTER_MESH_H - -/*************************************************************************/ -/* gltf_document_extension_convert_importer_mesh.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "core/reference.h" - -#include "gltf_document_extension.h" - -class GLTFState; -class Node; - -class GLTFDocumentExtensionConvertImporterMesh : public GLTFDocumentExtension { - GDCLASS(GLTFDocumentExtensionConvertImporterMesh, GLTFDocumentExtension); - -protected: - static void _bind_methods(); - -public: - int _import_post(Ref p_state, Node *p_root); -}; - -#endif // GLTF_DOCUMENT_EXTENSION_CONVERT_IMPORTER_MESH_H diff --git a/modules/gltf/extensions/gltf_light.cpp b/modules/gltf/gltf_light.cpp similarity index 91% rename from modules/gltf/extensions/gltf_light.cpp rename to modules/gltf/gltf_light.cpp index ec951e44b..05f0c7cc9 100644 --- a/modules/gltf/extensions/gltf_light.cpp +++ b/modules/gltf/gltf_light.cpp @@ -35,8 +35,8 @@ void GLTFLight::_bind_methods() { ClassDB::bind_method(D_METHOD("set_color", "color"), &GLTFLight::set_color); ClassDB::bind_method(D_METHOD("get_intensity"), &GLTFLight::get_intensity); ClassDB::bind_method(D_METHOD("set_intensity", "intensity"), &GLTFLight::set_intensity); - ClassDB::bind_method(D_METHOD("get_light_type"), &GLTFLight::get_light_type); - ClassDB::bind_method(D_METHOD("set_light_type", "light_type"), &GLTFLight::set_light_type); + ClassDB::bind_method(D_METHOD("get_type"), &GLTFLight::get_type); + ClassDB::bind_method(D_METHOD("set_type", "type"), &GLTFLight::set_type); ClassDB::bind_method(D_METHOD("get_range"), &GLTFLight::get_range); ClassDB::bind_method(D_METHOD("set_range", "range"), &GLTFLight::set_range); ClassDB::bind_method(D_METHOD("get_inner_cone_angle"), &GLTFLight::get_inner_cone_angle); @@ -46,7 +46,7 @@ void GLTFLight::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); // Color ADD_PROPERTY(PropertyInfo(Variant::REAL, "intensity"), "set_intensity", "get_intensity"); // float - ADD_PROPERTY(PropertyInfo(Variant::STRING, "light_type"), "set_light_type", "get_light_type"); // String + ADD_PROPERTY(PropertyInfo(Variant::STRING, "type"), "set_type", "get_type"); // String ADD_PROPERTY(PropertyInfo(Variant::REAL, "range"), "set_range", "get_range"); // float ADD_PROPERTY(PropertyInfo(Variant::REAL, "inner_cone_angle"), "set_inner_cone_angle", "get_inner_cone_angle"); // float ADD_PROPERTY(PropertyInfo(Variant::REAL, "outer_cone_angle"), "set_outer_cone_angle", "get_outer_cone_angle"); // float @@ -68,12 +68,12 @@ void GLTFLight::set_intensity(float p_intensity) { intensity = p_intensity; } -String GLTFLight::get_light_type() { - return light_type; +String GLTFLight::get_type() { + return type; } -void GLTFLight::set_light_type(String p_light_type) { - light_type = p_light_type; +void GLTFLight::set_type(String p_type) { + type = p_type; } float GLTFLight::get_range() { diff --git a/modules/gltf/extensions/gltf_light.h b/modules/gltf/gltf_light.h similarity index 95% rename from modules/gltf/extensions/gltf_light.h rename to modules/gltf/gltf_light.h index fbc4897c2..5076917ed 100644 --- a/modules/gltf/extensions/gltf_light.h +++ b/modules/gltf/gltf_light.h @@ -1,6 +1,5 @@ #ifndef GLTF_LIGHT_H #define GLTF_LIGHT_H - /*************************************************************************/ /* gltf_light.h */ /*************************************************************************/ @@ -31,9 +30,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "core/engine.h" #include "core/resource.h" -#include "scene/3d/light.h" class GLTFLight : public Resource { GDCLASS(GLTFLight, Resource) @@ -45,7 +42,7 @@ protected: private: Color color = Color(1.0f, 1.0f, 1.0f); float intensity = 1.0f; - String light_type; + String type; float range = INFINITY; float inner_cone_angle = 0.0f; float outer_cone_angle = Math_TAU / 8.0f; @@ -57,8 +54,8 @@ public: float get_intensity(); void set_intensity(float p_intensity); - String get_light_type(); - void set_light_type(String p_light_type); + String get_type(); + void set_type(String p_type); float get_range(); void set_range(float p_range); diff --git a/modules/gltf/structures/gltf_mesh.cpp b/modules/gltf/gltf_mesh.cpp similarity index 96% rename from modules/gltf/structures/gltf_mesh.cpp rename to modules/gltf/gltf_mesh.cpp index 924099727..f73b022d5 100644 --- a/modules/gltf/structures/gltf_mesh.cpp +++ b/modules/gltf/gltf_mesh.cpp @@ -30,8 +30,6 @@ #include "gltf_mesh.h" -#include "scene/resources/importer_mesh.h" - void GLTFMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_mesh"), &GLTFMesh::get_mesh); ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &GLTFMesh::set_mesh); @@ -45,11 +43,11 @@ void GLTFMesh::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "instance_materials"), "set_instance_materials", "get_instance_materials"); } -Ref GLTFMesh::get_mesh() { +Ref GLTFMesh::get_mesh() { return mesh; } -void GLTFMesh::set_mesh(Ref p_mesh) { +void GLTFMesh::set_mesh(Ref p_mesh) { mesh = p_mesh; } diff --git a/modules/gltf/structures/gltf_mesh.h b/modules/gltf/gltf_mesh.h similarity index 93% rename from modules/gltf/structures/gltf_mesh.h rename to modules/gltf/gltf_mesh.h index bcf2ff54e..780855b2c 100644 --- a/modules/gltf/structures/gltf_mesh.h +++ b/modules/gltf/gltf_mesh.h @@ -1,6 +1,5 @@ #ifndef GLTF_MESH_H #define GLTF_MESH_H - /*************************************************************************/ /* gltf_mesh.h */ /*************************************************************************/ @@ -32,15 +31,13 @@ /*************************************************************************/ #include "core/resource.h" -#include "scene/3d/importer_mesh_instance_3d.h" -#include "scene/resources/importer_mesh.h" #include "scene/resources/mesh.h" class GLTFMesh : public Resource { GDCLASS(GLTFMesh, Resource); private: - Ref mesh; + Ref mesh; Vector blend_weights; Array instance_materials; @@ -48,8 +45,8 @@ protected: static void _bind_methods(); public: - Ref get_mesh(); - void set_mesh(Ref p_mesh); + Ref get_mesh(); + void set_mesh(Ref p_mesh); Vector get_blend_weights(); void set_blend_weights(Vector p_blend_weights); Array get_instance_materials(); diff --git a/modules/gltf/structures/gltf_node.cpp b/modules/gltf/gltf_node.cpp similarity index 93% rename from modules/gltf/structures/gltf_node.cpp rename to modules/gltf/gltf_node.cpp index e3fb7e1a3..5324acb6e 100644 --- a/modules/gltf/structures/gltf_node.cpp +++ b/modules/gltf/gltf_node.cpp @@ -47,8 +47,8 @@ void GLTFNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_skeleton", "skeleton"), &GLTFNode::set_skeleton); ClassDB::bind_method(D_METHOD("get_joint"), &GLTFNode::get_joint); ClassDB::bind_method(D_METHOD("set_joint", "joint"), &GLTFNode::set_joint); - ClassDB::bind_method(D_METHOD("get_position"), &GLTFNode::get_position); - ClassDB::bind_method(D_METHOD("set_position", "position"), &GLTFNode::set_position); + ClassDB::bind_method(D_METHOD("get_translation"), &GLTFNode::get_translation); + ClassDB::bind_method(D_METHOD("set_translation", "translation"), &GLTFNode::set_translation); ClassDB::bind_method(D_METHOD("get_rotation"), &GLTFNode::get_rotation); ClassDB::bind_method(D_METHOD("set_rotation", "rotation"), &GLTFNode::set_rotation); ClassDB::bind_method(D_METHOD("get_scale"), &GLTFNode::get_scale); @@ -66,7 +66,7 @@ void GLTFNode::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "skin"), "set_skin", "get_skin"); // GLTFSkinIndex ADD_PROPERTY(PropertyInfo(Variant::INT, "skeleton"), "set_skeleton", "get_skeleton"); // GLTFSkeletonIndex ADD_PROPERTY(PropertyInfo(Variant::BOOL, "joint"), "set_joint", "get_joint"); // bool - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position"), "set_position", "get_position"); // Vector3 + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "translation"), "set_translation", "get_translation"); // Vector3 ADD_PROPERTY(PropertyInfo(Variant::QUAT, "rotation"), "set_rotation", "get_rotation"); // Quat ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale"), "set_scale", "get_scale"); // Vector3 ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "children"), "set_children", "get_children"); // Vector @@ -137,12 +137,12 @@ void GLTFNode::set_joint(bool p_joint) { joint = p_joint; } -Vector3 GLTFNode::get_position() { - return position; +Vector3 GLTFNode::get_translation() { + return translation; } -void GLTFNode::set_position(Vector3 p_position) { - position = p_position; +void GLTFNode::set_translation(Vector3 p_translation) { + translation = p_translation; } Quat GLTFNode::get_rotation() { diff --git a/modules/gltf/structures/gltf_node.h b/modules/gltf/gltf_node.h similarity index 95% rename from modules/gltf/structures/gltf_node.h rename to modules/gltf/gltf_node.h index 2e390c798..8e407a4a5 100644 --- a/modules/gltf/structures/gltf_node.h +++ b/modules/gltf/gltf_node.h @@ -1,6 +1,5 @@ #ifndef GLTF_NODE_H #define GLTF_NODE_H - /*************************************************************************/ /* gltf_node.h */ /*************************************************************************/ @@ -31,12 +30,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "../gltf_defines.h" #include "core/resource.h" +#include "gltf_document.h" + class GLTFNode : public Resource { GDCLASS(GLTFNode, Resource); friend class GLTFDocument; + friend class PackedSceneGLTF; private: // matrices need to be transformed to this @@ -48,7 +49,7 @@ private: GLTFSkinIndex skin = -1; GLTFSkeletonIndex skeleton = -1; bool joint = false; - Vector3 position; + Vector3 translation; Quat rotation; Vector3 scale = Vector3(1, 1, 1); Vector children; @@ -82,8 +83,8 @@ public: bool get_joint(); void set_joint(bool p_joint); - Vector3 get_position(); - void set_position(Vector3 p_position); + Vector3 get_translation(); + void set_translation(Vector3 p_translation); Quat get_rotation(); void set_rotation(Quat p_rotation); diff --git a/modules/gltf/structures/gltf_skeleton.cpp b/modules/gltf/gltf_skeleton.cpp similarity index 73% rename from modules/gltf/structures/gltf_skeleton.cpp rename to modules/gltf/gltf_skeleton.cpp index f6b0969e5..0d0e22ef4 100644 --- a/modules/gltf/structures/gltf_skeleton.cpp +++ b/modules/gltf/gltf_skeleton.cpp @@ -30,62 +30,59 @@ #include "gltf_skeleton.h" -#include "../gltf_template_convert.h" -#include "scene/3d/bone_attachment.h" - void GLTFSkeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_joints"), &GLTFSkeleton::get_joints); ClassDB::bind_method(D_METHOD("set_joints", "joints"), &GLTFSkeleton::set_joints); ClassDB::bind_method(D_METHOD("get_roots"), &GLTFSkeleton::get_roots); ClassDB::bind_method(D_METHOD("set_roots", "roots"), &GLTFSkeleton::set_roots); - ClassDB::bind_method(D_METHOD("get_godot_skeleton"), &GLTFSkeleton::get_godot_skeleton); + ClassDB::bind_method(D_METHOD("get_pandemonium_skeleton"), &GLTFSkeleton::get_pandemonium_skeleton); ClassDB::bind_method(D_METHOD("get_unique_names"), &GLTFSkeleton::get_unique_names); ClassDB::bind_method(D_METHOD("set_unique_names", "unique_names"), &GLTFSkeleton::set_unique_names); - ClassDB::bind_method(D_METHOD("get_godot_bone_node"), &GLTFSkeleton::get_godot_bone_node); - ClassDB::bind_method(D_METHOD("set_godot_bone_node", "godot_bone_node"), &GLTFSkeleton::set_godot_bone_node); + ClassDB::bind_method(D_METHOD("get_pandemonium_bone_node"), &GLTFSkeleton::get_pandemonium_bone_node); + ClassDB::bind_method(D_METHOD("set_pandemonium_bone_node", "pandemonium_bone_node"), &GLTFSkeleton::set_pandemonium_bone_node); ClassDB::bind_method(D_METHOD("get_bone_attachment_count"), &GLTFSkeleton::get_bone_attachment_count); ClassDB::bind_method(D_METHOD("get_bone_attachment", "idx"), &GLTFSkeleton::get_bone_attachment); - ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "joints"), "set_joints", "get_joints"); // Vector - ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "roots"), "set_roots", "get_roots"); // Vector + ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "joints"), "set_joints", "get_joints"); // PoolVector + ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "roots"), "set_roots", "get_roots"); // PoolVector ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_names", "get_unique_names"); // Set - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "godot_bone_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_godot_bone_node", "get_godot_bone_node"); // RBMap GLTFSkeleton::get_joints() { +PoolVector GLTFSkeleton::get_joints() { return joints; } -void GLTFSkeleton::set_joints(Vector p_joints) { +void GLTFSkeleton::set_joints(PoolVector p_joints) { joints = p_joints; } -Vector GLTFSkeleton::get_roots() { +PoolVector GLTFSkeleton::get_roots() { return roots; } -void GLTFSkeleton::set_roots(Vector p_roots) { +void GLTFSkeleton::set_roots(PoolVector p_roots) { roots = p_roots; } -Skeleton *GLTFSkeleton::get_godot_skeleton() { - return godot_skeleton; +Skeleton *GLTFSkeleton::get_pandemonium_skeleton() { + return pandemonium_skeleton; } Array GLTFSkeleton::get_unique_names() { - return GLTFTemplateConvert::to_array(unique_names); + return GLTFDocument::to_array(unique_names); } void GLTFSkeleton::set_unique_names(Array p_unique_names) { - GLTFTemplateConvert::set_from_array(unique_names, p_unique_names); + GLTFDocument::set_from_array(unique_names, p_unique_names); } -Dictionary GLTFSkeleton::get_godot_bone_node() { - return GLTFTemplateConvert::to_dict(godot_bone_node); +Dictionary GLTFSkeleton::get_pandemonium_bone_node() { + return GLTFDocument::to_dict(pandemonium_bone_node); } -void GLTFSkeleton::set_godot_bone_node(Dictionary p_indict) { - GLTFTemplateConvert::set_from_dict(godot_bone_node, p_indict); +void GLTFSkeleton::set_pandemonium_bone_node(Dictionary p_indict) { + GLTFDocument::set_from_dict(pandemonium_bone_node, p_indict); } BoneAttachment *GLTFSkeleton::get_bone_attachment(int idx) { diff --git a/modules/gltf/structures/gltf_skeleton.h b/modules/gltf/gltf_skeleton.h similarity index 70% rename from modules/gltf/structures/gltf_skeleton.h rename to modules/gltf/gltf_skeleton.h index 29708940b..364731480 100644 --- a/modules/gltf/structures/gltf_skeleton.h +++ b/modules/gltf/gltf_skeleton.h @@ -1,6 +1,5 @@ #ifndef GLTF_SKELETON_H #define GLTF_SKELETON_H - /*************************************************************************/ /* gltf_skeleton.h */ /*************************************************************************/ @@ -31,9 +30,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "../gltf_defines.h" #include "core/resource.h" -#include "core/hash_set.h" + +#include "gltf_document.h" class GLTFSkeleton : public Resource { GDCLASS(GLTFSkeleton, Resource); @@ -41,59 +40,39 @@ class GLTFSkeleton : public Resource { private: // The *synthesized* skeletons joints - Vector joints; + PoolVector joints; // The roots of the skeleton. If there are multiple, each root must have the // same parent (ie roots are siblings) - Vector roots; + PoolVector roots; // The created Skeleton for the scene - Skeleton *godot_skeleton = nullptr; + Skeleton *pandemonium_skeleton = nullptr; // Set of unique bone names for the skeleton - HashSet unique_names; + Set unique_names; - HashMap godot_bone_node; + Map pandemonium_bone_node; - Vector bone_attachments; + PoolVector bone_attachments; protected: static void _bind_methods(); public: - Vector get_joints(); - void set_joints(Vector p_joints); + PoolVector get_joints(); + void set_joints(PoolVector p_joints); - Vector get_roots(); - void set_roots(Vector p_roots); + PoolVector get_roots(); + void set_roots(PoolVector p_roots); - Skeleton *get_godot_skeleton(); - - // Skeleton *get_godot_skeleton() { - // return this->godot_skeleton; - // } - // void set_godot_skeleton(Skeleton p_*godot_skeleton) { - // this->godot_skeleton = p_godot_skeleton; - // } + Skeleton *get_pandemonium_skeleton(); Array get_unique_names(); void set_unique_names(Array p_unique_names); - //RBMap get_godot_bone_node() { - // return this->godot_bone_node; - //} - //void set_godot_bone_node(RBMap p_godot_bone_node) { - // this->godot_bone_node = p_godot_bone_node; - //} - Dictionary get_godot_bone_node(); - void set_godot_bone_node(Dictionary p_indict); - - //Dictionary get_godot_bone_node() { - // return VariantConversion::to_dict(this->godot_bone_node); - //} - //void set_godot_bone_node(Dictionary p_indict) { - // VariantConversion::set_from_dict(this->godot_bone_node, p_indict); - //} + Dictionary get_pandemonium_bone_node(); + void set_pandemonium_bone_node(Dictionary p_indict); BoneAttachment *get_bone_attachment(int idx); diff --git a/modules/gltf/structures/gltf_skin.cpp b/modules/gltf/gltf_skin.cpp similarity index 86% rename from modules/gltf/structures/gltf_skin.cpp rename to modules/gltf/gltf_skin.cpp index c2c59a149..5eacb2aa4 100644 --- a/modules/gltf/structures/gltf_skin.cpp +++ b/modules/gltf/gltf_skin.cpp @@ -30,7 +30,6 @@ #include "gltf_skin.h" -#include "../gltf_template_convert.h" #include "scene/resources/skin.h" void GLTFSkin::_bind_methods() { @@ -52,8 +51,8 @@ void GLTFSkin::_bind_methods() { ClassDB::bind_method(D_METHOD("set_joint_i_to_bone_i", "joint_i_to_bone_i"), &GLTFSkin::set_joint_i_to_bone_i); ClassDB::bind_method(D_METHOD("get_joint_i_to_name"), &GLTFSkin::get_joint_i_to_name); ClassDB::bind_method(D_METHOD("set_joint_i_to_name", "joint_i_to_name"), &GLTFSkin::set_joint_i_to_name); - ClassDB::bind_method(D_METHOD("get_godot_skin"), &GLTFSkin::get_godot_skin); - ClassDB::bind_method(D_METHOD("set_godot_skin", "godot_skin"), &GLTFSkin::set_godot_skin); + ClassDB::bind_method(D_METHOD("get_pandemonium_skin"), &GLTFSkin::get_pandemonium_skin); + ClassDB::bind_method(D_METHOD("set_pandemonium_skin", "pandemonium_skin"), &GLTFSkin::set_pandemonium_skin); ADD_PROPERTY(PropertyInfo(Variant::INT, "skin_root"), "set_skin_root", "get_skin_root"); // GLTFNodeIndex ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "joints_original"), "set_joints_original", "get_joints_original"); // Vector @@ -62,9 +61,9 @@ void GLTFSkin::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "non_joints"), "set_non_joints", "get_non_joints"); // Vector ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "roots"), "set_roots", "get_roots"); // Vector ADD_PROPERTY(PropertyInfo(Variant::INT, "skeleton"), "set_skeleton", "get_skeleton"); // int - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "joint_i_to_bone_i", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL), "set_joint_i_to_bone_i", "get_joint_i_to_bone_i"); // RBMap + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "joint_i_to_bone_i", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL), "set_joint_i_to_bone_i", "get_joint_i_to_bone_i"); // Map } GLTFNodeIndex GLTFSkin::get_skin_root() { @@ -84,11 +83,11 @@ void GLTFSkin::set_joints_original(Vector p_joints_original) { } Array GLTFSkin::get_inverse_binds() { - return GLTFTemplateConvert::to_array(inverse_binds); + return GLTFDocument::to_array(inverse_binds); } void GLTFSkin::set_inverse_binds(Array p_inverse_binds) { - GLTFTemplateConvert::set_from_array(inverse_binds, p_inverse_binds); + GLTFDocument::set_from_array(inverse_binds, p_inverse_binds); } Vector GLTFSkin::get_joints() { @@ -124,35 +123,41 @@ void GLTFSkin::set_skeleton(int p_skeleton) { } Dictionary GLTFSkin::get_joint_i_to_bone_i() { - return GLTFTemplateConvert::to_dict(joint_i_to_bone_i); + return GLTFDocument::to_dict(joint_i_to_bone_i); } void GLTFSkin::set_joint_i_to_bone_i(Dictionary p_joint_i_to_bone_i) { - GLTFTemplateConvert::set_from_dict(joint_i_to_bone_i, p_joint_i_to_bone_i); + GLTFDocument::set_from_dict(joint_i_to_bone_i, p_joint_i_to_bone_i); } Dictionary GLTFSkin::get_joint_i_to_name() { Dictionary ret; - - const int *key = NULL; - while ((key = joint_i_to_name.next(key))) { - ret[*key] = String(joint_i_to_name[*key]); + Map::Element *elem = joint_i_to_name.front(); + while (elem) { + ret[elem->key()] = String(elem->value()); + elem = elem->next(); } return ret; } void GLTFSkin::set_joint_i_to_name(Dictionary p_joint_i_to_name) { - joint_i_to_name = HashMap(); + joint_i_to_name = Map(); Array keys = p_joint_i_to_name.keys(); for (int i = 0; i < keys.size(); i++) { joint_i_to_name[keys[i]] = p_joint_i_to_name[keys[i]]; } } -Ref GLTFSkin::get_godot_skin() { - return godot_skin; +Ref GLTFSkin::get_pandemonium_skin() { + return pandemonium_skin; } -void GLTFSkin::set_godot_skin(Ref p_godot_skin) { - godot_skin = p_godot_skin; +void GLTFSkin::set_pandemonium_skin(Ref p_pandemonium_skin) { + pandemonium_skin = p_pandemonium_skin; +} + +GLTFSkin::GLTFSkin() { +} + +GLTFSkin::~GLTFSkin() { } diff --git a/modules/gltf/structures/gltf_skin.h b/modules/gltf/gltf_skin.h similarity index 93% rename from modules/gltf/structures/gltf_skin.h rename to modules/gltf/gltf_skin.h index 058439b75..26c17f729 100644 --- a/modules/gltf/structures/gltf_skin.h +++ b/modules/gltf/gltf_skin.h @@ -1,6 +1,5 @@ #ifndef GLTF_SKIN_H #define GLTF_SKIN_H - /*************************************************************************/ /* gltf_skin.h */ /*************************************************************************/ @@ -31,9 +30,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "../gltf_defines.h" #include "core/resource.h" +#include "gltf_document.h" + +class Skin; + class GLTFSkin : public Resource { GDCLASS(GLTFSkin, Resource); friend class GLTFDocument; @@ -64,13 +66,13 @@ private: GLTFSkeletonIndex skeleton = -1; // A mapping from the joint indices (in the order of joints_original) to the - // Godot Skeleton's bone_indices - HashMap joint_i_to_bone_i; - HashMap joint_i_to_name; + // Pandemonium Skeleton's bone_indices + Map joint_i_to_bone_i; + Map joint_i_to_name; // The Actual Skin that will be created as a mapping between the IBM's of // this skin to the generated skeleton for the mesh instances. - Ref godot_skin; + Ref pandemonium_skin; protected: static void _bind_methods(); @@ -103,8 +105,11 @@ public: Dictionary get_joint_i_to_name(); void set_joint_i_to_name(Dictionary p_joint_i_to_name); - Ref get_godot_skin(); - void set_godot_skin(Ref p_godot_skin); + Ref get_pandemonium_skin(); + void set_pandemonium_skin(Ref p_pandemonium_skin); + + GLTFSkin(); + ~GLTFSkin(); }; #endif // GLTF_SKIN_H diff --git a/modules/gltf/extensions/gltf_spec_gloss.cpp b/modules/gltf/gltf_spec_gloss.cpp similarity index 100% rename from modules/gltf/extensions/gltf_spec_gloss.cpp rename to modules/gltf/gltf_spec_gloss.cpp diff --git a/modules/gltf/extensions/gltf_spec_gloss.h b/modules/gltf/gltf_spec_gloss.h similarity index 99% rename from modules/gltf/extensions/gltf_spec_gloss.h rename to modules/gltf/gltf_spec_gloss.h index b577e5ae1..3a69f431c 100644 --- a/modules/gltf/extensions/gltf_spec_gloss.h +++ b/modules/gltf/gltf_spec_gloss.h @@ -1,6 +1,5 @@ #ifndef GLTF_SPEC_GLOSS_H #define GLTF_SPEC_GLOSS_H - /*************************************************************************/ /* gltf_spec_gloss.h */ /*************************************************************************/ diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index d3400d278..82beb2be8 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -30,6 +30,8 @@ #include "gltf_state.h" +#include "scene/resources/skin.h" + void GLTFState::_bind_methods() { ClassDB::bind_method(D_METHOD("get_json"), &GLTFState::get_json); ClassDB::bind_method(D_METHOD("set_json", "json"), &GLTFState::set_json); @@ -57,8 +59,6 @@ void GLTFState::_bind_methods() { ClassDB::bind_method(D_METHOD("set_materials", "materials"), &GLTFState::set_materials); ClassDB::bind_method(D_METHOD("get_scene_name"), &GLTFState::get_scene_name); ClassDB::bind_method(D_METHOD("set_scene_name", "scene_name"), &GLTFState::set_scene_name); - ClassDB::bind_method(D_METHOD("get_base_path"), &GLTFState::get_base_path); - ClassDB::bind_method(D_METHOD("set_base_path", "base_path"), &GLTFState::set_base_path); ClassDB::bind_method(D_METHOD("get_root_nodes"), &GLTFState::get_root_nodes); ClassDB::bind_method(D_METHOD("set_root_nodes", "root_nodes"), &GLTFState::set_root_nodes); ClassDB::bind_method(D_METHOD("get_textures"), &GLTFState::get_textures); @@ -95,7 +95,6 @@ void GLTFState::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "meshes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_meshes", "get_meshes"); // Vector> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "materials", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_materials", "get_materials"); // Vector ADD_PROPERTY(PropertyInfo(Variant::STRING, "scene_name"), "set_scene_name", "get_scene_name"); // String - ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_path"), "set_base_path", "get_base_path"); // String ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "root_nodes"), "set_root_nodes", "get_root_nodes"); // Vector ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_textures", "get_textures"); // Vector> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "images", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_images", "get_images"); // Vector @@ -105,7 +104,7 @@ void GLTFState::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_names", "get_unique_names"); // Set 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 ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skeletons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeletons", "get_skeletons"); // Vector> - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "skeleton_to_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeleton_to_node", "get_skeleton_to_node"); // RBMap> } @@ -150,51 +149,51 @@ void GLTFState::set_use_named_skin_binds(bool p_use_named_skin_binds) { } Array GLTFState::get_nodes() { - return GLTFTemplateConvert::to_array(nodes); + return GLTFDocument::to_array(nodes); } void GLTFState::set_nodes(Array p_nodes) { - GLTFTemplateConvert::set_from_array(nodes, p_nodes); + GLTFDocument::set_from_array(nodes, p_nodes); } Array GLTFState::get_buffers() { - return GLTFTemplateConvert::to_array(buffers); + return GLTFDocument::to_array(buffers); } void GLTFState::set_buffers(Array p_buffers) { - GLTFTemplateConvert::set_from_array(buffers, p_buffers); + GLTFDocument::set_from_array(buffers, p_buffers); } Array GLTFState::get_buffer_views() { - return GLTFTemplateConvert::to_array(buffer_views); + return GLTFDocument::to_array(buffer_views); } void GLTFState::set_buffer_views(Array p_buffer_views) { - GLTFTemplateConvert::set_from_array(buffer_views, p_buffer_views); + GLTFDocument::set_from_array(buffer_views, p_buffer_views); } Array GLTFState::get_accessors() { - return GLTFTemplateConvert::to_array(accessors); + return GLTFDocument::to_array(accessors); } void GLTFState::set_accessors(Array p_accessors) { - GLTFTemplateConvert::set_from_array(accessors, p_accessors); + GLTFDocument::set_from_array(accessors, p_accessors); } Array GLTFState::get_meshes() { - return GLTFTemplateConvert::to_array(meshes); + return GLTFDocument::to_array(meshes); } void GLTFState::set_meshes(Array p_meshes) { - GLTFTemplateConvert::set_from_array(meshes, p_meshes); + GLTFDocument::set_from_array(meshes, p_meshes); } Array GLTFState::get_materials() { - return GLTFTemplateConvert::to_array(materials); + return GLTFDocument::to_array(materials); } void GLTFState::set_materials(Array p_materials) { - GLTFTemplateConvert::set_from_array(materials, p_materials); + GLTFDocument::set_from_array(materials, p_materials); } String GLTFState::get_scene_name() { @@ -206,91 +205,91 @@ void GLTFState::set_scene_name(String p_scene_name) { } Array GLTFState::get_root_nodes() { - return GLTFTemplateConvert::to_array(root_nodes); + return GLTFDocument::to_array(root_nodes); } void GLTFState::set_root_nodes(Array p_root_nodes) { - GLTFTemplateConvert::set_from_array(root_nodes, p_root_nodes); + GLTFDocument::set_from_array(root_nodes, p_root_nodes); } Array GLTFState::get_textures() { - return GLTFTemplateConvert::to_array(textures); + return GLTFDocument::to_array(textures); } void GLTFState::set_textures(Array p_textures) { - GLTFTemplateConvert::set_from_array(textures, p_textures); + GLTFDocument::set_from_array(textures, p_textures); } Array GLTFState::get_images() { - return GLTFTemplateConvert::to_array(images); + return GLTFDocument::to_array(images); } void GLTFState::set_images(Array p_images) { - GLTFTemplateConvert::set_from_array(images, p_images); + GLTFDocument::set_from_array(images, p_images); } Array GLTFState::get_skins() { - return GLTFTemplateConvert::to_array(skins); + return GLTFDocument::to_array(skins); } void GLTFState::set_skins(Array p_skins) { - GLTFTemplateConvert::set_from_array(skins, p_skins); + GLTFDocument::set_from_array(skins, p_skins); } Array GLTFState::get_cameras() { - return GLTFTemplateConvert::to_array(cameras); + return GLTFDocument::to_array(cameras); } void GLTFState::set_cameras(Array p_cameras) { - GLTFTemplateConvert::set_from_array(cameras, p_cameras); + GLTFDocument::set_from_array(cameras, p_cameras); } Array GLTFState::get_lights() { - return GLTFTemplateConvert::to_array(lights); + return GLTFDocument::to_array(lights); } void GLTFState::set_lights(Array p_lights) { - GLTFTemplateConvert::set_from_array(lights, p_lights); + GLTFDocument::set_from_array(lights, p_lights); } Array GLTFState::get_unique_names() { - return GLTFTemplateConvert::to_array(unique_names); + return GLTFDocument::to_array(unique_names); } void GLTFState::set_unique_names(Array p_unique_names) { - GLTFTemplateConvert::set_from_array(unique_names, p_unique_names); + GLTFDocument::set_from_array(unique_names, p_unique_names); } Array GLTFState::get_unique_animation_names() { - return GLTFTemplateConvert::to_array(unique_animation_names); + return GLTFDocument::to_array(unique_animation_names); } void GLTFState::set_unique_animation_names(Array p_unique_animation_names) { - GLTFTemplateConvert::set_from_array(unique_animation_names, p_unique_animation_names); + GLTFDocument::set_from_array(unique_animation_names, p_unique_animation_names); } Array GLTFState::get_skeletons() { - return GLTFTemplateConvert::to_array(skeletons); + return GLTFDocument::to_array(skeletons); } void GLTFState::set_skeletons(Array p_skeletons) { - GLTFTemplateConvert::set_from_array(skeletons, p_skeletons); + GLTFDocument::set_from_array(skeletons, p_skeletons); } Dictionary GLTFState::get_skeleton_to_node() { - return GLTFTemplateConvert::to_dict(skeleton_to_node); + return GLTFDocument::to_dict(skeleton_to_node); } void GLTFState::set_skeleton_to_node(Dictionary p_skeleton_to_node) { - GLTFTemplateConvert::set_from_dict(skeleton_to_node, p_skeleton_to_node); + GLTFDocument::set_from_dict(skeleton_to_node, p_skeleton_to_node); } Array GLTFState::get_animations() { - return GLTFTemplateConvert::to_array(animations); + return GLTFDocument::to_array(animations); } void GLTFState::set_animations(Array p_animations) { - GLTFTemplateConvert::set_from_array(animations, p_animations); + GLTFDocument::set_from_array(animations, p_animations); } Node *GLTFState::get_scene_node(GLTFNodeIndex idx) { @@ -308,19 +307,3 @@ AnimationPlayer *GLTFState::get_animation_player(int idx) { ERR_FAIL_INDEX_V(idx, animation_players.size(), nullptr); return animation_players[idx]; } - -void GLTFState::set_discard_meshes_and_materials(bool p_discard_meshes_and_materials) { - discard_meshes_and_materials = p_discard_meshes_and_materials; -} - -bool GLTFState::get_discard_meshes_and_materials() { - return discard_meshes_and_materials; -} - -String GLTFState::get_base_path() { - return base_path; -} - -void GLTFState::set_base_path(String p_base_path) { - base_path = p_base_path; -} diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index e14e3cdbc..cc33c3a0b 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -1,6 +1,5 @@ #ifndef GLTF_STATE_H #define GLTF_STATE_H - /*************************************************************************/ /* gltf_state.h */ /*************************************************************************/ @@ -31,36 +30,38 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "extensions/gltf_light.h" -#include "gltf_template_convert.h" -#include "structures/gltf_accessor.h" -#include "structures/gltf_animation.h" -#include "structures/gltf_buffer_view.h" -#include "structures/gltf_camera.h" -#include "structures/gltf_mesh.h" -#include "structures/gltf_node.h" -#include "structures/gltf_skeleton.h" -#include "structures/gltf_skin.h" -#include "structures/gltf_texture.h" - -#include "core/rb_map.h" +#include "core/map.h" +#include "core/resource.h" +#include "core/vector.h" #include "scene/animation/animation_player.h" #include "scene/resources/texture.h" +#include "gltf_accessor.h" +#include "gltf_animation.h" +#include "gltf_buffer_view.h" +#include "gltf_camera.h" +#include "gltf_document.h" +#include "gltf_light.h" +#include "gltf_mesh.h" +#include "gltf_node.h" +#include "gltf_skeleton.h" +#include "gltf_skin.h" +#include "gltf_texture.h" + class GLTFState : public Resource { GDCLASS(GLTFState, Resource); friend class GLTFDocument; + friend class PackedSceneGLTF; String filename; - String base_path; Dictionary json; int major_version = 0; int minor_version = 0; Vector glb_data; bool use_named_skin_binds = false; - bool use_khr_texture_transform = false; - bool discard_meshes_and_materials = false; + bool use_legacy_names = false; + uint32_t compress_flags = 0; Vector> nodes; Vector> buffers; @@ -70,8 +71,8 @@ class GLTFState : public Resource { Vector> meshes; // meshes are loaded directly, no reason not to. Vector animation_players; - HashMap, GLTFMaterialIndex> material_cache; - Vector> materials; + Map, GLTFMaterialIndex> material_cache; + Vector> materials; String scene_name; Vector root_nodes; @@ -81,16 +82,16 @@ class GLTFState : public Resource { Vector> skins; Vector> cameras; Vector> lights; - HashSet unique_names; - HashSet unique_animation_names; + Set unique_names; + Set unique_animation_names; Vector> skeletons; - HashMap skeleton_to_node; + Map skeleton_to_node; Vector> animations; - HashMap scene_nodes; + Map scene_nodes; - HashMap skeleton3d_to_gltf_skeleton; - HashMap> skin_and_skeleton3d_to_gltf_skin; + Map skeleton3d_to_gltf_skeleton; + Map> skin_and_skeleton3d_to_gltf_skin; protected: static void _bind_methods(); @@ -111,9 +112,6 @@ public: bool get_use_named_skin_binds(); void set_use_named_skin_binds(bool p_use_named_skin_binds); - bool get_discard_meshes_and_materials(); - void set_discard_meshes_and_materials(bool p_discard_meshes_and_materials); - Array get_nodes(); void set_nodes(Array p_nodes); @@ -135,9 +133,6 @@ public: String get_scene_name(); void set_scene_name(String p_scene_name); - String get_base_path(); - void set_base_path(String p_base_path); - Array get_root_nodes(); void set_root_nodes(Array p_root_nodes); @@ -176,21 +171,6 @@ public: int get_animation_players_count(int idx); AnimationPlayer *get_animation_player(int idx); - - //void set_scene_nodes(RBMap p_scene_nodes) { - // this->scene_nodes = p_scene_nodes; - //} - - //void set_animation_players(Vector p_animation_players) { - // this->animation_players = p_animation_players; - //} - - //RBMap, GLTFMaterialIndex> get_material_cache() { - // return this->material_cache; - //} - //void set_material_cache(RBMap, GLTFMaterialIndex> p_material_cache) { - // this->material_cache = p_material_cache; - //} }; #endif // GLTF_STATE_H diff --git a/modules/gltf/gltf_template_convert.h b/modules/gltf/gltf_template_convert.h deleted file mode 100644 index a787c85b8..000000000 --- a/modules/gltf/gltf_template_convert.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef GLTF_TEMPLATE_CONVERT_H -#define GLTF_TEMPLATE_CONVERT_H - -/*************************************************************************/ -/* gltf_template_convert.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "core/array.h" -#include "core/dictionary.h" -#include "core/hash_set.h" - -namespace GLTFTemplateConvert { -template -static Array to_array(const Vector &p_inp) { - Array ret; - for (int i = 0; i < p_inp.size(); i++) { - ret.push_back(p_inp[i]); - } - return ret; -} - -template -static Array to_array(const HashSet &p_inp) { - Array ret; - typename HashSet::Iterator elem = p_inp.begin(); - while (elem) { - ret.push_back(*elem); - ++elem; - } - return ret; -} - -template -static void set_from_array(Vector &r_out, const Array &p_inp) { - r_out.clear(); - for (int i = 0; i < p_inp.size(); i++) { - r_out.push_back(p_inp[i]); - } -} - -template -static void set_from_array(HashSet &r_out, const Array &p_inp) { - r_out.clear(); - for (int i = 0; i < p_inp.size(); i++) { - r_out.insert(p_inp[i]); - } -} - -template -static Dictionary to_dict(const HashMap &p_inp) { - Dictionary ret; - const K *key = NULL; - while ((key = p_inp.next(key))) { - ret[*key] = p_inp[*key]; - } - return ret; -} - -template -static void set_from_dict(HashMap &r_out, const Dictionary &p_inp) { - r_out.clear(); - Array keys = p_inp.keys(); - for (int i = 0; i < keys.size(); i++) { - r_out[keys[i]] = p_inp[keys[i]]; - } -} -} //namespace GLTFTemplateConvert - -#endif // GLTF_TEMPLATE_CONVERT_H diff --git a/modules/gltf/structures/gltf_texture.cpp b/modules/gltf/gltf_texture.cpp similarity index 100% rename from modules/gltf/structures/gltf_texture.cpp rename to modules/gltf/gltf_texture.cpp diff --git a/modules/gltf/structures/gltf_texture.h b/modules/gltf/gltf_texture.h similarity index 98% rename from modules/gltf/structures/gltf_texture.h rename to modules/gltf/gltf_texture.h index 27c78041b..08998ba32 100644 --- a/modules/gltf/structures/gltf_texture.h +++ b/modules/gltf/gltf_texture.h @@ -1,6 +1,5 @@ #ifndef GLTF_TEXTURE_H #define GLTF_TEXTURE_H - /*************************************************************************/ /* gltf_texture.h */ /*************************************************************************/ @@ -31,9 +30,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "../gltf_defines.h" #include "core/resource.h" +#include "gltf_document.h" + class GLTFTexture : public Resource { GDCLASS(GLTFTexture, Resource); diff --git a/modules/gltf/packed_scene_gltf.cpp b/modules/gltf/packed_scene_gltf.cpp new file mode 100644 index 000000000..fc1daea50 --- /dev/null +++ b/modules/gltf/packed_scene_gltf.cpp @@ -0,0 +1,160 @@ +/*************************************************************************/ +/* packed_scene_gltf.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifdef TOOLS_ENABLED + +#include "packed_scene_gltf.h" + +#include "editor/import/resource_importer_scene.h" +#include "scene/3d/spatial.h" +#include "scene/animation/animation_player.h" +#include "scene/resources/mesh.h" +#include "scene/resources/skin.h" + +#include "gltf_document.h" + +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", "compress_flags", "state"), + &PackedSceneGLTF::pack_gltf, DEFVAL(0), DEFVAL(1000.0f), DEFVAL(Mesh::ARRAY_COMPRESS_DEFAULT), DEFVAL(Ref())); + ClassDB::bind_method(D_METHOD("import_gltf_scene", "path", "flags", "bake_fps", "compress_flags", "state"), + &PackedSceneGLTF::import_gltf_scene, DEFVAL(0), DEFVAL(1000.0f), DEFVAL(Mesh::ARRAY_COMPRESS_DEFAULT), DEFVAL(Ref())); +} + +Node *PackedSceneGLTF::import_gltf_scene(const String &p_path, uint32_t p_flags, float p_bake_fps, uint32_t p_compress_flags, Ref r_state) { + Error err = FAILED; + List deps; + return import_scene(p_path, p_flags, p_bake_fps, p_compress_flags, &deps, &err, r_state); +} + +Node *PackedSceneGLTF::import_scene(const String &p_path, uint32_t p_flags, + int p_bake_fps, uint32_t p_compress_flags, + List *r_missing_deps, + Error *r_err, + Ref r_state) { + if (r_state == Ref()) { + r_state.instance(); + } + r_state->use_named_skin_binds = + p_flags & EditorSceneImporter::IMPORT_USE_NAMED_SKIN_BINDS; + r_state->use_legacy_names = + p_flags & EditorSceneImporter::IMPORT_USE_LEGACY_NAMES; + r_state->compress_flags = p_compress_flags; + + Ref gltf_document; + gltf_document.instance(); + Error err = gltf_document->parse(r_state, p_path); + *r_err = err; + ERR_FAIL_COND_V(err != Error::OK, nullptr); + + Spatial *root = memnew(Spatial); + if (r_state->use_legacy_names) { + root->set_name(gltf_document->_legacy_validate_node_name(r_state->scene_name)); + } else { + root->set_name(r_state->scene_name); + } + 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(root); +} + +void PackedSceneGLTF::pack_gltf(String p_path, int32_t p_flags, + real_t p_bake_fps, uint32_t p_compress_flags, Ref r_state) { + Error err = FAILED; + List deps; + Node *root = import_scene(p_path, p_flags, p_bake_fps, p_compress_flags, &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 *r_missing_deps, + Error *r_err) { + Error err = FAILED; + if (r_err) { + *r_err = err; + } + Ref gltf_document; + gltf_document.instance(); + Ref state; + state.instance(); + err = gltf_document->serialize(state, p_node, p_path); + if (r_err) { + *r_err = err; + } +} + +void PackedSceneGLTF::_build_parent_hierachy(Ref 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 deps; + Error err; + String path = p_path; + int32_t flags = p_flags; + real_t baked_fps = p_bake_fps; + Ref exporter; + exporter.instance(); + 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; +} + +#endif // TOOLS_ENABLED diff --git a/modules/gltf/editor/editor_scene_importer_fbx.h b/modules/gltf/packed_scene_gltf.h similarity index 65% rename from modules/gltf/editor/editor_scene_importer_fbx.h rename to modules/gltf/packed_scene_gltf.h index 8c32a33f3..dc0960d49 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.h +++ b/modules/gltf/packed_scene_gltf.h @@ -1,8 +1,7 @@ -#ifndef EDITOR_SCENE_IMPORTER_FBX_H -#define EDITOR_SCENE_IMPORTER_FBX_H - +#ifndef PACKED_SCENE_GLTF_H +#define PACKED_SCENE_GLTF_H /*************************************************************************/ -/* editor_scene_importer_fbx.h */ +/* packed_scene_gltf.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -33,26 +32,34 @@ #ifdef TOOLS_ENABLED -#include "editor/import/resource_importer_scene.h" +#include "scene/main/node.h" +#include "scene/resources/packed_scene.h" -class Animation; -class Node; +#include "gltf_state.h" -class EditorSceneFormatImporterFBX : public EditorSceneImporter { - GDCLASS(EditorSceneFormatImporterFBX, EditorSceneImporter); +class PackedSceneGLTF : public PackedScene { + GDCLASS(PackedSceneGLTF, PackedScene); + +protected: + static void _bind_methods(); public: - virtual uint32_t get_import_flags() const; - virtual void get_extensions(List *r_extensions) const; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, uint32_t p_compress_flags, List *r_missing_deps = nullptr, Error *r_err = nullptr); - - virtual bool get_option_visibility(const String &p_option, const Map &p_options) const; - virtual void get_import_options(List *r_options, int p_preset = 0) const; - - EditorSceneFormatImporterFBX(); - ~EditorSceneFormatImporterFBX(); + 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 *r_missing_deps, Error *r_err = nullptr); + virtual void _build_parent_hierachy(Ref 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, uint32_t p_compress_flags, + List *r_missing_deps, + Error *r_err, + Ref r_state); + virtual Node *import_gltf_scene(const String &p_path, uint32_t p_flags, float p_bake_fps, uint32_t p_compress_flags, Ref r_state = Ref()); + virtual void pack_gltf(String p_path, int32_t p_flags = 0, + real_t p_bake_fps = 1000.0f, uint32_t p_compress_flags = Mesh::ARRAY_COMPRESS_DEFAULT, Ref r_state = Ref()); }; -#endif // TOOLS_ENABLED +#endif // PACKED_SCENE_GLTF_H -#endif // EDITOR_SCENE_IMPORTER_FBX_H +#endif // TOOLS_ENABLED diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp index 59b9e26d0..4ce376eaf 100644 --- a/modules/gltf/register_types.cpp +++ b/modules/gltf/register_types.cpp @@ -28,153 +28,66 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "register_types.h" - #ifndef _3D_DISABLED -#include "structures/gltf_accessor.h" -#include "structures/gltf_animation.h" -#include "structures/gltf_buffer_view.h" -#include "structures/gltf_camera.h" -#include "structures/gltf_mesh.h" -#include "structures/gltf_node.h" -#include "structures/gltf_skeleton.h" -#include "structures/gltf_skin.h" -#include "structures/gltf_texture.h" +#include "register_types.h" -#include "extensions/gltf_light.h" -#include "extensions/gltf_spec_gloss.h" - -#include "gltf_document_extension.h" -#include "gltf_document_extension_convert_importer_mesh.h" -#include "gltf_state.h" +#include "gltf_accessor.h" +#include "gltf_animation.h" +#include "gltf_buffer_view.h" +#include "gltf_camera.h" #include "gltf_document.h" +#include "gltf_light.h" +#include "gltf_mesh.h" +#include "gltf_node.h" +#include "gltf_skeleton.h" +#include "gltf_skin.h" +#include "gltf_spec_gloss.h" +#include "gltf_state.h" +#include "gltf_texture.h" +#include "packed_scene_gltf.h" + +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" +#include "editor_scene_exporter_gltf_plugin.h" +#include "editor_scene_importer_gltf.h" +#endif + +#ifdef TOOLS_ENABLED +static void _editor_init() { + Ref import_gltf; + import_gltf.instance(); + ResourceImporterScene::get_singleton()->add_importer(import_gltf); +} +#endif void register_gltf_types() { - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); +#ifdef TOOLS_ENABLED + ClassDB::APIType prev_api = ClassDB::get_current_api(); + ClassDB::set_current_api(ClassDB::API_EDITOR); + ClassDB::register_class(); + ClassDB::register_class(); + EditorPlugins::add_by_type(); + ClassDB::set_current_api(prev_api); + EditorNode::add_init_callback(_editor_init); +#endif - ClassDB::register_class(); - ClassDB::register_class(); - - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); } void unregister_gltf_types() { } -/* - -#ifdef TOOLS_ENABLED -#include "core/project_settings.h" -#include "editor/editor_node.h" -#include "editor/editor_scene_exporter_gltf_plugin.h" -#include "editor/editor_scene_importer_blend.h" -#include "editor/editor_scene_importer_fbx.h" -#include "editor/editor_scene_importer_gltf.h" -#include "editor/editor_settings.h" - -static void _editor_init() { - Ref import_gltf; - import_gltf.instantiate(); - ResourceImporterScene::add_importer(import_gltf); - - // Blend to glTF importer. - - bool blend_enabled = GLOBAL_GET("filesystem/import/blender/enabled"); - // Defined here because EditorSettings doesn't exist in `register_gltf_types` yet. - EDITOR_DEF_RST("filesystem/import/blender/blender3_path", ""); - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, - "filesystem/import/blender/blender3_path", PROPERTY_HINT_GLOBAL_DIR)); - if (blend_enabled) { - Ref importer; - importer.instantiate(); - ResourceImporterScene::add_importer(importer); - - Ref blend_import_query; - blend_import_query.instantiate(); - EditorFileSystem::get_singleton()->add_import_format_support_query(blend_import_query); - } - - // FBX to glTF importer. - - bool fbx_enabled = GLOBAL_GET("filesystem/import/fbx/enabled"); - // Defined here because EditorSettings doesn't exist in `register_gltf_types` yet. - String fbx2gltf_path = EDITOR_DEF_RST("filesystem/import/fbx/fbx2gltf_path", ""); - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, - "filesystem/import/fbx/fbx2gltf_path", PROPERTY_HINT_GLOBAL_FILE)); - if (fbx_enabled) { - DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - - if (fbx2gltf_path.is_empty()) { - WARN_PRINT("FBX file import is enabled, but no FBX2glTF path is configured. FBX files will not be imported."); - } else if (!da->file_exists(fbx2gltf_path)) { - WARN_PRINT("FBX file import is enabled, but the FBX2glTF path doesn't point to a valid FBX2glTF executable. FBX files will not be imported."); - } else { - Ref importer; - importer.instantiate(); - ResourceImporterScene::add_importer(importer); - } - - memdelete(da); - } -} -#endif // TOOLS_ENABLED - -void initialize_gltf_module() { - if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) { - // glTF API available at runtime. - GDREGISTER_CLASS(GLTFAccessor); - GDREGISTER_CLASS(GLTFAnimation); - GDREGISTER_CLASS(GLTFBufferView); - GDREGISTER_CLASS(GLTFCamera); - GDREGISTER_CLASS(GLTFDocument); - GDREGISTER_CLASS(GLTFDocumentExtension); - GDREGISTER_CLASS(GLTFDocumentExtensionConvertImporterMesh); - GDREGISTER_CLASS(GLTFLight); - GDREGISTER_CLASS(GLTFMesh); - GDREGISTER_CLASS(GLTFNode); - GDREGISTER_CLASS(GLTFSkeleton); - GDREGISTER_CLASS(GLTFSkin); - GDREGISTER_CLASS(GLTFSpecGloss); - GDREGISTER_CLASS(GLTFState); - GDREGISTER_CLASS(GLTFTexture); - } - -#ifdef TOOLS_ENABLED - if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) { - // Editor-specific API. - ClassDB::APIType prev_api = ClassDB::get_current_api(); - ClassDB::set_current_api(ClassDB::API_EDITOR); - - GDREGISTER_CLASS(EditorSceneFormatImporterGLTF); - EditorPlugins::add_by_type(); - - // Project settings defined here so doctool finds them. - GLOBAL_DEF_RST("filesystem/import/blender/enabled", true); - GLOBAL_DEF_RST("filesystem/import/fbx/enabled", true); - GDREGISTER_CLASS(EditorSceneFormatImporterBlend); - GDREGISTER_CLASS(EditorSceneFormatImporterFBX); - - ClassDB::set_current_api(prev_api); - EditorNode::add_init_callback(_editor_init); - } - -#endif // TOOLS_ENABLED -} - -void uninitialize_gltf_module() { -} -*/ - #endif // _3D_DISABLED diff --git a/modules/gltf/register_types.h b/modules/gltf/register_types.h index 4a9c31241..b3cdad7c9 100644 --- a/modules/gltf/register_types.h +++ b/modules/gltf/register_types.h @@ -1,3 +1,5 @@ +#ifndef GLTF_REGISTER_TYPES_H +#define GLTF_REGISTER_TYPES_H /*************************************************************************/ /* register_types.h */ /*************************************************************************/ @@ -28,5 +30,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef _3D_DISABLED + void register_gltf_types(); void unregister_gltf_types(); + +#endif // _3D_DISABLED + +#endif // GLTF_REGISTER_TYPES_H