summaryrefslogtreecommitdiff
path: root/modules/fbx/data
diff options
context:
space:
mode:
Diffstat (limited to 'modules/fbx/data')
-rw-r--r--modules/fbx/data/fbx_anim_container.h46
-rw-r--r--modules/fbx/data/fbx_bone.cpp56
-rw-r--r--modules/fbx/data/fbx_bone.h90
-rw-r--r--modules/fbx/data/fbx_material.cpp468
-rw-r--r--modules/fbx/data/fbx_material.h285
-rw-r--r--modules/fbx/data/fbx_mesh_data.cpp1446
-rw-r--r--modules/fbx/data/fbx_mesh_data.h200
-rw-r--r--modules/fbx/data/fbx_node.h63
-rw-r--r--modules/fbx/data/fbx_skeleton.cpp130
-rw-r--r--modules/fbx/data/fbx_skeleton.h53
-rw-r--r--modules/fbx/data/import_state.h112
-rw-r--r--modules/fbx/data/model_abstraction.h52
-rw-r--r--modules/fbx/data/pivot_transform.cpp307
-rw-r--r--modules/fbx/data/pivot_transform.h115
14 files changed, 0 insertions, 3423 deletions
diff --git a/modules/fbx/data/fbx_anim_container.h b/modules/fbx/data/fbx_anim_container.h
deleted file mode 100644
index 6559add858..0000000000
--- a/modules/fbx/data/fbx_anim_container.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*************************************************************************/
-/* fbx_anim_container.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. */
-/*************************************************************************/
-
-#ifndef FBX_ANIM_CONTAINER_H
-#define FBX_ANIM_CONTAINER_H
-
-#include "core/math/vector3.h"
-
-// Generic keyframes 99.99 percent of files will be vector3, except if quat interp is used, or visibility tracks
-// FBXTrack is used in a map in the implementation in fbx/editor_scene_importer_fbx.cpp
-// to avoid having to rewrite the entire logic I refactored this into the code instead.
-// once it works I can rewrite so we can add the fun misc features / small features
-struct FBXTrack {
- bool has_default = false;
- Vector3 default_value;
- std::map<int64_t, Vector3> keyframes;
-};
-
-#endif //MODEL_ABSTRACTION_ANIM_CONTAINER_H
diff --git a/modules/fbx/data/fbx_bone.cpp b/modules/fbx/data/fbx_bone.cpp
deleted file mode 100644
index 72aba20fd4..0000000000
--- a/modules/fbx/data/fbx_bone.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*************************************************************************/
-/* fbx_bone.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 "fbx_bone.h"
-
-#include "fbx_node.h"
-#include "import_state.h"
-
-Ref<FBXNode> FBXSkinDeformer::get_link(const ImportState &state) const {
- print_verbose("bone name: " + bone->bone_name);
-
- // safe for when deformers must be polyfilled when skin has different count of binds to bones in the scene ;)
- if (!cluster) {
- return nullptr;
- }
-
- ERR_FAIL_COND_V_MSG(cluster->TargetNode() == nullptr, nullptr, "bone has invalid target node");
-
- Ref<FBXNode> link_node;
- uint64_t id = cluster->TargetNode()->ID();
- if (state.fbx_target_map.has(id)) {
- link_node = state.fbx_target_map[id];
- } else {
- print_error("link node not found for " + itos(id));
- }
-
- // the node in space this is for, like if it's FOR a target.
- return link_node;
-}
diff --git a/modules/fbx/data/fbx_bone.h b/modules/fbx/data/fbx_bone.h
deleted file mode 100644
index 6c8f7f7cae..0000000000
--- a/modules/fbx/data/fbx_bone.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*************************************************************************/
-/* fbx_bone.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. */
-/*************************************************************************/
-
-#ifndef FBX_BONE_H
-#define FBX_BONE_H
-
-#include "fbx_node.h"
-#include "import_state.h"
-
-#include "fbx_parser/FBXDocument.h"
-
-struct PivotTransform;
-
-struct FBXBone : public RefCounted {
- uint64_t parent_bone_id = 0;
- uint64_t bone_id = 0;
-
- bool valid_parent = false; // if the parent bone id is set up.
- String bone_name = String(); // bone name
-
- bool is_root_bone() const {
- return !valid_parent;
- }
-
- // Godot specific data
- int godot_bone_id = -2; // godot internal bone id assigned after import
-
- // if a bone / armature is the root then FBX skeleton will contain the bone not any other skeleton.
- // this is to support joints by themselves in scenes
- bool valid_armature_id = false;
- uint64_t armature_id = 0;
-
- /* link node is the parent bone */
- mutable const FBXDocParser::Geometry *geometry = nullptr;
- mutable const FBXDocParser::ModelLimbNode *limb_node = nullptr;
-
- void set_node(Ref<FBXNode> p_node) {
- node = p_node;
- }
-
- // Stores the pivot xform for this bone
-
- Ref<FBXNode> node = nullptr;
- Ref<FBXBone> parent_bone = nullptr;
- Ref<FBXSkeleton> fbx_skeleton = nullptr;
-};
-
-struct FBXSkinDeformer {
- FBXSkinDeformer(Ref<FBXBone> p_bone, const FBXDocParser::Cluster *p_cluster) :
- cluster(p_cluster), bone(p_bone) {}
- ~FBXSkinDeformer() {}
- const FBXDocParser::Cluster *cluster;
- Ref<FBXBone> bone;
-
- /* get associate model - the model can be invalid sometimes */
- Ref<FBXBone> get_associate_model() const {
- return bone->parent_bone;
- }
-
- Ref<FBXNode> get_link(const ImportState &state) const;
-};
-
-#endif // FBX_BONE_H
diff --git a/modules/fbx/data/fbx_material.cpp b/modules/fbx/data/fbx_material.cpp
deleted file mode 100644
index 36e20df3a9..0000000000
--- a/modules/fbx/data/fbx_material.cpp
+++ /dev/null
@@ -1,468 +0,0 @@
-/*************************************************************************/
-/* fbx_material.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 "fbx_material.h"
-
-// FIXME: Shouldn't depend on core_bind.h! Use DirAccessRef like the rest of
-// the engine instead of core_bind::Directory.
-#include "core/core_bind.h"
-#include "scene/resources/material.h"
-#include "scene/resources/texture.h"
-#include "tools/validation_tools.h"
-
-String FBXMaterial::get_material_name() const {
- return material_name;
-}
-
-void FBXMaterial::set_imported_material(FBXDocParser::Material *p_material) {
- material = p_material;
-}
-
-void FBXMaterial::add_search_string(String p_filename, String p_current_directory, String search_directory, Vector<String> &texture_search_paths) {
- if (search_directory.is_empty()) {
- texture_search_paths.push_back(p_current_directory.get_base_dir().plus_file(p_filename));
- } else {
- texture_search_paths.push_back(p_current_directory.get_base_dir().plus_file(search_directory + "/" + p_filename));
- texture_search_paths.push_back(p_current_directory.get_base_dir().plus_file("../" + search_directory + "/" + p_filename));
- }
-}
-
-String find_file(const String &p_base, const String &p_file_to_find) {
- core_bind::Directory dir;
- dir.open(p_base);
-
- dir.list_dir_begin();
- String n = dir.get_next();
- while (!n.is_empty()) {
- if (n == "." || n == "..") {
- n = dir.get_next();
- continue;
- }
- if (dir.current_is_dir()) {
- // Don't use `path_to` or the returned path will be wrong.
- const String f = find_file(p_base + "/" + n, p_file_to_find);
- if (!f.is_empty()) {
- return f;
- }
- } else if (n == p_file_to_find) {
- return p_base + "/" + n;
- }
- n = dir.get_next();
- }
- dir.list_dir_end();
-
- return String();
-}
-
-// fbx will not give us good path information and let's not regex them to fix them
-// no relative paths are in fbx generally they have a rel field but it's populated incorrectly by the SDK.
-String FBXMaterial::find_texture_path_by_filename(const String p_filename, const String p_current_directory) {
- core_bind::Directory dir;
- Vector<String> paths;
- add_search_string(p_filename, p_current_directory, "", paths);
- add_search_string(p_filename, p_current_directory, "texture", paths);
- add_search_string(p_filename, p_current_directory, "textures", paths);
- add_search_string(p_filename, p_current_directory, "Textures", paths);
- add_search_string(p_filename, p_current_directory, "materials", paths);
- add_search_string(p_filename, p_current_directory, "mats", paths);
- add_search_string(p_filename, p_current_directory, "pictures", paths);
- add_search_string(p_filename, p_current_directory, "images", paths);
-
- for (int i = 0; i < paths.size(); i++) {
- if (dir.file_exists(paths[i])) {
- return paths[i];
- }
- }
-
- // We were not able to find the texture in the common locations,
- // try to find it into the project globally.
- // The common textures can be stored into one of those folders:
- // res://asset
- // res://texture
- // res://material
- // res://mat
- // res://image
- // res://picture
- //
- // Note the folders can also be called with custom names, like:
- // res://my_assets
- // since the keyword `asset` is into the directory name the textures will be
- // searched there too.
-
- dir.open("res://");
- dir.list_dir_begin();
- String n = dir.get_next();
- while (!n.is_empty()) {
- if (n == "." || n == "..") {
- n = dir.get_next();
- continue;
- }
- if (dir.current_is_dir()) {
- const String lower_n = n.to_lower();
- if (
- // Don't need to use plural.
- lower_n.find("asset") >= 0 ||
- lower_n.find("texture") >= 0 ||
- lower_n.find("material") >= 0 ||
- lower_n.find("mat") >= 0 ||
- lower_n.find("image") >= 0 ||
- lower_n.find("picture") >= 0) {
- // Don't use `path_to` or the returned path will be wrong.
- const String f = find_file(String("res://") + n, p_filename);
- if (!f.is_empty()) {
- return f;
- }
- }
- }
- n = dir.get_next();
- }
- dir.list_dir_end();
-
- return "";
-}
-
-template <class T>
-T extract_from_prop(FBXDocParser::PropertyPtr prop, const T &p_default, const std::string &p_name, const String &p_type) {
- ERR_FAIL_COND_V_MSG(prop == nullptr, p_default, "invalid property passed to extractor");
- const FBXDocParser::TypedProperty<T> *val = dynamic_cast<const FBXDocParser::TypedProperty<T> *>(prop);
-
- ERR_FAIL_COND_V_MSG(val == nullptr, p_default, "The FBX is corrupted, the property `" + String(p_name.c_str()) + "` is a `" + String(typeid(*prop).name()) + "` but should be a " + p_type);
- // Make sure to not lost any eventual opacity.
- return val->Value();
-}
-
-Ref<StandardMaterial3D> FBXMaterial::import_material(ImportState &state) {
- ERR_FAIL_COND_V(material == nullptr, nullptr);
-
- const String p_fbx_current_directory = state.path;
-
- Ref<StandardMaterial3D> spatial_material;
- spatial_material.instantiate();
-
- // read the material file
- // is material two sided
- // read material name
- print_verbose("[material] material name: " + ImportUtils::FBXNodeToName(material->Name()));
-
- material_name = ImportUtils::FBXNodeToName(material->Name());
-
- for (const std::pair<std::string, const FBXDocParser::Texture *> iter : material->Textures()) {
- const uint64_t texture_id = iter.second->ID();
- const std::string &fbx_mapping_name = iter.first;
- const FBXDocParser::Texture *fbx_texture_data = iter.second;
- const String absolute_texture_path = iter.second->FileName().c_str();
- const String texture_name = absolute_texture_path.get_file();
- const String file_extension = absolute_texture_path.get_extension().to_upper();
-
- const String debug_string = "texture id: " + itos(texture_id) + " texture name: " + String(iter.second->Name().c_str()) + " mapping name: " + String(fbx_mapping_name.c_str());
- // remember errors STILL need this string at the end for when you aren't in verbose debug mode :) they need context for when you're not verbose-ing.
- print_verbose(debug_string);
-
- const String file_extension_uppercase = file_extension.to_upper();
-
- if (fbx_transparency_flags.count(fbx_mapping_name) > 0) {
- // just enable it later let's make this fine-tuned.
- spatial_material->set_transparency(BaseMaterial3D::TRANSPARENCY_ALPHA);
- }
-
- ERR_CONTINUE_MSG(file_extension.is_empty(), "your texture has no file extension so we had to ignore it, let us know if you think this is wrong file an issue on github! " + debug_string);
- ERR_CONTINUE_MSG(fbx_texture_map.count(fbx_mapping_name) <= 0, "This material has a texture with mapping name: " + String(fbx_mapping_name.c_str()) + " which is not yet supported by this importer. Consider opening an issue so we can support it.");
- ERR_CONTINUE_MSG(
- file_extension_uppercase != "PNG" &&
- file_extension_uppercase != "JPEG" &&
- file_extension_uppercase != "JPG" &&
- file_extension_uppercase != "TGA" &&
- file_extension_uppercase != "WEBP" &&
- file_extension_uppercase != "DDS",
- "The FBX file contains a texture with an unrecognized extension: " + file_extension_uppercase);
-
- print_verbose("Getting FBX mapping mode for " + String(fbx_mapping_name.c_str()));
- // get the texture map type
- const StandardMaterial3D::TextureParam mapping_mode = fbx_texture_map.at(fbx_mapping_name);
- print_verbose("Set FBX mapping mode to " + get_texture_param_name(mapping_mode));
-
- Ref<Texture> texture;
- print_verbose("texture mapping name: " + texture_name);
-
- if (state.cached_image_searches.has(texture_name)) {
- texture = state.cached_image_searches[texture_name];
- } else {
- String path = find_texture_path_by_filename(texture_name, p_fbx_current_directory);
- if (!path.is_empty()) {
- Ref<Texture2D> image_texture = ResourceLoader::load(path);
-
- ERR_CONTINUE(image_texture.is_null());
-
- texture = image_texture;
- state.cached_image_searches.insert(texture_name, texture);
- print_verbose("Created texture from loaded image file.");
-
- } else if (fbx_texture_data != nullptr && fbx_texture_data->Media() != nullptr && fbx_texture_data->Media()->IsEmbedded()) {
- // This is an embedded texture. Extract it.
- Ref<Image> image;
- //image.instantiate(); // oooo double instance bug? why make Image::_png_blah call
-
- const String extension = texture_name.get_extension().to_upper();
- if (extension == "PNG") {
- // The stored file is a PNG.
- image = Image::_png_mem_loader_func(fbx_texture_data->Media()->Content(), fbx_texture_data->Media()->ContentLength());
- ERR_CONTINUE_MSG(image.is_valid() == false, "FBX Embedded PNG image load fail.");
-
- } else if (
- extension == "JPEG" ||
- extension == "JPG") {
- // The stored file is a JPEG.
- image = Image::_jpg_mem_loader_func(fbx_texture_data->Media()->Content(), fbx_texture_data->Media()->ContentLength());
- ERR_CONTINUE_MSG(image.is_valid() == false, "FBX Embedded JPEG image load fail.");
-
- } else if (extension == "TGA") {
- // The stored file is a TGA.
- image = Image::_tga_mem_loader_func(fbx_texture_data->Media()->Content(), fbx_texture_data->Media()->ContentLength());
- ERR_CONTINUE_MSG(image.is_valid() == false, "FBX Embedded TGA image load fail.");
-
- } else if (extension == "WEBP") {
- // The stored file is a WEBP.
- image = Image::_webp_mem_loader_func(fbx_texture_data->Media()->Content(), fbx_texture_data->Media()->ContentLength());
- ERR_CONTINUE_MSG(image.is_valid() == false, "FBX Embedded WEBP image load fail.");
-
- // } else if (extension == "DDS") {
- // // In this moment is not possible to extract a DDS from a buffer, TODO consider add it to godot. See `textureloader_dds.cpp::load().
- // // The stored file is a DDS.
- } else {
- ERR_CONTINUE_MSG(true, "The embedded image with extension: " + extension + " is not yet supported. Open an issue please.");
- }
-
- Ref<ImageTexture> image_texture;
- image_texture.instantiate();
- image_texture->create_from_image(image);
-
- texture = image_texture;
-
- // TODO: this is potentially making something with the same name have a match incorrectly USE FBX ID as Hash. #fuck it later.
- state.cached_image_searches[texture_name] = texture;
- print_verbose("Created texture from embedded image.");
- } else {
- ERR_CONTINUE_MSG(true, "The FBX texture, with name: `" + texture_name + "`, is not found into the project nor is stored as embedded file. Make sure to insert the texture as embedded file or into the project, then reimport.");
- }
- }
-
- spatial_material->set_texture(mapping_mode, texture);
- }
-
- if (spatial_material.is_valid()) {
- spatial_material->set_name(material_name);
- }
-
- /// ALL below is related to properties
- for (FBXDocParser::LazyPropertyMap::value_type iter : material->GetLazyProperties()) {
- const std::string name = iter.first;
-
- if (name.empty()) {
- continue;
- }
-
- PropertyDesc desc = PROPERTY_DESC_NOT_FOUND;
- if (fbx_properties_desc.count(name) > 0) {
- desc = fbx_properties_desc.at(name);
- }
-
- // check if we can ignore this it will be done at the next phase
- if (desc == PROPERTY_DESC_NOT_FOUND || desc == PROPERTY_DESC_IGNORE) {
- // count the texture mapping references. Skip this one if it's found and we can't look up a property value.
- if (fbx_texture_map.count(name) > 0) {
- continue; // safe to ignore it's a texture mapping.
- }
- }
-
- if (desc == PROPERTY_DESC_IGNORE) {
- //WARN_PRINT("[Ignored] The FBX material parameter: `" + String(name.c_str()) + "` is ignored.");
- continue;
- } else {
- print_verbose("FBX Material parameter: " + String(name.c_str()));
-
- // Check for Diffuse material system / lambert materials / legacy basically
- if (name == "Diffuse" && !warning_non_pbr_material) {
- ValidationTracker::get_singleton()->add_validation_error(state.path, "Invalid material settings change to Ai Standard Surface shader, mat name: " + material_name.c_escape());
- warning_non_pbr_material = true;
- }
- }
-
- // DISABLE when adding support for all weird and wonderful material formats
- if (desc == PROPERTY_DESC_NOT_FOUND) {
- continue;
- }
-
- ERR_CONTINUE_MSG(desc == PROPERTY_DESC_NOT_FOUND, "The FBX material parameter: `" + String(name.c_str()) + "` was not recognized. Please open an issue so we can add the support to it.");
-
- const FBXDocParser::PropertyTable *tbl = material;
- FBXDocParser::PropertyPtr prop = tbl->Get(name);
-
- ERR_CONTINUE_MSG(prop == nullptr, "This file may be corrupted because is not possible to extract the material parameter: " + String(name.c_str()));
-
- if (spatial_material.is_null()) {
- // Done here so if no data no material is created.
- spatial_material.instantiate();
- }
-
- const FBXDocParser::TypedProperty<real_t> *real_value = dynamic_cast<const FBXDocParser::TypedProperty<real_t> *>(prop);
- const FBXDocParser::TypedProperty<Vector3> *vector_value = dynamic_cast<const FBXDocParser::TypedProperty<Vector3> *>(prop);
-
- if (!real_value && !vector_value) {
- //WARN_PRINT("unsupported datatype in property: " + String(name.c_str()));
- continue;
- }
-
- if (vector_value && !real_value) {
- if (vector_value->Value() == Vector3(0, 0, 0) && !real_value) {
- continue;
- }
- }
-
- switch (desc) {
- case PROPERTY_DESC_ALBEDO_COLOR: {
- if (vector_value) {
- const Vector3 &color = vector_value->Value();
- // Make sure to not lost any eventual opacity.
- if (color != Vector3(0, 0, 0)) {
- Color c = Color();
- c[0] = color[0];
- c[1] = color[1];
- c[2] = color[2];
- spatial_material->set_albedo(c);
- }
-
- } else if (real_value) {
- print_error("albedo is unsupported format?");
- }
- } break;
- case PROPERTY_DESC_TRANSPARENT: {
- if (real_value) {
- const real_t opacity = real_value->Value();
- if (opacity < (1.0 - CMP_EPSILON)) {
- Color c = spatial_material->get_albedo();
- c.a = opacity;
- spatial_material->set_albedo(c);
-
- spatial_material->set_transparency(BaseMaterial3D::TRANSPARENCY_ALPHA);
- spatial_material->set_depth_draw_mode(BaseMaterial3D::DEPTH_DRAW_OPAQUE_ONLY);
- }
- } else if (vector_value) {
- print_error("unsupported transparent desc type vector!");
- }
- } break;
- case PROPERTY_DESC_SPECULAR: {
- if (real_value) {
- print_verbose("specular real value: " + rtos(real_value->Value()));
- spatial_material->set_specular(MIN(1.0, real_value->Value()));
- }
-
- if (vector_value) {
- print_error("unsupported specular vector value: " + vector_value->Value());
- }
- } break;
-
- case PROPERTY_DESC_SPECULAR_COLOR: {
- if (vector_value) {
- print_error("unsupported specular color: " + vector_value->Value());
- }
- } break;
- case PROPERTY_DESC_SHINYNESS: {
- if (real_value) {
- print_error("unsupported shinyness:" + rtos(real_value->Value()));
- }
- } break;
- case PROPERTY_DESC_METALLIC: {
- if (real_value) {
- print_verbose("metallic real value: " + rtos(real_value->Value()));
- spatial_material->set_metallic(MIN(1.0f, real_value->Value()));
- } else {
- print_error("unsupported value type for metallic");
- }
- } break;
- case PROPERTY_DESC_ROUGHNESS: {
- if (real_value) {
- print_verbose("roughness real value: " + rtos(real_value->Value()));
- spatial_material->set_roughness(MIN(1.0f, real_value->Value()));
- } else {
- print_error("unsupported value type for roughness");
- }
- } break;
- case PROPERTY_DESC_COAT: {
- if (real_value) {
- print_verbose("clearcoat real value: " + rtos(real_value->Value()));
- spatial_material->set_clearcoat(MIN(1.0f, real_value->Value()));
- } else {
- print_error("unsupported value type for clearcoat");
- }
- } break;
- case PROPERTY_DESC_COAT_ROUGHNESS: {
- // meaning is that approx equal to zero is disabled not actually zero. ;)
- if (real_value && Math::is_zero_approx(real_value->Value())) {
- print_verbose("clearcoat real value: " + rtos(real_value->Value()));
- spatial_material->set_clearcoat_roughness(real_value->Value());
- } else {
- print_error("unsupported value type for clearcoat gloss");
- }
- } break;
- case PROPERTY_DESC_EMISSIVE: {
- if (real_value && Math::is_zero_approx(real_value->Value())) {
- print_verbose("Emissive real value: " + rtos(real_value->Value()));
- spatial_material->set_emission_energy(real_value->Value());
- } else if (vector_value && !vector_value->Value().is_equal_approx(Vector3(0, 0, 0))) {
- const Vector3 &color = vector_value->Value();
- Color c;
- c[0] = color[0];
- c[1] = color[1];
- c[2] = color[2];
- spatial_material->set_emission(c);
- }
- } break;
- case PROPERTY_DESC_EMISSIVE_COLOR: {
- if (vector_value && !vector_value->Value().is_equal_approx(Vector3(0, 0, 0))) {
- const Vector3 &color = vector_value->Value();
- Color c;
- c[0] = color[0];
- c[1] = color[1];
- c[2] = color[2];
- spatial_material->set_emission(c);
- } else {
- print_error("unsupported value type for emissive color");
- }
- } break;
- case PROPERTY_DESC_NOT_FOUND:
- case PROPERTY_DESC_IGNORE:
- break;
- default:
- break;
- }
- }
-
- return spatial_material;
-}
diff --git a/modules/fbx/data/fbx_material.h b/modules/fbx/data/fbx_material.h
deleted file mode 100644
index e20b43561b..0000000000
--- a/modules/fbx/data/fbx_material.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/*************************************************************************/
-/* fbx_material.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. */
-/*************************************************************************/
-
-#ifndef FBX_MATERIAL_H
-#define FBX_MATERIAL_H
-
-#include "tools/import_utils.h"
-
-#include "core/object/ref_counted.h"
-#include "core/string/ustring.h"
-
-struct FBXMaterial : public RefCounted {
- String material_name = String();
- bool warning_non_pbr_material = false;
- FBXDocParser::Material *material = nullptr;
-
- /* Godot materials
- *** Texture Maps:
- * Albedo - color, texture
- * Metallic - specular, metallic, texture
- * Roughness - roughness, texture
- * Emission - color, texture
- * Normal Map - scale, texture
- * Ambient Occlusion - texture
- * Refraction - scale, texture
- *** Has Settings for:
- * UV1 - SCALE, OFFSET
- * UV2 - SCALE, OFFSET
- *** Flags for
- * Transparent
- * Cull Mode
- */
-
- enum class MapMode {
- AlbedoM = 0,
- MetallicM,
- SpecularM,
- EmissionM,
- RoughnessM,
- NormalM,
- AmbientOcclusionM,
- RefractionM,
- ReflectionM,
- };
-
- /* Returns the string representation of the TextureParam enum */
- static String get_texture_param_name(StandardMaterial3D::TextureParam param) {
- switch (param) {
- case StandardMaterial3D::TEXTURE_ALBEDO:
- return "TEXTURE_ALBEDO";
- case StandardMaterial3D::TEXTURE_METALLIC:
- return "TEXTURE_METALLIC";
- case StandardMaterial3D::TEXTURE_ROUGHNESS:
- return "TEXTURE_ROUGHNESS";
- case StandardMaterial3D::TEXTURE_EMISSION:
- return "TEXTURE_EMISSION";
- case StandardMaterial3D::TEXTURE_NORMAL:
- return "TEXTURE_NORMAL";
- case StandardMaterial3D::TEXTURE_RIM:
- return "TEXTURE_RIM";
- case StandardMaterial3D::TEXTURE_CLEARCOAT:
- return "TEXTURE_CLEARCOAT";
- case StandardMaterial3D::TEXTURE_FLOWMAP:
- return "TEXTURE_FLOWMAP";
- case StandardMaterial3D::TEXTURE_AMBIENT_OCCLUSION:
- return "TEXTURE_AMBIENT_OCCLUSION";
- // case StandardMaterial3D::TEXTURE_DEPTH: // TODO: work out how to make this function again!
- // return "TEXTURE_DEPTH";
- case StandardMaterial3D::TEXTURE_SUBSURFACE_SCATTERING:
- return "TEXTURE_SUBSURFACE_SCATTERING";
- // case StandardMaterial3D::TEXTURE_TRANSMISSION: // TODO: work out how to make this function again!
- // return "TEXTURE_TRANSMISSION";
- case StandardMaterial3D::TEXTURE_REFRACTION:
- return "TEXTURE_REFRACTION";
- case StandardMaterial3D::TEXTURE_DETAIL_MASK:
- return "TEXTURE_DETAIL_MASK";
- case StandardMaterial3D::TEXTURE_DETAIL_ALBEDO:
- return "TEXTURE_DETAIL_ALBEDO";
- case StandardMaterial3D::TEXTURE_DETAIL_NORMAL:
- return "TEXTURE_DETAIL_NORMAL";
- case StandardMaterial3D::TEXTURE_MAX:
- return "TEXTURE_MAX";
- default:
- return "broken horribly";
- }
- };
-
- // TODO make this static?
- const std::map<std::string, bool> fbx_transparency_flags = {
- /* Transparent */
- { "TransparentColor", true },
- { "Maya|opacity", true }
- };
-
- // TODO make this static?
- const std::map<std::string, StandardMaterial3D::TextureParam> fbx_texture_map = {
- /* Diffuse */
- { "Maya|base", StandardMaterial3D::TextureParam::TEXTURE_ALBEDO },
- { "DiffuseColor", StandardMaterial3D::TextureParam::TEXTURE_ALBEDO },
- { "Maya|DiffuseTexture", StandardMaterial3D::TextureParam::TEXTURE_ALBEDO },
- { "Maya|baseColor", StandardMaterial3D::TextureParam::TEXTURE_ALBEDO },
- { "Maya|baseColor|file", StandardMaterial3D::TextureParam::TEXTURE_ALBEDO },
- { "3dsMax|Parameters|base_color_map", StandardMaterial3D::TextureParam::TEXTURE_ALBEDO },
- { "Maya|TEX_color_map|file", StandardMaterial3D::TextureParam::TEXTURE_ALBEDO },
- { "Maya|TEX_color_map", StandardMaterial3D::TextureParam::TEXTURE_ALBEDO },
- /* Emission */
- { "EmissiveColor", StandardMaterial3D::TextureParam::TEXTURE_EMISSION },
- { "EmissiveFactor", StandardMaterial3D::TextureParam::TEXTURE_EMISSION },
- { "Maya|emissionColor", StandardMaterial3D::TextureParam::TEXTURE_EMISSION },
- { "Maya|emissionColor|file", StandardMaterial3D::TextureParam::TEXTURE_EMISSION },
- { "3dsMax|Parameters|emission_map", StandardMaterial3D::TextureParam::TEXTURE_EMISSION },
- { "Maya|TEX_emissive_map", StandardMaterial3D::TextureParam::TEXTURE_EMISSION },
- { "Maya|TEX_emissive_map|file", StandardMaterial3D::TextureParam::TEXTURE_EMISSION },
- /* Metallic */
- { "Maya|metalness", StandardMaterial3D::TextureParam::TEXTURE_METALLIC },
- { "Maya|metalness|file", StandardMaterial3D::TextureParam::TEXTURE_METALLIC },
- { "3dsMax|Parameters|metalness_map", StandardMaterial3D::TextureParam::TEXTURE_METALLIC },
- { "Maya|TEX_metallic_map", StandardMaterial3D::TextureParam::TEXTURE_METALLIC },
- { "Maya|TEX_metallic_map|file", StandardMaterial3D::TextureParam::TEXTURE_METALLIC },
-
- /* Roughness */
- // Arnold Roughness Map
- { "Maya|specularRoughness", StandardMaterial3D::TextureParam::TEXTURE_ROUGHNESS },
-
- { "3dsMax|Parameters|roughness_map", StandardMaterial3D::TextureParam::TEXTURE_ROUGHNESS },
- { "Maya|TEX_roughness_map", StandardMaterial3D::TextureParam::TEXTURE_ROUGHNESS },
- { "Maya|TEX_roughness_map|file", StandardMaterial3D::TextureParam::TEXTURE_ROUGHNESS },
-
- /* Normal */
- { "NormalMap", StandardMaterial3D::TextureParam::TEXTURE_NORMAL },
- //{ "Bump", Material::TextureParam::TEXTURE_NORMAL },
- //{ "3dsMax|Parameters|bump_map", Material::TextureParam::TEXTURE_NORMAL },
- { "Maya|NormalTexture", StandardMaterial3D::TextureParam::TEXTURE_NORMAL },
- //{ "Maya|normalCamera", Material::TextureParam::TEXTURE_NORMAL },
- //{ "Maya|normalCamera|file", Material::TextureParam::TEXTURE_NORMAL },
- { "Maya|TEX_normal_map", StandardMaterial3D::TextureParam::TEXTURE_NORMAL },
- { "Maya|TEX_normal_map|file", StandardMaterial3D::TextureParam::TEXTURE_NORMAL },
- /* AO */
- { "Maya|TEX_ao_map", StandardMaterial3D::TextureParam::TEXTURE_AMBIENT_OCCLUSION },
- { "Maya|TEX_ao_map|file", StandardMaterial3D::TextureParam::TEXTURE_AMBIENT_OCCLUSION },
-
- // TODO: specular workflow conversion
- // { "SpecularColor", StandardMaterial3D::TextureParam::TEXTURE_METALLIC },
- // { "Maya|specularColor", StandardMaterial3D::TextureParam::TEXTURE_METALLIC },
- // { "Maya|SpecularTexture", StandardMaterial3D::TextureParam::TEXTURE_METALLIC },
- // { "Maya|SpecularTexture|file", StandardMaterial3D::TextureParam::TEXTURE_METALLIC },
- // { "ShininessExponent", SpatialMaterial::TextureParam::UNSUPPORTED },
- // { "ReflectionFactor", SpatialMaterial::TextureParam::UNSUPPORTED },
-
- //{ "TransparentColor",SpatialMaterial::TextureParam::TEXTURE_CHANNEL_ALPHA },
- //{ "TransparencyFactor",SpatialMaterial::TextureParam::TEXTURE_CHANNEL_ALPHA }
-
- // TODO: diffuse roughness
- //{ "Maya|diffuseRoughness", SpatialMaterial::TextureParam::UNSUPPORTED },
- //{ "Maya|diffuseRoughness|file", SpatialMaterial::TextureParam::UNSUPPORTED },
-
- };
-
- // TODO make this static?
- enum PropertyDesc {
- PROPERTY_DESC_NOT_FOUND,
- PROPERTY_DESC_ALBEDO_COLOR,
- PROPERTY_DESC_TRANSPARENT,
- PROPERTY_DESC_METALLIC,
- PROPERTY_DESC_ROUGHNESS,
- PROPERTY_DESC_SPECULAR,
- PROPERTY_DESC_SPECULAR_COLOR,
- PROPERTY_DESC_SHINYNESS,
- PROPERTY_DESC_COAT,
- PROPERTY_DESC_COAT_ROUGHNESS,
- PROPERTY_DESC_EMISSIVE,
- PROPERTY_DESC_EMISSIVE_COLOR,
- PROPERTY_DESC_IGNORE
- };
-
- const std::map<std::string, PropertyDesc> fbx_properties_desc = {
- /* Albedo */
- { "DiffuseColor", PROPERTY_DESC_ALBEDO_COLOR },
- { "Maya|baseColor", PROPERTY_DESC_ALBEDO_COLOR },
-
- /* Specular */
- { "Maya|specular", PROPERTY_DESC_SPECULAR },
- { "Maya|specularColor", PROPERTY_DESC_SPECULAR_COLOR },
-
- /* Specular roughness - arnold roughness map */
- { "Maya|specularRoughness", PROPERTY_DESC_ROUGHNESS },
-
- /* Transparent */
- { "Opacity", PROPERTY_DESC_TRANSPARENT },
- { "TransparencyFactor", PROPERTY_DESC_TRANSPARENT },
- { "Maya|opacity", PROPERTY_DESC_TRANSPARENT },
-
- { "Maya|metalness", PROPERTY_DESC_METALLIC },
- { "Maya|metallic", PROPERTY_DESC_METALLIC },
-
- /* Roughness */
- { "Maya|roughness", PROPERTY_DESC_ROUGHNESS },
-
- /* Coat */
- //{ "Maya|coat", PROPERTY_DESC_COAT },
-
- /* Coat roughness */
- //{ "Maya|coatRoughness", PROPERTY_DESC_COAT_ROUGHNESS },
-
- /* Emissive */
- { "Maya|emission", PROPERTY_DESC_EMISSIVE },
- { "Maya|emissive", PROPERTY_DESC_EMISSIVE },
-
- /* Emissive color */
- { "EmissiveColor", PROPERTY_DESC_EMISSIVE_COLOR },
- { "Maya|emissionColor", PROPERTY_DESC_EMISSIVE_COLOR },
-
- /* Ignore */
- { "Shininess", PROPERTY_DESC_IGNORE },
- { "Reflectivity", PROPERTY_DESC_IGNORE },
- { "Maya|diffuseRoughness", PROPERTY_DESC_IGNORE },
- { "Maya", PROPERTY_DESC_IGNORE },
- { "Diffuse", PROPERTY_DESC_ALBEDO_COLOR },
- { "Maya|TypeId", PROPERTY_DESC_IGNORE },
- { "Ambient", PROPERTY_DESC_IGNORE },
- { "AmbientColor", PROPERTY_DESC_IGNORE },
- { "ShininessExponent", PROPERTY_DESC_IGNORE },
- { "Specular", PROPERTY_DESC_IGNORE },
- { "SpecularColor", PROPERTY_DESC_IGNORE },
- { "SpecularFactor", PROPERTY_DESC_IGNORE },
- //{ "BumpFactor", PROPERTY_DESC_IGNORE },
- { "Maya|exitToBackground", PROPERTY_DESC_IGNORE },
- { "Maya|indirectDiffuse", PROPERTY_DESC_IGNORE },
- { "Maya|indirectSpecular", PROPERTY_DESC_IGNORE },
- { "Maya|internalReflections", PROPERTY_DESC_IGNORE },
- { "DiffuseFactor", PROPERTY_DESC_IGNORE },
- { "AmbientFactor", PROPERTY_DESC_IGNORE },
- { "ReflectionColor", PROPERTY_DESC_IGNORE },
- { "Emissive", PROPERTY_DESC_IGNORE },
- { "Maya|coatColor", PROPERTY_DESC_IGNORE },
- { "Maya|coatNormal", PROPERTY_DESC_IGNORE },
- { "Maya|coatIOR", PROPERTY_DESC_IGNORE },
- };
-
- /* storing the texture properties like color */
- template <class T>
- struct TexturePropertyMapping : RefCounted {
- StandardMaterial3D::TextureParam map_mode = StandardMaterial3D::TextureParam::TEXTURE_ALBEDO;
- const T property = T();
- };
-
- static void add_search_string(String p_filename, String p_current_directory, String search_directory, Vector<String> &texture_search_paths);
-
- static String find_texture_path_by_filename(const String p_filename, const String p_current_directory);
-
- String get_material_name() const;
-
- void set_imported_material(FBXDocParser::Material *p_material);
-
- Ref<StandardMaterial3D> import_material(ImportState &state);
-};
-
-#endif // FBX_MATERIAL_H
diff --git a/modules/fbx/data/fbx_mesh_data.cpp b/modules/fbx/data/fbx_mesh_data.cpp
deleted file mode 100644
index 1d59851778..0000000000
--- a/modules/fbx/data/fbx_mesh_data.cpp
+++ /dev/null
@@ -1,1446 +0,0 @@
-/*************************************************************************/
-/* fbx_mesh_data.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 "fbx_mesh_data.h"
-
-#include "core/templates/local_vector.h"
-#include "scene/resources/importer_mesh.h"
-#include "scene/resources/mesh.h"
-#include "scene/resources/surface_tool.h"
-
-#include "thirdparty/misc/polypartition.h"
-
-template <class T>
-T collect_first(const Vector<VertexData<T>> *p_data, T p_fall_back) {
- if (p_data->is_empty()) {
- return p_fall_back;
- }
-
- return (*p_data)[0].data;
-}
-
-template <class T>
-HashMap<int, T> collect_all(const Vector<VertexData<T>> *p_data, HashMap<int, T> p_fall_back) {
- if (p_data->is_empty()) {
- return p_fall_back;
- }
-
- HashMap<int, T> collection;
- for (int i = 0; i < p_data->size(); i += 1) {
- const VertexData<T> &vd = (*p_data)[i];
- collection[vd.polygon_index] = vd.data;
- }
- return collection;
-}
-
-template <class T>
-T collect_average(const Vector<VertexData<T>> *p_data, T p_fall_back) {
- if (p_data->is_empty()) {
- return p_fall_back;
- }
-
- T combined = (*p_data)[0].data; // Make sure the data is always correctly initialized.
- print_verbose("size of data: " + itos(p_data->size()));
- for (int i = 1; i < p_data->size(); i += 1) {
- combined += (*p_data)[i].data;
- }
- combined = combined / real_t(p_data->size());
-
- return combined.normalized();
-}
-
-HashMap<int, Vector3> collect_normal(const Vector<VertexData<Vector3>> *p_data, HashMap<int, Vector3> p_fall_back) {
- if (p_data->is_empty()) {
- return p_fall_back;
- }
-
- HashMap<int, Vector3> collection;
- for (int i = 0; i < p_data->size(); i += 1) {
- const VertexData<Vector3> &vd = (*p_data)[i];
- collection[vd.polygon_index] = vd.data;
- }
- return collection;
-}
-
-HashMap<int, Vector2> collect_uv(const Vector<VertexData<Vector2>> *p_data, HashMap<int, Vector2> p_fall_back) {
- if (p_data->is_empty()) {
- return p_fall_back;
- }
-
- HashMap<int, Vector2> collection;
- for (int i = 0; i < p_data->size(); i += 1) {
- const VertexData<Vector2> &vd = (*p_data)[i];
- collection[vd.polygon_index] = vd.data;
- }
- return collection;
-}
-
-ImporterMeshInstance3D *FBXMeshData::create_fbx_mesh(const ImportState &state, const FBXDocParser::MeshGeometry *p_mesh_geometry, const FBXDocParser::Model *model, bool use_compression) {
- mesh_geometry = p_mesh_geometry;
- // todo: make this just use a uint64_t FBX ID this is a copy of our original materials unfortunately.
- const std::vector<const FBXDocParser::Material *> &material_lookup = model->GetMaterials();
-
- // TODO: perf hotspot on large files
- // this can be a very large copy
- std::vector<int> polygon_indices = mesh_geometry->get_polygon_indices();
- std::vector<Vector3> vertices = mesh_geometry->get_vertices();
-
- // Phase 1. Parse all FBX data.
- HashMap<int, Vector3> normals;
- HashMap<int, HashMap<int, Vector3>> normals_raw = extract_per_vertex_data(
- vertices.size(),
- mesh_geometry->get_edge_map(),
- polygon_indices,
- mesh_geometry->get_normals(),
- &collect_all,
- HashMap<int, Vector3>());
-
- HashMap<int, Vector2> uvs_0;
- HashMap<int, HashMap<int, Vector2>> uvs_0_raw = extract_per_vertex_data(
- vertices.size(),
- mesh_geometry->get_edge_map(),
- polygon_indices,
- mesh_geometry->get_uv_0(),
- &collect_all,
- HashMap<int, Vector2>());
-
- HashMap<int, Vector2> uvs_1;
- HashMap<int, HashMap<int, Vector2>> uvs_1_raw = extract_per_vertex_data(
- vertices.size(),
- mesh_geometry->get_edge_map(),
- polygon_indices,
- mesh_geometry->get_uv_1(),
- &collect_all,
- HashMap<int, Vector2>());
-
- HashMap<int, Color> colors;
- HashMap<int, HashMap<int, Color>> colors_raw = extract_per_vertex_data(
- vertices.size(),
- mesh_geometry->get_edge_map(),
- polygon_indices,
- mesh_geometry->get_colors(),
- &collect_all,
- HashMap<int, Color>());
-
- // TODO what about tangents?
- // TODO what about bi-nomials?
- // TODO there is other?
-
- HashMap<int, SurfaceId> polygon_surfaces = extract_per_polygon(
- vertices.size(),
- polygon_indices,
- mesh_geometry->get_material_allocation_id(),
- -1);
-
- HashMap<String, MorphVertexData> morphs;
- extract_morphs(mesh_geometry, morphs);
-
- // TODO please add skinning.
- //mesh_id = mesh_geometry->ID();
-
- sanitize_vertex_weights(state);
-
- // Reorganize polygon vertices to correctly take into account strange
- // UVs.
- reorganize_vertices(
- polygon_indices,
- vertices,
- normals,
- uvs_0,
- uvs_1,
- colors,
- morphs,
- normals_raw,
- colors_raw,
- uvs_0_raw,
- uvs_1_raw);
-
- const int color_count = colors.size();
- print_verbose("Vertex color count: " + itos(color_count));
-
- // Make sure that from this moment on the mesh_geometry is no used anymore.
- // This is a safety step, because the mesh_geometry data are no more valid
- // at this point.
-
- const int vertex_count = vertices.size();
-
- print_verbose("Vertex count: " + itos(vertex_count));
-
- // The map key is the material allocator id that is also used as surface id.
- HashMap<SurfaceId, SurfaceData> surfaces;
-
- // Phase 2. For each material create a surface tool (So a different mesh).
- {
- if (polygon_surfaces.is_empty()) {
- // No material, just use the default one with index -1.
- // Set -1 to all polygons.
- const int polygon_count = count_polygons(polygon_indices);
- for (int p = 0; p < polygon_count; p += 1) {
- polygon_surfaces[p] = -1;
- }
- }
-
- // Create the surface now.
- for (const int *polygon_id = polygon_surfaces.next(nullptr); polygon_id != nullptr; polygon_id = polygon_surfaces.next(polygon_id)) {
- const int surface_id = polygon_surfaces[*polygon_id];
- if (surfaces.has(surface_id) == false) {
- SurfaceData sd;
- sd.surface_tool.instantiate();
- sd.surface_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
-
- if (surface_id < 0) {
- // nothing to do
- } else if (surface_id < (int)material_lookup.size()) {
- const FBXDocParser::Material *mat_mapping = material_lookup.at(surface_id);
- const uint64_t mapping_id = mat_mapping->ID();
- if (state.cached_materials.has(mapping_id)) {
- sd.material = state.cached_materials[mapping_id];
- }
- } else {
- WARN_PRINT("out of bounds surface detected, FBX file has corrupt material data");
- }
-
- surfaces.set(surface_id, sd);
- }
- }
- }
-
- // Phase 3. Map the vertices relative to each surface, in this way we can
- // just insert the vertices that we need per each surface.
- {
- PolygonId polygon_index = -1;
- SurfaceId surface_id = -1;
- SurfaceData *surface_data = nullptr;
-
- for (size_t polygon_vertex = 0; polygon_vertex < polygon_indices.size(); polygon_vertex += 1) {
- if (is_start_of_polygon(polygon_indices, polygon_vertex)) {
- polygon_index += 1;
- ERR_FAIL_COND_V_MSG(polygon_surfaces.has(polygon_index) == false, nullptr, "The FBX file is corrupted, This surface_index is not expected.");
- surface_id = polygon_surfaces[polygon_index];
- surface_data = surfaces.getptr(surface_id);
- CRASH_COND(surface_data == nullptr); // Can't be null.
- }
-
- const int vertex = get_vertex_from_polygon_vertex(polygon_indices, polygon_vertex);
-
- // The vertex position in the surface
- // Uses a lookup table for speed with large scenes
- bool has_polygon_vertex_index = surface_data->lookup_table.has(vertex);
- int surface_polygon_vertex_index = -1;
-
- if (has_polygon_vertex_index) {
- surface_polygon_vertex_index = surface_data->lookup_table[vertex];
- } else {
- surface_polygon_vertex_index = surface_data->vertices_map.size();
- surface_data->lookup_table[vertex] = surface_polygon_vertex_index;
- surface_data->vertices_map.push_back(vertex);
- }
-
- surface_data->surface_polygon_vertex[polygon_index].push_back(surface_polygon_vertex_index);
- }
- }
-
- //print_verbose("[debug UV 1] UV1: " + itos(uvs_0.size()));
- //print_verbose("[debug UV 2] UV2: " + itos(uvs_1.size()));
-
- // Phase 4. Per each surface just insert the vertices and add the indices.
- for (const SurfaceId *surface_id = surfaces.next(nullptr); surface_id != nullptr; surface_id = surfaces.next(surface_id)) {
- SurfaceData *surface = surfaces.getptr(*surface_id);
-
- // Just add the vertices data.
- for (unsigned int i = 0; i < surface->vertices_map.size(); i += 1) {
- const Vertex vertex = surface->vertices_map[i];
-
- // This must be done before add_vertex because the surface tool is
- // expecting this before the st->add_vertex() call
- add_vertex(state,
- surface->surface_tool,
- state.scale,
- vertex,
- vertices,
- normals,
- uvs_0,
- uvs_1,
- colors);
- }
-
- // Triangulate the various polygons and add the indices.
- for (const PolygonId *polygon_id = surface->surface_polygon_vertex.next(nullptr); polygon_id != nullptr; polygon_id = surface->surface_polygon_vertex.next(polygon_id)) {
- const Vector<DataIndex> *indices = surface->surface_polygon_vertex.getptr(*polygon_id);
- triangulate_polygon(
- surface,
- *indices,
- vertices);
- }
- }
-
- // Phase 5. Compose the morphs if any.
- for (const SurfaceId *surface_id = surfaces.next(nullptr); surface_id != nullptr; surface_id = surfaces.next(surface_id)) {
- SurfaceData *surface = surfaces.getptr(*surface_id);
-
- for (const String *morph_name = morphs.next(nullptr); morph_name != nullptr; morph_name = morphs.next(morph_name)) {
- MorphVertexData *morph_data = morphs.getptr(*morph_name);
-
- // As said by the docs, this is not supposed to be different than
- // vertex_count.
- CRASH_COND(morph_data->vertices.size() != vertex_count);
- CRASH_COND(morph_data->normals.size() != vertex_count);
-
- Vector3 *vertices_ptr = morph_data->vertices.ptrw();
- Vector3 *normals_ptr = morph_data->normals.ptrw();
-
- Ref<SurfaceTool> morph_st;
- morph_st.instantiate();
- morph_st->begin(Mesh::PRIMITIVE_TRIANGLES);
-
- for (unsigned int vi = 0; vi < surface->vertices_map.size(); vi += 1) {
- const Vertex &vertex = surface->vertices_map[vi];
- add_vertex(
- state,
- morph_st,
- state.scale,
- vertex,
- vertices,
- normals,
- uvs_0,
- uvs_1,
- colors,
- vertices_ptr[vertex],
- normals_ptr[vertex]);
- }
-
- if (state.is_blender_fbx) {
- morph_st->generate_normals();
- }
- morph_st->generate_tangents();
- surface->morphs.push_back(morph_st->commit_to_arrays());
- }
- }
-
- // Phase 6. Compose the mesh and return it.
- Ref<ImporterMesh> mesh;
- mesh.instantiate();
-
- // Add blend shape info.
- for (const String *morph_name = morphs.next(nullptr); morph_name != nullptr; morph_name = morphs.next(morph_name)) {
- mesh->add_blend_shape(*morph_name);
- }
-
- // TODO always normalized, Why?
- mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);
-
- // Add surfaces.
- for (const SurfaceId *surface_id = surfaces.next(nullptr); surface_id != nullptr; surface_id = surfaces.next(surface_id)) {
- SurfaceData *surface = surfaces.getptr(*surface_id);
-
- if (state.is_blender_fbx) {
- surface->surface_tool->generate_normals();
- }
- // you can't generate them without a valid uv map.
- if (uvs_0_raw.size() > 0) {
- surface->surface_tool->generate_tangents();
- }
-
- Array mesh_array = surface->surface_tool->commit_to_arrays();
- Array blend_shapes = surface->morphs;
-
- // Enforce blend shape mask array format
- for (int i = 0; i < blend_shapes.size(); i++) {
- Array bsdata = blend_shapes[i];
-
- for (int j = 0; j < Mesh::ARRAY_MAX; j++) {
- if (!(Mesh::ARRAY_FORMAT_BLEND_SHAPE_MASK & (1 << j))) {
- bsdata[j] = Variant();
- }
- }
- }
-
- if (surface->material.is_valid()) {
- mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES, mesh_array, blend_shapes, Dictionary(), surface->material, surface->material->get_name());
- } else {
- mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES, mesh_array, blend_shapes);
- }
- }
-
- ImporterMeshInstance3D *godot_mesh = memnew(ImporterMeshInstance3D);
- godot_mesh->set_mesh(mesh);
- const String name = ImportUtils::FBXNodeToName(model->Name());
- godot_mesh->set_name(name); // hurry up compiling >.<
- mesh->set_name("mesh3d-" + name);
- return godot_mesh;
-}
-
-void FBXMeshData::sanitize_vertex_weights(const ImportState &state) {
- const int max_vertex_influence_count = RS::ARRAY_WEIGHTS_SIZE;
- Map<int, int> skeleton_to_skin_bind_id;
- // TODO: error's need added
- const FBXDocParser::Skin *fbx_skin = mesh_geometry->DeformerSkin();
-
- if (fbx_skin == nullptr || fbx_skin->Clusters().size() == 0) {
- return; // do nothing
- }
-
- //
- // Precalculate the skin cluster mapping
- //
-
- int bind_id = 0;
- for (const FBXDocParser::Cluster *cluster : fbx_skin->Clusters()) {
- ERR_CONTINUE_MSG(!state.fbx_bone_map.has(cluster->TargetNode()->ID()), "Missing bone map for cluster target node with id " + uitos(cluster->TargetNode()->ID()) + ".");
- Ref<FBXBone> bone = state.fbx_bone_map[cluster->TargetNode()->ID()];
- skeleton_to_skin_bind_id.insert(bone->godot_bone_id, bind_id);
- bind_id++;
- }
-
- for (const Vertex *v = vertex_weights.next(nullptr); v != nullptr; v = vertex_weights.next(v)) {
- VertexWeightMapping *vm = vertex_weights.getptr(*v);
- ERR_CONTINUE(vm->bones.size() != vm->weights.size()); // No message, already checked.
- ERR_CONTINUE(vm->bones_ref.size() != vm->weights.size()); // No message, already checked.
-
- const int initial_size = vm->weights.size();
- {
- // Init bone id
- int *bones_ptr = vm->bones.ptrw();
- Ref<FBXBone> *bones_ref_ptr = vm->bones_ref.ptrw();
-
- for (int i = 0; i < vm->weights.size(); i += 1) {
- // At this point this is not possible because the skeleton is already initialized.
- CRASH_COND(bones_ref_ptr[i]->godot_bone_id == -2);
- bones_ptr[i] = skeleton_to_skin_bind_id[bones_ref_ptr[i]->godot_bone_id];
- }
-
- // From this point on the data is no more valid.
- vm->bones_ref.clear();
- }
-
- {
- // Sort
- float *weights_ptr = vm->weights.ptrw();
- int *bones_ptr = vm->bones.ptrw();
- for (int i = 0; i < vm->weights.size(); i += 1) {
- for (int x = i + 1; x < vm->weights.size(); x += 1) {
- if (weights_ptr[i] < weights_ptr[x]) {
- SWAP(weights_ptr[i], weights_ptr[x]);
- SWAP(bones_ptr[i], bones_ptr[x]);
- }
- }
- }
- }
-
- {
- // Resize
- vm->weights.resize(max_vertex_influence_count);
- vm->bones.resize(max_vertex_influence_count);
- float *weights_ptr = vm->weights.ptrw();
- int *bones_ptr = vm->bones.ptrw();
- for (int i = initial_size; i < max_vertex_influence_count; i += 1) {
- weights_ptr[i] = 0.0;
- bones_ptr[i] = 0;
- }
-
- // Normalize
- real_t sum = 0.0;
- for (int i = 0; i < max_vertex_influence_count; i += 1) {
- sum += weights_ptr[i];
- }
- if (sum > 0.0) {
- for (int i = 0; i < vm->weights.size(); i += 1) {
- weights_ptr[i] = weights_ptr[i] / sum;
- }
- }
- }
- }
-}
-
-void FBXMeshData::reorganize_vertices(
- // TODO: perf hotspot on insane files
- std::vector<int> &r_polygon_indices,
- std::vector<Vector3> &r_vertices,
- HashMap<int, Vector3> &r_normals,
- HashMap<int, Vector2> &r_uv_1,
- HashMap<int, Vector2> &r_uv_2,
- HashMap<int, Color> &r_color,
- HashMap<String, MorphVertexData> &r_morphs,
- HashMap<int, HashMap<int, Vector3>> &r_normals_raw,
- HashMap<int, HashMap<int, Color>> &r_colors_raw,
- HashMap<int, HashMap<int, Vector2>> &r_uv_1_raw,
- HashMap<int, HashMap<int, Vector2>> &r_uv_2_raw) {
- // Key: OldVertex; Value: [New vertices];
- HashMap<int, Vector<int>> duplicated_vertices;
-
- PolygonId polygon_index = -1;
- for (int pv = 0; pv < (int)r_polygon_indices.size(); pv += 1) {
- if (is_start_of_polygon(r_polygon_indices, pv)) {
- polygon_index += 1;
- }
- const Vertex index = get_vertex_from_polygon_vertex(r_polygon_indices, pv);
-
- bool need_duplication = false;
- Vector2 this_vert_poly_uv1 = Vector2();
- Vector2 this_vert_poly_uv2 = Vector2();
- Vector3 this_vert_poly_normal = Vector3();
- Color this_vert_poly_color = Color();
-
- // Take the normal and see if we need to duplicate this polygon.
- if (r_normals_raw.has(index)) {
- const HashMap<PolygonId, Vector3> *nrml_arr = r_normals_raw.getptr(index);
-
- if (nrml_arr->has(polygon_index)) {
- this_vert_poly_normal = nrml_arr->get(polygon_index);
- } else if (nrml_arr->has(-1)) {
- this_vert_poly_normal = nrml_arr->get(-1);
- } else {
- print_error("invalid normal detected: " + itos(index) + " polygon index: " + itos(polygon_index));
- for (const PolygonId *pid = nrml_arr->next(nullptr); pid != nullptr; pid = nrml_arr->next(pid)) {
- print_verbose("debug contents key: " + itos(*pid));
-
- if (nrml_arr->has(*pid)) {
- print_verbose("contents valid: " + nrml_arr->get(*pid));
- }
- }
- }
-
- // Now, check if we need to duplicate it.
- for (const PolygonId *pid = nrml_arr->next(nullptr); pid != nullptr; pid = nrml_arr->next(pid)) {
- if (*pid == polygon_index) {
- continue;
- }
-
- const Vector3 vert_poly_normal = *nrml_arr->getptr(*pid);
- if (!vert_poly_normal.is_equal_approx(this_vert_poly_normal)) {
- // Yes this polygon need duplication.
- need_duplication = true;
- break;
- }
- }
- }
-
- // TODO: make me vertex color
- // Take the normal and see if we need to duplicate this polygon.
- if (r_colors_raw.has(index)) {
- const HashMap<PolygonId, Color> *color_arr = r_colors_raw.getptr(index);
-
- if (color_arr->has(polygon_index)) {
- this_vert_poly_color = color_arr->get(polygon_index);
- } else if (color_arr->has(-1)) {
- this_vert_poly_color = color_arr->get(-1);
- } else {
- print_error("invalid color detected: " + itos(index) + " polygon index: " + itos(polygon_index));
- for (const PolygonId *pid = color_arr->next(nullptr); pid != nullptr; pid = color_arr->next(pid)) {
- print_verbose("debug contents key: " + itos(*pid));
-
- if (color_arr->has(*pid)) {
- print_verbose("contents valid: " + color_arr->get(*pid));
- }
- }
- }
-
- // Now, check if we need to duplicate it.
- for (const PolygonId *pid = color_arr->next(nullptr); pid != nullptr; pid = color_arr->next(pid)) {
- if (*pid == polygon_index) {
- continue;
- }
-
- const Color vert_poly_color = *color_arr->getptr(*pid);
- if (!this_vert_poly_color.is_equal_approx(vert_poly_color)) {
- // Yes this polygon need duplication.
- need_duplication = true;
- break;
- }
- }
- }
-
- // Take the UV1 and UV2 and see if we need to duplicate this polygon.
- {
- HashMap<int, HashMap<int, Vector2>> *uv_raw = &r_uv_1_raw;
- Vector2 *this_vert_poly_uv = &this_vert_poly_uv1;
- for (int kk = 0; kk < 2; kk++) {
- if (uv_raw->has(index)) {
- const HashMap<PolygonId, Vector2> *uvs = uv_raw->getptr(index);
-
- if (uvs->has(polygon_index)) {
- // This Polygon has its own uv.
- (*this_vert_poly_uv) = *uvs->getptr(polygon_index);
-
- // Check if we need to duplicate it.
- for (const PolygonId *pid = uvs->next(nullptr); pid != nullptr; pid = uvs->next(pid)) {
- if (*pid == polygon_index) {
- continue;
- }
- const Vector2 vert_poly_uv = *uvs->getptr(*pid);
- if (!vert_poly_uv.is_equal_approx(*this_vert_poly_uv)) {
- // Yes this polygon need duplication.
- need_duplication = true;
- break;
- }
- }
- } else if (uvs->has(-1)) {
- // It has the default UV.
- (*this_vert_poly_uv) = *uvs->getptr(-1);
- } else if (uvs->size() > 0) {
- // No uv, this is strange, just take the first and duplicate.
- (*this_vert_poly_uv) = *uvs->getptr(*uvs->next(nullptr));
- WARN_PRINT("No UVs for this polygon, while there is no default and some other polygons have it. This FBX file may be corrupted.");
- }
- }
- uv_raw = &r_uv_2_raw;
- this_vert_poly_uv = &this_vert_poly_uv2;
- }
- }
-
- // If we want to duplicate it, Let's see if we already duplicated this
- // vertex.
- if (need_duplication) {
- if (duplicated_vertices.has(index)) {
- Vertex similar_vertex = -1;
- // Let's see if one of the new vertices has the same data of this.
- const Vector<int> *new_vertices = duplicated_vertices.getptr(index);
- for (int j = 0; j < new_vertices->size(); j += 1) {
- const Vertex new_vertex = (*new_vertices)[j];
- bool same_uv1 = false;
- bool same_uv2 = false;
- bool same_normal = false;
- bool same_color = false;
-
- if (r_uv_1.has(new_vertex)) {
- if ((this_vert_poly_uv1 - (*r_uv_1.getptr(new_vertex))).length_squared() <= CMP_EPSILON) {
- same_uv1 = true;
- }
- }
-
- if (r_uv_2.has(new_vertex)) {
- if ((this_vert_poly_uv2 - (*r_uv_2.getptr(new_vertex))).length_squared() <= CMP_EPSILON) {
- same_uv2 = true;
- }
- }
-
- if (r_color.has(new_vertex)) {
- if (this_vert_poly_color.is_equal_approx((*r_color.getptr(new_vertex)))) {
- same_color = true;
- }
- }
-
- if (r_normals.has(new_vertex)) {
- if ((this_vert_poly_normal - (*r_normals.getptr(new_vertex))).length_squared() <= CMP_EPSILON) {
- same_uv2 = true;
- }
- }
-
- if (same_uv1 && same_uv2 && same_normal && same_color) {
- similar_vertex = new_vertex;
- break;
- }
- }
-
- if (similar_vertex != -1) {
- // Update polygon.
- if (is_end_of_polygon(r_polygon_indices, pv)) {
- r_polygon_indices[pv] = ~similar_vertex;
- } else {
- r_polygon_indices[pv] = similar_vertex;
- }
- need_duplication = false;
- }
- }
- }
-
- if (need_duplication) {
- const Vertex old_index = index;
- const Vertex new_index = r_vertices.size();
-
- // Polygon index.
- if (is_end_of_polygon(r_polygon_indices, pv)) {
- r_polygon_indices[pv] = ~new_index;
- } else {
- r_polygon_indices[pv] = new_index;
- }
-
- // Vertex position.
- r_vertices.push_back(r_vertices[old_index]);
-
- // Normals
- if (r_normals_raw.has(old_index)) {
- r_normals.set(new_index, this_vert_poly_normal);
- r_normals_raw.getptr(old_index)->erase(polygon_index);
- r_normals_raw[new_index][polygon_index] = this_vert_poly_normal;
- }
-
- // Vertex Color
- if (r_colors_raw.has(old_index)) {
- r_color.set(new_index, this_vert_poly_color);
- r_colors_raw.getptr(old_index)->erase(polygon_index);
- r_colors_raw[new_index][polygon_index] = this_vert_poly_color;
- }
-
- // UV 0
- if (r_uv_1_raw.has(old_index)) {
- r_uv_1.set(new_index, this_vert_poly_uv1);
- r_uv_1_raw.getptr(old_index)->erase(polygon_index);
- r_uv_1_raw[new_index][polygon_index] = this_vert_poly_uv1;
- }
-
- // UV 1
- if (r_uv_2_raw.has(old_index)) {
- r_uv_2.set(new_index, this_vert_poly_uv2);
- r_uv_2_raw.getptr(old_index)->erase(polygon_index);
- r_uv_2_raw[new_index][polygon_index] = this_vert_poly_uv2;
- }
-
- // Morphs
- for (const String *mname = r_morphs.next(nullptr); mname != nullptr; mname = r_morphs.next(mname)) {
- MorphVertexData *d = r_morphs.getptr(*mname);
- // This can't never happen.
- CRASH_COND(d == nullptr);
- if (d->vertices.size() > old_index) {
- d->vertices.push_back(d->vertices[old_index]);
- }
- if (d->normals.size() > old_index) {
- d->normals.push_back(d->normals[old_index]);
- }
- }
-
- if (vertex_weights.has(old_index)) {
- vertex_weights.set(new_index, vertex_weights[old_index]);
- }
-
- duplicated_vertices[old_index].push_back(new_index);
- } else {
- if (r_normals_raw.has(index) &&
- r_normals.has(index) == false) {
- r_normals.set(index, this_vert_poly_normal);
- }
-
- if (r_colors_raw.has(index) && r_color.has(index) == false) {
- r_color.set(index, this_vert_poly_color);
- }
-
- if (r_uv_1_raw.has(index) &&
- r_uv_1.has(index) == false) {
- r_uv_1.set(index, this_vert_poly_uv1);
- }
-
- if (r_uv_2_raw.has(index) &&
- r_uv_2.has(index) == false) {
- r_uv_2.set(index, this_vert_poly_uv2);
- }
- }
- }
-}
-
-void FBXMeshData::add_vertex(
- const ImportState &state,
- Ref<SurfaceTool> p_surface_tool,
- real_t p_scale,
- Vertex p_vertex,
- const std::vector<Vector3> &p_vertices_position,
- const HashMap<int, Vector3> &p_normals,
- const HashMap<int, Vector2> &p_uvs_0,
- const HashMap<int, Vector2> &p_uvs_1,
- const HashMap<int, Color> &p_colors,
- const Vector3 &p_morph_value,
- const Vector3 &p_morph_normal) {
- ERR_FAIL_INDEX_MSG(p_vertex, (Vertex)p_vertices_position.size(), "FBX file is corrupted, the position of the vertex can't be retrieved.");
-
- if (p_normals.has(p_vertex) && !state.is_blender_fbx) {
- p_surface_tool->set_normal(p_normals[p_vertex] + p_morph_normal);
- }
-
- if (p_uvs_0.has(p_vertex)) {
- //print_verbose("uv1: [" + itos(p_vertex) + "] " + p_uvs_0[p_vertex]);
- // Inverts Y UV.
- p_surface_tool->set_uv(Vector2(p_uvs_0[p_vertex].x, 1 - p_uvs_0[p_vertex].y));
- }
-
- if (p_uvs_1.has(p_vertex)) {
- //print_verbose("uv2: [" + itos(p_vertex) + "] " + p_uvs_1[p_vertex]);
- // Inverts Y UV.
- p_surface_tool->set_uv2(Vector2(p_uvs_1[p_vertex].x, 1 - p_uvs_1[p_vertex].y));
- }
-
- if (p_colors.has(p_vertex)) {
- p_surface_tool->set_color(p_colors[p_vertex]);
- }
-
- // TODO what about binormals?
- // TODO there is other?
-
- if (vertex_weights.has(p_vertex)) {
- // Let's extract the weight info.
- const VertexWeightMapping *vm = vertex_weights.getptr(p_vertex);
- const Vector<int> &bones = vm->bones;
-
- // the bug is that the bone idx is wrong because it is not ref'ing the skin.
-
- if (bones.size() > RS::ARRAY_WEIGHTS_SIZE) {
- print_error("[weight overflow detected]");
- }
-
- p_surface_tool->set_weights(vm->weights);
- // 0 1 2 3 4 5 6 7 < local skeleton / skin for mesh
- // 0 1 2 3 4 5 6 7 8 9 10 < actual skeleton with all joints
- p_surface_tool->set_bones(bones);
- }
-
- // The surface tool want the vertex position as last thing.
- p_surface_tool->add_vertex((p_vertices_position[p_vertex] + p_morph_value) * p_scale);
-}
-
-void FBXMeshData::triangulate_polygon(SurfaceData *surface, const Vector<int> &p_polygon_vertex, const std::vector<Vector3> &p_vertices) const {
- Ref<SurfaceTool> st(surface->surface_tool);
- const int polygon_vertex_count = p_polygon_vertex.size();
- //const Vector<Vertex>& p_surface_vertex_map
- if (polygon_vertex_count == 1) {
- // point to triangle
- st->add_index(p_polygon_vertex[0]);
- st->add_index(p_polygon_vertex[0]);
- st->add_index(p_polygon_vertex[0]);
- return;
- } else if (polygon_vertex_count == 2) {
- // line to triangle
- st->add_index(p_polygon_vertex[1]);
- st->add_index(p_polygon_vertex[1]);
- st->add_index(p_polygon_vertex[0]);
- return;
- } else if (polygon_vertex_count == 3) {
- // triangle to triangle
- st->add_index(p_polygon_vertex[0]);
- st->add_index(p_polygon_vertex[2]);
- st->add_index(p_polygon_vertex[1]);
- return;
- } else if (polygon_vertex_count == 4) {
- // quad to triangle - this code is awesome for import times
- // it prevents triangles being generated slowly
- st->add_index(p_polygon_vertex[0]);
- st->add_index(p_polygon_vertex[2]);
- st->add_index(p_polygon_vertex[1]);
- st->add_index(p_polygon_vertex[2]);
- st->add_index(p_polygon_vertex[0]);
- st->add_index(p_polygon_vertex[3]);
- return;
- } else {
- // non triangulated - we must run the triangulation algorithm
- bool is_simple_convex = false;
- // this code is 'slow' but required it triangulates all the unsupported geometry.
- // Doesn't allow for bigger polygons because those are unlikely be convex
- if (polygon_vertex_count <= 6) {
- // Start from true, check if it's false.
- is_simple_convex = true;
- Vector3 first_vec;
- for (int i = 0; i < polygon_vertex_count; i += 1) {
- const Vector3 p1 = p_vertices[surface->vertices_map[p_polygon_vertex[i]]];
- const Vector3 p2 = p_vertices[surface->vertices_map[p_polygon_vertex[(i + 1) % polygon_vertex_count]]];
- const Vector3 p3 = p_vertices[surface->vertices_map[p_polygon_vertex[(i + 2) % polygon_vertex_count]]];
-
- const Vector3 edge1 = p1 - p2;
- const Vector3 edge2 = p3 - p2;
-
- const Vector3 res = edge1.normalized().cross(edge2.normalized()).normalized();
- if (i == 0) {
- first_vec = res;
- } else {
- if (first_vec.dot(res) < 0.0) {
- // Ok we found an angle that is not the same dir of the
- // others.
- is_simple_convex = false;
- break;
- }
- }
- }
- }
-
- if (is_simple_convex) {
- // This is a convex polygon, so just triangulate it.
- for (int i = 0; i < (polygon_vertex_count - 2); i += 1) {
- st->add_index(p_polygon_vertex[2 + i]);
- st->add_index(p_polygon_vertex[1 + i]);
- st->add_index(p_polygon_vertex[0]);
- }
- return;
- }
- }
-
- {
- // This is a concave polygon.
-
- std::vector<Vector3> poly_vertices(polygon_vertex_count);
- for (int i = 0; i < polygon_vertex_count; i += 1) {
- poly_vertices[i] = p_vertices[surface->vertices_map[p_polygon_vertex[i]]];
- }
-
- const Vector3 poly_norm = get_poly_normal(poly_vertices);
- if (poly_norm.length_squared() <= CMP_EPSILON) {
- ERR_FAIL_COND_MSG(poly_norm.length_squared() <= CMP_EPSILON, "The normal of this poly was not computed. Is this FBX file corrupted.");
- }
-
- // Select the plan coordinate.
- int axis_1_coord = 0;
- int axis_2_coord = 1;
- {
- real_t inv = poly_norm.z;
-
- const real_t axis_x = ABS(poly_norm.x);
- const real_t axis_y = ABS(poly_norm.y);
- const real_t axis_z = ABS(poly_norm.z);
-
- if (axis_x > axis_y) {
- if (axis_x > axis_z) {
- // For the most part the normal point toward X.
- axis_1_coord = 1;
- axis_2_coord = 2;
- inv = poly_norm.x;
- }
- } else if (axis_y > axis_z) {
- // For the most part the normal point toward Y.
- axis_1_coord = 2;
- axis_2_coord = 0;
- inv = poly_norm.y;
- }
-
- // Swap projection axes to take the negated projection vector into account
- if (inv < 0.0f) {
- SWAP(axis_1_coord, axis_2_coord);
- }
- }
-
- TPPLPoly tppl_poly;
- tppl_poly.Init(polygon_vertex_count);
- std::vector<Vector2> projected_vertices(polygon_vertex_count);
- for (int i = 0; i < polygon_vertex_count; i += 1) {
- const Vector2 pv(poly_vertices[i][axis_1_coord], poly_vertices[i][axis_2_coord]);
- projected_vertices[i] = pv;
- tppl_poly.GetPoint(i) = pv;
- }
- tppl_poly.SetOrientation(TPPL_ORIENTATION_CCW);
-
- List<TPPLPoly> out_poly;
-
- TPPLPartition tppl_partition;
- if (tppl_partition.Triangulate_OPT(&tppl_poly, &out_poly) == 0) { // Good result.
- if (tppl_partition.Triangulate_EC(&tppl_poly, &out_poly) == 0) { // Medium result.
- if (tppl_partition.Triangulate_MONO(&tppl_poly, &out_poly) == 0) { // Really poor result.
- ERR_FAIL_MSG("The triangulation of this polygon failed, please try to triangulate your mesh or check if it has broken polygons.");
- }
- }
- }
-
- std::vector<Vector2> tris(out_poly.size());
- for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) {
- TPPLPoly &tp = I->get();
-
- ERR_FAIL_COND_MSG(tp.GetNumPoints() != 3, "The triangulator returned more points, how this is possible?");
- // Find Index
- for (int i = 2; i >= 0; i -= 1) {
- const Vector2 vertex = tp.GetPoint(i);
- bool done = false;
- // Find Index
- for (int y = 0; y < polygon_vertex_count; y += 1) {
- if ((projected_vertices[y] - vertex).length_squared() <= CMP_EPSILON) {
- // This seems the right vertex
- st->add_index(p_polygon_vertex[y]);
- done = true;
- break;
- }
- }
- ERR_FAIL_COND(done == false);
- }
- }
- }
-}
-
-void FBXMeshData::gen_weight_info(Ref<SurfaceTool> st, Vertex vertex_id) const {
- if (vertex_weights.is_empty()) {
- return;
- }
-
- if (vertex_weights.has(vertex_id)) {
- // Let's extract the weight info.
- const VertexWeightMapping *vm = vertex_weights.getptr(vertex_id);
- st->set_weights(vm->weights);
- st->set_bones(vm->bones);
- }
-}
-
-int FBXMeshData::get_vertex_from_polygon_vertex(const std::vector<int> &p_polygon_indices, int p_index) const {
- if (p_index < 0 || p_index >= (int)p_polygon_indices.size()) {
- return -1;
- }
-
- const int vertex = p_polygon_indices[p_index];
- if (vertex >= 0) {
- return vertex;
- } else {
- // Negative numbers are the end of the face, reversing the bits is
- // possible to obtain the positive correct vertex number.
- return ~vertex;
- }
-}
-
-bool FBXMeshData::is_end_of_polygon(const std::vector<int> &p_polygon_indices, int p_index) const {
- if (p_index < 0 || p_index >= (int)p_polygon_indices.size()) {
- return false;
- }
-
- const int vertex = p_polygon_indices[p_index];
-
- // If the index is negative this is the end of the Polygon.
- return vertex < 0;
-}
-
-bool FBXMeshData::is_start_of_polygon(const std::vector<int> &p_polygon_indices, int p_index) const {
- if (p_index < 0 || p_index >= (int)p_polygon_indices.size()) {
- return false;
- }
-
- if (p_index == 0) {
- return true;
- }
-
- // If the previous indices is negative this is the begin of a new Polygon.
- return p_polygon_indices[p_index - 1] < 0;
-}
-
-int FBXMeshData::count_polygons(const std::vector<int> &p_polygon_indices) const {
- // The negative numbers define the end of the polygon. Counting the amount of
- // negatives the numbers of polygons are obtained.
- int count = 0;
- for (size_t i = 0; i < p_polygon_indices.size(); i += 1) {
- if (p_polygon_indices[i] < 0) {
- count += 1;
- }
- }
- return count;
-}
-
-template <class R, class T>
-HashMap<int, R> FBXMeshData::extract_per_vertex_data(
- int p_vertex_count,
- const std::vector<FBXDocParser::MeshGeometry::Edge> &p_edge_map,
- const std::vector<int> &p_mesh_indices,
- const FBXDocParser::MeshGeometry::MappingData<T> &p_mapping_data,
- R (*collector_function)(const Vector<VertexData<T>> *p_vertex_data, R p_fall_back),
- R p_fall_back) const {
- /* When index_to_direct is set
- * index size is 184 ( contains index for the data array [values 0, 96] )
- * data size is 96 (contains uv coordinates)
- * this means index is simple data reduction basically
- */
- ////
- if (p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::index_to_direct && p_mapping_data.index.size() == 0) {
- print_verbose("debug count: index size: " + itos(p_mapping_data.index.size()) + ", data size: " + itos(p_mapping_data.data.size()));
- print_verbose("vertex indices count: " + itos(p_mesh_indices.size()));
- print_verbose("Edge map size: " + itos(p_edge_map.size()));
- }
-
- ERR_FAIL_COND_V_MSG(p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::index_to_direct && p_mapping_data.index.size() == 0, (HashMap<int, R>()), "FBX importer needs to map correctly to this field, please specify the override index name to fix this problem!");
- ERR_FAIL_COND_V_MSG(p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::index && p_mapping_data.index.size() == 0, (HashMap<int, R>()), "The FBX seems corrupted");
-
- // Aggregate vertex data.
- HashMap<Vertex, Vector<VertexData<T>>> aggregate_vertex_data;
-
- switch (p_mapping_data.map_type) {
- case FBXDocParser::MeshGeometry::MapType::none: {
- // No data nothing to do.
- return (HashMap<int, R>());
- }
- case FBXDocParser::MeshGeometry::MapType::vertex: {
- ERR_FAIL_COND_V_MSG(p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::index_to_direct, (HashMap<int, R>()), "We will support in future");
-
- if (p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::direct) {
- // The data is mapped per vertex directly.
- ERR_FAIL_COND_V_MSG((int)p_mapping_data.data.size() != p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR01");
- for (size_t vertex_index = 0; vertex_index < p_mapping_data.data.size(); vertex_index += 1) {
- aggregate_vertex_data[vertex_index].push_back({ -1, p_mapping_data.data[vertex_index] });
- }
- } else {
- // The data is mapped per vertex using a reference.
- // The indices array, contains a *reference_id for each vertex.
- // * Note that the reference_id is the id of data into the data array.
- //
- // https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_layer_element_html
- ERR_FAIL_COND_V_MSG((int)p_mapping_data.index.size() != p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR02");
- for (size_t vertex_index = 0; vertex_index < p_mapping_data.index.size(); vertex_index += 1) {
- ERR_FAIL_INDEX_V_MSG(p_mapping_data.index[vertex_index], (int)p_mapping_data.data.size(), (HashMap<int, R>()), "FBX file seems corrupted: #ERR03.");
- aggregate_vertex_data[vertex_index].push_back({ -1, p_mapping_data.data[p_mapping_data.index[vertex_index]] });
- }
- }
- } break;
- case FBXDocParser::MeshGeometry::MapType::polygon_vertex: {
- if (p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::index_to_direct) {
- // The data is mapped using each index from the indexes array then direct to the data (data reduction algorithm)
- ERR_FAIL_COND_V_MSG((int)p_mesh_indices.size() != (int)p_mapping_data.index.size(), (HashMap<int, R>()), "FBX file seems corrupted: #ERR04");
- int polygon_id = -1;
- for (size_t polygon_vertex_index = 0; polygon_vertex_index < p_mapping_data.index.size(); polygon_vertex_index += 1) {
- if (is_start_of_polygon(p_mesh_indices, polygon_vertex_index)) {
- polygon_id += 1;
- }
- const int vertex_index = get_vertex_from_polygon_vertex(p_mesh_indices, polygon_vertex_index);
- ERR_FAIL_COND_V_MSG(vertex_index < 0, (HashMap<int, R>()), "FBX file corrupted: #ERR05");
- ERR_FAIL_COND_V_MSG(vertex_index >= p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR06");
- const int index_to_direct = get_vertex_from_polygon_vertex(p_mapping_data.index, polygon_vertex_index);
- T value = p_mapping_data.data[index_to_direct];
- aggregate_vertex_data[vertex_index].push_back({ polygon_id, value });
- }
- } else if (p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::direct) {
- // The data are mapped per polygon vertex directly.
- ERR_FAIL_COND_V_MSG((int)p_mesh_indices.size() != (int)p_mapping_data.data.size(), (HashMap<int, R>()), "FBX file seems corrupted: #ERR04");
- int polygon_id = -1;
- for (size_t polygon_vertex_index = 0; polygon_vertex_index < p_mapping_data.data.size(); polygon_vertex_index += 1) {
- if (is_start_of_polygon(p_mesh_indices, polygon_vertex_index)) {
- polygon_id += 1;
- }
- const int vertex_index = get_vertex_from_polygon_vertex(p_mesh_indices, polygon_vertex_index);
- ERR_FAIL_COND_V_MSG(vertex_index < 0, (HashMap<int, R>()), "FBX file corrupted: #ERR05");
- ERR_FAIL_COND_V_MSG(vertex_index >= p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR06");
-
- aggregate_vertex_data[vertex_index].push_back({ polygon_id, p_mapping_data.data[polygon_vertex_index] });
- }
- } else {
- // The data is mapped per polygon_vertex using a reference.
- // The indices array, contains a *reference_id for each polygon_vertex.
- // * Note that the reference_id is the id of data into the data array.
- //
- // https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_layer_element_html
- ERR_FAIL_COND_V_MSG(p_mesh_indices.size() != p_mapping_data.index.size(), (HashMap<int, R>()), "FBX file corrupted: #ERR7");
- int polygon_id = -1;
- for (size_t polygon_vertex_index = 0; polygon_vertex_index < p_mapping_data.index.size(); polygon_vertex_index += 1) {
- if (is_start_of_polygon(p_mesh_indices, polygon_vertex_index)) {
- polygon_id += 1;
- }
- const int vertex_index = get_vertex_from_polygon_vertex(p_mesh_indices, polygon_vertex_index);
- ERR_FAIL_COND_V_MSG(vertex_index < 0, (HashMap<int, R>()), "FBX file corrupted: #ERR8");
- ERR_FAIL_COND_V_MSG(vertex_index >= p_vertex_count, (HashMap<int, R>()), "FBX file seems corrupted: #ERR9.");
- ERR_FAIL_COND_V_MSG(p_mapping_data.index[polygon_vertex_index] < 0, (HashMap<int, R>()), "FBX file seems corrupted: #ERR10.");
- ERR_FAIL_COND_V_MSG(p_mapping_data.index[polygon_vertex_index] >= (int)p_mapping_data.data.size(), (HashMap<int, R>()), "FBX file seems corrupted: #ERR11.");
- aggregate_vertex_data[vertex_index].push_back({ polygon_id, p_mapping_data.data[p_mapping_data.index[polygon_vertex_index]] });
- }
- }
- } break;
- case FBXDocParser::MeshGeometry::MapType::polygon: {
- if (p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::direct) {
- // The data are mapped per polygon directly.
- const int polygon_count = count_polygons(p_mesh_indices);
- ERR_FAIL_COND_V_MSG(polygon_count != (int)p_mapping_data.data.size(), (HashMap<int, R>()), "FBX file seems corrupted: #ERR12");
-
- // Advance each polygon vertex, each new polygon advance the polygon index.
- int polygon_index = -1;
- for (size_t polygon_vertex_index = 0;
- polygon_vertex_index < p_mesh_indices.size();
- polygon_vertex_index += 1) {
- if (is_start_of_polygon(p_mesh_indices, polygon_vertex_index)) {
- polygon_index += 1;
- ERR_FAIL_INDEX_V_MSG(polygon_index, (int)p_mapping_data.data.size(), (HashMap<int, R>()), "FBX file seems corrupted: #ERR13");
- }
-
- const int vertex_index = get_vertex_from_polygon_vertex(p_mesh_indices, polygon_vertex_index);
- ERR_FAIL_INDEX_V_MSG(vertex_index, p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR14");
-
- aggregate_vertex_data[vertex_index].push_back({ polygon_index, p_mapping_data.data[polygon_index] });
- }
- ERR_FAIL_COND_V_MSG((polygon_index + 1) != polygon_count, (HashMap<int, R>()), "FBX file seems corrupted: #ERR16. Not all Polygons are present in the file.");
- } else {
- // The data is mapped per polygon using a reference.
- // The indices array, contains a *reference_id for each polygon.
- // * Note that the reference_id is the id of data into the data array.
- //
- // https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_layer_element_html
- const int polygon_count = count_polygons(p_mesh_indices);
- ERR_FAIL_COND_V_MSG(polygon_count != (int)p_mapping_data.index.size(), (HashMap<int, R>()), "FBX file seems corrupted: #ERR17");
-
- // Advance each polygon vertex, each new polygon advance the polygon index.
- int polygon_index = -1;
- for (size_t polygon_vertex_index = 0;
- polygon_vertex_index < p_mesh_indices.size();
- polygon_vertex_index += 1) {
- if (is_start_of_polygon(p_mesh_indices, polygon_vertex_index)) {
- polygon_index += 1;
- ERR_FAIL_INDEX_V_MSG(polygon_index, (int)p_mapping_data.index.size(), (HashMap<int, R>()), "FBX file seems corrupted: #ERR18");
- ERR_FAIL_INDEX_V_MSG(p_mapping_data.index[polygon_index], (int)p_mapping_data.data.size(), (HashMap<int, R>()), "FBX file seems corrupted: #ERR19");
- }
-
- const int vertex_index = get_vertex_from_polygon_vertex(p_mesh_indices, polygon_vertex_index);
- ERR_FAIL_INDEX_V_MSG(vertex_index, p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR20");
-
- aggregate_vertex_data[vertex_index].push_back({ polygon_index, p_mapping_data.data[p_mapping_data.index[polygon_index]] });
- }
- ERR_FAIL_COND_V_MSG((polygon_index + 1) != polygon_count, (HashMap<int, R>()), "FBX file seems corrupted: #ERR22. Not all Polygons are present in the file.");
- }
- } break;
- case FBXDocParser::MeshGeometry::MapType::edge: {
- if (p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::direct) {
- // The data are mapped per edge directly.
- ERR_FAIL_COND_V_MSG(p_edge_map.size() != p_mapping_data.data.size(), (HashMap<int, R>()), "FBX file seems corrupted: #ERR23");
- for (size_t edge_index = 0; edge_index < p_mapping_data.data.size(); edge_index += 1) {
- const FBXDocParser::MeshGeometry::Edge edge = FBXDocParser::MeshGeometry::get_edge(p_edge_map, edge_index);
- ERR_FAIL_INDEX_V_MSG(edge.vertex_0, p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR24");
- ERR_FAIL_INDEX_V_MSG(edge.vertex_1, p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR25");
- ERR_FAIL_INDEX_V_MSG(edge.vertex_0, (int)p_mapping_data.data.size(), (HashMap<int, R>()), "FBX file corrupted: #ERR26");
- ERR_FAIL_INDEX_V_MSG(edge.vertex_1, (int)p_mapping_data.data.size(), (HashMap<int, R>()), "FBX file corrupted: #ERR27");
- aggregate_vertex_data[edge.vertex_0].push_back({ -1, p_mapping_data.data[edge_index] });
- aggregate_vertex_data[edge.vertex_1].push_back({ -1, p_mapping_data.data[edge_index] });
- }
- } else {
- // The data is mapped per edge using a reference.
- // The indices array, contains a *reference_id for each polygon.
- // * Note that the reference_id is the id of data into the data array.
- //
- // https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_layer_element_html
- ERR_FAIL_COND_V_MSG(p_edge_map.size() != p_mapping_data.index.size(), (HashMap<int, R>()), "FBX file seems corrupted: #ERR28");
- for (size_t edge_index = 0; edge_index < p_mapping_data.data.size(); edge_index += 1) {
- const FBXDocParser::MeshGeometry::Edge edge = FBXDocParser::MeshGeometry::get_edge(p_edge_map, edge_index);
- ERR_FAIL_INDEX_V_MSG(edge.vertex_0, p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR29");
- ERR_FAIL_INDEX_V_MSG(edge.vertex_1, p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR30");
- ERR_FAIL_INDEX_V_MSG(edge.vertex_0, (int)p_mapping_data.index.size(), (HashMap<int, R>()), "FBX file corrupted: #ERR31");
- ERR_FAIL_INDEX_V_MSG(edge.vertex_1, (int)p_mapping_data.index.size(), (HashMap<int, R>()), "FBX file corrupted: #ERR32");
- ERR_FAIL_INDEX_V_MSG(p_mapping_data.index[edge.vertex_0], (int)p_mapping_data.data.size(), (HashMap<int, R>()), "FBX file corrupted: #ERR33");
- ERR_FAIL_INDEX_V_MSG(p_mapping_data.index[edge.vertex_1], (int)p_mapping_data.data.size(), (HashMap<int, R>()), "FBX file corrupted: #ERR34");
- aggregate_vertex_data[edge.vertex_0].push_back({ -1, p_mapping_data.data[p_mapping_data.index[edge_index]] });
- aggregate_vertex_data[edge.vertex_1].push_back({ -1, p_mapping_data.data[p_mapping_data.index[edge_index]] });
- }
- }
- } break;
- case FBXDocParser::MeshGeometry::MapType::all_the_same: {
- // No matter the mode, no matter the data size; The first always win
- // and is set to all the vertices.
- ERR_FAIL_COND_V_MSG(p_mapping_data.data.size() <= 0, (HashMap<int, R>()), "FBX file seems corrupted: #ERR35");
- if (p_mapping_data.data.size() > 0) {
- for (int vertex_index = 0; vertex_index < p_vertex_count; vertex_index += 1) {
- aggregate_vertex_data[vertex_index].push_back({ -1, p_mapping_data.data[0] });
- }
- }
- } break;
- }
-
- if (aggregate_vertex_data.size() == 0) {
- return (HashMap<int, R>());
- }
-
- // A map is used because turns out that the some FBX file are not well organized
- // with vertices well compacted. Using a map allows avoid those issues.
- HashMap<Vertex, R> result;
-
- // Aggregate the collected data.
- for (const Vertex *index = aggregate_vertex_data.next(nullptr); index != nullptr; index = aggregate_vertex_data.next(index)) {
- Vector<VertexData<T>> *aggregated_vertex = aggregate_vertex_data.getptr(*index);
- // This can't be null because we are just iterating.
- CRASH_COND(aggregated_vertex == nullptr);
-
- ERR_FAIL_INDEX_V_MSG(0, aggregated_vertex->size(), (HashMap<int, R>()), "The FBX file is corrupted, No valid data for this vertex index.");
- result[*index] = collector_function(aggregated_vertex, p_fall_back);
- }
-
- // Sanitize the data now, if the file is broken we can try import it anyway.
- bool problem_found = false;
- for (size_t i = 0; i < p_mesh_indices.size(); i += 1) {
- const Vertex vertex = get_vertex_from_polygon_vertex(p_mesh_indices, i);
- if (result.has(vertex) == false) {
- result[vertex] = p_fall_back;
- problem_found = true;
- }
- }
- if (problem_found) {
- WARN_PRINT("Some data is missing, this FBX file may be corrupted: #WARN0.");
- }
-
- return result;
-}
-
-template <class T>
-HashMap<int, T> FBXMeshData::extract_per_polygon(
- int p_vertex_count,
- const std::vector<int> &p_polygon_indices,
- const FBXDocParser::MeshGeometry::MappingData<T> &p_fbx_data,
- T p_fallback_value) const {
- ERR_FAIL_COND_V_MSG(p_fbx_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::index_to_direct && p_fbx_data.data.size() == 0, (HashMap<int, T>()), "invalid index to direct array");
- ERR_FAIL_COND_V_MSG(p_fbx_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::index && p_fbx_data.index.size() == 0, (HashMap<int, T>()), "The FBX seems corrupted");
-
- const int polygon_count = count_polygons(p_polygon_indices);
-
- // Aggregate vertex data.
- HashMap<int, Vector<T>> aggregate_polygon_data;
-
- switch (p_fbx_data.map_type) {
- case FBXDocParser::MeshGeometry::MapType::none: {
- // No data nothing to do.
- return (HashMap<int, T>());
- }
- case FBXDocParser::MeshGeometry::MapType::vertex: {
- ERR_FAIL_V_MSG((HashMap<int, T>()), "This data can't be extracted and organized per polygon, since into the FBX is mapped per vertex. This should not happen.");
- } break;
- case FBXDocParser::MeshGeometry::MapType::polygon_vertex: {
- ERR_FAIL_V_MSG((HashMap<int, T>()), "This data can't be extracted and organized per polygon, since into the FBX is mapped per polygon vertex. This should not happen.");
- } break;
- case FBXDocParser::MeshGeometry::MapType::polygon: {
- if (p_fbx_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::index_to_direct) {
- // The data is stored efficiently index_to_direct allows less data in the FBX file.
- for (int polygon_index = 0;
- polygon_index < polygon_count;
- polygon_index += 1) {
- if (p_fbx_data.index.size() == 0) {
- ERR_FAIL_INDEX_V_MSG(polygon_index, (int)p_fbx_data.data.size(), (HashMap<int, T>()), "FBX file is corrupted: #ERR62");
- aggregate_polygon_data[polygon_index].push_back(p_fbx_data.data[polygon_index]);
- } else {
- ERR_FAIL_INDEX_V_MSG(polygon_index, (int)p_fbx_data.index.size(), (HashMap<int, T>()), "FBX file is corrupted: #ERR62");
-
- const int index_to_direct = get_vertex_from_polygon_vertex(p_fbx_data.index, polygon_index);
- T value = p_fbx_data.data[index_to_direct];
- aggregate_polygon_data[polygon_index].push_back(value);
- }
- }
- } else if (p_fbx_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::direct) {
- // The data are mapped per polygon directly.
- ERR_FAIL_COND_V_MSG(polygon_count != (int)p_fbx_data.data.size(), (HashMap<int, T>()), "FBX file is corrupted: #ERR51");
-
- // Advance each polygon vertex, each new polygon advance the polygon index.
- for (int polygon_index = 0;
- polygon_index < polygon_count;
- polygon_index += 1) {
- ERR_FAIL_INDEX_V_MSG(polygon_index, (int)p_fbx_data.data.size(), (HashMap<int, T>()), "FBX file is corrupted: #ERR52");
- aggregate_polygon_data[polygon_index].push_back(p_fbx_data.data[polygon_index]);
- }
- } else {
- // The data is mapped per polygon using a reference.
- // The indices array, contains a *reference_id for each polygon.
- // * Note that the reference_id is the id of data into the data array.
- //
- // https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_layer_element_html
- ERR_FAIL_COND_V_MSG(polygon_count != (int)p_fbx_data.index.size(), (HashMap<int, T>()), "FBX file seems corrupted: #ERR52");
-
- // Advance each polygon vertex, each new polygon advance the polygon index.
- for (int polygon_index = 0;
- polygon_index < polygon_count;
- polygon_index += 1) {
- ERR_FAIL_INDEX_V_MSG(polygon_index, (int)p_fbx_data.index.size(), (HashMap<int, T>()), "FBX file is corrupted: #ERR53");
- ERR_FAIL_INDEX_V_MSG(p_fbx_data.index[polygon_index], (int)p_fbx_data.data.size(), (HashMap<int, T>()), "FBX file is corrupted: #ERR54");
- aggregate_polygon_data[polygon_index].push_back(p_fbx_data.data[p_fbx_data.index[polygon_index]]);
- }
- }
- } break;
- case FBXDocParser::MeshGeometry::MapType::edge: {
- ERR_FAIL_V_MSG((HashMap<int, T>()), "This data can't be extracted and organized per polygon, since into the FBX is mapped per edge. This should not happen.");
- } break;
- case FBXDocParser::MeshGeometry::MapType::all_the_same: {
- // No matter the mode, no matter the data size; The first always win
- // and is set to all the vertices.
- ERR_FAIL_COND_V_MSG(p_fbx_data.data.size() <= 0, (HashMap<int, T>()), "FBX file seems corrupted: #ERR55");
- if (p_fbx_data.data.size() > 0) {
- for (int polygon_index = 0; polygon_index < polygon_count; polygon_index += 1) {
- aggregate_polygon_data[polygon_index].push_back(p_fbx_data.data[0]);
- }
- }
- } break;
- }
-
- if (aggregate_polygon_data.size() == 0) {
- return (HashMap<int, T>());
- }
-
- // A map is used because turns out that the some FBX file are not well organized
- // with vertices well compacted. Using a map allows avoid those issues.
- HashMap<int, T> polygons;
-
- // Take the first value for each vertex.
- for (const Vertex *index = aggregate_polygon_data.next(nullptr); index != nullptr; index = aggregate_polygon_data.next(index)) {
- Vector<T> *aggregated_polygon = aggregate_polygon_data.getptr(*index);
- // This can't be null because we are just iterating.
- CRASH_COND(aggregated_polygon == nullptr);
-
- ERR_FAIL_INDEX_V_MSG(0, (int)aggregated_polygon->size(), (HashMap<int, T>()), "The FBX file is corrupted, No valid data for this polygon index.");
-
- // Validate the final value.
- polygons[*index] = (*aggregated_polygon)[0];
- }
-
- // Sanitize the data now, if the file is broken we can try import it anyway.
- bool problem_found = false;
- for (int polygon_i = 0; polygon_i < polygon_count; polygon_i += 1) {
- if (polygons.has(polygon_i) == false) {
- polygons[polygon_i] = p_fallback_value;
- problem_found = true;
- }
- }
- if (problem_found) {
- WARN_PRINT("Some data is missing, this FBX file may be corrupted: #WARN1.");
- }
-
- return polygons;
-}
-
-void FBXMeshData::extract_morphs(const FBXDocParser::MeshGeometry *mesh_geometry, HashMap<String, MorphVertexData> &r_data) {
- r_data.clear();
-
- const int vertex_count = mesh_geometry->get_vertices().size();
-
- for (const FBXDocParser::BlendShape *blend_shape : mesh_geometry->get_blend_shapes()) {
- for (const FBXDocParser::BlendShapeChannel *blend_shape_channel : blend_shape->BlendShapeChannels()) {
- const std::vector<const FBXDocParser::ShapeGeometry *> &shape_geometries = blend_shape_channel->GetShapeGeometries();
- for (const FBXDocParser::ShapeGeometry *shape_geometry : shape_geometries) {
- String morph_name = ImportUtils::FBXAnimMeshName(shape_geometry->Name()).c_str();
- if (morph_name.is_empty()) {
- morph_name = "morph";
- }
-
- // TODO we have only these??
- const std::vector<unsigned int> &morphs_vertex_indices = shape_geometry->GetIndices();
- const std::vector<Vector3> &morphs_vertices = shape_geometry->GetVertices();
- const std::vector<Vector3> &morphs_normals = shape_geometry->GetNormals();
-
- ERR_FAIL_COND_MSG((int)morphs_vertex_indices.size() > vertex_count, "The FBX file is corrupted: #ERR103");
- ERR_FAIL_COND_MSG(morphs_vertex_indices.size() != morphs_vertices.size(), "The FBX file is corrupted: #ERR104");
- ERR_FAIL_COND_MSG((int)morphs_vertices.size() > vertex_count, "The FBX file is corrupted: #ERR105");
- ERR_FAIL_COND_MSG(morphs_normals.size() != 0 && morphs_normals.size() != morphs_vertices.size(), "The FBX file is corrupted: #ERR106");
-
- if (r_data.has(morph_name) == false) {
- // This morph doesn't exist yet.
- // Create it.
- MorphVertexData md;
- md.vertices.resize(vertex_count);
- md.normals.resize(vertex_count);
- r_data.set(morph_name, md);
- }
-
- MorphVertexData *data = r_data.getptr(morph_name);
- Vector3 *data_vertices_ptr = data->vertices.ptrw();
- Vector3 *data_normals_ptr = data->normals.ptrw();
-
- for (int i = 0; i < (int)morphs_vertex_indices.size(); i += 1) {
- const Vertex vertex = morphs_vertex_indices[i];
-
- ERR_FAIL_INDEX_MSG(vertex, vertex_count, "The blend shapes of this FBX file are corrupted. It has a not valid vertex.");
-
- data_vertices_ptr[vertex] = morphs_vertices[i];
-
- if (morphs_normals.size() != 0) {
- data_normals_ptr[vertex] = morphs_normals[i];
- }
- }
- }
- }
- }
-}
diff --git a/modules/fbx/data/fbx_mesh_data.h b/modules/fbx/data/fbx_mesh_data.h
deleted file mode 100644
index 358d0c2cb6..0000000000
--- a/modules/fbx/data/fbx_mesh_data.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*************************************************************************/
-/* fbx_mesh_data.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. */
-/*************************************************************************/
-
-#ifndef FBX_MESH_DATA_H
-#define FBX_MESH_DATA_H
-
-#include "core/templates/hash_map.h"
-#include "core/templates/local_vector.h"
-#include "core/templates/ordered_hash_map.h"
-#include "editor/import/resource_importer_scene.h"
-#include "scene/3d/importer_mesh_instance_3d.h"
-#include "scene/3d/mesh_instance_3d.h"
-#include "scene/resources/surface_tool.h"
-
-#include "fbx_bone.h"
-#include "fbx_parser/FBXMeshGeometry.h"
-#include "import_state.h"
-#include "tools/import_utils.h"
-
-struct FBXNode;
-struct FBXMeshData;
-struct FBXBone;
-struct ImportState;
-
-typedef int Vertex;
-typedef int SurfaceId;
-typedef int PolygonId;
-typedef int DataIndex;
-
-struct SurfaceData {
- Ref<SurfaceTool> surface_tool;
- OrderedHashMap<Vertex, int> lookup_table; // proposed fix is to replace lookup_table[vertex_id] to give the position of the vertices_map[int] index.
- LocalVector<Vertex> vertices_map; // this must be ordered the same as insertion <-- slow to do find() operation.
- Ref<Material> material;
- HashMap<PolygonId, Vector<DataIndex>> surface_polygon_vertex;
- Array morphs;
-};
-
-struct VertexWeightMapping {
- Vector<float> weights;
- Vector<int> bones;
- // This extra vector is used because the bone id is computed in a second step.
- // TODO Get rid of this extra step is a good idea.
- Vector<Ref<FBXBone>> bones_ref;
-};
-
-template <class T>
-struct VertexData {
- int polygon_index;
- T data;
-};
-
-// Caches mesh information and instantiates meshes for you using helper functions.
-struct FBXMeshData : RefCounted {
- struct MorphVertexData {
- // TODO we have only these??
- /// Each element is a vertex. Not supposed to be void.
- Vector<Vector3> vertices;
- /// Each element is a vertex. Not supposed to be void.
- Vector<Vector3> normals;
- };
-
- // FIXME: remove this is a hack for testing only
- mutable const FBXDocParser::MeshGeometry *mesh_geometry = nullptr;
-
- Ref<FBXNode> mesh_node = nullptr;
- /// vertex id, Weight Info
- /// later: perf we can use array here
- HashMap<int, VertexWeightMapping> vertex_weights;
-
- // translate fbx mesh data from document context to FBX Mesh Geometry Context
- bool valid_weight_indexes = false;
-
- ImporterMeshInstance3D *create_fbx_mesh(const ImportState &state, const FBXDocParser::MeshGeometry *p_mesh_geometry, const FBXDocParser::Model *model, bool use_compression);
-
- void gen_weight_info(Ref<SurfaceTool> st, int vertex_id) const;
-
- /* mesh maximum weight count */
- bool valid_weight_count = false;
- int max_weight_count = 0;
- uint64_t armature_id = 0;
- bool valid_armature_id = false;
- ImporterMeshInstance3D *godot_mesh_instance = nullptr;
-
-private:
- void sanitize_vertex_weights(const ImportState &state);
-
- /// Make sure to reorganize the vertices so that the correct UV is taken.
- /// This step is needed because differently from the normal, that can be
- /// combined, the UV may need its own triangle because sometimes they have
- /// really different UV for the same vertex but different polygon.
- /// This function make sure to add another vertex for those UVS.
- void reorganize_vertices(
- std::vector<int> &r_polygon_indices,
- std::vector<Vector3> &r_vertices,
- HashMap<int, Vector3> &r_normals,
- HashMap<int, Vector2> &r_uv_1,
- HashMap<int, Vector2> &r_uv_2,
- HashMap<int, Color> &r_color,
- HashMap<String, MorphVertexData> &r_morphs,
- HashMap<int, HashMap<int, Vector3>> &r_normals_raw,
- HashMap<int, HashMap<int, Color>> &r_colors_raw,
- HashMap<int, HashMap<int, Vector2>> &r_uv_1_raw,
- HashMap<int, HashMap<int, Vector2>> &r_uv_2_raw);
-
- void add_vertex(
- const ImportState &state,
- Ref<SurfaceTool> p_surface_tool,
- real_t p_scale,
- int p_vertex,
- const std::vector<Vector3> &p_vertices_position,
- const HashMap<int, Vector3> &p_normals,
- const HashMap<int, Vector2> &p_uvs_0,
- const HashMap<int, Vector2> &p_uvs_1,
- const HashMap<int, Color> &p_colors,
- const Vector3 &p_morph_value = Vector3(),
- const Vector3 &p_morph_normal = Vector3());
-
- void triangulate_polygon(SurfaceData *surface, const Vector<int> &p_polygon_vertex, const std::vector<Vector3> &p_vertices) const;
-
- /// This function is responsible to convert the FBX polygon vertex to
- /// vertex index.
- /// The polygon vertices are stored in an array with some negative
- /// values. The negative values define the last face index.
- /// For example the following `face_array` contains two faces, the former
- /// with 3 vertices and the latter with a line:
- /// [0,2,-2,3,-5]
- /// Parsed as:
- /// [0, 2, 1, 3, 4]
- /// The negative values are computed using this formula: `(-value) - 1`
- ///
- /// Returns the vertex index from the polygon vertex.
- /// Returns -1 if `p_index` is invalid.
- int get_vertex_from_polygon_vertex(const std::vector<int> &p_face_indices, int p_index) const;
-
- /// Returns true if this polygon_vertex_index is the end of a new polygon.
- bool is_end_of_polygon(const std::vector<int> &p_face_indices, int p_index) const;
-
- /// Returns true if this polygon_vertex_index is the begin of a new polygon.
- bool is_start_of_polygon(const std::vector<int> &p_face_indices, int p_index) const;
-
- /// Returns the number of polygons.
- int count_polygons(const std::vector<int> &p_face_indices) const;
-
- /// Used to extract data from the `MappingData` aligned with vertex.
- /// Useful to extract normal/uvs/colors/tangents/etc...
- /// If the function fails somehow, it returns an hollow vector and print an error.
- template <class R, class T>
- HashMap<int, R> extract_per_vertex_data(
- int p_vertex_count,
- const std::vector<FBXDocParser::MeshGeometry::Edge> &p_edges,
- const std::vector<int> &p_mesh_indices,
- const FBXDocParser::MeshGeometry::MappingData<T> &p_mapping_data,
- R (*collector_function)(const Vector<VertexData<T>> *p_vertex_data, R p_fall_back),
- R p_fall_back) const;
-
- /// Used to extract data from the `MappingData` organized per polygon.
- /// Useful to extract the material
- /// If the function fails somehow, it returns an hollow vector and print an error.
- template <class T>
- HashMap<int, T> extract_per_polygon(
- int p_vertex_count,
- const std::vector<int> &p_face_indices,
- const FBXDocParser::MeshGeometry::MappingData<T> &p_fbx_data,
- T p_fallback_value) const;
-
- /// Extracts the morph data and organizes it per vertices.
- /// The returned `MorphVertexData` arrays are never something different
- /// then the `vertex_count`.
- void extract_morphs(const FBXDocParser::MeshGeometry *mesh_geometry, HashMap<String, MorphVertexData> &r_data);
-};
-
-#endif // FBX_MESH_DATA_H
diff --git a/modules/fbx/data/fbx_node.h b/modules/fbx/data/fbx_node.h
deleted file mode 100644
index 7a4139dcdf..0000000000
--- a/modules/fbx/data/fbx_node.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*************************************************************************/
-/* fbx_node.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. */
-/*************************************************************************/
-
-#ifndef FBX_NODE_H
-#define FBX_NODE_H
-
-#include "fbx_skeleton.h"
-#include "model_abstraction.h"
-#include "pivot_transform.h"
-
-#include "fbx_parser/FBXDocument.h"
-
-class Node3D;
-struct PivotTransform;
-
-struct FBXNode : RefCounted, ModelAbstraction {
- uint64_t current_node_id = 0;
- String node_name = String();
- Node3D *godot_node = nullptr;
-
- // used to parent the skeleton once the tree is built.
- Ref<FBXSkeleton> skeleton_node = Ref<FBXSkeleton>();
-
- void set_parent(Ref<FBXNode> p_parent) {
- fbx_parent = p_parent;
- }
-
- void set_pivot_transform(Ref<PivotTransform> p_pivot_transform) {
- pivot_transform = p_pivot_transform;
- }
-
- Ref<PivotTransform> pivot_transform = Ref<PivotTransform>(); // local and global xform data
- Ref<FBXNode> fbx_parent = Ref<FBXNode>(); // parent node
-};
-
-#endif // FBX_NODE_H
diff --git a/modules/fbx/data/fbx_skeleton.cpp b/modules/fbx/data/fbx_skeleton.cpp
deleted file mode 100644
index 0225df16af..0000000000
--- a/modules/fbx/data/fbx_skeleton.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/*************************************************************************/
-/* fbx_skeleton.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 "fbx_skeleton.h"
-
-#include "import_state.h"
-
-#include "tools/import_utils.h"
-
-void FBXSkeleton::init_skeleton(const ImportState &state) {
- int skeleton_bone_count = skeleton_bones.size();
-
- if (skeleton == nullptr && skeleton_bone_count > 0) {
- skeleton = memnew(Skeleton3D);
-
- if (fbx_node.is_valid()) {
- // cache skeleton attachment for later during node creation
- // can't be done until after node hierarchy is built
- if (fbx_node->godot_node != state.root) {
- fbx_node->skeleton_node = Ref<FBXSkeleton>(this);
- print_verbose("cached armature skeleton attachment for node " + fbx_node->node_name);
- } else {
- // root node must never be a skeleton to prevent cyclic skeletons from being allowed (skeleton in a skeleton)
- fbx_node->godot_node->add_child(skeleton);
- skeleton->set_owner(state.root_owner);
- skeleton->set_name("Skeleton3D");
- print_verbose("created armature skeleton for root");
- }
- } else {
- memfree(skeleton);
- skeleton = nullptr;
- print_error("[doc] skeleton has no valid node to parent nodes to - erasing");
- skeleton_bones.clear();
- return;
- }
- }
-
- // Make the bone name uniques.
- for (int x = 0; x < skeleton_bone_count; x++) {
- Ref<FBXBone> bone = skeleton_bones[x];
- if (bone.is_valid()) {
- // Make sure the bone name is unique.
- const String bone_name = bone->bone_name;
- int same_name_count = 0;
- for (int y = x + 1; y < skeleton_bone_count; y++) {
- Ref<FBXBone> other_bone = skeleton_bones[y];
- if (other_bone.is_valid()) {
- if (other_bone->bone_name == bone_name) {
- same_name_count += 1;
- other_bone->bone_name += "_" + itos(same_name_count);
- }
- }
- }
- }
- }
-
- Map<int, Ref<FBXBone>> bone_map;
- // implement fbx cluster skin logic here this is where it goes
- int bone_count = 0;
- for (int x = 0; x < skeleton_bone_count; x++) {
- Ref<FBXBone> bone = skeleton_bones[x];
- if (bone.is_valid()) {
- skeleton->add_bone(bone->bone_name);
- bone->godot_bone_id = bone_count;
- bone->fbx_skeleton = Ref<FBXSkeleton>(this);
- bone_map.insert(bone_count, bone);
- print_verbose("added bone " + itos(bone->bone_id) + " " + bone->bone_name);
- bone_count++;
- }
- }
-
- ERR_FAIL_COND_MSG(skeleton->get_bone_count() != bone_count, "Not all bones got added, is the file corrupted?");
-
- for (const KeyValue<int, Ref<FBXBone>> &bone_element : bone_map) {
- const Ref<FBXBone> bone = bone_element.value;
- int bone_index = bone_element.key;
- print_verbose("working on bone: " + itos(bone_index) + " bone name:" + bone->bone_name);
-
- skeleton->set_bone_rest(bone->godot_bone_id, get_unscaled_transform(bone->node->pivot_transform->LocalTransform, state.scale));
- {
- Transform3D base_xform = bone->node->pivot_transform->LocalTransform;
-
- skeleton->set_bone_pose_position(bone_index, base_xform.origin);
- skeleton->set_bone_pose_rotation(bone_index, base_xform.basis.get_rotation_quaternion());
- skeleton->set_bone_pose_scale(bone_index, base_xform.basis.get_scale());
- }
-
- // lookup parent ID
- if (bone->valid_parent && state.fbx_bone_map.has(bone->parent_bone_id)) {
- Ref<FBXBone> parent_bone = state.fbx_bone_map[bone->parent_bone_id];
- int bone_id = skeleton->find_bone(parent_bone->bone_name);
- if (bone_id != -1) {
- skeleton->set_bone_parent(bone_index, bone_id);
- } else {
- print_error("invalid bone parent: " + parent_bone->bone_name);
- }
- } else {
- if (bone->godot_bone_id != -1) {
- skeleton->set_bone_parent(bone_index, -1); // no parent for this bone
- }
- }
- }
-}
diff --git a/modules/fbx/data/fbx_skeleton.h b/modules/fbx/data/fbx_skeleton.h
deleted file mode 100644
index e615d0f5e3..0000000000
--- a/modules/fbx/data/fbx_skeleton.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*************************************************************************/
-/* fbx_skeleton.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. */
-/*************************************************************************/
-
-#ifndef FBX_SKELETON_H
-#define FBX_SKELETON_H
-
-#include "fbx_bone.h"
-#include "fbx_node.h"
-#include "model_abstraction.h"
-
-#include "core/object/ref_counted.h"
-#include "scene/3d/skeleton_3d.h"
-
-struct FBXNode;
-struct ImportState;
-struct FBXBone;
-
-struct FBXSkeleton : RefCounted {
- Ref<FBXNode> fbx_node = Ref<FBXNode>();
- Vector<Ref<FBXBone>> skeleton_bones = Vector<Ref<FBXBone>>();
- Skeleton3D *skeleton = nullptr;
-
- void init_skeleton(const ImportState &state);
-};
-
-#endif // FBX_SKELETON_H
diff --git a/modules/fbx/data/import_state.h b/modules/fbx/data/import_state.h
deleted file mode 100644
index eff11e3bb8..0000000000
--- a/modules/fbx/data/import_state.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*************************************************************************/
-/* import_state.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. */
-/*************************************************************************/
-
-#ifndef IMPORT_STATE_H
-#define IMPORT_STATE_H
-
-#include "fbx_mesh_data.h"
-#include "tools/import_utils.h"
-#include "tools/validation_tools.h"
-
-#include "pivot_transform.h"
-
-#include "core/io/resource_importer.h"
-#include "core/templates/vector.h"
-#include "editor/import/resource_importer_scene.h"
-#include "editor/project_settings_editor.h"
-#include "scene/3d/mesh_instance_3d.h"
-#include "scene/3d/node_3d.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/animation/animation_player.h"
-#include "scene/resources/animation.h"
-#include "scene/resources/surface_tool.h"
-
-#include "modules/fbx/fbx_parser/FBXDocument.h"
-#include "modules/fbx/fbx_parser/FBXImportSettings.h"
-#include "modules/fbx/fbx_parser/FBXMeshGeometry.h"
-#include "modules/fbx/fbx_parser/FBXParser.h"
-#include "modules/fbx/fbx_parser/FBXTokenizer.h"
-#include "modules/fbx/fbx_parser/FBXUtil.h"
-
-struct FBXBone;
-struct FBXMeshData;
-struct FBXNode;
-struct FBXSkeleton;
-
-struct ImportState {
- bool enable_material_import = true;
- bool enable_animation_import = true;
- bool is_blender_fbx = false;
-
- Map<StringName, Ref<Texture>> cached_image_searches;
- Map<uint64_t, Ref<Material>> cached_materials;
-
- String path = String();
- Node3D *root_owner = nullptr;
- Node3D *root = nullptr;
- real_t scale = 0.01;
- Ref<FBXNode> fbx_root_node = Ref<FBXNode>();
- // skeleton map - merged automatically when they are on the same x node in the tree so we can merge them automatically.
- Map<uint64_t, Ref<FBXSkeleton>> skeleton_map = Map<uint64_t, Ref<FBXSkeleton>>();
-
- // nodes on the same level get merged automatically.
- //Map<uint64_t, Skeleton3D *> armature_map;
- AnimationPlayer *animation_player = nullptr;
-
- // Generation 4 - Raw document accessing for bone/skin/joint/kLocators
- // joints are not necessarily bones but must be merged into the skeleton
- // (bone id), bone
- Map<uint64_t, Ref<FBXBone>> fbx_bone_map = Map<uint64_t, Ref<FBXBone>>(); // this is the bone name and setup information required for joints
- // this will never contain joints only bones attached to a mesh.
-
- // Generation 4 - Raw document for creating the nodes transforms in the scene
- // this is a list of the nodes in the scene
- // (id, node)
- List<Ref<FBXNode>> fbx_node_list = List<Ref<FBXNode>>();
-
- // All nodes which have been created in the scene
- // this will not contain the root node of the scene
- Map<uint64_t, Ref<FBXNode>> fbx_target_map = Map<uint64_t, Ref<FBXNode>>();
-
- // mesh nodes which are created in node / mesh step - used for populating skin poses in MeshSkins
- Map<uint64_t, Ref<FBXNode>> MeshNodes = Map<uint64_t, Ref<FBXNode>>();
- // mesh skin map
- Map<uint64_t, Ref<Skin>> MeshSkins = Map<uint64_t, Ref<Skin>>();
-
- // this is the container for the mesh weight information and eventually
- // any mesh data
- // but not the skin, just stuff important for rendering
- // skin is applied to mesh instance so not really required to be in here yet.
- // maybe later
- // fbx mesh id, FBXMeshData
- Map<uint64_t, Ref<FBXMeshData>> renderer_mesh_data = Map<uint64_t, Ref<FBXMeshData>>();
-};
-
-#endif // IMPORT_STATE_H
diff --git a/modules/fbx/data/model_abstraction.h b/modules/fbx/data/model_abstraction.h
deleted file mode 100644
index 4c3f81b163..0000000000
--- a/modules/fbx/data/model_abstraction.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*************************************************************************/
-/* model_abstraction.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. */
-/*************************************************************************/
-
-#ifndef MODEL_ABSTRACTION_H
-#define MODEL_ABSTRACTION_H
-
-#include "modules/fbx/fbx_parser/FBXDocument.h"
-
-struct ModelAbstraction {
- mutable const FBXDocParser::Model *fbx_model = nullptr;
-
- void set_model(const FBXDocParser::Model *p_model) {
- fbx_model = p_model;
- }
-
- bool has_model() const {
- return fbx_model != nullptr;
- }
-
- const FBXDocParser::Model *get_model() const {
- return fbx_model;
- }
-};
-
-#endif // MODEL_ABSTRACTION_H
diff --git a/modules/fbx/data/pivot_transform.cpp b/modules/fbx/data/pivot_transform.cpp
deleted file mode 100644
index 9457b19a7f..0000000000
--- a/modules/fbx/data/pivot_transform.cpp
+++ /dev/null
@@ -1,307 +0,0 @@
-/*************************************************************************/
-/* pivot_transform.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 "pivot_transform.h"
-
-#include "tools/import_utils.h"
-
-void PivotTransform::ReadTransformChain() {
- const FBXDocParser::PropertyTable *props = fbx_model;
- const FBXDocParser::Model::RotOrder &rot = fbx_model->RotationOrder();
- const FBXDocParser::TransformInheritance &inheritType = fbx_model->InheritType();
- inherit_type = inheritType; // copy the inherit type we need it in the second step.
- print_verbose("Model: " + String(fbx_model->Name().c_str()) + " Has inherit type: " + itos(fbx_model->InheritType()));
- bool ok = false;
- raw_pre_rotation = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "PreRotation", ok));
- if (ok) {
- pre_rotation = ImportUtils::EulerToQuaternion(rot, ImportUtils::deg2rad(raw_pre_rotation));
- print_verbose("valid pre_rotation: " + raw_pre_rotation + " euler conversion: " + (pre_rotation.get_euler() * (180 / Math_PI)));
- }
- raw_post_rotation = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "PostRotation", ok));
- if (ok) {
- post_rotation = ImportUtils::EulerToQuaternion(FBXDocParser::Model::RotOrder_EulerXYZ, ImportUtils::deg2rad(raw_post_rotation));
- print_verbose("valid post_rotation: " + raw_post_rotation + " euler conversion: " + (pre_rotation.get_euler() * (180 / Math_PI)));
- }
- const Vector3 &RotationPivot = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "RotationPivot", ok));
- if (ok) {
- rotation_pivot = ImportUtils::FixAxisConversions(RotationPivot);
- }
- const Vector3 &RotationOffset = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "RotationOffset", ok));
- if (ok) {
- rotation_offset = ImportUtils::FixAxisConversions(RotationOffset);
- }
- const Vector3 &ScalingOffset = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "ScalingOffset", ok));
- if (ok) {
- scaling_offset = ImportUtils::FixAxisConversions(ScalingOffset);
- }
- const Vector3 &ScalingPivot = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "ScalingPivot", ok));
- if (ok) {
- scaling_pivot = ImportUtils::FixAxisConversions(ScalingPivot);
- }
- const Vector3 &Translation = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "Lcl Translation", ok));
- if (ok) {
- translation = ImportUtils::FixAxisConversions(Translation);
- }
- raw_rotation = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "Lcl Rotation", ok));
- if (ok) {
- rotation = ImportUtils::EulerToQuaternion(rot, ImportUtils::deg2rad(raw_rotation));
- }
- const Vector3 &Scaling = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "Lcl Scaling", ok));
- if (ok) {
- scaling = Scaling;
- } else {
- scaling = Vector3(1, 1, 1);
- }
- const Vector3 &GeometricScaling = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "GeometricScaling", ok));
- if (ok) {
- geometric_scaling = GeometricScaling;
- } else {
- geometric_scaling = Vector3(1, 1, 1);
- }
-
- const Vector3 &GeometricRotation = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "GeometricRotation", ok));
- if (ok) {
- geometric_rotation = ImportUtils::EulerToQuaternion(rot, ImportUtils::deg2rad(GeometricRotation));
- } else {
- geometric_rotation = Quaternion();
- }
-
- const Vector3 &GeometricTranslation = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "GeometricTranslation", ok));
- if (ok) {
- geometric_translation = ImportUtils::FixAxisConversions(GeometricTranslation);
- } else {
- geometric_translation = Vector3(0, 0, 0);
- }
-
- if (geometric_rotation != Quaternion()) {
- print_error("geometric rotation is unsupported!");
- //CRASH_COND(true);
- }
-
- if (!geometric_scaling.is_equal_approx(Vector3(1, 1, 1))) {
- print_error("geometric scaling is unsupported!");
- //CRASH_COND(true);
- }
-
- if (!geometric_translation.is_equal_approx(Vector3(0, 0, 0))) {
- print_error("geometric translation is unsupported.");
- //CRASH_COND(true);
- }
-}
-
-Transform3D PivotTransform::ComputeLocalTransform(Vector3 p_translation, Quaternion p_rotation, Vector3 p_scaling) const {
- Transform3D T, Roff, Rp, Soff, Sp, S;
-
- // Here I assume this is the operation which needs done.
- // Its WorldTransform * V
-
- // Origin pivots
- T.set_origin(p_translation);
- Roff.set_origin(rotation_offset);
- Rp.set_origin(rotation_pivot);
- Soff.set_origin(scaling_offset);
- Sp.set_origin(scaling_pivot);
-
- // Scaling node
- S.scale(p_scaling);
- // Rotation pivots
- Transform3D Rpre = Transform3D(pre_rotation);
- Transform3D R = Transform3D(p_rotation);
- Transform3D Rpost = Transform3D(post_rotation);
-
- return T * Roff * Rp * Rpre * R * Rpost.affine_inverse() * Rp.affine_inverse() * Soff * Sp * S * Sp.affine_inverse();
-}
-
-Transform3D PivotTransform::ComputeGlobalTransform(Transform3D t) const {
- Vector3 pos = t.origin;
- Vector3 scale = t.basis.get_scale();
- Quaternion rot = t.basis.get_rotation_quaternion();
- return ComputeGlobalTransform(pos, rot, scale);
-}
-
-Transform3D PivotTransform::ComputeLocalTransform(Transform3D t) const {
- Vector3 pos = t.origin;
- Vector3 scale = t.basis.get_scale();
- Quaternion rot = t.basis.get_rotation_quaternion();
- return ComputeLocalTransform(pos, rot, scale);
-}
-
-Transform3D PivotTransform::ComputeGlobalTransform(Vector3 p_translation, Quaternion p_rotation, Vector3 p_scaling) const {
- Transform3D T, Roff, Rp, Soff, Sp, S;
-
- // Here I assume this is the operation which needs done.
- // Its WorldTransform * V
-
- // Origin pivots
- T.set_origin(p_translation);
- Roff.set_origin(rotation_offset);
- Rp.set_origin(rotation_pivot);
- Soff.set_origin(scaling_offset);
- Sp.set_origin(scaling_pivot);
-
- // Scaling node
- S.scale(p_scaling);
-
- // Rotation pivots
- Transform3D Rpre = Transform3D(pre_rotation);
- Transform3D R = Transform3D(p_rotation);
- Transform3D Rpost = Transform3D(post_rotation);
-
- Transform3D parent_global_xform;
- Transform3D parent_local_scaling_m;
-
- if (parent_transform.is_valid()) {
- parent_global_xform = parent_transform->GlobalTransform;
- parent_local_scaling_m = parent_transform->Local_Scaling_Matrix;
- }
-
- Transform3D local_rotation_m, parent_global_rotation_m;
- Quaternion parent_global_rotation = parent_global_xform.basis.get_rotation_quaternion();
- parent_global_rotation_m.basis.set_quaternion(parent_global_rotation);
- local_rotation_m = Rpre * R * Rpost;
-
- //Basis parent_global_rotation = Basis(parent_global_xform.get_basis().get_rotation_quaternion().normalized());
-
- Transform3D local_shear_scaling, parent_shear_scaling, parent_shear_rotation, parent_shear_translation;
- Vector3 parent_translation = parent_global_xform.get_origin();
- parent_shear_translation.origin = parent_translation;
- parent_shear_rotation = parent_shear_translation.affine_inverse() * parent_global_xform;
- parent_shear_scaling = parent_global_rotation_m.affine_inverse() * parent_shear_rotation;
- local_shear_scaling = S;
-
- // Inherit type handler - we don't care about T here, just reordering RSrs etc.
- Transform3D global_rotation_scale;
- if (inherit_type == FBXDocParser::Transform_RrSs) {
- global_rotation_scale = parent_global_rotation_m * local_rotation_m * parent_shear_scaling * local_shear_scaling;
- } else if (inherit_type == FBXDocParser::Transform_RSrs) {
- global_rotation_scale = parent_global_rotation_m * parent_shear_scaling * local_rotation_m * local_shear_scaling;
- } else if (inherit_type == FBXDocParser::Transform_Rrs) {
- Transform3D parent_global_shear_m_noLocal = parent_shear_scaling * parent_local_scaling_m.affine_inverse();
- global_rotation_scale = parent_global_rotation_m * local_rotation_m * parent_global_shear_m_noLocal * local_shear_scaling;
- }
- Transform3D local_transform = T * Roff * Rp * Rpre * R * Rpost.affine_inverse() * Rp.affine_inverse() * Soff * Sp * S * Sp.affine_inverse();
- //Transform3D local_translation_pivoted = Transform3D(Basis(), LocalTransform.origin);
-
- ERR_FAIL_COND_V_MSG(local_transform.basis.determinant() == 0, Transform3D(), "Det == 0 prevented in scene file");
-
- // manual hack to force SSC not to be compensated for - until we can handle it properly with tests
- return parent_global_xform * local_transform;
-}
-
-void PivotTransform::ComputePivotTransform() {
- Transform3D T, Roff, Rp, Soff, Sp, S;
-
- // Here I assume this is the operation which needs done.
- // Its WorldTransform * V
-
- // Origin pivots
- T.set_origin(translation);
- Roff.set_origin(rotation_offset);
- Rp.set_origin(rotation_pivot);
- Soff.set_origin(scaling_offset);
- Sp.set_origin(scaling_pivot);
-
- // Scaling node
- if (!scaling.is_equal_approx(Vector3())) {
- S.scale(scaling);
- } else {
- S.scale(Vector3(1, 1, 1));
- }
- Local_Scaling_Matrix = S; // copy for when node / child is looking for the value of this.
-
- // Rotation pivots
- Transform3D Rpre = Transform3D(pre_rotation);
- Transform3D R = Transform3D(rotation);
- Transform3D Rpost = Transform3D(post_rotation);
-
- Transform3D parent_global_xform;
- Transform3D parent_local_scaling_m;
-
- if (parent_transform.is_valid()) {
- parent_global_xform = parent_transform->GlobalTransform;
- parent_local_scaling_m = parent_transform->Local_Scaling_Matrix;
- }
-
- Transform3D local_rotation_m, parent_global_rotation_m;
- Quaternion parent_global_rotation = parent_global_xform.basis.get_rotation_quaternion();
- parent_global_rotation_m.basis.set_quaternion(parent_global_rotation);
- local_rotation_m = Rpre * R * Rpost;
-
- //Basis parent_global_rotation = Basis(parent_global_xform.get_basis().get_rotation_quaternion().normalized());
-
- Transform3D local_shear_scaling, parent_shear_scaling, parent_shear_rotation, parent_shear_translation;
- Vector3 parent_translation = parent_global_xform.get_origin();
- parent_shear_translation.origin = parent_translation;
- parent_shear_rotation = parent_shear_translation.affine_inverse() * parent_global_xform;
- parent_shear_scaling = parent_global_rotation_m.affine_inverse() * parent_shear_rotation;
- local_shear_scaling = S;
-
- // Inherit type handler - we don't care about T here, just reordering RSrs etc.
- Transform3D global_rotation_scale;
- if (inherit_type == FBXDocParser::Transform_RrSs) {
- global_rotation_scale = parent_global_rotation_m * local_rotation_m * parent_shear_scaling * local_shear_scaling;
- } else if (inherit_type == FBXDocParser::Transform_RSrs) {
- global_rotation_scale = parent_global_rotation_m * parent_shear_scaling * local_rotation_m * local_shear_scaling;
- } else if (inherit_type == FBXDocParser::Transform_Rrs) {
- Transform3D parent_global_shear_m_noLocal = parent_shear_scaling * parent_local_scaling_m.inverse();
- global_rotation_scale = parent_global_rotation_m * local_rotation_m * parent_global_shear_m_noLocal * local_shear_scaling;
- }
- LocalTransform = Transform3D();
- LocalTransform = T * Roff * Rp * Rpre * R * Rpost.affine_inverse() * Rp.affine_inverse() * Soff * Sp * S * Sp.affine_inverse();
-
- ERR_FAIL_COND_MSG(LocalTransform.basis.determinant() == 0, "invalid scale reset");
-
- Transform3D local_translation_pivoted = Transform3D(Basis(), LocalTransform.origin);
- GlobalTransform = Transform3D();
- //GlobalTransform = parent_global_xform * LocalTransform;
- Transform3D global_origin = Transform3D(Basis(), parent_translation);
- GlobalTransform = (global_origin * local_translation_pivoted) * global_rotation_scale;
-
- ImportUtils::debug_xform("local xform calculation", LocalTransform);
- print_verbose("scale of node: " + S.basis.get_scale_local());
- print_verbose("---------------------------------------------------------------");
-}
-
-void PivotTransform::Execute() {
- ReadTransformChain();
- ComputePivotTransform();
-
- ImportUtils::debug_xform("global xform: ", GlobalTransform);
-
- if (LocalTransform.basis.determinant() == 0) {
- print_error("Serious det == 0!");
- }
-
- if (GlobalTransform.basis.determinant() == 0) {
- print_error("Serious! node has det == 0!");
- }
-
- computed_global_xform = true;
-}
diff --git a/modules/fbx/data/pivot_transform.h b/modules/fbx/data/pivot_transform.h
deleted file mode 100644
index df97c8db57..0000000000
--- a/modules/fbx/data/pivot_transform.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*************************************************************************/
-/* pivot_transform.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. */
-/*************************************************************************/
-
-#ifndef PIVOT_TRANSFORM_H
-#define PIVOT_TRANSFORM_H
-
-#include "core/math/transform_3d.h"
-#include "core/object/ref_counted.h"
-
-#include "model_abstraction.h"
-
-#include "fbx_parser/FBXDocument.h"
-#include "tools/import_utils.h"
-
-enum TransformationComp {
- TransformationComp_Translation,
- TransformationComp_Scaling,
- TransformationComp_Rotation,
- TransformationComp_RotationOffset,
- TransformationComp_RotationPivot,
- TransformationComp_PreRotation,
- TransformationComp_PostRotation,
- TransformationComp_ScalingOffset,
- TransformationComp_ScalingPivot,
- TransformationComp_GeometricTranslation,
- TransformationComp_GeometricRotation,
- TransformationComp_GeometricScaling,
- TransformationComp_MAXIMUM
-};
-// Abstract away pivot data so its simpler to handle
-struct PivotTransform : RefCounted, ModelAbstraction {
- // at the end we want to keep geometric_ everything, post and pre rotation
- // these are used during animation data processing / keyframe ingestion the rest can be simplified down / out.
- Quaternion pre_rotation = Quaternion();
- Quaternion post_rotation = Quaternion();
- Quaternion rotation = Quaternion();
- Quaternion geometric_rotation = Quaternion();
- Vector3 rotation_pivot = Vector3();
- Vector3 rotation_offset = Vector3();
- Vector3 scaling_offset = Vector3(1.0, 1.0, 1.0);
- Vector3 scaling_pivot = Vector3(1.0, 1.0, 1.0);
- Vector3 translation = Vector3();
- Vector3 scaling = Vector3(1.0, 1.0, 1.0);
- Vector3 geometric_scaling = Vector3(1.0, 1.0, 1.0);
- Vector3 geometric_translation = Vector3();
-
- Vector3 raw_rotation = Vector3();
- Vector3 raw_post_rotation = Vector3();
- Vector3 raw_pre_rotation = Vector3();
-
- /* Read pivots from the document */
- void ReadTransformChain();
-
- void debug_pivot_xform(String p_name) {
- print_verbose("debugging node name: " + p_name);
- print_verbose("raw rotation: " + raw_rotation * (180 / Math_PI));
- print_verbose("raw pre_rotation " + raw_pre_rotation * (180 / Math_PI));
- print_verbose("raw post_rotation " + raw_post_rotation * (180 / Math_PI));
- }
-
- Transform3D ComputeGlobalTransform(Transform3D t) const;
- Transform3D ComputeLocalTransform(Transform3D t) const;
- Transform3D ComputeGlobalTransform(Vector3 p_translation, Quaternion p_rotation, Vector3 p_scaling) const;
- Transform3D ComputeLocalTransform(Vector3 p_translation, Quaternion p_rotation, Vector3 p_scaling) const;
-
- /* Extract into xforms and calculate once */
- void ComputePivotTransform();
-
- /* Execute the command for the pivot generation */
- void Execute();
-
- void set_parent(Ref<PivotTransform> p_parent) {
- parent_transform = p_parent;
- }
-
- bool computed_global_xform = false;
- Ref<PivotTransform> parent_transform = Ref<PivotTransform>();
- //Transform chain[TransformationComp_MAXIMUM];
-
- // cached for later use
- Transform3D GlobalTransform = Transform3D();
- Transform3D LocalTransform = Transform3D();
- Transform3D Local_Scaling_Matrix = Transform3D(); // used for inherit type.
- Transform3D GeometricTransform = Transform3D(); // 3DS max only
- FBXDocParser::TransformInheritance inherit_type = FBXDocParser::TransformInheritance_MAX; // maya fbx requires this - sorry <3
-};
-
-#endif // PIVOT_TRANSFORM_H