From 31bc1af82a37c17f8b02d64540bb41ab63f22390 Mon Sep 17 00:00:00 2001 From: Gordon MacPherson Date: Sun, 3 Jan 2021 20:16:57 +0000 Subject: [PATCH] Preliminary Blender FBX support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit limitations: - always has to use generated normal's. - some animations won't be compatible (yet) Co-authored-by: RĂ©mi Verschelde --- modules/fbx/data/fbx_mesh_data.cpp | 28 +++++--------------- modules/fbx/data/import_state.h | 1 + modules/fbx/editor_scene_importer_fbx.cpp | 32 +++++++++++++---------- modules/fbx/editor_scene_importer_fbx.h | 4 ++- 4 files changed, 29 insertions(+), 36 deletions(-) diff --git a/modules/fbx/data/fbx_mesh_data.cpp b/modules/fbx/data/fbx_mesh_data.cpp index 1b59a42683c..b525f04d703 100644 --- a/modules/fbx/data/fbx_mesh_data.cpp +++ b/modules/fbx/data/fbx_mesh_data.cpp @@ -134,26 +134,6 @@ MeshInstance *FBXMeshData::create_fbx_mesh(const ImportState &state, const FBXDo &collect_all, HashMap()); - // List keys; - // normals.get_key_list(&keys); - // - // const std::vector& edges = mesh_geometry->get_edge_map(); - // for (int index = 0; index < keys.size(); index++) { - // const int key = keys[index]; - // const int v1 = edges[key].vertex_0; - // const int v2 = edges[key].vertex_1; - // const Vector3& n1 = normals.get(v1); - // const Vector3& n2 = normals.get(v2); - // print_verbose("[" + itos(v1) + "] n1: " + n1 + "\n[" + itos(v2) + "] n2: " + n2); - // //print_verbose("[" + itos(key) + "] n1: " + n1 + ", n2: " + n2) ; - // //print_verbose("vindex: " + itos(edges[key].vertex_0) + ", vindex2: " + itos(edges[key].vertex_1)); - // //Vector3 ver1 = vertices[edges[key].vertex_0]; - // //Vector3 ver2 = vertices[edges[key].vertex_1]; - // /*real_t angle1 = Math::rad2deg(n1.angle_to(n2)); - // real_t angle2 = Math::rad2deg(n2.angle_to(n1)); - // print_verbose("angle of normals: " + rtos(angle1) + " angle 2" + rtos(angle2));*/ - // } - HashMap uvs_0; HashMap > uvs_0_raw = extract_per_vertex_data( vertices.size(), @@ -370,6 +350,9 @@ MeshInstance *FBXMeshData::create_fbx_mesh(const ImportState &state, const FBXDo normals_ptr[vertex]); } + if (state.is_blender_fbx) { + morph_st->generate_normals(); + } morph_st->generate_tangents(); surface->morphs.push_back(morph_st->commit_to_arrays()); } @@ -392,6 +375,9 @@ MeshInstance *FBXMeshData::create_fbx_mesh(const ImportState &state, const FBXDo for (const SurfaceId *surface_id = surfaces.next(nullptr); surface_id != nullptr; surface_id = surfaces.next(surface_id)) { SurfaceData *surface = surfaces.getptr(*surface_id); + if (state.is_blender_fbx) { + surface->surface_tool->generate_normals(); + } // you can't generate them without a valid uv map. if (uvs_0_raw.size() > 0) { surface->surface_tool->generate_tangents(); @@ -790,7 +776,7 @@ void FBXMeshData::add_vertex( ERR_FAIL_INDEX_MSG(p_vertex, (Vertex)p_vertices_position.size(), "FBX file is corrupted, the position of the vertex can't be retrieved."); - if (p_normals.has(p_vertex)) { + if (p_normals.has(p_vertex) && !state.is_blender_fbx) { p_surface_tool->add_normal(p_normals[p_vertex] + p_morph_normal); } diff --git a/modules/fbx/data/import_state.h b/modules/fbx/data/import_state.h index 61d3fb33a6e..ed16a6f2147 100644 --- a/modules/fbx/data/import_state.h +++ b/modules/fbx/data/import_state.h @@ -64,6 +64,7 @@ struct FBXSkeleton; struct ImportState { bool enable_material_import = true; bool enable_animation_import = true; + bool is_blender_fbx = false; Map > cached_image_searches; Map > cached_materials; diff --git a/modules/fbx/editor_scene_importer_fbx.cpp b/modules/fbx/editor_scene_importer_fbx.cpp index ef1818d34ac..0ee1df1a6de 100644 --- a/modules/fbx/editor_scene_importer_fbx.cpp +++ b/modules/fbx/editor_scene_importer_fbx.cpp @@ -180,21 +180,23 @@ Node *EditorSceneImporterFBX::import_scene(const String &p_path, uint32_t p_flag } } - if (!is_blender_fbx) { - Spatial *spatial = _generate_scene(p_path, &doc, p_flags, p_bake_fps, 8); - // todo: move to document shutdown (will need to be validated after moving; this code has been validated already) - for (FBXDocParser::TokenPtr token : tokens) { - if (token) { - delete token; - token = nullptr; - } - } - - return spatial; - } else { - ERR_PRINT("We can't import Blender FBX files for the time being. Please favor glTF 2.0 when exporting from Blender."); + if (is_blender_fbx) { + WARN_PRINT("We don't officially support Blender FBX animations yet, due to issues with upstream Blender,\n" + "so please wait for us to work around remaining issues. We will continue to import the file but it may be broken.\n" + "For minimal breakage, please export FBX from Blender with -Z forward, and Y up."); } + Spatial *spatial = _generate_scene(p_path, &doc, p_flags, p_bake_fps, 8, is_blender_fbx); + // todo: move to document shutdown (will need to be validated after moving; this code has been validated already) + for (FBXDocParser::TokenPtr token : tokens) { + if (token) { + delete token; + token = nullptr; + } + } + + return spatial; + } else { ERR_PRINT(vformat("Cannot import FBX file: %s. It uses file format %d which is unsupported by Godot. Please re-export it or convert it to a newer format.", p_path, doc.FBXVersion())); } @@ -368,9 +370,11 @@ Spatial *EditorSceneImporterFBX::_generate_scene( const FBXDocParser::Document *p_document, const uint32_t p_flags, int p_bake_fps, - const int32_t p_max_bone_weights) { + const int32_t p_max_bone_weights, + bool p_is_blender_fbx) { ImportState state; + state.is_blender_fbx = p_is_blender_fbx; state.path = p_path; state.animation_player = NULL; diff --git a/modules/fbx/editor_scene_importer_fbx.h b/modules/fbx/editor_scene_importer_fbx.h index 1317b58330e..348356e61d4 100644 --- a/modules/fbx/editor_scene_importer_fbx.h +++ b/modules/fbx/editor_scene_importer_fbx.h @@ -115,7 +115,9 @@ private: Spatial *_generate_scene(const String &p_path, const FBXDocParser::Document *p_document, const uint32_t p_flags, - int p_bake_fps, const int32_t p_max_bone_weights); + int p_bake_fps, + const int32_t p_max_bone_weights, + bool p_is_blender_fbx); template T _interpolate_track(const Vector &p_times, const Vector &p_values, float p_time, AssetImportAnimation::Interpolation p_interp);