Browse Source

OBJ file importing!

Juan Linietsky 8 years ago
parent
commit
9ce2ab9749

+ 8 - 2
tools/editor/editor_node.cpp

@@ -99,9 +99,10 @@
 #include "plugins/color_ramp_editor_plugin.h"
 #include "plugins/collision_shape_2d_editor_plugin.h"
 #include "plugins/gi_probe_editor_plugin.h"
-#include "import/resource_import_texture.h"
+#include "import/resource_importer_texture.h"
 #include "import/resource_importer_csv_translation.h"
-#include "import/resource_import_wav.h"
+#include "import/resource_importer_wav.h"
+#include "import/resource_importer_obj.h"
 // end
 #include "editor_settings.h"
 #include "io_plugins/editor_texture_import_plugin.h"
@@ -5131,6 +5132,11 @@ 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);
+
 	}
 
 	_pvrtc_register_compressors();

+ 231 - 0
tools/editor/import/resource_importer_obj.cpp

@@ -0,0 +1,231 @@
+#include "resource_importer_obj.h"
+
+#include "io/resource_saver.h"
+#include "scene/resources/mesh.h"
+#include "scene/resources/surface_tool.h"
+#include "scene/resources/surface_tool.h"
+#include "os/file_access.h"
+
+String ResourceImporterOBJ::get_importer_name() const {
+
+	return "obj_mesh";
+}
+
+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 "msh";
+}
+
+String ResourceImporterOBJ::get_resource_type() const{
+
+	return "Mesh";
+}
+
+bool ResourceImporterOBJ::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
+
+	return true;
+}
+
+int ResourceImporterOBJ::get_preset_count() const {
+	return 0;
+}
+String ResourceImporterOBJ::get_preset_name(int p_idx) const {
+
+	return String();
+}
+
+
+void ResourceImporterOBJ::get_import_options(List<ImportOption> *r_options,int p_preset) const {
+
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"generate/tangents"),true));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"generate/normals"),true));
+	//not for nowp
+	//r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"import/materials")));
+	//r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"import/textures")));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/flip_faces"),false));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/smooth_shading"),true));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/weld_vertices"),true));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"force/weld_tolerance",PROPERTY_HINT_RANGE,"0.00001,16,0.00001"),0.0001));
+	//r_options->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192"));
+
+}
+
+
+
+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) {
+
+	FileAccessRef f = FileAccess::open(p_source_file,FileAccess::READ);
+	ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
+
+	Ref<Mesh> mesh = Ref<Mesh>( memnew( Mesh ) );
+	Map<String,Ref<Material> > name_map;
+
+
+
+	bool generate_normals=p_options["generate/normals"];
+	bool generate_tangents=p_options["generate/tangents"];
+	bool flip_faces=p_options["force/flip_faces"];
+	bool force_smooth=p_options["force/smooth_shading"];
+	bool weld_vertices=p_options["force/weld_vertices"];
+	float weld_tolerance=p_options["force/weld_tolerance"];
+	Vector<Vector3> vertices;
+	Vector<Vector3> normals;
+	Vector<Vector2> uvs;
+	String name;
+
+	Ref<SurfaceTool> surf_tool = memnew( SurfaceTool) ;
+	surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
+	if (force_smooth)
+		surf_tool->add_smooth_group(true);
+	int has_index_data=false;
+
+	while(true) {
+
+
+		String l = f->get_line().strip_edges();
+
+		if (l.begins_with("v ")) {
+			//vertex
+			Vector<String> v = l.split(" ",false);
+			ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
+			Vector3 vtx;
+			vtx.x=v[1].to_float();
+			vtx.y=v[2].to_float();
+			vtx.z=v[3].to_float();
+			vertices.push_back(vtx);
+		} else  if (l.begins_with("vt ")) {
+			//uv
+			Vector<String> v = l.split(" ",false);
+			ERR_FAIL_COND_V(v.size()<3,ERR_INVALID_DATA);
+			Vector2 uv;
+			uv.x=v[1].to_float();
+			uv.y=1.0-v[2].to_float();
+			uvs.push_back(uv);
+
+		} else if (l.begins_with("vn ")) {
+			//normal
+			Vector<String> v = l.split(" ",false);
+			ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
+			Vector3 nrm;
+			nrm.x=v[1].to_float();
+			nrm.y=v[2].to_float();
+			nrm.z=v[3].to_float();
+			normals.push_back(nrm);
+		} if (l.begins_with("f ")) {
+				//vertex
+
+			has_index_data=true;
+			Vector<String> v = l.split(" ",false);
+			ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
+
+			//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,ERR_PARSE_ERROR);
+			ERR_FAIL_COND_V(face[0].size()!=face[1].size(),ERR_PARSE_ERROR);
+			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(),ERR_PARSE_ERROR);
+				for(int j=0;j<3;j++) {
+
+					int idx=j;
+
+					if (!flip_faces && idx<2) {
+						idx=1^idx;
+					}
+
+
+					if (face[idx].size()==3) {
+						int norm = face[idx][2].to_int()-1;
+						ERR_FAIL_INDEX_V(norm,normals.size(),ERR_PARSE_ERROR);
+						surf_tool->add_normal(normals[norm]);
+					}
+
+					if (face[idx].size()>=2 && face[idx][1]!=String()) {
+
+						int uv = face[idx][1].to_int()-1;
+						ERR_FAIL_INDEX_V(uv,uvs.size(),ERR_PARSE_ERROR);
+						surf_tool->add_uv(uvs[uv]);
+					}
+
+					int vtx = face[idx][0].to_int()-1;
+					ERR_FAIL_INDEX_V(vtx,vertices.size(),ERR_PARSE_ERROR);
+
+					Vector3 vertex = vertices[vtx];
+					if (weld_vertices)
+						vertex=vertex.snapped(weld_tolerance);
+					surf_tool->add_vertex(vertex);
+				}
+
+				face[1]=face[2];
+			}
+		} else if (l.begins_with("s ") && !force_smooth) { //smoothing
+			String what = l.substr(2,l.length()).strip_edges();
+			if (what=="off")
+				surf_tool->add_smooth_group(false);
+			else
+				surf_tool->add_smooth_group(true);
+
+		} else if (l.begins_with("o ") || f->eof_reached()) { //new surface or done
+
+			if (has_index_data) {
+				//new object/surface
+				if (generate_normals || force_smooth)
+					surf_tool->generate_normals();
+				if (uvs.size() && (normals.size() || generate_normals) && generate_tangents)
+					surf_tool->generate_tangents();
+
+				surf_tool->index();
+				mesh = surf_tool->commit(mesh);
+				if (name=="")
+					name=vformat(TTR("Surface %d"),mesh->get_surface_count()-1);
+				mesh->surface_set_name(mesh->get_surface_count()-1,name);
+				name="";
+				surf_tool->clear();
+				surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
+				if (force_smooth)
+					surf_tool->add_smooth_group(true);
+
+				has_index_data=false;
+
+				if (f->eof_reached())
+					break;
+			}
+
+			if (l.begins_with("o ")) //name
+				name=l.substr(2,l.length()).strip_edges();
+		}
+	}
+
+/*
+	TODO, check existing materials and merge?
+	//re-apply materials if exist
+	for(int i=0;i<mesh->get_surface_count();i++) {
+
+		String n = mesh->surface_get_name(i);
+		if (name_map.has(n))
+			mesh->surface_set_material(i,name_map[n]);
+	}
+*/
+
+	Error err = ResourceSaver::save(p_save_path+".msh",mesh);
+
+	return err;
+
+}
+
+ResourceImporterOBJ::ResourceImporterOBJ()
+{
+
+}

+ 28 - 0
tools/editor/import/resource_importer_obj.h

@@ -0,0 +1,28 @@
+#ifndef RESOURCEIMPORTEROBJ_H
+#define RESOURCEIMPORTEROBJ_H
+
+
+#include "io/resource_import.h"
+
+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

+ 1 - 1
tools/editor/import/resource_import_texture.cpp → tools/editor/import/resource_importer_texture.cpp

@@ -1,4 +1,4 @@
-#include "resource_import_texture.h"
+#include "resource_importer_texture.h"
 #include "io/image_loader.h"
 #include "scene/resources/texture.h"
 

+ 0 - 0
tools/editor/import/resource_import_texture.h → tools/editor/import/resource_importer_texture.h


+ 1 - 1
tools/editor/import/resource_import_wav.cpp → tools/editor/import/resource_importer_wav.cpp

@@ -1,4 +1,4 @@
-#include "resource_import_wav.h"
+#include "resource_importer_wav.h"
 
 #include "scene/resources/audio_stream_sample.h"
 #include "os/file_access.h"

+ 0 - 0
tools/editor/import/resource_import_wav.h → tools/editor/import/resource_importer_wav.h