Quellcode durchsuchen

Restored ability to import OBJ files as meshes directly. Finally closes #9445.

Juan Linietsky vor 8 Jahren
Ursprung
Commit
f494470005
3 geänderte Dateien mit 144 neuen und 54 gelöschten Zeilen
  1. 4 0
      editor/editor_node.cpp
  2. 120 52
      editor/import/resource_importer_obj.cpp
  3. 20 2
      editor/import/resource_importer_obj.h

+ 4 - 0
editor/editor_node.cpp

@@ -4623,6 +4623,10 @@ EditorNode::EditorNode() {
 		import_wav.instance();
 		ResourceFormatImporter::get_singleton()->add_importer(import_wav);
 
+		Ref<ResourceImporterOBJ> import_obj;
+		import_obj.instance();
+		ResourceFormatImporter::get_singleton()->add_importer(import_obj);
+
 		Ref<ResourceImporterScene> import_scene;
 		import_scene.instance();
 		ResourceFormatImporter::get_singleton()->add_importer(import_scene);

+ 120 - 52
editor/import/resource_importer_obj.cpp

@@ -40,12 +40,8 @@ uint32_t EditorOBJImporter::get_import_flags() const {
 
 	return IMPORT_SCENE;
 }
-void EditorOBJImporter::get_extensions(List<String> *r_extensions) const {
 
-	r_extensions->push_back("obj");
-}
-
-Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<String, Ref<SpatialMaterial> > &material_map, List<String> *r_missing_deps) {
+static Error _parse_material_library(const String &p_path, Map<String, Ref<SpatialMaterial> > &material_map, List<String> *r_missing_deps) {
 
 	FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
 	ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
@@ -134,7 +130,7 @@ Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<Strin
 
 			if (texture.is_valid()) {
 				current->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture);
-			} else {
+			} else if (r_missing_deps) {
 				r_missing_deps->push_back(path);
 			}
 
@@ -149,7 +145,7 @@ Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<Strin
 
 			if (texture.is_valid()) {
 				current->set_texture(SpatialMaterial::TEXTURE_METALLIC, texture);
-			} else {
+			} else if (r_missing_deps) {
 				r_missing_deps->push_back(path);
 			}
 
@@ -164,7 +160,7 @@ Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<Strin
 
 			if (texture.is_valid()) {
 				current->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, texture);
-			} else {
+			} else if (r_missing_deps) {
 				r_missing_deps->push_back(path);
 			}
 		} else if (l.begins_with("map_bump ")) {
@@ -179,7 +175,7 @@ Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<Strin
 			if (texture.is_valid()) {
 				current->set_feature(SpatialMaterial::FEATURE_NORMAL_MAPPING, true);
 				current->set_texture(SpatialMaterial::TEXTURE_NORMAL, texture);
-			} else {
+			} else if (r_missing_deps) {
 				r_missing_deps->push_back(path);
 			}
 		} else if (f->eof_reached()) {
@@ -190,28 +186,16 @@ Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<Strin
 	return OK;
 }
 
-Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
+static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p_single_mesh, bool p_generate_tangents, List<String> *r_missing_deps) {
 
 	FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
 
-	if (r_err) {
-		*r_err = ERR_CANT_OPEN;
-	}
-
-	ERR_FAIL_COND_V(!f, NULL);
-
-	if (r_err) {
-		*r_err = OK;
-	}
-
-	Spatial *scene = memnew(Spatial);
+	ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
 
 	Ref<ArrayMesh> mesh;
 	mesh.instance();
 
-	Map<String, Ref<Material> > name_map;
-
-	bool generate_tangents = p_flags & IMPORT_GENERATE_TANGENT_ARRAYS;
+	bool generate_tangents = p_generate_tangents;
 	bool flip_faces = false;
 	//bool flip_faces = p_options["force/flip_faces"];
 	//bool force_smooth = p_options["force/smooth_shading"];
@@ -239,7 +223,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
 		if (l.begins_with("v ")) {
 			//vertex
 			Vector<String> v = l.split(" ", false);
-			ERR_FAIL_COND_V(v.size() < 4, NULL);
+			ERR_FAIL_COND_V(v.size() < 4, ERR_FILE_CORRUPT);
 			Vector3 vtx;
 			vtx.x = v[1].to_float();
 			vtx.y = v[2].to_float();
@@ -248,7 +232,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
 		} else if (l.begins_with("vt ")) {
 			//uv
 			Vector<String> v = l.split(" ", false);
-			ERR_FAIL_COND_V(v.size() < 3, NULL);
+			ERR_FAIL_COND_V(v.size() < 3, ERR_FILE_CORRUPT);
 			Vector2 uv;
 			uv.x = v[1].to_float();
 			uv.y = 1.0 - v[2].to_float();
@@ -257,7 +241,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
 		} else if (l.begins_with("vn ")) {
 			//normal
 			Vector<String> v = l.split(" ", false);
-			ERR_FAIL_COND_V(v.size() < 4, NULL);
+			ERR_FAIL_COND_V(v.size() < 4, ERR_FILE_CORRUPT);
 			Vector3 nrm;
 			nrm.x = v[1].to_float();
 			nrm.y = v[2].to_float();
@@ -267,19 +251,19 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
 			//vertex
 
 			Vector<String> v = l.split(" ", false);
-			ERR_FAIL_COND_V(v.size() < 4, NULL);
+			ERR_FAIL_COND_V(v.size() < 4, ERR_FILE_CORRUPT);
 
 			//not very fast, could be sped up
 
 			Vector<String> face[3];
 			face[0] = v[1].split("/");
 			face[1] = v[2].split("/");
-			ERR_FAIL_COND_V(face[0].size() == 0, NULL);
-			ERR_FAIL_COND_V(face[0].size() != face[1].size(), NULL);
+			ERR_FAIL_COND_V(face[0].size() == 0, ERR_FILE_CORRUPT);
+			ERR_FAIL_COND_V(face[0].size() != face[1].size(), ERR_FILE_CORRUPT);
 			for (int i = 2; i < v.size() - 1; i++) {
 
 				face[2] = v[i + 1].split("/");
-				ERR_FAIL_COND_V(face[0].size() != face[2].size(), NULL);
+				ERR_FAIL_COND_V(face[0].size() != face[2].size(), ERR_FILE_CORRUPT);
 				for (int j = 0; j < 3; j++) {
 
 					int idx = j;
@@ -292,7 +276,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
 						int norm = face[idx][2].to_int() - 1;
 						if (norm < 0)
 							norm += normals.size() + 1;
-						ERR_FAIL_INDEX_V(norm, normals.size(), NULL);
+						ERR_FAIL_INDEX_V(norm, normals.size(), ERR_FILE_CORRUPT);
 						surf_tool->add_normal(normals[norm]);
 					}
 
@@ -300,14 +284,14 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
 						int uv = face[idx][1].to_int() - 1;
 						if (uv < 0)
 							uv += uvs.size() + 1;
-						ERR_FAIL_INDEX_V(uv, uvs.size(), NULL);
+						ERR_FAIL_INDEX_V(uv, uvs.size(), ERR_FILE_CORRUPT);
 						surf_tool->add_uv(uvs[uv]);
 					}
 
 					int vtx = face[idx][0].to_int() - 1;
 					if (vtx < 0)
 						vtx += vertices.size() + 1;
-					ERR_FAIL_INDEX_V(vtx, vertices.size(), NULL);
+					ERR_FAIL_INDEX_V(vtx, vertices.size(), ERR_FILE_CORRUPT);
 
 					Vector3 vertex = vertices[vtx];
 					//if (weld_vertices)
@@ -359,16 +343,13 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
 
 			if (l.begins_with("o ") || f->eof_reached()) {
 
-				MeshInstance *mi = memnew(MeshInstance);
-				mi->set_name(name);
-				mi->set_mesh(mesh);
-
-				scene->add_child(mi);
-				mi->set_owner(scene);
-
-				mesh.instance();
-				current_group = "";
-				current_material = "";
+				if (!p_single_mesh) {
+					mesh->set_name(name);
+					r_meshes.push_back(mesh);
+					mesh.instance();
+					current_group = "";
+					current_material = "";
+				}
 			}
 
 			if (f->eof_reached()) {
@@ -406,16 +387,40 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
 		}
 	}
 
-	/*
-	TODO, check existing materials and merge?
-	//re-apply materials if exist
-	for(int i=0;i<mesh->get_surface_count();i++) {
+	if (p_single_mesh) {
+
+		r_meshes.push_back(mesh);
+	}
+
+	return OK;
+}
+
+Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
+
+	List<Ref<Mesh> > meshes;
+
+	Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, r_missing_deps);
+
+	if (err != OK) {
+		if (r_err) {
+			*r_err = err;
+		}
+		return NULL;
+	}
+
+	Spatial *scene = memnew(Spatial);
+
+	for (List<Ref<Mesh> >::Element *E = meshes.front(); E; E = E->next()) {
+
+		MeshInstance *mi = memnew(MeshInstance);
+		mi->set_name(E->get()->get_name());
+		scene->add_child(mi);
+		mi->set_owner(scene);
+	}
 
-		String n = mesh->surface_get_name(i);
-		if (name_map.has(n))
-			mesh->surface_set_material(i,name_map[n]);
+	if (r_err) {
+		*r_err = OK;
 	}
-*/
 
 	return scene;
 }
@@ -423,5 +428,68 @@ Ref<Animation> EditorOBJImporter::import_animation(const String &p_path, uint32_
 
 	return Ref<Animation>();
 }
+
+void EditorOBJImporter::get_extensions(List<String> *r_extensions) const {
+
+	r_extensions->push_back("obj");
+}
+
 EditorOBJImporter::EditorOBJImporter() {
 }
+////////////////////////////////////////////////////
+
+String ResourceImporterOBJ::get_importer_name() const {
+	return "wavefront_obj";
+}
+String ResourceImporterOBJ::get_visible_name() const {
+	return "OBJ As Mesh";
+}
+void ResourceImporterOBJ::get_recognized_extensions(List<String> *p_extensions) const {
+
+	p_extensions->push_back("obj");
+}
+String ResourceImporterOBJ::get_save_extension() const {
+	return "mesh";
+}
+String ResourceImporterOBJ::get_resource_type() const {
+	return "Mesh";
+}
+
+int ResourceImporterOBJ::get_preset_count() const {
+	return 0;
+}
+String ResourceImporterOBJ::get_preset_name(int p_idx) const {
+	return "";
+}
+
+void ResourceImporterOBJ::get_import_options(List<ImportOption> *r_options, int p_preset) const {
+
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_tangents"), true));
+}
+bool ResourceImporterOBJ::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
+
+	return true;
+}
+
+Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) {
+
+	List<Ref<Mesh> > meshes;
+
+	Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], NULL);
+
+	ERR_FAIL_COND_V(err != OK, err);
+	ERR_FAIL_COND_V(meshes.size() != 1, ERR_BUG);
+
+	String save_path = p_save_path + ".mesh";
+
+	err = ResourceSaver::save(save_path, meshes.front()->get());
+
+	ERR_FAIL_COND_V(err != OK, err);
+
+	r_gen_files->push_back(save_path);
+
+	return OK;
+}
+
+ResourceImporterOBJ::ResourceImporterOBJ() {
+}

+ 20 - 2
editor/import/resource_importer_obj.h

@@ -36,8 +36,6 @@ class EditorOBJImporter : public EditorSceneImporter {
 
 	GDCLASS(EditorOBJImporter, EditorSceneImporter);
 
-	Error _parse_material_library(const String &p_path, Map<String, Ref<SpatialMaterial> > &material_map, List<String> *r_missing_deps);
-
 public:
 	virtual uint32_t get_import_flags() const;
 	virtual void get_extensions(List<String> *r_extensions) const;
@@ -47,4 +45,24 @@ public:
 	EditorOBJImporter();
 };
 
+class ResourceImporterOBJ : public ResourceImporter {
+	GDCLASS(ResourceImporterOBJ, ResourceImporter)
+public:
+	virtual String get_importer_name() const;
+	virtual String get_visible_name() const;
+	virtual void get_recognized_extensions(List<String> *p_extensions) const;
+	virtual String get_save_extension() const;
+	virtual String get_resource_type() const;
+
+	virtual int get_preset_count() const;
+	virtual String get_preset_name(int p_idx) const;
+
+	virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const;
+	virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const;
+
+	virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL);
+
+	ResourceImporterOBJ();
+};
+
 #endif // RESOURCEIMPORTEROBJ_H