Restored ability to import OBJ files as meshes directly. Finally closes #9445.
This commit is contained in:
parent
0a5799fb43
commit
f494470005
3 changed files with 144 additions and 54 deletions
|
@ -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);
|
||||||
|
|
|
@ -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() {
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue