Browse Source

Preliminary Blender FBX support [4.0]

limitations:
- always has to use generated normal's.
- some animations won't be compatible (yet)

Co-authored-by: Rémi Verschelde <[email protected]>
Gordon MacPherson 4 years ago
parent
commit
74a72cf85e

+ 7 - 21
modules/fbx/data/fbx_mesh_data.cpp

@@ -135,26 +135,6 @@ EditorSceneImporterMeshNode3D *FBXMeshData::create_fbx_mesh(const ImportState &s
 			&collect_all,
 			&collect_all,
 			HashMap<int, Vector3>());
 			HashMap<int, Vector3>());
 
 
-	//	List<int> keys;
-	//	normals.get_key_list(&keys);
-	//
-	//	const std::vector<Assimp::FBX::MeshGeometry::Edge>& 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<int, Vector2> uvs_0;
 	HashMap<int, Vector2> uvs_0;
 	HashMap<int, HashMap<int, Vector2>> uvs_0_raw = extract_per_vertex_data(
 	HashMap<int, HashMap<int, Vector2>> uvs_0_raw = extract_per_vertex_data(
 			vertices.size(),
 			vertices.size(),
@@ -371,6 +351,9 @@ EditorSceneImporterMeshNode3D *FBXMeshData::create_fbx_mesh(const ImportState &s
 						normals_ptr[vertex]);
 						normals_ptr[vertex]);
 			}
 			}
 
 
+			if (state.is_blender_fbx) {
+				morph_st->generate_normals();
+			}
 			morph_st->generate_tangents();
 			morph_st->generate_tangents();
 			surface->morphs.push_back(morph_st->commit_to_arrays());
 			surface->morphs.push_back(morph_st->commit_to_arrays());
 		}
 		}
@@ -393,6 +376,9 @@ EditorSceneImporterMeshNode3D *FBXMeshData::create_fbx_mesh(const ImportState &s
 	for (const SurfaceId *surface_id = surfaces.next(nullptr); surface_id != nullptr; surface_id = surfaces.next(surface_id)) {
 	for (const SurfaceId *surface_id = surfaces.next(nullptr); surface_id != nullptr; surface_id = surfaces.next(surface_id)) {
 		SurfaceData *surface = surfaces.getptr(*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.
 		// you can't generate them without a valid uv map.
 		if (uvs_0_raw.size() > 0) {
 		if (uvs_0_raw.size() > 0) {
 			surface->surface_tool->generate_tangents();
 			surface->surface_tool->generate_tangents();
@@ -785,7 +771,7 @@ void FBXMeshData::add_vertex(
 		const Vector3 &p_morph_normal) {
 		const Vector3 &p_morph_normal) {
 	ERR_FAIL_INDEX_MSG(p_vertex, (Vertex)p_vertices_position.size(), "FBX file is corrupted, the position of the vertex can't be retrieved.");
 	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->set_normal(p_normals[p_vertex] + p_morph_normal);
 		p_surface_tool->set_normal(p_normals[p_vertex] + p_morph_normal);
 	}
 	}
 
 

+ 1 - 0
modules/fbx/data/import_state.h

@@ -64,6 +64,7 @@ struct FBXSkeleton;
 struct ImportState {
 struct ImportState {
 	bool enable_material_import = true;
 	bool enable_material_import = true;
 	bool enable_animation_import = true;
 	bool enable_animation_import = true;
+	bool is_blender_fbx = false;
 
 
 	Map<StringName, Ref<Texture>> cached_image_searches;
 	Map<StringName, Ref<Texture>> cached_image_searches;
 	Map<uint64_t, Ref<Material>> cached_materials;
 	Map<uint64_t, Ref<Material>> cached_materials;

+ 7 - 3
modules/fbx/editor_scene_importer_fbx.cpp

@@ -180,10 +180,12 @@ Node3D *EditorSceneImporterFBX::import_scene(const String &p_path, uint32_t p_fl
 			}
 			}
 
 
 			if (is_blender_fbx) {
 			if (is_blender_fbx) {
-				WARN_PRINT("Blender FBX files will not work properly with keyframes or skeletons until we make fixes. Please stand by.");
+				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.");
 			}
 			}
 
 
-			Node3D *spatial = _generate_scene(p_path, &doc, p_flags, p_bake_fps, 8);
+			Node3D *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)
 			// todo: move to document shutdown (will need to be validated after moving; this code has been validated already)
 			for (FBXDocParser::TokenPtr token : tokens) {
 			for (FBXDocParser::TokenPtr token : tokens) {
 				if (token) {
 				if (token) {
@@ -327,8 +329,10 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
 		const FBXDocParser::Document *p_document,
 		const FBXDocParser::Document *p_document,
 		const uint32_t p_flags,
 		const uint32_t p_flags,
 		int p_bake_fps,
 		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;
 	ImportState state;
+	state.is_blender_fbx = p_is_blender_fbx;
 	state.path = p_path;
 	state.path = p_path;
 	state.animation_player = NULL;
 	state.animation_player = NULL;
 
 

+ 3 - 1
modules/fbx/editor_scene_importer_fbx.h

@@ -114,7 +114,9 @@ private:
 
 
 	Node3D *_generate_scene(const String &p_path, const FBXDocParser::Document *p_document,
 	Node3D *_generate_scene(const String &p_path, const FBXDocParser::Document *p_document,
 			const uint32_t p_flags,
 			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 <class T>
 	template <class T>
 	T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, AssetImportAnimation::Interpolation p_interp);
 	T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, AssetImportAnimation::Interpolation p_interp);