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

This commit is contained in:
Juan Linietsky 2017-09-29 20:38:27 -03:00
parent 0a5799fb43
commit f494470005
3 changed files with 144 additions and 54 deletions

View file

@ -4623,6 +4623,10 @@ EditorNode::EditorNode() {
import_wav.instance(); import_wav.instance();
ResourceFormatImporter::get_singleton()->add_importer(import_wav); 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; Ref<ResourceImporterScene> import_scene;
import_scene.instance(); import_scene.instance();
ResourceFormatImporter::get_singleton()->add_importer(import_scene); ResourceFormatImporter::get_singleton()->add_importer(import_scene);

View file

@ -40,12 +40,8 @@ uint32_t EditorOBJImporter::get_import_flags() const {
return IMPORT_SCENE; return IMPORT_SCENE;
} }
void EditorOBJImporter::get_extensions(List<String> *r_extensions) const {
r_extensions->push_back("obj"); static Error _parse_material_library(const String &p_path, Map<String, Ref<SpatialMaterial> > &material_map, List<String> *r_missing_deps) {
}
Error EditorOBJImporter::_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); FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); 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()) { if (texture.is_valid()) {
current->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture); current->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture);
} else { } else if (r_missing_deps) {
r_missing_deps->push_back(path); 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()) { if (texture.is_valid()) {
current->set_texture(SpatialMaterial::TEXTURE_METALLIC, texture); current->set_texture(SpatialMaterial::TEXTURE_METALLIC, texture);
} else { } else if (r_missing_deps) {
r_missing_deps->push_back(path); 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()) { if (texture.is_valid()) {
current->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, texture); current->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, texture);
} else { } else if (r_missing_deps) {
r_missing_deps->push_back(path); r_missing_deps->push_back(path);
} }
} else if (l.begins_with("map_bump ")) { } 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()) { if (texture.is_valid()) {
current->set_feature(SpatialMaterial::FEATURE_NORMAL_MAPPING, true); current->set_feature(SpatialMaterial::FEATURE_NORMAL_MAPPING, true);
current->set_texture(SpatialMaterial::TEXTURE_NORMAL, texture); current->set_texture(SpatialMaterial::TEXTURE_NORMAL, texture);
} else { } else if (r_missing_deps) {
r_missing_deps->push_back(path); r_missing_deps->push_back(path);
} }
} else if (f->eof_reached()) { } else if (f->eof_reached()) {
@ -190,28 +186,16 @@ Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<Strin
return OK; 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); FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
if (r_err) { ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
*r_err = ERR_CANT_OPEN;
}
ERR_FAIL_COND_V(!f, NULL);
if (r_err) {
*r_err = OK;
}
Spatial *scene = memnew(Spatial);
Ref<ArrayMesh> mesh; Ref<ArrayMesh> mesh;
mesh.instance(); mesh.instance();
Map<String, Ref<Material> > name_map; bool generate_tangents = p_generate_tangents;
bool generate_tangents = p_flags & IMPORT_GENERATE_TANGENT_ARRAYS;
bool flip_faces = false; bool flip_faces = false;
//bool flip_faces = p_options["force/flip_faces"]; //bool flip_faces = p_options["force/flip_faces"];
//bool force_smooth = p_options["force/smooth_shading"]; //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 ")) { if (l.begins_with("v ")) {
//vertex //vertex
Vector<String> v = l.split(" ", false); 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; Vector3 vtx;
vtx.x = v[1].to_float(); vtx.x = v[1].to_float();
vtx.y = v[2].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 ")) { } else if (l.begins_with("vt ")) {
//uv //uv
Vector<String> v = l.split(" ", false); 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; Vector2 uv;
uv.x = v[1].to_float(); uv.x = v[1].to_float();
uv.y = 1.0 - v[2].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 ")) { } else if (l.begins_with("vn ")) {
//normal //normal
Vector<String> v = l.split(" ", false); 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; Vector3 nrm;
nrm.x = v[1].to_float(); nrm.x = v[1].to_float();
nrm.y = v[2].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 //vertex
Vector<String> v = l.split(" ", false); 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 //not very fast, could be sped up
Vector<String> face[3]; Vector<String> face[3];
face[0] = v[1].split("/"); face[0] = v[1].split("/");
face[1] = v[2].split("/"); face[1] = v[2].split("/");
ERR_FAIL_COND_V(face[0].size() == 0, NULL); ERR_FAIL_COND_V(face[0].size() == 0, ERR_FILE_CORRUPT);
ERR_FAIL_COND_V(face[0].size() != face[1].size(), NULL); ERR_FAIL_COND_V(face[0].size() != face[1].size(), ERR_FILE_CORRUPT);
for (int i = 2; i < v.size() - 1; i++) { for (int i = 2; i < v.size() - 1; i++) {
face[2] = v[i + 1].split("/"); 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++) { for (int j = 0; j < 3; j++) {
int idx = 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; int norm = face[idx][2].to_int() - 1;
if (norm < 0) if (norm < 0)
norm += normals.size() + 1; 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]); 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; int uv = face[idx][1].to_int() - 1;
if (uv < 0) if (uv < 0)
uv += uvs.size() + 1; 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]); surf_tool->add_uv(uvs[uv]);
} }
int vtx = face[idx][0].to_int() - 1; int vtx = face[idx][0].to_int() - 1;
if (vtx < 0) if (vtx < 0)
vtx += vertices.size() + 1; 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]; Vector3 vertex = vertices[vtx];
//if (weld_vertices) //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()) { if (l.begins_with("o ") || f->eof_reached()) {
MeshInstance *mi = memnew(MeshInstance); if (!p_single_mesh) {
mi->set_name(name); mesh->set_name(name);
mi->set_mesh(mesh); r_meshes.push_back(mesh);
mesh.instance();
scene->add_child(mi); current_group = "";
mi->set_owner(scene); current_material = "";
}
mesh.instance();
current_group = "";
current_material = "";
} }
if (f->eof_reached()) { if (f->eof_reached()) {
@ -406,16 +387,40 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
} }
} }
/* if (p_single_mesh) {
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); r_meshes.push_back(mesh);
if (name_map.has(n)) }
mesh->surface_set_material(i,name_map[n]);
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);
}
if (r_err) {
*r_err = OK;
} }
*/
return scene; return scene;
} }
@ -423,5 +428,68 @@ Ref<Animation> EditorOBJImporter::import_animation(const String &p_path, uint32_
return Ref<Animation>(); return Ref<Animation>();
} }
void EditorOBJImporter::get_extensions(List<String> *r_extensions) const {
r_extensions->push_back("obj");
}
EditorOBJImporter::EditorOBJImporter() { 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() {
}

View file

@ -36,8 +36,6 @@ class EditorOBJImporter : public EditorSceneImporter {
GDCLASS(EditorOBJImporter, EditorSceneImporter); GDCLASS(EditorOBJImporter, EditorSceneImporter);
Error _parse_material_library(const String &p_path, Map<String, Ref<SpatialMaterial> > &material_map, List<String> *r_missing_deps);
public: public:
virtual uint32_t get_import_flags() const; virtual uint32_t get_import_flags() const;
virtual void get_extensions(List<String> *r_extensions) const; virtual void get_extensions(List<String> *r_extensions) const;
@ -47,4 +45,24 @@ public:
EditorOBJImporter(); 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 #endif // RESOURCEIMPORTEROBJ_H