diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/assimp/SCsub | 108 | ||||
-rw-r--r-- | modules/assimp/config.py | 6 | ||||
-rw-r--r-- | modules/assimp/editor_scene_importer_assimp.cpp | 1485 | ||||
-rw-r--r-- | modules/assimp/editor_scene_importer_assimp.h | 149 | ||||
-rwxr-xr-x | modules/assimp/godot_update_assimp.sh | 262 | ||||
-rw-r--r-- | modules/assimp/import_state.h | 132 | ||||
-rw-r--r-- | modules/assimp/import_utils.h | 463 | ||||
-rw-r--r-- | modules/assimp/register_types.cpp | 58 | ||||
-rw-r--r-- | modules/assimp/register_types.h | 37 |
9 files changed, 0 insertions, 2700 deletions
diff --git a/modules/assimp/SCsub b/modules/assimp/SCsub deleted file mode 100644 index 7213efb74d..0000000000 --- a/modules/assimp/SCsub +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python - -Import("env") -Import("env_modules") - -env_assimp = env_modules.Clone() - -# Thirdparty source files - -thirdparty_obj = [] - -# Force bundled version for now, there's no released version of Assimp with -# support for ArmaturePopulate which we use from their master branch. - -if True: # env['builtin_assimp']: - thirdparty_dir = "#thirdparty/assimp" - - env_assimp.Prepend(CPPPATH=["#thirdparty/assimp"]) - env_assimp.Prepend(CPPPATH=["#thirdparty/assimp/code"]) - env_assimp.Prepend(CPPPATH=["#thirdparty/assimp/include"]) - - # env_assimp.Append(CPPDEFINES=['ASSIMP_DOUBLE_PRECISION']) # TODO default to what godot is compiled with for future double support - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_SINGLETHREADED"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_BOOST_WORKAROUND"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OWN_ZLIB"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_EXPORT"]) - - # Importers we don't need - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_3D_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_3DS_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_3MF_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_AC_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_AMF_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_ASE_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_ASSBIN_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_B3D_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_BLEND_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_BVH_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_C4D_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_COB_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_COLLADA_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_CSM_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_DXF_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_GLTF2_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_GLTF_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_HMP_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_IFC_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_IRR_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_IRRMESH_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_LWO_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_LWS_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_M3D_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MD2_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MD3_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MD5_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MD5_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MDC_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MDL_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MMD_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MS3D_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_NDO_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_NFF_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OBJ_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OFF_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OGRE_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OPENGEX_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_PLY_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_Q3BSP_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_Q3D_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_RAW_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_SIB_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_SMD_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_STEP_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_STL_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_TERRAGEN_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_X3D_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_XGL_IMPORTER"]) - env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_X_IMPORTER"]) - - if env["platform"] == "windows": - env_assimp.Append(CPPDEFINES=["PLATFORM_WINDOWS"]) - env_assimp.Append(CPPDEFINES=[("PLATFORM", "WINDOWS")]) - elif env["platform"] == "linuxbsd": - env_assimp.Append(CPPDEFINES=["PLATFORM_LINUX"]) - env_assimp.Append(CPPDEFINES=[("PLATFORM", "LINUX")]) - elif env["platform"] == "osx": - env_assimp.Append(CPPDEFINES=["PLATFORM_DARWIN"]) - env_assimp.Append(CPPDEFINES=[("PLATFORM", "DARWIN")]) - - env_thirdparty = env_assimp.Clone() - env_thirdparty.disable_warnings() - env_thirdparty.add_source_files(thirdparty_obj, Glob("#thirdparty/assimp/code/CApi/*.cpp")) - env_thirdparty.add_source_files(thirdparty_obj, Glob("#thirdparty/assimp/code/Common/*.cpp")) - env_thirdparty.add_source_files(thirdparty_obj, Glob("#thirdparty/assimp/code/PostProcessing/*.cpp")) - env_thirdparty.add_source_files(thirdparty_obj, Glob("#thirdparty/assimp/code/Material/*.cpp")) - env_thirdparty.add_source_files(thirdparty_obj, Glob("#thirdparty/assimp/code/FBX/*.cpp")) - env.modules_sources += thirdparty_obj - - -# Godot source files - -module_obj = [] - -env_assimp.add_source_files(module_obj, "*.cpp") -env.modules_sources += module_obj - -# Needed to force rebuilding the module files when the thirdparty library is updated. -env.Depends(module_obj, thirdparty_obj) diff --git a/modules/assimp/config.py b/modules/assimp/config.py deleted file mode 100644 index 53b8f2f2e3..0000000000 --- a/modules/assimp/config.py +++ /dev/null @@ -1,6 +0,0 @@ -def can_build(env, platform): - return env["tools"] - - -def configure(env): - pass diff --git a/modules/assimp/editor_scene_importer_assimp.cpp b/modules/assimp/editor_scene_importer_assimp.cpp deleted file mode 100644 index 796ee27a7d..0000000000 --- a/modules/assimp/editor_scene_importer_assimp.cpp +++ /dev/null @@ -1,1485 +0,0 @@ -/*************************************************************************/ -/* editor_scene_importer_assimp.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "editor_scene_importer_assimp.h" -#include "core/io/image_loader.h" -#include "editor/import/resource_importer_scene.h" -#include "import_utils.h" -#include "scene/3d/camera_3d.h" -#include "scene/3d/light_3d.h" -#include "scene/3d/mesh_instance_3d.h" -#include "scene/main/node.h" -#include "scene/resources/material.h" -#include "scene/resources/surface_tool.h" - -#include <assimp/matrix4x4.h> -#include <assimp/postprocess.h> -#include <assimp/scene.h> -#include <assimp/Importer.hpp> -#include <assimp/LogStream.hpp> - -// move into assimp -aiBone *get_bone_by_name(const aiScene *scene, aiString bone_name) { - for (unsigned int mesh_id = 0; mesh_id < scene->mNumMeshes; ++mesh_id) { - aiMesh *mesh = scene->mMeshes[mesh_id]; - - // iterate over all the bones on the mesh for this node only! - for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; boneIndex++) { - aiBone *bone = mesh->mBones[boneIndex]; - if (bone->mName == bone_name) { - printf("matched bone by name: %s\n", bone->mName.C_Str()); - return bone; - } - } - } - - return nullptr; -} - -void EditorSceneImporterAssimp::get_extensions(List<String> *r_extensions) const { - const String import_setting_string = "filesystem/import/open_asset_import/"; - - Map<String, ImportFormat> import_format; - { - Vector<String> exts; - exts.push_back("fbx"); - ImportFormat import = { exts, true }; - import_format.insert("fbx", import); - } - for (Map<String, ImportFormat>::Element *E = import_format.front(); E; E = E->next()) { - _register_project_setting_import(E->key(), import_setting_string, E->get().extensions, r_extensions, - E->get().is_default); - } -} - -void EditorSceneImporterAssimp::_register_project_setting_import(const String generic, const String import_setting_string, - const Vector<String> &exts, List<String> *r_extensions, - const bool p_enabled) const { - const String use_generic = "use_" + generic; - _GLOBAL_DEF(import_setting_string + use_generic, p_enabled, true); - if (ProjectSettings::get_singleton()->get(import_setting_string + use_generic)) { - for (int32_t i = 0; i < exts.size(); i++) { - r_extensions->push_back(exts[i]); - } - } -} - -uint32_t EditorSceneImporterAssimp::get_import_flags() const { - return IMPORT_SCENE; -} - -void EditorSceneImporterAssimp::_bind_methods() { -} - -Node *EditorSceneImporterAssimp::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, - List<String> *r_missing_deps, Error *r_err) { - Assimp::Importer importer; - importer.SetPropertyBool(AI_CONFIG_PP_FD_REMOVE, true); - // Cannot remove pivot points because the static mesh will be in the wrong place - importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, false); - int32_t max_bone_weights = 4; - //if (p_flags & IMPORT_ANIMATION_EIGHT_WEIGHTS) { - // const int eight_bones = 8; - // importer.SetPropertyBool(AI_CONFIG_PP_LBW_MAX_WEIGHTS, eight_bones); - // max_bone_weights = eight_bones; - //} - - importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT); - - //importer.SetPropertyFloat(AI_CONFIG_PP_DB_THRESHOLD, 1.0f); - int32_t post_process_Steps = aiProcess_CalcTangentSpace | - aiProcess_GlobalScale | - // imports models and listens to their file scale for CM to M conversions - //aiProcess_FlipUVs | - aiProcess_FlipWindingOrder | - // very important for culling so that it is done in the correct order. - //aiProcess_DropNormals | - //aiProcess_GenSmoothNormals | - //aiProcess_JoinIdenticalVertices | - aiProcess_ImproveCacheLocality | - //aiProcess_RemoveRedundantMaterials | // Causes a crash - //aiProcess_SplitLargeMeshes | - aiProcess_Triangulate | - aiProcess_GenUVCoords | - //aiProcess_FindDegenerates | - //aiProcess_SortByPType | - // aiProcess_FindInvalidData | - aiProcess_TransformUVCoords | - aiProcess_FindInstances | - //aiProcess_FixInfacingNormals | - //aiProcess_ValidateDataStructure | - aiProcess_OptimizeMeshes | - aiProcess_PopulateArmatureData | - //aiProcess_OptimizeGraph | - //aiProcess_Debone | - // aiProcess_EmbedTextures | - //aiProcess_SplitByBoneCount | - 0; - String g_path = ProjectSettings::get_singleton()->globalize_path(p_path); - aiScene *scene = (aiScene *)importer.ReadFile(g_path.utf8().ptr(), post_process_Steps); - - ERR_FAIL_COND_V_MSG(scene == nullptr, nullptr, String("Open Asset Import failed to open: ") + String(importer.GetErrorString())); - - return _generate_scene(p_path, scene, p_flags, p_bake_fps, max_bone_weights); -} - -template <class T> -struct EditorSceneImporterAssetImportInterpolate { - T lerp(const T &a, const T &b, float c) const { - return a + (b - a) * c; - } - - T catmull_rom(const T &p0, const T &p1, const T &p2, const T &p3, float t) { - float t2 = t * t; - float t3 = t2 * t; - - return 0.5f * ((2.0f * p1) + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3) * t2 + (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3); - } - - T bezier(T start, T control_1, T control_2, T end, float t) { - /* Formula from Wikipedia article on Bezier curves. */ - real_t omt = (1.0 - t); - real_t omt2 = omt * omt; - real_t omt3 = omt2 * omt; - real_t t2 = t * t; - real_t t3 = t2 * t; - - return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3; - } -}; - -//thank you for existing, partial specialization -template <> -struct EditorSceneImporterAssetImportInterpolate<Quat> { - Quat lerp(const Quat &a, const Quat &b, float c) const { - ERR_FAIL_COND_V_MSG(!a.is_normalized(), Quat(), "The quaternion \"a\" must be normalized."); - ERR_FAIL_COND_V_MSG(!b.is_normalized(), Quat(), "The quaternion \"b\" must be normalized."); - - return a.slerp(b, c).normalized(); - } - - Quat catmull_rom(const Quat &p0, const Quat &p1, const Quat &p2, const Quat &p3, float c) { - ERR_FAIL_COND_V_MSG(!p1.is_normalized(), Quat(), "The quaternion \"p1\" must be normalized."); - ERR_FAIL_COND_V_MSG(!p2.is_normalized(), Quat(), "The quaternion \"p2\" must be normalized."); - - return p1.slerp(p2, c).normalized(); - } - - Quat bezier(Quat start, Quat control_1, Quat control_2, Quat end, float t) { - ERR_FAIL_COND_V_MSG(!start.is_normalized(), Quat(), "The start quaternion must be normalized."); - ERR_FAIL_COND_V_MSG(!end.is_normalized(), Quat(), "The end quaternion must be normalized."); - - return start.slerp(end, t).normalized(); - } -}; - -template <class T> -T EditorSceneImporterAssimp::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, - AssetImportAnimation::Interpolation p_interp) { - //could use binary search, worth it? - int idx = -1; - for (int i = 0; i < p_times.size(); i++) { - if (p_times[i] > p_time) { - break; - } - idx++; - } - - EditorSceneImporterAssetImportInterpolate<T> interp; - - switch (p_interp) { - case AssetImportAnimation::INTERP_LINEAR: { - if (idx == -1) { - return p_values[0]; - } else if (idx >= p_times.size() - 1) { - return p_values[p_times.size() - 1]; - } - - float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]); - - return interp.lerp(p_values[idx], p_values[idx + 1], c); - - } break; - case AssetImportAnimation::INTERP_STEP: { - if (idx == -1) { - return p_values[0]; - } else if (idx >= p_times.size() - 1) { - return p_values[p_times.size() - 1]; - } - - return p_values[idx]; - - } break; - case AssetImportAnimation::INTERP_CATMULLROMSPLINE: { - if (idx == -1) { - return p_values[1]; - } else if (idx >= p_times.size() - 1) { - return p_values[1 + p_times.size() - 1]; - } - - float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]); - - return interp.catmull_rom(p_values[idx - 1], p_values[idx], p_values[idx + 1], p_values[idx + 3], c); - - } break; - case AssetImportAnimation::INTERP_CUBIC_SPLINE: { - if (idx == -1) { - return p_values[1]; - } else if (idx >= p_times.size() - 1) { - return p_values[(p_times.size() - 1) * 3 + 1]; - } - - float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]); - - T from = p_values[idx * 3 + 1]; - T c1 = from + p_values[idx * 3 + 2]; - T to = p_values[idx * 3 + 4]; - T c2 = to + p_values[idx * 3 + 3]; - - return interp.bezier(from, c1, c2, to, c); - - } break; - } - - ERR_FAIL_V(p_values[0]); -} - -aiBone *EditorSceneImporterAssimp::get_bone_from_stack(ImportState &state, aiString name) { - List<aiBone *>::Element *iter; - aiBone *bone = nullptr; - for (iter = state.bone_stack.front(); iter; iter = iter->next()) { - bone = (aiBone *)iter->get(); - - if (bone && bone->mName == name) { - state.bone_stack.erase(bone); - return bone; - } - } - - return nullptr; -} - -Node3D * -EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, const uint32_t p_flags, int p_bake_fps, - const int32_t p_max_bone_weights) { - ERR_FAIL_COND_V(scene == nullptr, nullptr); - - ImportState state; - state.path = p_path; - state.assimp_scene = scene; - state.max_bone_weights = p_max_bone_weights; - state.animation_player = nullptr; - state.import_flags = p_flags; - - // populate light map - for (unsigned int l = 0; l < scene->mNumLights; l++) { - aiLight *ai_light = scene->mLights[l]; - ERR_CONTINUE(ai_light == nullptr); - state.light_cache[AssimpUtils::get_assimp_string(ai_light->mName)] = l; - } - - // fill camera cache - for (unsigned int c = 0; c < scene->mNumCameras; c++) { - aiCamera *ai_camera = scene->mCameras[c]; - ERR_CONTINUE(ai_camera == nullptr); - state.camera_cache[AssimpUtils::get_assimp_string(ai_camera->mName)] = c; - } - - if (scene->mRootNode) { - state.nodes.push_back(scene->mRootNode); - - // make flat node tree - in order to make processing deterministic - for (unsigned int i = 0; i < scene->mRootNode->mNumChildren; i++) { - _generate_node(state, scene->mRootNode->mChildren[i]); - } - - RegenerateBoneStack(state); - - Node *last_valid_parent = nullptr; - - List<const aiNode *>::Element *iter; - for (iter = state.nodes.front(); iter; iter = iter->next()) { - const aiNode *element_assimp_node = iter->get(); - const aiNode *parent_assimp_node = element_assimp_node->mParent; - - String node_name = AssimpUtils::get_assimp_string(element_assimp_node->mName); - //print_verbose("node: " + node_name); - - Node3D *spatial = nullptr; - Transform transform = AssimpUtils::assimp_matrix_transform(element_assimp_node->mTransformation); - - // retrieve this node bone - aiBone *bone = get_bone_from_stack(state, element_assimp_node->mName); - - if (state.light_cache.has(node_name)) { - spatial = create_light(state, node_name, transform); - } else if (state.camera_cache.has(node_name)) { - spatial = create_camera(state, node_name, transform); - } else if (state.armature_nodes.find(element_assimp_node)) { - // create skeleton - print_verbose("Making skeleton: " + node_name); - Skeleton3D *skeleton = memnew(Skeleton3D); - spatial = skeleton; - if (!state.armature_skeletons.has(element_assimp_node)) { - state.armature_skeletons.insert(element_assimp_node, skeleton); - } - } else if (bone != nullptr) { - continue; - } else { - spatial = memnew(Node3D); - } - - ERR_CONTINUE_MSG(spatial == nullptr, "FBX Import - are we out of ram?"); - // we on purpose set the transform and name after creating the node. - - spatial->set_name(node_name); - spatial->set_global_transform(transform); - - // first element is root - if (iter == state.nodes.front()) { - state.root = spatial; - } - - // flat node map parent lookup tool - state.flat_node_map.insert(element_assimp_node, spatial); - - Map<const aiNode *, Node3D *>::Element *parent_lookup = state.flat_node_map.find(parent_assimp_node); - - // note: this always fails on the root node :) keep that in mind this is by design - if (parent_lookup) { - Node3D *parent_node = parent_lookup->value(); - - ERR_FAIL_COND_V_MSG(parent_node == nullptr, state.root, - "Parent node invalid even though lookup successful, out of ram?"); - - if (spatial != state.root) { - parent_node->add_child(spatial); - spatial->set_owner(state.root); - } else { - // required - think about it root never has a parent yet is valid, anything else without a parent is not valid. - } - } else if (spatial != state.root) { - // if the ainode is not in the tree - // parent it to the last good parent found - if (last_valid_parent) { - last_valid_parent->add_child(spatial); - spatial->set_owner(state.root); - } else { - // this is a serious error? - memdelete(spatial); - } - } - - // update last valid parent - last_valid_parent = spatial; - } - print_verbose("node counts: " + itos(state.nodes.size())); - - // make clean bone stack - RegenerateBoneStack(state); - - print_verbose("generating godot bone data"); - - print_verbose("Godot bone stack count: " + itos(state.bone_stack.size())); - - // This is a list of bones, duplicates are from other meshes and must be dealt with properly - for (List<aiBone *>::Element *element = state.bone_stack.front(); element; element = element->next()) { - aiBone *bone = element->get(); - - ERR_CONTINUE_MSG(!bone, "invalid bone read from assimp?"); - - // Utilities for armature lookup - for now only FBX makes these - aiNode *armature_for_bone = bone->mArmature; - - // Utilities for bone node lookup - for now only FBX makes these - aiNode *bone_node = bone->mNode; - aiNode *parent_node = bone_node->mParent; - - String bone_name = AssimpUtils::get_anim_string_from_assimp(bone->mName); - ERR_CONTINUE_MSG(armature_for_bone == nullptr, "Armature for bone invalid: " + bone_name); - Skeleton3D *skeleton = state.armature_skeletons[armature_for_bone]; - - state.skeleton_bone_map[bone] = skeleton; - - if (bone_name.empty()) { - bone_name = "untitled_bone_name"; - WARN_PRINT("Untitled bone name detected... report with file please"); - } - - // todo: this is where skin support goes - if (skeleton && skeleton->find_bone(bone_name) == -1) { - print_verbose("[Godot Glue] Imported bone" + bone_name); - int boneIdx = skeleton->get_bone_count(); - - Transform pform = AssimpUtils::assimp_matrix_transform(bone->mNode->mTransformation); - skeleton->add_bone(bone_name); - skeleton->set_bone_rest(boneIdx, pform); - - if (parent_node != nullptr) { - int parent_bone_id = skeleton->find_bone(AssimpUtils::get_anim_string_from_assimp(parent_node->mName)); - int current_bone_id = boneIdx; - skeleton->set_bone_parent(current_bone_id, parent_bone_id); - } - } - } - - print_verbose("generating mesh phase from skeletal mesh"); - - List<Node3D *> cleanup_template_nodes; - - for (Map<const aiNode *, Node3D *>::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) { - const aiNode *assimp_node = key_value_pair->key(); - Node3D *mesh_template = key_value_pair->value(); - - ERR_CONTINUE(assimp_node == nullptr); - ERR_CONTINUE(mesh_template == nullptr); - - Node *parent_node = mesh_template->get_parent(); - - if (mesh_template == state.root) { - continue; - } - - if (parent_node == nullptr) { - print_error("Found invalid parent node!"); - continue; // root node - } - - String node_name = AssimpUtils::get_assimp_string(assimp_node->mName); - Transform node_transform = AssimpUtils::assimp_matrix_transform(assimp_node->mTransformation); - - if (assimp_node->mNumMeshes > 0) { - MeshInstance3D *mesh = create_mesh(state, assimp_node, node_name, parent_node, node_transform); - if (mesh) { - parent_node->remove_child(mesh_template); - - // re-parent children - List<Node *> children; - // re-parent all children to new node - // note: since get_child_count will change during execution we must build a list first to be safe. - for (int childId = 0; childId < mesh_template->get_child_count(); childId++) { - // get child - Node *child = mesh_template->get_child(childId); - children.push_back(child); - } - - for (List<Node *>::Element *element = children.front(); element; element = element->next()) { - // reparent the children to the real mesh node. - mesh_template->remove_child(element->get()); - mesh->add_child(element->get()); - element->get()->set_owner(state.root); - } - - // update mesh in list so that each mesh node is available - // this makes the template unavailable which is the desired behaviour - state.flat_node_map[assimp_node] = mesh; - - cleanup_template_nodes.push_back(mesh_template); - - // clean up this list we don't need it - children.clear(); - } - } - } - - for (List<Node3D *>::Element *element = cleanup_template_nodes.front(); element; element = element->next()) { - if (element->get()) { - memdelete(element->get()); - } - } - } - - if (p_flags & IMPORT_ANIMATION && scene->mNumAnimations) { - state.animation_player = memnew(AnimationPlayer); - state.root->add_child(state.animation_player); - state.animation_player->set_owner(state.root); - - for (uint32_t i = 0; i < scene->mNumAnimations; i++) { - _import_animation(state, i, p_bake_fps); - } - } - - // - // Cleanup operations - // - - state.mesh_cache.clear(); - state.material_cache.clear(); - state.light_cache.clear(); - state.camera_cache.clear(); - state.assimp_node_map.clear(); - state.path_to_image_cache.clear(); - state.nodes.clear(); - state.flat_node_map.clear(); - state.armature_skeletons.clear(); - state.bone_stack.clear(); - return state.root; -} - -void EditorSceneImporterAssimp::_insert_animation_track(ImportState &scene, const aiAnimation *assimp_anim, int track_id, - int anim_fps, Ref<Animation> animation, float ticks_per_second, - Skeleton3D *skeleton, const NodePath &node_path, - const String &node_name, aiBone *track_bone) { - const aiNodeAnim *assimp_track = assimp_anim->mChannels[track_id]; - //make transform track - int track_idx = animation->get_track_count(); - animation->add_track(Animation::TYPE_TRANSFORM); - animation->track_set_path(track_idx, node_path); - //first determine animation length - - float increment = 1.0 / float(anim_fps); - float time = 0.0; - - bool last = false; - - Vector<Vector3> pos_values; - Vector<float> pos_times; - Vector<Vector3> scale_values; - Vector<float> scale_times; - Vector<Quat> rot_values; - Vector<float> rot_times; - - for (size_t p = 0; p < assimp_track->mNumPositionKeys; p++) { - aiVector3D pos = assimp_track->mPositionKeys[p].mValue; - pos_values.push_back(Vector3(pos.x, pos.y, pos.z)); - pos_times.push_back(assimp_track->mPositionKeys[p].mTime / ticks_per_second); - } - - for (size_t r = 0; r < assimp_track->mNumRotationKeys; r++) { - aiQuaternion quat = assimp_track->mRotationKeys[r].mValue; - rot_values.push_back(Quat(quat.x, quat.y, quat.z, quat.w).normalized()); - rot_times.push_back(assimp_track->mRotationKeys[r].mTime / ticks_per_second); - } - - for (size_t sc = 0; sc < assimp_track->mNumScalingKeys; sc++) { - aiVector3D scale = assimp_track->mScalingKeys[sc].mValue; - scale_values.push_back(Vector3(scale.x, scale.y, scale.z)); - scale_times.push_back(assimp_track->mScalingKeys[sc].mTime / ticks_per_second); - } - - while (true) { - Vector3 pos; - Quat rot; - Vector3 scale(1, 1, 1); - - if (pos_values.size()) { - pos = _interpolate_track<Vector3>(pos_times, pos_values, time, AssetImportAnimation::INTERP_LINEAR); - } - - if (rot_values.size()) { - rot = _interpolate_track<Quat>(rot_times, rot_values, time, - AssetImportAnimation::INTERP_LINEAR) - .normalized(); - } - - if (scale_values.size()) { - scale = _interpolate_track<Vector3>(scale_times, scale_values, time, AssetImportAnimation::INTERP_LINEAR); - } - - if (skeleton) { - int skeleton_bone = skeleton->find_bone(node_name); - - if (skeleton_bone >= 0 && track_bone) { - Transform xform; - xform.basis.set_quat_scale(rot, scale); - xform.origin = pos; - - xform = skeleton->get_bone_rest(skeleton_bone).inverse() * xform; - - rot = xform.basis.get_rotation_quat(); - rot.normalize(); - scale = xform.basis.get_scale(); - pos = xform.origin; - } else { - ERR_FAIL_MSG("Skeleton bone lookup failed for skeleton: " + skeleton->get_name()); - } - } - - animation->track_set_interpolation_type(track_idx, Animation::INTERPOLATION_LINEAR); - animation->transform_track_insert_key(track_idx, time, pos, rot, scale); - - if (last) { //done this way so a key is always inserted past the end (for proper interpolation) - break; - } - time += increment; - if (time >= animation->get_length()) { - last = true; - } - } -} - -// I really do not like this but need to figure out a better way of removing it later. -Node *EditorSceneImporterAssimp::get_node_by_name(ImportState &state, String name) { - for (Map<const aiNode *, Node3D *>::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) { - const aiNode *assimp_node = key_value_pair->key(); - Node3D *node = key_value_pair->value(); - - String node_name = AssimpUtils::get_assimp_string(assimp_node->mName); - if (name == node_name && node) { - return node; - } - } - return nullptr; -} - -/* Bone stack is a fifo handler for multiple armatures since armatures aren't a thing in assimp (yet) */ -void EditorSceneImporterAssimp::RegenerateBoneStack(ImportState &state) { - state.bone_stack.clear(); - // build bone stack list - for (unsigned int mesh_id = 0; mesh_id < state.assimp_scene->mNumMeshes; ++mesh_id) { - aiMesh *mesh = state.assimp_scene->mMeshes[mesh_id]; - - // iterate over all the bones on the mesh for this node only! - for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; boneIndex++) { - aiBone *bone = mesh->mBones[boneIndex]; - - // doubtful this is required right now but best to check - if (!state.bone_stack.find(bone)) { - //print_verbose("[assimp] bone stack added: " + String(bone->mName.C_Str()) ); - state.bone_stack.push_back(bone); - } - } - } -} - -/* Bone stack is a fifo handler for multiple armatures since armatures aren't a thing in assimp (yet) */ -void EditorSceneImporterAssimp::RegenerateBoneStack(ImportState &state, aiMesh *mesh) { - state.bone_stack.clear(); - // iterate over all the bones on the mesh for this node only! - for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; boneIndex++) { - aiBone *bone = mesh->mBones[boneIndex]; - if (state.bone_stack.find(bone) == nullptr) { - state.bone_stack.push_back(bone); - } - } -} - -// animation tracks are per bone - -void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_animation_index, int p_bake_fps) { - ERR_FAIL_INDEX(p_animation_index, (int)state.assimp_scene->mNumAnimations); - - const aiAnimation *anim = state.assimp_scene->mAnimations[p_animation_index]; - String name = AssimpUtils::get_anim_string_from_assimp(anim->mName); - if (name == String()) { - name = "Animation " + itos(p_animation_index + 1); - } - print_verbose("import animation: " + name); - float ticks_per_second = anim->mTicksPerSecond; - - if (state.assimp_scene->mMetaData != nullptr && Math::is_equal_approx(ticks_per_second, 0.0f)) { - int32_t time_mode = 0; - state.assimp_scene->mMetaData->Get("TimeMode", time_mode); - ticks_per_second = AssimpUtils::get_fbx_fps(time_mode, state.assimp_scene); - } - - //? - //if ((p_path.get_file().get_extension().to_lower() == "glb" || p_path.get_file().get_extension().to_lower() == "gltf") && Math::is_equal_approx(ticks_per_second, 0.0f)) { - // ticks_per_second = 1000.0f; - //} - - if (Math::is_equal_approx(ticks_per_second, 0.0f)) { - ticks_per_second = 25.0f; - } - - Ref<Animation> animation; - animation.instance(); - animation->set_name(name); - animation->set_length(anim->mDuration / ticks_per_second); - - if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) { - animation->set_loop(true); - } - - // generate bone stack for animation import - RegenerateBoneStack(state); - - //regular tracks - for (size_t i = 0; i < anim->mNumChannels; i++) { - const aiNodeAnim *track = anim->mChannels[i]; - String node_name = AssimpUtils::get_assimp_string(track->mNodeName); - print_verbose("track name import: " + node_name); - if (track->mNumRotationKeys == 0 && track->mNumPositionKeys == 0 && track->mNumScalingKeys == 0) { - continue; //do not bother - } - - Skeleton3D *skeleton = nullptr; - NodePath node_path; - aiBone *bone = nullptr; - - // Import skeleton bone animation for this track - // Any bone will do, no point in processing more than just what is in the skeleton - { - bone = get_bone_from_stack(state, track->mNodeName); - - if (bone) { - // get skeleton by bone - skeleton = state.armature_skeletons[bone->mArmature]; - - if (skeleton) { - String path = state.root->get_path_to(skeleton); - path += ":" + node_name; - node_path = path; - - if (node_path != NodePath()) { - _insert_animation_track(state, anim, i, p_bake_fps, animation, ticks_per_second, skeleton, - node_path, node_name, bone); - } else { - print_error("Failed to find valid node path for animation"); - } - } - } - } - - // not a bone - // note this is flaky it uses node names which is unreliable - Node *allocated_node = get_node_by_name(state, node_name); - // todo: implement skeleton grabbing for node based animations too :) - // check if node exists, if it does then also apply animation track for node and bones above are all handled. - // this is now inclusive animation handling so that - // we import all the data and do not miss anything. - if (allocated_node) { - node_path = state.root->get_path_to(allocated_node); - - if (node_path != NodePath()) { - _insert_animation_track(state, anim, i, p_bake_fps, animation, ticks_per_second, skeleton, - node_path, node_name, nullptr); - } - } - } - - //blend shape tracks - - for (size_t i = 0; i < anim->mNumMorphMeshChannels; i++) { - const aiMeshMorphAnim *anim_mesh = anim->mMorphMeshChannels[i]; - - const String prop_name = AssimpUtils::get_assimp_string(anim_mesh->mName); - const String mesh_name = prop_name.split("*")[0]; - - ERR_CONTINUE(prop_name.split("*").size() != 2); - - Node *item = get_node_by_name(state, mesh_name); - ERR_CONTINUE_MSG(!item, "failed to look up node by name"); - const MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(item); - ERR_CONTINUE(mesh_instance == nullptr); - - String base_path = state.root->get_path_to(mesh_instance); - - Ref<Mesh> mesh = mesh_instance->get_mesh(); - ERR_CONTINUE(mesh.is_null()); - - //add the tracks for this mesh - int base_track = animation->get_track_count(); - for (int j = 0; j < mesh->get_blend_shape_count(); j++) { - animation->add_track(Animation::TYPE_VALUE); - animation->track_set_path(base_track + j, base_path + ":blend_shapes/" + mesh->get_blend_shape_name(j)); - } - - for (size_t k = 0; k < anim_mesh->mNumKeys; k++) { - for (size_t j = 0; j < anim_mesh->mKeys[k].mNumValuesAndWeights; j++) { - float t = anim_mesh->mKeys[k].mTime / ticks_per_second; - float w = anim_mesh->mKeys[k].mWeights[j]; - - animation->track_insert_key(base_track + j, t, w); - } - } - } - - if (animation->get_track_count()) { - state.animation_player->add_animation(name, animation); - } -} - -// -// Mesh Generation from indices ? why do we need so much mesh code -// [debt needs looked into] -Ref<Mesh> -EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &state, const Vector<int> &p_surface_indices, - const aiNode *assimp_node, Ref<Skin> &skin, - Skeleton3D *&skeleton_assigned) { - Ref<ArrayMesh> mesh; - mesh.instance(); - bool has_uvs = false; - uint32_t mesh_flags = 0; - - Map<String, uint32_t> morph_mesh_string_lookup; - - for (int i = 0; i < p_surface_indices.size(); i++) { - const unsigned int mesh_idx = p_surface_indices[0]; - const aiMesh *ai_mesh = state.assimp_scene->mMeshes[mesh_idx]; - for (size_t j = 0; j < ai_mesh->mNumAnimMeshes; j++) { - String ai_anim_mesh_name = AssimpUtils::get_assimp_string(ai_mesh->mAnimMeshes[j]->mName); - if (!morph_mesh_string_lookup.has(ai_anim_mesh_name)) { - morph_mesh_string_lookup.insert(ai_anim_mesh_name, j); - mesh->set_blend_shape_mode(ArrayMesh::BLEND_SHAPE_MODE_NORMALIZED); - if (ai_anim_mesh_name.empty()) { - ai_anim_mesh_name = String("morph_") + itos(j); - } - mesh->add_blend_shape(ai_anim_mesh_name); - } - } - } - // - // Process Vertex Weights - // - for (int i = 0; i < p_surface_indices.size(); i++) { - const unsigned int mesh_idx = p_surface_indices[i]; - const aiMesh *ai_mesh = state.assimp_scene->mMeshes[mesh_idx]; - - Map<uint32_t, Vector<BoneInfo>> vertex_weights; - - if (ai_mesh->mNumBones > 0) { - for (size_t b = 0; b < ai_mesh->mNumBones; b++) { - aiBone *bone = ai_mesh->mBones[b]; - - if (!skeleton_assigned) { - print_verbose("Assigned mesh skeleton during mesh creation"); - skeleton_assigned = state.skeleton_bone_map[bone]; - - if (!skin.is_valid()) { - print_verbose("Configured new skin"); - skin.instance(); - } else { - print_verbose("Reusing existing skin!"); - } - } - // skeleton_assigned = - String bone_name = AssimpUtils::get_assimp_string(bone->mName); - int bone_index = skeleton_assigned->find_bone(bone_name); - ERR_CONTINUE(bone_index == -1); - for (size_t w = 0; w < bone->mNumWeights; w++) { - aiVertexWeight ai_weights = bone->mWeights[w]; - - BoneInfo bi; - uint32_t vertex_index = ai_weights.mVertexId; - bi.bone = bone_index; - bi.weight = ai_weights.mWeight; - - if (!vertex_weights.has(vertex_index)) { - vertex_weights[vertex_index] = Vector<BoneInfo>(); - } - - vertex_weights[vertex_index].push_back(bi); - } - } - } - - // - // Create mesh from data from assimp - // - - Ref<SurfaceTool> st; - st.instance(); - st->begin(Mesh::PRIMITIVE_TRIANGLES); - - for (size_t j = 0; j < ai_mesh->mNumVertices; j++) { - // Get the texture coordinates if they exist - if (ai_mesh->HasTextureCoords(0)) { - has_uvs = true; - st->set_uv(Vector2(ai_mesh->mTextureCoords[0][j].x, 1.0f - ai_mesh->mTextureCoords[0][j].y)); - } - - if (ai_mesh->HasTextureCoords(1)) { - has_uvs = true; - st->set_uv2(Vector2(ai_mesh->mTextureCoords[1][j].x, 1.0f - ai_mesh->mTextureCoords[1][j].y)); - } - - // Assign vertex colors - if (ai_mesh->HasVertexColors(0)) { - Color color = Color(ai_mesh->mColors[0]->r, ai_mesh->mColors[0]->g, ai_mesh->mColors[0]->b, - ai_mesh->mColors[0]->a); - st->set_color(color); - } - - // Work out normal calculations? - this needs work it doesn't work properly on huestos - if (ai_mesh->mNormals != nullptr) { - const aiVector3D normals = ai_mesh->mNormals[j]; - const Vector3 godot_normal = Vector3(normals.x, normals.y, normals.z); - st->set_normal(godot_normal); - if (ai_mesh->HasTangentsAndBitangents()) { - const aiVector3D tangents = ai_mesh->mTangents[j]; - const Vector3 godot_tangent = Vector3(tangents.x, tangents.y, tangents.z); - const aiVector3D bitangent = ai_mesh->mBitangents[j]; - const Vector3 godot_bitangent = Vector3(bitangent.x, bitangent.y, bitangent.z); - float d = godot_normal.cross(godot_tangent).dot(godot_bitangent) > 0.0f ? 1.0f : -1.0f; - st->set_tangent(Plane(tangents.x, tangents.y, tangents.z, d)); - } - } - - // We have vertex weights right? - if (vertex_weights.has(j)) { - Vector<BoneInfo> bone_info = vertex_weights[j]; - Vector<int> bones; - bones.resize(bone_info.size()); - Vector<float> weights; - weights.resize(bone_info.size()); - - // todo? do we really need to loop over all bones? - assimp may have helper to find all influences on this vertex. - for (int k = 0; k < bone_info.size(); k++) { - bones.write[k] = bone_info[k].bone; - weights.write[k] = bone_info[k].weight; - } - - st->set_bones(bones); - st->set_weights(weights); - } - - // Assign vertex - const aiVector3D pos = ai_mesh->mVertices[j]; - - // note we must include node offset transform as this is relative to world space not local space. - Vector3 godot_pos = Vector3(pos.x, pos.y, pos.z); - st->add_vertex(godot_pos); - } - - // fire replacement for face handling - for (size_t j = 0; j < ai_mesh->mNumFaces; j++) { - const aiFace face = ai_mesh->mFaces[j]; - for (unsigned int k = 0; k < face.mNumIndices; k++) { - st->add_index(face.mIndices[k]); - } - } - - if (ai_mesh->HasTangentsAndBitangents() == false && has_uvs) { - st->generate_tangents(); - } - - aiMaterial *ai_material = state.assimp_scene->mMaterials[ai_mesh->mMaterialIndex]; - Ref<StandardMaterial3D> mat; - mat.instance(); - - int32_t mat_two_sided = 0; - if (AI_SUCCESS == ai_material->Get(AI_MATKEY_TWOSIDED, mat_two_sided)) { - if (mat_two_sided > 0) { - mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED); - } else { - mat->set_cull_mode(StandardMaterial3D::CULL_BACK); - } - } - - aiString mat_name; - if (AI_SUCCESS == ai_material->Get(AI_MATKEY_NAME, mat_name)) { - mat->set_name(AssimpUtils::get_assimp_string(mat_name)); - } - - // Culling handling for meshes - - // cull all back faces - mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED); - - // Now process materials - aiTextureType base_color = aiTextureType_BASE_COLOR; - { - String filename, path; - AssimpImageData image_data; - - if (AssimpUtils::GetAssimpTexture(state, ai_material, base_color, filename, path, image_data)) { - AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); - - // anything transparent must be culled - if (image_data.raw_image->detect_alpha() != Image::ALPHA_NONE) { - mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS); - mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED); // since you can see both sides in transparent mode - } - - mat->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, image_data.texture); - } - } - - aiTextureType tex_diffuse = aiTextureType_DIFFUSE; - { - String filename, path; - AssimpImageData image_data; - - if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_diffuse, filename, path, image_data)) { - AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); - - // anything transparent must be culled - if (image_data.raw_image->detect_alpha() != Image::ALPHA_NONE) { - mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS); - mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED); // since you can see both sides in transparent mode - } - - mat->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, image_data.texture); - } - - aiColor4D clr_diffuse; - if (AI_SUCCESS == ai_material->Get(AI_MATKEY_COLOR_DIFFUSE, clr_diffuse)) { - if (Math::is_equal_approx(clr_diffuse.a, 1.0f) == false) { - mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS); - mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED); // since you can see both sides in transparent mode - } - mat->set_albedo(Color(clr_diffuse.r, clr_diffuse.g, clr_diffuse.b, clr_diffuse.a)); - } - } - - aiTextureType tex_normal = aiTextureType_NORMALS; - { - String filename, path; - Ref<ImageTexture> texture; - AssimpImageData image_data; - - // Process texture normal map - if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_normal, filename, path, image_data)) { - AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); - mat->set_feature(StandardMaterial3D::Feature::FEATURE_NORMAL_MAPPING, true); - mat->set_texture(StandardMaterial3D::TEXTURE_NORMAL, image_data.texture); - } else { - aiString texture_path; - if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_NORMAL_TEXTURE, AI_PROPERTIES, texture_path)) { - if (AssimpUtils::CreateAssimpTexture(state, texture_path, filename, path, image_data)) { - mat->set_feature(StandardMaterial3D::Feature::FEATURE_NORMAL_MAPPING, true); - mat->set_texture(StandardMaterial3D::TEXTURE_NORMAL, image_data.texture); - } - } - } - } - - aiTextureType tex_normal_camera = aiTextureType_NORMAL_CAMERA; - { - String filename, path; - Ref<ImageTexture> texture; - AssimpImageData image_data; - - // Process texture normal map - if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_normal_camera, filename, path, image_data)) { - AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); - mat->set_feature(StandardMaterial3D::Feature::FEATURE_NORMAL_MAPPING, true); - mat->set_texture(StandardMaterial3D::TEXTURE_NORMAL, image_data.texture); - } - } - - aiTextureType tex_emission_color = aiTextureType_EMISSION_COLOR; - { - String filename, path; - Ref<ImageTexture> texture; - AssimpImageData image_data; - - // Process texture normal map - if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_emission_color, filename, path, image_data)) { - AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); - mat->set_feature(StandardMaterial3D::Feature::FEATURE_NORMAL_MAPPING, true); - mat->set_texture(StandardMaterial3D::TEXTURE_NORMAL, image_data.texture); - } - } - - aiTextureType tex_metalness = aiTextureType_METALNESS; - { - String filename, path; - Ref<ImageTexture> texture; - AssimpImageData image_data; - - // Process texture normal map - if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_metalness, filename, path, image_data)) { - AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); - mat->set_texture(StandardMaterial3D::TEXTURE_METALLIC, image_data.texture); - } - } - - aiTextureType tex_roughness = aiTextureType_DIFFUSE_ROUGHNESS; - { - String filename, path; - Ref<ImageTexture> texture; - AssimpImageData image_data; - - // Process texture normal map - if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_roughness, filename, path, image_data)) { - AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); - mat->set_texture(StandardMaterial3D::TEXTURE_ROUGHNESS, image_data.texture); - } - } - - aiTextureType tex_emissive = aiTextureType_EMISSIVE; - { - String filename = ""; - String path = ""; - Ref<Image> texture; - AssimpImageData image_data; - - if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_emissive, filename, path, image_data)) { - AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); - mat->set_feature(StandardMaterial3D::FEATURE_EMISSION, true); - mat->set_texture(StandardMaterial3D::TEXTURE_EMISSION, image_data.texture); - } else { - // Process emission textures - aiString texture_emissive_path; - if (AI_SUCCESS == - ai_material->Get(AI_MATKEY_FBX_MAYA_EMISSION_TEXTURE, AI_PROPERTIES, texture_emissive_path)) { - if (AssimpUtils::CreateAssimpTexture(state, texture_emissive_path, filename, path, image_data)) { - mat->set_feature(StandardMaterial3D::FEATURE_EMISSION, true); - mat->set_texture(StandardMaterial3D::TEXTURE_EMISSION, image_data.texture); - } - } else { - float pbr_emission = 0.0f; - if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_EMISSIVE_FACTOR, AI_NULL, pbr_emission)) { - mat->set_emission(Color(pbr_emission, pbr_emission, pbr_emission, 1.0f)); - } - } - } - } - - aiTextureType tex_specular = aiTextureType_SPECULAR; - { - String filename, path; - Ref<ImageTexture> texture; - AssimpImageData image_data; - - // Process texture normal map - if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_specular, filename, path, image_data)) { - AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); - mat->set_texture(StandardMaterial3D::TEXTURE_METALLIC, image_data.texture); - } - } - - aiTextureType tex_ao_map = aiTextureType_AMBIENT_OCCLUSION; - { - String filename, path; - Ref<ImageTexture> texture; - AssimpImageData image_data; - - // Process texture normal map - if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_ao_map, filename, path, image_data)) { - AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); - mat->set_feature(StandardMaterial3D::FEATURE_AMBIENT_OCCLUSION, true); - mat->set_texture(StandardMaterial3D::TEXTURE_AMBIENT_OCCLUSION, image_data.texture); - } - } - - Array array_mesh = st->commit_to_arrays(); - Array morphs; - morphs.resize(ai_mesh->mNumAnimMeshes); - Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES; - - for (size_t j = 0; j < ai_mesh->mNumAnimMeshes; j++) { - String ai_anim_mesh_name = AssimpUtils::get_assimp_string(ai_mesh->mAnimMeshes[j]->mName); - - if (ai_anim_mesh_name.empty()) { - ai_anim_mesh_name = String("morph_") + itos(j); - } - - Array array_copy; - array_copy.resize(RenderingServer::ARRAY_MAX); - - for (int l = 0; l < RenderingServer::ARRAY_MAX; l++) { - array_copy[l] = array_mesh[l].duplicate(true); - } - - const size_t num_vertices = ai_mesh->mAnimMeshes[j]->mNumVertices; - array_copy[Mesh::ARRAY_INDEX] = Variant(); - if (ai_mesh->mAnimMeshes[j]->HasPositions()) { - PackedVector3Array vertices; - vertices.resize(num_vertices); - for (size_t l = 0; l < num_vertices; l++) { - const aiVector3D ai_pos = ai_mesh->mAnimMeshes[j]->mVertices[l]; - Vector3 position = Vector3(ai_pos.x, ai_pos.y, ai_pos.z); - vertices.ptrw()[l] = position; - } - PackedVector3Array new_vertices = array_copy[RenderingServer::ARRAY_VERTEX].duplicate(true); - ERR_CONTINUE(vertices.size() != new_vertices.size()); - for (int32_t l = 0; l < new_vertices.size(); l++) { - Vector3 *w = new_vertices.ptrw(); - w[l] = vertices[l]; - } - array_copy[RenderingServer::ARRAY_VERTEX] = new_vertices; - } - - int32_t color_set = 0; - if (ai_mesh->mAnimMeshes[j]->HasVertexColors(color_set)) { - PackedColorArray colors; - colors.resize(num_vertices); - for (size_t l = 0; l < num_vertices; l++) { - const aiColor4D ai_color = ai_mesh->mAnimMeshes[j]->mColors[color_set][l]; - Color color = Color(ai_color.r, ai_color.g, ai_color.b, ai_color.a); - colors.ptrw()[l] = color; - } - PackedColorArray new_colors = array_copy[RenderingServer::ARRAY_COLOR].duplicate(true); - ERR_CONTINUE(colors.size() != new_colors.size()); - for (int32_t l = 0; l < colors.size(); l++) { - Color *w = new_colors.ptrw(); - w[l] = colors[l]; - } - array_copy[RenderingServer::ARRAY_COLOR] = new_colors; - } - - if (ai_mesh->mAnimMeshes[j]->HasNormals()) { - PackedVector3Array normals; - normals.resize(num_vertices); - for (size_t l = 0; l < num_vertices; l++) { - const aiVector3D ai_normal = ai_mesh->mAnimMeshes[j]->mNormals[l]; - Vector3 normal = Vector3(ai_normal.x, ai_normal.y, ai_normal.z); - normals.ptrw()[l] = normal; - } - PackedVector3Array new_normals = array_copy[RenderingServer::ARRAY_NORMAL].duplicate(true); - ERR_CONTINUE(normals.size() != new_normals.size()); - for (int l = 0; l < normals.size(); l++) { - Vector3 *w = new_normals.ptrw(); - w[l] = normals[l]; - } - array_copy[RenderingServer::ARRAY_NORMAL] = new_normals; - } - - if (ai_mesh->mAnimMeshes[j]->HasTangentsAndBitangents()) { - PackedColorArray tangents; - tangents.resize(num_vertices); - Color *w = tangents.ptrw(); - for (size_t l = 0; l < num_vertices; l++) { - AssimpUtils::calc_tangent_from_mesh(ai_mesh, j, l, l, w); - } - PackedFloat32Array new_tangents = array_copy[RenderingServer::ARRAY_TANGENT].duplicate(true); - ERR_CONTINUE(new_tangents.size() != tangents.size() * 4); - for (int32_t l = 0; l < tangents.size(); l++) { - new_tangents.ptrw()[l + 0] = tangents[l].r; - new_tangents.ptrw()[l + 1] = tangents[l].g; - new_tangents.ptrw()[l + 2] = tangents[l].b; - new_tangents.ptrw()[l + 3] = tangents[l].a; - } - array_copy[RenderingServer::ARRAY_TANGENT] = new_tangents; - } - - morphs[j] = array_copy; - } - mesh->add_surface_from_arrays(primitive, array_mesh, morphs, Dictionary(), mesh_flags); - mesh->surface_set_material(i, mat); - mesh->surface_set_name(i, AssimpUtils::get_assimp_string(ai_mesh->mName)); - } - - return mesh; -} - -/** - * Create a new mesh for the node supplied - */ -MeshInstance3D * -EditorSceneImporterAssimp::create_mesh(ImportState &state, const aiNode *assimp_node, const String &node_name, Node *active_node, Transform node_transform) { - /* MESH NODE */ - Ref<Mesh> mesh; - Ref<Skin> skin; - // see if we have mesh cache for this. - Vector<int> surface_indices; - - RegenerateBoneStack(state); - - // Configure indices - for (uint32_t i = 0; i < assimp_node->mNumMeshes; i++) { - int mesh_index = assimp_node->mMeshes[i]; - // create list of mesh indexes - surface_indices.push_back(mesh_index); - } - - //surface_indices.sort(); - String mesh_key; - for (int i = 0; i < surface_indices.size(); i++) { - if (i > 0) { - mesh_key += ":"; - } - mesh_key += itos(surface_indices[i]); - } - - Skeleton3D *skeleton = nullptr; - aiNode *armature = nullptr; - - if (!state.mesh_cache.has(mesh_key)) { - mesh = _generate_mesh_from_surface_indices(state, surface_indices, assimp_node, skin, skeleton); - state.mesh_cache[mesh_key] = mesh; - } - - MeshInstance3D *mesh_node = memnew(MeshInstance3D); - mesh = state.mesh_cache[mesh_key]; - mesh_node->set_mesh(mesh); - - // if we have a valid skeleton set it up - if (skin.is_valid()) { - for (uint32_t i = 0; i < assimp_node->mNumMeshes; i++) { - unsigned int mesh_index = assimp_node->mMeshes[i]; - const aiMesh *ai_mesh = state.assimp_scene->mMeshes[mesh_index]; - - // please remember bone id relative to the skin is NOT the mesh relative index. - // it is the index relative to the skeleton that is why - // we have state.bone_id_map, it allows for duplicate bone id's too :) - // hope this makes sense - - int bind_count = 0; - for (unsigned int boneId = 0; boneId < ai_mesh->mNumBones; ++boneId) { - aiBone *iterBone = ai_mesh->mBones[boneId]; - - // used to reparent mesh to the correct armature later on if assigned. - if (!armature) { - print_verbose("Configured mesh armature, will reparent later to armature"); - armature = iterBone->mArmature; - } - - if (skeleton) { - int id = skeleton->find_bone(AssimpUtils::get_assimp_string(iterBone->mName)); - if (id != -1) { - print_verbose("Set bind bone: mesh: " + itos(mesh_index) + " bone index: " + itos(id)); - Transform t = AssimpUtils::assimp_matrix_transform(iterBone->mOffsetMatrix); - - skin->add_bind(bind_count, t); - skin->set_bind_bone(bind_count, id); - bind_count++; - } - } - } - } - - print_verbose("Finished configuring bind pose for skin mesh"); - } - - // this code parents all meshes with bones to the armature they are for - // GLTF2 specification relies on this and we are enforcing it for FBX. - if (armature && state.flat_node_map[armature]) { - Node *armature_parent = state.flat_node_map[armature]; - print_verbose("Parented mesh " + node_name + " to armature " + armature_parent->get_name()); - // static mesh handling - armature_parent->add_child(mesh_node); - // transform must be identity - mesh_node->set_global_transform(Transform()); - mesh_node->set_name(node_name); - mesh_node->set_owner(state.root); - } else { - // static mesh handling - active_node->add_child(mesh_node); - mesh_node->set_global_transform(node_transform); - mesh_node->set_name(node_name); - mesh_node->set_owner(state.root); - } - - if (skeleton) { - print_verbose("Attempted to set skeleton path!"); - mesh_node->set_skeleton_path(mesh_node->get_path_to(skeleton)); - mesh_node->set_skin(skin); - } - - return mesh_node; -} - -/** - * Create a light for the scene - * Automatically caches lights for lookup later - */ -Node3D *EditorSceneImporterAssimp::create_light( - ImportState &state, - const String &node_name, - Transform &look_at_transform) { - Light3D *light = nullptr; - aiLight *assimp_light = state.assimp_scene->mLights[state.light_cache[node_name]]; - ERR_FAIL_COND_V(!assimp_light, nullptr); - - if (assimp_light->mType == aiLightSource_DIRECTIONAL) { - light = memnew(DirectionalLight3D); - } else if (assimp_light->mType == aiLightSource_POINT) { - light = memnew(OmniLight3D); - } else if (assimp_light->mType == aiLightSource_SPOT) { - light = memnew(SpotLight3D); - } - ERR_FAIL_COND_V(light == nullptr, nullptr); - - if (assimp_light->mType != aiLightSource_POINT) { - Vector3 pos = Vector3( - assimp_light->mPosition.x, - assimp_light->mPosition.y, - assimp_light->mPosition.z); - Vector3 look_at = Vector3( - assimp_light->mDirection.y, - assimp_light->mDirection.x, - assimp_light->mDirection.z) - .normalized(); - Vector3 up = Vector3( - assimp_light->mUp.x, - assimp_light->mUp.y, - assimp_light->mUp.z); - - look_at_transform.set_look_at(pos, look_at, up); - } - // properties for light variables should be put here. - // not really hugely important yet but we will need them in the future - - light->set_color( - Color(assimp_light->mColorDiffuse.r, assimp_light->mColorDiffuse.g, assimp_light->mColorDiffuse.b)); - - return light; -} - -/** - * Create camera for the scene - */ -Node3D *EditorSceneImporterAssimp::create_camera( - ImportState &state, - const String &node_name, - Transform &look_at_transform) { - aiCamera *camera = state.assimp_scene->mCameras[state.camera_cache[node_name]]; - ERR_FAIL_COND_V(!camera, nullptr); - - Camera3D *camera_node = memnew(Camera3D); - ERR_FAIL_COND_V(!camera_node, nullptr); - float near = camera->mClipPlaneNear; - if (Math::is_equal_approx(near, 0.0f)) { - near = 0.1f; - } - camera_node->set_perspective(Math::rad2deg(camera->mHorizontalFOV) * 2.0f, near, camera->mClipPlaneFar); - Vector3 pos = Vector3(camera->mPosition.x, camera->mPosition.y, camera->mPosition.z); - Vector3 look_at = Vector3(camera->mLookAt.y, camera->mLookAt.x, camera->mLookAt.z).normalized(); - Vector3 up = Vector3(camera->mUp.x, camera->mUp.y, camera->mUp.z); - - look_at_transform.set_look_at(pos + look_at_transform.origin, look_at, up); - return camera_node; -} - -/** - * Generate node - * Recursive call to iterate over all nodes - */ -void EditorSceneImporterAssimp::_generate_node( - ImportState &state, - const aiNode *assimp_node) { - ERR_FAIL_COND(assimp_node == nullptr); - state.nodes.push_back(assimp_node); - String parent_name = AssimpUtils::get_assimp_string(assimp_node->mParent->mName); - - // please note - // duplicate bone names exist - // this is why we only check if the bone exists - // so everything else is useless but the name - // please do not copy any other values from get_bone_by_name. - aiBone *parent_bone = get_bone_by_name(state.assimp_scene, assimp_node->mParent->mName); - aiBone *current_bone = get_bone_by_name(state.assimp_scene, assimp_node->mName); - - // is this an armature - // parent null - // and this is the first bone :) - if (parent_bone == nullptr && current_bone) { - state.armature_nodes.push_back(assimp_node->mParent); - print_verbose("found valid armature: " + parent_name); - } - - for (size_t i = 0; i < assimp_node->mNumChildren; i++) { - _generate_node(state, assimp_node->mChildren[i]); - } -} diff --git a/modules/assimp/editor_scene_importer_assimp.h b/modules/assimp/editor_scene_importer_assimp.h deleted file mode 100644 index 80bba6ad66..0000000000 --- a/modules/assimp/editor_scene_importer_assimp.h +++ /dev/null @@ -1,149 +0,0 @@ -/*************************************************************************/ -/* editor_scene_importer_assimp.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 EDITOR_SCENE_IMPORTER_ASSIMP_H -#define EDITOR_SCENE_IMPORTER_ASSIMP_H - -#ifdef TOOLS_ENABLED -#include "core/core_bind.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 <assimp/matrix4x4.h> -#include <assimp/scene.h> -#include <assimp/types.h> -#include <assimp/DefaultLogger.hpp> -#include <assimp/LogStream.hpp> -#include <assimp/Logger.hpp> -#include <map> - -#include "import_state.h" -#include "import_utils.h" - -using namespace AssimpImporter; - -class AssimpStream : public Assimp::LogStream { -public: - // Constructor - AssimpStream() {} - - // Destructor - ~AssimpStream() {} - // Write something using your own functionality - void write(const char *message) { - print_verbose(String("Open Asset Import: ") + String(message).strip_edges()); - } -}; - -class EditorSceneImporterAssimp : public EditorSceneImporter { -private: - GDCLASS(EditorSceneImporterAssimp, EditorSceneImporter); - - struct AssetImportAnimation { - enum Interpolation { - INTERP_LINEAR, - INTERP_STEP, - INTERP_CATMULLROMSPLINE, - INTERP_CUBIC_SPLINE - }; - }; - - struct BoneInfo { - uint32_t bone; - float weight; - }; - - Ref<Mesh> _generate_mesh_from_surface_indices(ImportState &state, const Vector<int> &p_surface_indices, - const aiNode *assimp_node, Ref<Skin> &skin, - Skeleton3D *&skeleton_assigned); - - // simple object creation functions - Node3D *create_light(ImportState &state, - const String &node_name, - Transform &look_at_transform); - Node3D *create_camera( - ImportState &state, - const String &node_name, - Transform &look_at_transform); - // non recursive - linear so must not use recursive arguments - MeshInstance3D *create_mesh(ImportState &state, const aiNode *assimp_node, const String &node_name, Node *active_node, Transform node_transform); - // recursive node generator - void _generate_node(ImportState &state, const aiNode *assimp_node); - void _insert_animation_track(ImportState &scene, const aiAnimation *assimp_anim, int track_id, - int anim_fps, Ref<Animation> animation, float ticks_per_second, - Skeleton3D *skeleton, const NodePath &node_path, - const String &node_name, aiBone *track_bone); - - void _import_animation(ImportState &state, int p_animation_index, int p_bake_fps); - Node *get_node_by_name(ImportState &state, String name); - aiBone *get_bone_from_stack(ImportState &state, aiString name); - Node3D *_generate_scene(const String &p_path, aiScene *scene, const uint32_t p_flags, int p_bake_fps, const int32_t p_max_bone_weights); - - template <class T> - T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, AssetImportAnimation::Interpolation p_interp); - void _register_project_setting_import(const String generic, const String import_setting_string, const Vector<String> &exts, List<String> *r_extensions, const bool p_enabled) const; - - struct ImportFormat { - Vector<String> extensions; - bool is_default; - }; - -protected: - static void _bind_methods(); - -public: - EditorSceneImporterAssimp() { - Assimp::DefaultLogger::create("", Assimp::Logger::VERBOSE); - unsigned int severity = Assimp::Logger::Info | Assimp::Logger::Err | Assimp::Logger::Warn; - Assimp::DefaultLogger::get()->attachStream(new AssimpStream(), severity); - } - ~EditorSceneImporterAssimp() { - Assimp::DefaultLogger::kill(); - } - - virtual void get_extensions(List<String> *r_extensions) const override; - virtual uint32_t get_import_flags() const override; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; - Ref<Image> load_image(ImportState &state, const aiScene *p_scene, String p_path); - - static void RegenerateBoneStack(ImportState &state); - - void RegenerateBoneStack(ImportState &state, aiMesh *mesh); -}; -#endif -#endif diff --git a/modules/assimp/godot_update_assimp.sh b/modules/assimp/godot_update_assimp.sh deleted file mode 100755 index ff8ff59e97..0000000000 --- a/modules/assimp/godot_update_assimp.sh +++ /dev/null @@ -1,262 +0,0 @@ -rm -rf ../../thirdparty/assimp -cd ../../thirdparty/ -git clone https://github.com/assimp/assimp.git -cd assimp -rm -rf code/3DSExporter.h -rm -rf code/3DSLoader.h -rm -rf code/3MFXmlTags.h -rm -rf code/ABCImporter.h -rm -rf code/ACLoader.h -rm -rf code/AMFImporter_Macro.hpp -rm -rf code/ASELoader.h -rm -rf code/assbin_chunks.h -rm -rf code/AssbinExporter.h -rm -rf code/AssbinLoader.h -rm -rf code/AssimpCExport.cpp -rm -rf code/AssxmlExporter.h -rm -rf code/B3DImporter.h -# rm -rf code/BaseProcess.cpp -# rm -rf code/BaseProcess.h -# rm -rf code/Bitmap.cpp -rm -rf code/BlenderBMesh.cpp -rm -rf code/BlenderBMesh.h -rm -rf code/BlenderCustomData.cpp -rm -rf code/BlenderCustomData.h -rm -rf code/BlenderIntermediate.h -rm -rf code/BlenderLoader.h -rm -rf code/BlenderModifier.h -rm -rf code/BlenderSceneGen.h -rm -rf code/BlenderTessellator.h -rm -rf code/BVHLoader.h -rm -rf code/C4DImporter.h -# rm -rf code/CalcTangentsProcess.h -# rm -rf code/CInterfaceIOWrapper.cpp -# rm -rf code/CInterfaceIOWrapper.h -rm -rf code/COBLoader.h -rm -rf code/COBScene.h -rm -rf code/ColladaExporter.h -rm -rf code/ColladaLoader.h -# rm -rf code/ComputeUVMappingProcess.h -# rm -rf code/ConvertToLHProcess.h -# rm -rf code/CreateAnimMesh.cpp -rm -rf code/CSMLoader.h -rm -rf code/D3MFExporter.h -rm -rf code/D3MFImporter.h -rm -rf code/D3MFOpcPackage.h -# rm -rf code/DeboneProcess.h -# rm -rf code/DefaultIOStream.cpp -# rm -rf code/DefaultIOSystem.cpp -# rm -rf code/DefaultProgressHandler.h -# rm -rf code/DropFaceNormalsProcess.cpp -# rm -rf code/DropFaceNormalsProcess.h -rm -rf code/DXFHelper.h -rm -rf code/DXFLoader.h -# rm -rf code/EmbedTexturesProcess.cpp -# rm -rf code/EmbedTexturesProcess.h -# rm -rf code/FBXCommon.h -# rm -rf code/FBXCompileConfig.h -# rm -rf code/FBXDeformer.cpp -# rm -rf code/FBXDocumentUtil.cpp -# rm -rf code/FBXDocumentUtil.h -# rm -rf code/FBXExporter.h -# rm -rf code/FBXExportNode.h -# rm -rf code/FBXExportProperty.h -# rm -rf code/FBXImporter.cpp -# rm -rf code/FBXImporter.h -# rm -rf code/FBXImportSettings.h -# rm -rf code/FBXMeshGeometry.h -# rm -rf code/FBXModel.cpp -# rm -rf code/FBXNodeAttribute.cpp -# rm -rf code/FBXParser.h -# rm -rf code/FBXProperties.cpp -# rm -rf code/FBXProperties.h -# rm -rf code/FBXTokenizer.cpp -# rm -rf code/FBXTokenizer.h -# rm -rf code/FBXUtil.cpp -# rm -rf code/FBXUtil.h -# rm -rf code/FileLogStream.h -# rm -rf code/FindDegenerates.h -# rm -rf code/FindInstancesProcess.h -# rm -rf code/FindInvalidDataProcess.h -rm -rf code/FIReader.hpp -# rm -rf code/FixNormalsStep.cpp -# rm -rf code/FixNormalsStep.h -# rm -rf code/GenFaceNormalsProcess.cpp -# rm -rf code/GenFaceNormalsProcess.h -# rm -rf code/GenVertexNormalsProcess.cpp -# rm -rf code/GenVertexNormalsProcess.h -rm -rf code/glTF2Asset.h -rm -rf code/glTF2Asset.inl -rm -rf code/glTF2AssetWriter.inl -rm -rf code/glTF2Exporter.cpp -rm -rf code/glTF2Importer.cpp -rm -rf code/glTF2AssetWriter.h -rm -rf code/glTFAsset.h -rm -rf code/glTFAsset.inl -rm -rf code/glTFAssetWriter.inl -rm -rf code/glTFExporter.cpp -rm -rf code/glTFImporter.cpp -rm -rf code/glTF2Exporter.h -rm -rf code/glTF2Importer.h -rm -rf code/glTFAssetWriter.h -rm -rf code/glTFExporter.h -rm -rf code/glTFImporter.h -rm -rf code/HalfLifeFileData.h -rm -rf code/HMPFileData.h -rm -rf code/HMPLoader.h -rm -rf code/HMPLoader.cpp -rm -rf code/IFF.h -# rm -rf code/Importer.h -# rm -rf code/ImproveCacheLocality.h -rm -rf code/IRRLoader.h -rm -rf code/IRRMeshLoader.h -rm -rf code/IRRShared.h -# rm -rf code/JoinVerticesProcess.h -# rm -rf code/LimitBoneWeightsProcess.cpp -# rm -rf code/LimitBoneWeightsProcess.h -rm -rf code/LWSLoader.h -rm -rf code/makefile.mingw -# rm -rf code/MakeVerboseFormat.cpp -# rm -rf code/MakeVerboseFormat.h -# rm -rf code/MaterialSystem.h -rm -rf code/MD2FileData.h -rm -rf code/MD2Loader.h -rm -rf code/MD2NormalTable.h -rm -rf code/MD3FileData.h -rm -rf code/MD3Loader.h -rm -rf code/MD4FileData.h -rm -rf code/MD5Loader.h -rm -rf code/MD5Parser.cpp -rm -rf code/MDCFileData.h -rm -rf code/MDCLoader.h -rm -rf code/MDLDefaultColorMap.h -# rm -rf code/MMDCpp14.h -# rm -rf code/MMDImporter.h -rm -rf code/MS3DLoader.h -rm -rf code/NDOLoader.h -rm -rf code/NFFLoader.h -rm -rf code/ObjExporter.h -rm -rf code/ObjFileImporter.h -rm -rf code/ObjFileMtlImporter.h -rm -rf code/ObjFileParser.h -rm -rf code/ObjTools.h -rm -rf code/ObjExporter.cpp -rm -rf code/ObjFileImporter.cpp -rm -rf code/ObjFileMtlImporter.cpp -rm -rf code/ObjFileParser.cpp -rm -rf code/OFFLoader.h -rm -rf code/OFFLoader.cpp -rm -rf code/OgreImporter.cpp -rm -rf code/OgreImporter.h -rm -rf code/OgreParsingUtils.h -rm -rf code/OgreXmlSerializer.h -rm -rf code/OgreXmlSerializer.cpp -rm -rf code/OgreBinarySerializer.cpp -rm -rf code/OpenGEXExporter.cpp -rm -rf code/OpenGEXExporter.h -rm -rf code/OpenGEXImporter.h -rm -rf code/OpenGEXStructs.h -rm -rf code/OpenGEXImporter.cpp -# rm -rf code/OptimizeGraph.h -# rm -rf code/OptimizeMeshes.cpp -# rm -rf code/OptimizeMeshes.h -rm -rf code/PlyExporter.h -rm -rf code/PlyLoader.h -# rm -rf code/PolyTools.h -# rm -rf code/PostStepRegistry.cpp -# rm -rf code/PretransformVertices.h -rm -rf code/Q3BSPFileData.h -rm -rf code/Q3BSPFileImporter.h -rm -rf code/Q3BSPFileParser.cpp -rm -rf code/Q3BSPFileParser.h -rm -rf code/Q3BSPZipArchive.cpp -rm -rf code/Q3BSPZipArchive.h -rm -rf code/Q3DLoader.h -rm -rf code/Q3DLoader.cpp -rm -rf code/Q3BSPFileImporter.cpp -rm -rf code/RawLoader.h -# rm -rf code/RemoveComments.cpp -# rm -rf code/RemoveRedundantMaterials.cpp -# rm -rf code/RemoveRedundantMaterials.h -# rm -rf code/RemoveVCProcess.h -# rm -rf code/ScaleProcess.cpp -# rm -rf code/ScaleProcess.h -# rm -rf code/scene.cpp -# rm -rf code/ScenePreprocessor.cpp -# rm -rf code/ScenePreprocessor.h -# rm -rf code/ScenePrivate.h -# rm -rf code/SGSpatialSort.cpp -rm -rf code/SIBImporter.h -rm -rf code/SMDLoader.cpp -# rm -rf code/simd.cpp -# rm -rf code/simd.h -# rm -rf code/SortByPTypeProcess.h -# rm -rf code/SplitByBoneCountProcess.h -# rm -rf code/SplitLargeMeshes.h -# rm -rf code/StdOStreamLogStream.h -rm -rf code/StepExporter.h -rm -rf code/StepExporter.cpp -rm -rf code/STLExporter.cpp -rm -rf code/STLExporter.h -rm -rf code/STLLoader.h -rm -rf code/STLLoader.cpp -# rm -rf code/TargetAnimation.cpp -# rm -rf code/TargetAnimation.h -rm -rf code/TerragenLoader.h -rm -rf code/TerragenLoader.cpp -# rm -rf code/TextureTransform.h -# rm -rf code/TriangulateProcess.h -rm -rf code/UnrealLoader.h -# rm -rf code/ValidateDataStructure.h -# rm -rf code/Version.cpp -# rm -rf code/VertexTriangleAdjacency.cpp -# rm -rf code/VertexTriangleAdjacency.h -# rm -rf code/Win32DebugLogStream.h -rm -rf code/X3DImporter_Macro.hpp -rm -rf code/X3DImporter_Metadata.cpp -rm -rf code/X3DImporter_Networking.cpp -rm -rf code/X3DImporter_Texturing.cpp -rm -rf code/X3DImporter_Shape.cpp -rm -rf code/X3DImporter_Rendering.cpp -rm -rf code/X3DImporter_Postprocess.cpp -rm -rf code/X3DImporter_Light.cpp -rm -rf code/X3DImporter_Group.cpp -rm -rf code/X3DImporter_Geometry3D.cpp -rm -rf code/X3DImporter_Geometry2D.cpp -rm -rf code/X3DImporter.cpp -rm -rf code/X3DExporter.cpp -rm -rf code/X3DVocabulary.cpp -rm -rf code/XFileExporter.h -rm -rf code/XFileExporter.cpp -rm -rf code/XFileHelper.h -rm -rf code/XFileHelper.cpp -rm -rf code/XFileImporter.h -rm -rf code/XFileImporter.cpp -rm -rf code/XFileParser.h -rm -rf code/XFileParser.cpp -rm -rf code/XGLLoader.h -rm -rf code/XGLLoader.cpp -rm -rf code/Importer -rm -rf .git -rm -rf cmake-modules -rm -rf doc -rm -rf packaging -rm -rf port -rm -rf samples -rm -rf scripts -rm -rf test -rm -rf tools -rm -rf contrib/zlib -rm -rf contrib/android-cmake -rm -rf contrib/gtest -rm -rf contrib/clipper -rm -rf contrib/irrXML -rm -rf contrib/Open3DGC -rm -rf contrib/openddlparser -rm -rf contrib/poly2tri -#rm -rf contrib/rapidjson -rm -rf contrib/unzip -rm -rf contrib/zip -rm -rf contrib/stb_image -rm .travis* - diff --git a/modules/assimp/import_state.h b/modules/assimp/import_state.h deleted file mode 100644 index a1cce6968b..0000000000 --- a/modules/assimp/import_state.h +++ /dev/null @@ -1,132 +0,0 @@ -/*************************************************************************/ -/* import_state.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 EDITOR_SCENE_IMPORT_STATE_H -#define EDITOR_SCENE_IMPORT_STATE_H - -#include "core/core_bind.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 <assimp/matrix4x4.h> -#include <assimp/scene.h> -#include <assimp/types.h> -#include <assimp/DefaultLogger.hpp> -#include <assimp/LogStream.hpp> -#include <assimp/Logger.hpp> - -namespace AssimpImporter { -/** Import state is for global scene import data - * This makes the code simpler and contains useful lookups. - */ -struct ImportState { - String path; - Node3D *root; - const aiScene *assimp_scene; - uint32_t max_bone_weights; - - Map<String, Ref<Mesh>> mesh_cache; - Map<int, Ref<Material>> material_cache; - Map<String, int> light_cache; - Map<String, int> camera_cache; - - // very useful for when you need to ask assimp for the bone mesh - - Map<const aiNode *, Node *> assimp_node_map; - Map<String, Ref<Image>> path_to_image_cache; - - // Generation 3 - determinisitic iteration - // to lower potential recursion errors - List<const aiNode *> nodes; - Map<const aiNode *, Node3D *> flat_node_map; - AnimationPlayer *animation_player; - - // Generation 3 - deterministic armatures - // list of armature nodes - flat and simple to parse - // assimp node, node in godot - List<aiNode *> armature_nodes; - Map<const aiNode *, Skeleton3D *> armature_skeletons; - Map<aiBone *, Skeleton3D *> skeleton_bone_map; - // Generation 3 - deterministic bone handling - // bones from the stack are popped when found - // this means we can detect - // what bones are for other armatures - List<aiBone *> bone_stack; - - // EditorSceneImporter::ImportFlags - uint32_t import_flags; -}; - -struct AssimpImageData { - Ref<Image> raw_image; - Ref<ImageTexture> texture; - aiTextureMapMode map_mode[2]; -}; - -/** Recursive state is used to push state into functions instead of specifying them - * This makes the code easier to handle too and add extra arguments without breaking things - */ -struct RecursiveState { - RecursiveState() {} // do not construct :) - RecursiveState( - Transform &_node_transform, - Skeleton3D *_skeleton, - Node3D *_new_node, - String &_node_name, - aiNode *_assimp_node, - Node *_parent_node, - aiBone *_bone) : - node_transform(_node_transform), - skeleton(_skeleton), - new_node(_new_node), - node_name(_node_name), - assimp_node(_assimp_node), - parent_node(_parent_node), - bone(_bone) {} - - Transform node_transform; - Skeleton3D *skeleton = nullptr; - Node3D *new_node = nullptr; - String node_name; - aiNode *assimp_node = nullptr; - Node *parent_node = nullptr; - aiBone *bone = nullptr; -}; -} // namespace AssimpImporter - -#endif // EDITOR_SCENE_IMPORT_STATE_H diff --git a/modules/assimp/import_utils.h b/modules/assimp/import_utils.h deleted file mode 100644 index dc85d06fed..0000000000 --- a/modules/assimp/import_utils.h +++ /dev/null @@ -1,463 +0,0 @@ -/*************************************************************************/ -/* import_utils.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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_UTILS_IMPORTER_ASSIMP_H -#define IMPORT_UTILS_IMPORTER_ASSIMP_H - -#include "core/io/image_loader.h" -#include "import_state.h" - -#include <assimp/SceneCombiner.h> -#include <assimp/cexport.h> -#include <assimp/cimport.h> -#include <assimp/matrix4x4.h> -#include <assimp/pbrmaterial.h> -#include <assimp/postprocess.h> -#include <assimp/scene.h> -#include <assimp/DefaultLogger.hpp> -#include <assimp/Importer.hpp> -#include <assimp/LogStream.hpp> -#include <assimp/Logger.hpp> -#include <string> - -using namespace AssimpImporter; - -#define AI_PROPERTIES aiTextureType_UNKNOWN, 0 -#define AI_NULL 0, 0 -#define AI_MATKEY_FBX_MAYA_BASE_COLOR_FACTOR "$raw.Maya|baseColor" -#define AI_MATKEY_FBX_MAYA_METALNESS_FACTOR "$raw.Maya|metalness" -#define AI_MATKEY_FBX_MAYA_DIFFUSE_ROUGHNESS_FACTOR "$raw.Maya|diffuseRoughness" - -#define AI_MATKEY_FBX_MAYA_EMISSION_TEXTURE "$raw.Maya|emissionColor|file" -#define AI_MATKEY_FBX_MAYA_EMISSIVE_FACTOR "$raw.Maya|emission" -#define AI_MATKEY_FBX_MAYA_METALNESS_TEXTURE "$raw.Maya|metalness|file" -#define AI_MATKEY_FBX_MAYA_METALNESS_UV_XFORM "$raw.Maya|metalness|uvtrafo" -#define AI_MATKEY_FBX_MAYA_DIFFUSE_ROUGHNESS_TEXTURE "$raw.Maya|diffuseRoughness|file" -#define AI_MATKEY_FBX_MAYA_DIFFUSE_ROUGHNESS_UV_XFORM "$raw.Maya|diffuseRoughness|uvtrafo" -#define AI_MATKEY_FBX_MAYA_BASE_COLOR_TEXTURE "$raw.Maya|baseColor|file" -#define AI_MATKEY_FBX_MAYA_BASE_COLOR_UV_XFORM "$raw.Maya|baseColor|uvtrafo" -#define AI_MATKEY_FBX_MAYA_NORMAL_TEXTURE "$raw.Maya|normalCamera|file" -#define AI_MATKEY_FBX_MAYA_NORMAL_UV_XFORM "$raw.Maya|normalCamera|uvtrafo" - -#define AI_MATKEY_FBX_NORMAL_TEXTURE "$raw.Maya|normalCamera|file" -#define AI_MATKEY_FBX_NORMAL_UV_XFORM "$raw.Maya|normalCamera|uvtrafo" - -#define AI_MATKEY_FBX_MAYA_STINGRAY_DISPLACEMENT_SCALING_FACTOR "$raw.Maya|displacementscaling" -#define AI_MATKEY_FBX_MAYA_STINGRAY_BASE_COLOR_FACTOR "$raw.Maya|base_color" -#define AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_FACTOR "$raw.Maya|emissive" -#define AI_MATKEY_FBX_MAYA_STINGRAY_METALLIC_FACTOR "$raw.Maya|metallic" -#define AI_MATKEY_FBX_MAYA_STINGRAY_ROUGHNESS_FACTOR "$raw.Maya|roughness" -#define AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_INTENSITY_FACTOR "$raw.Maya|emissive_intensity" - -#define AI_MATKEY_FBX_MAYA_STINGRAY_NORMAL_TEXTURE "$raw.Maya|TEX_normal_map|file" -#define AI_MATKEY_FBX_MAYA_STINGRAY_NORMAL_UV_XFORM "$raw.Maya|TEX_normal_map|uvtrafo" -#define AI_MATKEY_FBX_MAYA_STINGRAY_COLOR_TEXTURE "$raw.Maya|TEX_color_map|file" -#define AI_MATKEY_FBX_MAYA_STINGRAY_COLOR_UV_XFORM "$raw.Maya|TEX_color_map|uvtrafo" -#define AI_MATKEY_FBX_MAYA_STINGRAY_METALLIC_TEXTURE "$raw.Maya|TEX_metallic_map|file" -#define AI_MATKEY_FBX_MAYA_STINGRAY_METALLIC_UV_XFORM "$raw.Maya|TEX_metallic_map|uvtrafo" -#define AI_MATKEY_FBX_MAYA_STINGRAY_ROUGHNESS_TEXTURE "$raw.Maya|TEX_roughness_map|file" -#define AI_MATKEY_FBX_MAYA_STINGRAY_ROUGHNESS_UV_XFORM "$raw.Maya|TEX_roughness_map|uvtrafo" -#define AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_TEXTURE "$raw.Maya|TEX_emissive_map|file" -#define AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_UV_XFORM "$raw.Maya|TEX_emissive_map|uvtrafo" -#define AI_MATKEY_FBX_MAYA_STINGRAY_AO_TEXTURE "$raw.Maya|TEX_ao_map|file" -#define AI_MATKEY_FBX_MAYA_STINGRAY_AO_UV_XFORM "$raw.Maya|TEX_ao_map|uvtrafo" - -/** - * Assimp Utils - * Conversion tools / glue code to convert from assimp to godot -*/ -class AssimpUtils { -public: - /** - * calculate tangents for mesh data from assimp data - */ - static void calc_tangent_from_mesh(const aiMesh *ai_mesh, int i, int tri_index, int index, Color *w) { - const aiVector3D normals = ai_mesh->mAnimMeshes[i]->mNormals[tri_index]; - const Vector3 godot_normal = Vector3(normals.x, normals.y, normals.z); - const aiVector3D tangent = ai_mesh->mAnimMeshes[i]->mTangents[tri_index]; - const Vector3 godot_tangent = Vector3(tangent.x, tangent.y, tangent.z); - const aiVector3D bitangent = ai_mesh->mAnimMeshes[i]->mBitangents[tri_index]; - const Vector3 godot_bitangent = Vector3(bitangent.x, bitangent.y, bitangent.z); - float d = godot_normal.cross(godot_tangent).dot(godot_bitangent) > 0.0f ? 1.0f : -1.0f; - Color plane_tangent = Color(tangent.x, tangent.y, tangent.z, d); - w[index] = plane_tangent; - } - - struct AssetImportFbx { - enum ETimeMode { - TIME_MODE_DEFAULT = 0, - TIME_MODE_120 = 1, - TIME_MODE_100 = 2, - TIME_MODE_60 = 3, - TIME_MODE_50 = 4, - TIME_MODE_48 = 5, - TIME_MODE_30 = 6, - TIME_MODE_30_DROP = 7, - TIME_MODE_NTSC_DROP_FRAME = 8, - TIME_MODE_NTSC_FULL_FRAME = 9, - TIME_MODE_PAL = 10, - TIME_MODE_CINEMA = 11, - TIME_MODE_1000 = 12, - TIME_MODE_CINEMA_ND = 13, - TIME_MODE_CUSTOM = 14, - TIME_MODE_TIME_MODE_COUNT = 15 - }; - enum UpAxis { - UP_VECTOR_AXIS_X = 1, - UP_VECTOR_AXIS_Y = 2, - UP_VECTOR_AXIS_Z = 3 - }; - enum FrontAxis { - FRONT_PARITY_EVEN = 1, - FRONT_PARITY_ODD = 2, - }; - - enum CoordAxis { - COORD_RIGHT = 0, - COORD_LEFT = 1 - }; - }; - - /** Get assimp string - * automatically filters the string data - */ - static String get_assimp_string(const aiString &p_string) { - //convert an assimp String to a Godot String - String name; - name.parse_utf8(p_string.C_Str() /*,p_string.length*/); - if (name.find(":") != -1) { - String replaced_name = name.split(":")[1]; - print_verbose("Replacing " + name + " containing : with " + replaced_name); - name = replaced_name; - } - - return name; - } - - static String get_anim_string_from_assimp(const aiString &p_string) { - String name; - name.parse_utf8(p_string.C_Str() /*,p_string.length*/); - if (name.find(":") != -1) { - String replaced_name = name.split(":")[1]; - print_verbose("Replacing " + name + " containing : with " + replaced_name); - name = replaced_name; - } - return name; - } - - /** - * No filter logic get_raw_string_from_assimp - * This just convers the aiString to a parsed utf8 string - * Without removing special chars etc - */ - static String get_raw_string_from_assimp(const aiString &p_string) { - String name; - name.parse_utf8(p_string.C_Str() /*,p_string.length*/); - return name; - } - - static Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { - return Ref<Animation>(); - } - - /** - * Converts aiMatrix4x4 to godot Transform - */ - static const Transform assimp_matrix_transform(const aiMatrix4x4 p_matrix) { - aiMatrix4x4 matrix = p_matrix; - Transform xform; - xform.set(matrix.a1, matrix.a2, matrix.a3, matrix.b1, matrix.b2, matrix.b3, matrix.c1, matrix.c2, matrix.c3, matrix.a4, matrix.b4, matrix.c4); - return xform; - } - - /** Get fbx fps for time mode meta data - */ - static float get_fbx_fps(int32_t time_mode, const aiScene *p_scene) { - switch (time_mode) { - case AssetImportFbx::TIME_MODE_DEFAULT: - return 24; //hack - case AssetImportFbx::TIME_MODE_120: - return 120; - case AssetImportFbx::TIME_MODE_100: - return 100; - case AssetImportFbx::TIME_MODE_60: - return 60; - case AssetImportFbx::TIME_MODE_50: - return 50; - case AssetImportFbx::TIME_MODE_48: - return 48; - case AssetImportFbx::TIME_MODE_30: - return 30; - case AssetImportFbx::TIME_MODE_30_DROP: - return 30; - case AssetImportFbx::TIME_MODE_NTSC_DROP_FRAME: - return 29.9700262f; - case AssetImportFbx::TIME_MODE_NTSC_FULL_FRAME: - return 29.9700262f; - case AssetImportFbx::TIME_MODE_PAL: - return 25; - case AssetImportFbx::TIME_MODE_CINEMA: - return 24; - case AssetImportFbx::TIME_MODE_1000: - return 1000; - case AssetImportFbx::TIME_MODE_CINEMA_ND: - return 23.976f; - case AssetImportFbx::TIME_MODE_CUSTOM: - int32_t frame_rate = -1; - p_scene->mMetaData->Get("FrameRate", frame_rate); - return frame_rate; - } - return 0; - } - - /** - * Get global transform for the current node - so we can use world space rather than - * local space coordinates - * useful if you need global - although recommend using local wherever possible over global - * as you could break fbx scaling :) - */ - static Transform _get_global_assimp_node_transform(const aiNode *p_current_node) { - aiNode const *current_node = p_current_node; - Transform xform; - while (current_node != nullptr) { - xform = assimp_matrix_transform(current_node->mTransformation) * xform; - current_node = current_node->mParent; - } - return xform; - } - - /** - * Find hardcoded textures from assimp which could be in many different directories - */ - static void find_texture_path(const String &p_path, _Directory &dir, String &path, bool &found, String extension) { - Vector<String> paths; - paths.push_back(path.get_basename() + extension); - paths.push_back(path + extension); - paths.push_back(path); - paths.push_back(p_path.get_base_dir().plus_file(path.get_file().get_basename() + extension)); - paths.push_back(p_path.get_base_dir().plus_file(path.get_file() + extension)); - paths.push_back(p_path.get_base_dir().plus_file(path.get_file())); - paths.push_back(p_path.get_base_dir().plus_file("textures/" + path.get_file().get_basename() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("textures/" + path.get_file() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("textures/" + path.get_file())); - paths.push_back(p_path.get_base_dir().plus_file("Textures/" + path.get_file().get_basename() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("Textures/" + path.get_file() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("Textures/" + path.get_file())); - paths.push_back(p_path.get_base_dir().plus_file("../Textures/" + path.get_file() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("../Textures/" + path.get_file().get_basename() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("../Textures/" + path.get_file())); - paths.push_back(p_path.get_base_dir().plus_file("../textures/" + path.get_file().get_basename() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("../textures/" + path.get_file() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("../textures/" + path.get_file())); - paths.push_back(p_path.get_base_dir().plus_file("texture/" + path.get_file().get_basename() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("texture/" + path.get_file() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("texture/" + path.get_file())); - paths.push_back(p_path.get_base_dir().plus_file("Texture/" + path.get_file().get_basename() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("Texture/" + path.get_file() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("Texture/" + path.get_file())); - paths.push_back(p_path.get_base_dir().plus_file("../Texture/" + path.get_file() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("../Texture/" + path.get_file().get_basename() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("../Texture/" + path.get_file())); - paths.push_back(p_path.get_base_dir().plus_file("../texture/" + path.get_file().get_basename() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("../texture/" + path.get_file() + extension)); - paths.push_back(p_path.get_base_dir().plus_file("../texture/" + path.get_file())); - for (int i = 0; i < paths.size(); i++) { - if (dir.file_exists(paths[i])) { - found = true; - path = paths[i]; - return; - } - } - } - - /** find the texture path for the supplied fbx path inside godot - * very simple lookup for subfolders etc for a texture which may or may not be in a directory - */ - static void find_texture_path(const String &r_p_path, String &r_path, bool &r_found) { - _Directory dir; - - List<String> exts; - ImageLoader::get_recognized_extensions(&exts); - - Vector<String> split_path = r_path.get_basename().split("*"); - if (split_path.size() == 2) { - r_found = true; - return; - } - - if (dir.file_exists(r_p_path.get_base_dir() + r_path.get_file())) { - r_path = r_p_path.get_base_dir() + r_path.get_file(); - r_found = true; - return; - } - - for (int32_t i = 0; i < exts.size(); i++) { - if (r_found) { - return; - } - find_texture_path(r_p_path, dir, r_path, r_found, "." + exts[i]); - } - } - - /** - * set_texture_mapping_mode - * Helper to check the mapping mode of the texture (repeat, clamp and mirror) - */ - static void set_texture_mapping_mode(aiTextureMapMode *map_mode, Ref<ImageTexture> texture) { - ERR_FAIL_COND(texture.is_null()); - ERR_FAIL_COND(map_mode == nullptr); - // FIXME: Commented out during Vulkan port. - /* - aiTextureMapMode tex_mode = map_mode[0]; - - int32_t flags = Texture2D::FLAGS_DEFAULT; - if (tex_mode == aiTextureMapMode_Wrap) { - //Default - } else if (tex_mode == aiTextureMapMode_Clamp) { - flags = flags & ~Texture2D::FLAG_REPEAT; - } else if (tex_mode == aiTextureMapMode_Mirror) { - flags = flags | Texture2D::FLAG_MIRRORED_REPEAT; - } - texture->set_flags(flags); - */ - } - - /** - * Load or load from cache image :) - */ - static Ref<Image> load_image(ImportState &state, const aiScene *p_scene, String p_path) { - Map<String, Ref<Image>>::Element *match = state.path_to_image_cache.find(p_path); - - // if our cache contains this image then don't bother - if (match) { - return match->get(); - } - - Vector<String> split_path = p_path.get_basename().split("*"); - if (split_path.size() == 2) { - size_t texture_idx = split_path[1].to_int(); - ERR_FAIL_COND_V(texture_idx >= p_scene->mNumTextures, Ref<Image>()); - aiTexture *tex = p_scene->mTextures[texture_idx]; - String filename = AssimpUtils::get_raw_string_from_assimp(tex->mFilename); - filename = filename.get_file(); - print_verbose("Open Asset Import: Loading embedded texture " + filename); - if (tex->mHeight == 0) { - if (tex->CheckFormat("png")) { - ERR_FAIL_COND_V(Image::_png_mem_loader_func == nullptr, Ref<Image>()); - Ref<Image> img = Image::_png_mem_loader_func((uint8_t *)tex->pcData, tex->mWidth); - ERR_FAIL_COND_V(img.is_null(), Ref<Image>()); - state.path_to_image_cache.insert(p_path, img); - return img; - } else if (tex->CheckFormat("jpg")) { - ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == nullptr, Ref<Image>()); - Ref<Image> img = Image::_jpg_mem_loader_func((uint8_t *)tex->pcData, tex->mWidth); - ERR_FAIL_COND_V(img.is_null(), Ref<Image>()); - state.path_to_image_cache.insert(p_path, img); - return img; - } else if (tex->CheckFormat("dds")) { - ERR_FAIL_COND_V_MSG(true, Ref<Image>(), "Open Asset Import: Embedded dds not implemented"); - } - } else { - Ref<Image> img; - img.instance(); - PackedByteArray arr; - uint32_t size = tex->mWidth * tex->mHeight; - arr.resize(size); - memcpy(arr.ptrw(), tex->pcData, size); - ERR_FAIL_COND_V(arr.size() % 4 != 0, Ref<Image>()); - //ARGB8888 to RGBA8888 - for (int32_t i = 0; i < arr.size() / 4; i++) { - arr.ptrw()[(4 * i) + 3] = arr[(4 * i) + 0]; - arr.ptrw()[(4 * i) + 0] = arr[(4 * i) + 1]; - arr.ptrw()[(4 * i) + 1] = arr[(4 * i) + 2]; - arr.ptrw()[(4 * i) + 2] = arr[(4 * i) + 3]; - } - img->create(tex->mWidth, tex->mHeight, true, Image::FORMAT_RGBA8, arr); - ERR_FAIL_COND_V(img.is_null(), Ref<Image>()); - state.path_to_image_cache.insert(p_path, img); - return img; - } - return Ref<Image>(); - } else { - Ref<Texture2D> texture = ResourceLoader::load(p_path); - ERR_FAIL_COND_V(texture.is_null(), Ref<Image>()); - Ref<Image> image = texture->get_data(); - ERR_FAIL_COND_V(image.is_null(), Ref<Image>()); - state.path_to_image_cache.insert(p_path, image); - return image; - } - - return Ref<Image>(); - } - - /* create texture from assimp data, if found in path */ - static bool CreateAssimpTexture( - AssimpImporter::ImportState &state, - aiString texture_path, - String &filename, - String &path, - AssimpImageData &image_state) { - filename = get_raw_string_from_assimp(texture_path); - path = state.path.get_base_dir().plus_file(filename.replace("\\", "/")); - bool found = false; - find_texture_path(state.path, path, found); - if (found) { - image_state.raw_image = AssimpUtils::load_image(state, state.assimp_scene, path); - if (image_state.raw_image.is_valid()) { - image_state.texture.instance(); - image_state.texture->create_from_image(image_state.raw_image); - // FIXME: Commented out during Vulkan port. - //image_state.texture->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSY); - return true; - } - } - - return false; - } - /** GetAssimpTexture - * Designed to retrieve textures for you - */ - static bool GetAssimpTexture( - AssimpImporter::ImportState &state, - aiMaterial *ai_material, - aiTextureType texture_type, - String &filename, - String &path, - AssimpImageData &image_state) { - aiString ai_filename = aiString(); - if (AI_SUCCESS == ai_material->GetTexture(texture_type, 0, &ai_filename, nullptr, nullptr, nullptr, nullptr, image_state.map_mode)) { - return CreateAssimpTexture(state, ai_filename, filename, path, image_state); - } - - return false; - } -}; - -#endif // IMPORT_UTILS_IMPORTER_ASSIMP_H diff --git a/modules/assimp/register_types.cpp b/modules/assimp/register_types.cpp deleted file mode 100644 index 6cb0fc982f..0000000000 --- a/modules/assimp/register_types.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************/ -/* register_types.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 "register_types.h" - -#include "editor/editor_node.h" -#include "editor_scene_importer_assimp.h" - -#ifdef TOOLS_ENABLED -static void _editor_init() { - Ref<EditorSceneImporterAssimp> import_assimp; - import_assimp.instance(); - ResourceImporterScene::get_singleton()->add_importer(import_assimp); -} -#endif - -void register_assimp_types() { -#ifdef TOOLS_ENABLED - ClassDB::APIType prev_api = ClassDB::get_current_api(); - ClassDB::set_current_api(ClassDB::API_EDITOR); - - ClassDB::register_class<EditorSceneImporterAssimp>(); - - ClassDB::set_current_api(prev_api); - - EditorNode::add_init_callback(_editor_init); -#endif -} - -void unregister_assimp_types() { -} diff --git a/modules/assimp/register_types.h b/modules/assimp/register_types.h deleted file mode 100644 index f399a7acc6..0000000000 --- a/modules/assimp/register_types.h +++ /dev/null @@ -1,37 +0,0 @@ -/*************************************************************************/ -/* register_types.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 ASSIMP_REGISTER_TYPES_H -#define ASSIMP_REGISTER_TYPES_H - -void register_assimp_types(); -void unregister_assimp_types(); - -#endif // ASSIMP_REGISTER_TYPES_H |