mirror of
https://github.com/godotengine/godot.git
synced 2025-11-01 06:01:14 +00:00
OBJ importer: Support bump multiplier (normal scale)
This improves compatibility with OBJ/MTL files found in the wild.
This commit is contained in:
parent
1f7630f1bf
commit
2f3eaa965c
1 changed files with 36 additions and 16 deletions
|
|
@ -49,18 +49,17 @@ static Error _parse_material_library(const String &p_path, HashMap<String, Ref<S
|
||||||
String l = f->get_line().strip_edges();
|
String l = f->get_line().strip_edges();
|
||||||
|
|
||||||
if (l.begins_with("newmtl ")) {
|
if (l.begins_with("newmtl ")) {
|
||||||
//vertex
|
// Start of a new material.
|
||||||
|
|
||||||
current_name = l.replace("newmtl", "").strip_edges();
|
current_name = l.replace("newmtl", "").strip_edges();
|
||||||
current.instantiate();
|
current.instantiate();
|
||||||
current->set_name(current_name);
|
current->set_name(current_name);
|
||||||
material_map[current_name] = current;
|
material_map[current_name] = current;
|
||||||
} else if (l.begins_with("Ka ")) {
|
} else if (l.begins_with("Ka ")) {
|
||||||
//uv
|
// Ambient color.
|
||||||
WARN_PRINT("OBJ: Ambient light for material '" + current_name + "' is ignored in PBR");
|
WARN_PRINT("OBJ: Ambient light for material '" + current_name + "' is ignored in PBR");
|
||||||
|
|
||||||
} else if (l.begins_with("Kd ")) {
|
} else if (l.begins_with("Kd ")) {
|
||||||
//normal
|
// Diffuse color.
|
||||||
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
||||||
Vector<String> v = l.split(" ", false);
|
Vector<String> v = l.split(" ", false);
|
||||||
ERR_FAIL_COND_V(v.size() < 4, ERR_INVALID_DATA);
|
ERR_FAIL_COND_V(v.size() < 4, ERR_INVALID_DATA);
|
||||||
|
|
@ -70,7 +69,7 @@ static Error _parse_material_library(const String &p_path, HashMap<String, Ref<S
|
||||||
c.b = v[3].to_float();
|
c.b = v[3].to_float();
|
||||||
current->set_albedo(c);
|
current->set_albedo(c);
|
||||||
} else if (l.begins_with("Ks ")) {
|
} else if (l.begins_with("Ks ")) {
|
||||||
//normal
|
// Specular color.
|
||||||
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
||||||
Vector<String> v = l.split(" ", false);
|
Vector<String> v = l.split(" ", false);
|
||||||
ERR_FAIL_COND_V(v.size() < 4, ERR_INVALID_DATA);
|
ERR_FAIL_COND_V(v.size() < 4, ERR_INVALID_DATA);
|
||||||
|
|
@ -80,14 +79,14 @@ static Error _parse_material_library(const String &p_path, HashMap<String, Ref<S
|
||||||
float metalness = MAX(r, MAX(g, b));
|
float metalness = MAX(r, MAX(g, b));
|
||||||
current->set_metallic(metalness);
|
current->set_metallic(metalness);
|
||||||
} else if (l.begins_with("Ns ")) {
|
} else if (l.begins_with("Ns ")) {
|
||||||
//normal
|
// Specular exponent.
|
||||||
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
||||||
Vector<String> v = l.split(" ", false);
|
Vector<String> v = l.split(" ", false);
|
||||||
ERR_FAIL_COND_V(v.size() != 2, ERR_INVALID_DATA);
|
ERR_FAIL_COND_V(v.size() != 2, ERR_INVALID_DATA);
|
||||||
float s = v[1].to_float();
|
float s = v[1].to_float();
|
||||||
current->set_metallic((1000.0 - s) / 1000.0);
|
current->set_metallic((1000.0 - s) / 1000.0);
|
||||||
} else if (l.begins_with("d ")) {
|
} else if (l.begins_with("d ")) {
|
||||||
//normal
|
// Dissolve (1.0 is fully opaque, 0.0 is completely transparent).
|
||||||
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
||||||
Vector<String> v = l.split(" ", false);
|
Vector<String> v = l.split(" ", false);
|
||||||
ERR_FAIL_COND_V(v.size() != 2, ERR_INVALID_DATA);
|
ERR_FAIL_COND_V(v.size() != 2, ERR_INVALID_DATA);
|
||||||
|
|
@ -99,7 +98,7 @@ static Error _parse_material_library(const String &p_path, HashMap<String, Ref<S
|
||||||
current->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
|
current->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
|
||||||
}
|
}
|
||||||
} else if (l.begins_with("Tr ")) {
|
} else if (l.begins_with("Tr ")) {
|
||||||
//normal
|
// Transparency (1.0 is completely transparent, 0.0 is fully opaque).
|
||||||
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
||||||
Vector<String> v = l.split(" ", false);
|
Vector<String> v = l.split(" ", false);
|
||||||
ERR_FAIL_COND_V(v.size() != 2, ERR_INVALID_DATA);
|
ERR_FAIL_COND_V(v.size() != 2, ERR_INVALID_DATA);
|
||||||
|
|
@ -112,11 +111,11 @@ static Error _parse_material_library(const String &p_path, HashMap<String, Ref<S
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (l.begins_with("map_Ka ")) {
|
} else if (l.begins_with("map_Ka ")) {
|
||||||
//uv
|
// Ambient texture map.
|
||||||
WARN_PRINT("OBJ: Ambient light texture for material '" + current_name + "' is ignored in PBR");
|
WARN_PRINT("OBJ: Ambient light texture for material '" + current_name + "' is ignored in PBR");
|
||||||
|
|
||||||
} else if (l.begins_with("map_Kd ")) {
|
} else if (l.begins_with("map_Kd ")) {
|
||||||
//normal
|
// Diffuse texture map.
|
||||||
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
||||||
|
|
||||||
String p = l.replace("map_Kd", "").replace_char('\\', '/').strip_edges();
|
String p = l.replace("map_Kd", "").replace_char('\\', '/').strip_edges();
|
||||||
|
|
@ -136,7 +135,7 @@ static Error _parse_material_library(const String &p_path, HashMap<String, Ref<S
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (l.begins_with("map_Ks ")) {
|
} else if (l.begins_with("map_Ks ")) {
|
||||||
//normal
|
// Specular color texture map.
|
||||||
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
||||||
|
|
||||||
String p = l.replace("map_Ks", "").replace_char('\\', '/').strip_edges();
|
String p = l.replace("map_Ks", "").replace_char('\\', '/').strip_edges();
|
||||||
|
|
@ -156,7 +155,7 @@ static Error _parse_material_library(const String &p_path, HashMap<String, Ref<S
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (l.begins_with("map_Ns ")) {
|
} else if (l.begins_with("map_Ns ")) {
|
||||||
//normal
|
// Specular exponent texture map.
|
||||||
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
||||||
|
|
||||||
String p = l.replace("map_Ns", "").replace_char('\\', '/').strip_edges();
|
String p = l.replace("map_Ns", "").replace_char('\\', '/').strip_edges();
|
||||||
|
|
@ -174,18 +173,39 @@ static Error _parse_material_library(const String &p_path, HashMap<String, Ref<S
|
||||||
} else if (r_missing_deps) {
|
} 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 ") || l.begins_with("map_Bump ")) {
|
||||||
//normal
|
// Bump texture map.
|
||||||
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT);
|
||||||
|
|
||||||
String p = l.replace("map_bump", "").replace_char('\\', '/').strip_edges();
|
l = l.begins_with("map_bump ") ? l.trim_prefix("map_bump ") : l.trim_prefix("map_Bump ");
|
||||||
String path = base_path.path_join(p);
|
l = l.strip_edges();
|
||||||
|
|
||||||
|
// Read path and optional bump multiplier.
|
||||||
|
String p;
|
||||||
|
float bm = 1.0;
|
||||||
|
int bm_pos = l.find("-bm ");
|
||||||
|
if (bm_pos >= 0) {
|
||||||
|
int bm_start = bm_pos + 4;
|
||||||
|
int bm_end = l.find_char(' ', bm_start);
|
||||||
|
if (bm_end >= 0) {
|
||||||
|
bm = l.substr(bm_start, bm_end - bm_start).to_float();
|
||||||
|
p = l.substr(bm_end + 1);
|
||||||
|
} else { // Bump multiplier ends at end of line.
|
||||||
|
bm = l.substr(bm_start).to_float();
|
||||||
|
p = l.substr(0, bm_pos);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = base_path.path_join(p.replace_char('\\', '/').strip_edges());
|
||||||
|
|
||||||
Ref<Texture2D> texture = ResourceLoader::load(path);
|
Ref<Texture2D> texture = ResourceLoader::load(path);
|
||||||
|
|
||||||
if (texture.is_valid()) {
|
if (texture.is_valid()) {
|
||||||
current->set_feature(StandardMaterial3D::FEATURE_NORMAL_MAPPING, true);
|
current->set_feature(StandardMaterial3D::FEATURE_NORMAL_MAPPING, true);
|
||||||
current->set_texture(StandardMaterial3D::TEXTURE_NORMAL, texture);
|
current->set_texture(StandardMaterial3D::TEXTURE_NORMAL, texture);
|
||||||
|
current->set_normal_scale(bm);
|
||||||
} else if (r_missing_deps) {
|
} else if (r_missing_deps) {
|
||||||
r_missing_deps->push_back(path);
|
r_missing_deps->push_back(path);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue