Return parsed material information in `parseObj` API..
Parse PBR extension in MTL
diff --git a/experimental/tinyobj_loader_opt.h b/experimental/tinyobj_loader_opt.h
index 8c745d3..91902fb 100644
--- a/experimental/tinyobj_loader_opt.h
+++ b/experimental/tinyobj_loader_opt.h
@@ -292,6 +292,22 @@
std::string bump_texname; // map_bump, bump
std::string displacement_texname; // disp
std::string alpha_texname; // map_d
+
+ // PBR extension
+ // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr
+ float roughness; // [0, 1] default 0
+ float metallic; // [0, 1] default 0
+ float sheen; // [0, 1] default 0
+ float clearcoat_thickness; // [0, 1] default 0
+ float clearcoat_roughness; // [0, 1] default 0
+ float anisotropy; // aniso. [0, 1] default 0
+ float anisotropy_rotation; // anisor. [0, 1] default 0
+ std::string roughness_texname; // map_Pr
+ std::string metallic_texname; // map_Pm
+ std::string sheen_texname; // map_Ps
+ std::string emissive_texname; // map_Ke
+ std::string normal_texname; // norm. For normal mapping.
+
std::map<std::string, std::string> unknown_parameter;
} material_t;
@@ -304,7 +320,8 @@
struct index_t {
int vertex_index, texcoord_index, normal_index;
index_t() : vertex_index(-1), texcoord_index(-1), normal_index(-1) {}
- explicit index_t(int idx) : vertex_index(idx), texcoord_index(idx), normal_index(idx) {}
+ explicit index_t(int idx)
+ : vertex_index(idx), texcoord_index(idx), normal_index(idx) {}
index_t(int vidx, int vtidx, int vnidx)
: vertex_index(vidx), texcoord_index(vtidx), normal_index(vnidx) {}
};
@@ -660,6 +677,11 @@
std::string linebuf(&buf[0]);
+ // Trim trailing whitespace.
+ if (linebuf.size() > 0) {
+ linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1);
+ }
+
// Trim newline '\r\n' or '\n'
if (linebuf.size() > 0) {
if (linebuf[linebuf.size() - 1] == '\n')
@@ -790,6 +812,7 @@
material.dissolve = parseFloat(&token);
continue;
}
+
if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) {
token += 2;
// Invert value of Tr(assume Tr is in range [0, 1])
@@ -797,6 +820,55 @@
continue;
}
+ // PBR: roughness
+ if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) {
+ token += 2;
+ material.roughness = parseFloat(&token);
+ continue;
+ }
+
+ // PBR: metallic
+ if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) {
+ token += 2;
+ material.metallic = parseFloat(&token);
+ continue;
+ }
+
+ // PBR: sheen
+ if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) {
+ token += 2;
+ material.sheen = parseFloat(&token);
+ continue;
+ }
+
+ // PBR: clearcoat thickness
+ if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) {
+ token += 2;
+ material.clearcoat_thickness = parseFloat(&token);
+ continue;
+ }
+
+ // PBR: clearcoat roughness
+ if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) {
+ token += 4;
+ material.clearcoat_roughness = parseFloat(&token);
+ continue;
+ }
+
+ // PBR: anisotropy
+ if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) {
+ token += 6;
+ material.anisotropy = parseFloat(&token);
+ continue;
+ }
+
+ // PBR: anisotropy rotation
+ if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) {
+ token += 7;
+ material.anisotropy_rotation = parseFloat(&token);
+ continue;
+ }
+
// ambient texture
if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) {
token += 7;
@@ -853,6 +925,41 @@
continue;
}
+ // PBR: roughness texture
+ if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) {
+ token += 7;
+ material.roughness_texname = token;
+ continue;
+ }
+
+ // PBR: metallic texture
+ if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) {
+ token += 7;
+ material.metallic_texname = token;
+ continue;
+ }
+
+ // PBR: sheen texture
+ if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) {
+ token += 7;
+ material.sheen_texname = token;
+ continue;
+ }
+
+ // PBR: emissive texture
+ if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) {
+ token += 7;
+ material.emissive_texname = token;
+ continue;
+ }
+
+ // PBR: normal map texture
+ if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) {
+ token += 5;
+ material.normal_texname = token;
+ continue;
+ }
+
// unknown parameter
const char *_space = strchr(token, ' ');
if (!_space) {
@@ -935,8 +1042,9 @@
/// Parse wavefront .obj(.obj string data is expanded to linear char array
/// `buf')
/// -1 to req_num_threads use the number of HW threads in the running system.
-bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes, const char *buf,
- size_t len, const LoadOption &option);
+bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes,
+ std::vector<material_t> *materials, const char *buf, size_t len,
+ const LoadOption &option);
#ifdef TINYOBJ_LOADER_OPT_IMPLEMENTATION
@@ -1137,8 +1245,9 @@
return false;
}
-bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes, const char *buf,
- size_t len, const LoadOption &option) {
+bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes,
+ std::vector<material_t> *materials, const char *buf, size_t len,
+ const LoadOption &option) {
attrib->vertices.clear();
attrib->normals.clear();
attrib->texcoords.clear();
@@ -1313,7 +1422,6 @@
}
std::map<std::string, int> material_map;
- std::vector<material_t> materials;
// Load material(if exits)
if (mtllib_i_index >= 0 && mtllib_t_index >= 0 &&
@@ -1328,7 +1436,7 @@
std::ifstream ifs(material_filename);
if (ifs.good()) {
- LoadMtl(&material_map, &materials, &ifs);
+ LoadMtl(&material_map, materials, &ifs);
// std::cout << "maetrials = " << materials.size() << std::endl;
@@ -1361,10 +1469,10 @@
num_indices += command_count[t].num_indices;
}
- //std::cout << "# v " << num_v << std::endl;
- //std::cout << "# vn " << num_vn << std::endl;
- //std::cout << "# vt " << num_vt << std::endl;
- //std::cout << "# f " << num_f << std::endl;
+ // std::cout << "# v " << num_v << std::endl;
+ // std::cout << "# vn " << num_vn << std::endl;
+ // std::cout << "# vt " << num_vt << std::endl;
+ // std::cout << "# f " << num_f << std::endl;
// 4. merge
// @todo { parallelize merge. }
@@ -1445,7 +1553,8 @@
int vertex_index = fixIndex(vi.vertex_index, v_count);
int texcoord_index = fixIndex(vi.texcoord_index, t_count);
int normal_index = fixIndex(vi.normal_index, n_count);
- attrib->indices[f_count + k] = index_t(vertex_index, texcoord_index, normal_index);
+ attrib->indices[f_count + k] =
+ index_t(vertex_index, texcoord_index, normal_index);
}
attrib->material_ids[face_count] = material_id;
attrib->face_num_verts[face_count] = commands[t][i].f.size();
diff --git a/experimental/viewer.cc b/experimental/viewer.cc
index f4ab5ed..be17c7a 100644
--- a/experimental/viewer.cc
+++ b/experimental/viewer.cc
@@ -218,6 +218,7 @@
{
tinyobj_opt::attrib_t attrib;
std::vector<tinyobj_opt::shape_t> shapes;
+ std::vector<tinyobj_opt::material_t> materials;
size_t data_len = 0;
const char* data = get_file_data(&data_len, filename);
@@ -229,7 +230,7 @@
tinyobj_opt::LoadOption option;
option.req_num_threads = num_threads;
option.verbose = verbose;
- bool ret = parseObj(&attrib, &shapes, data, data_len, option);
+ bool ret = parseObj(&attrib, &shapes, &materials, data, data_len, option);
bmin[0] = bmin[1] = bmin[2] = std::numeric_limits<float>::max();
bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits<float>::max();
@@ -528,6 +529,7 @@
tinyobj_opt::attrib_t attrib;
std::vector<tinyobj_opt::shape_t> shapes;
+ std::vector<tinyobj_opt::material_t> materials;
size_t data_len = 0;
const char* data = get_file_data(&data_len, argv[1]);
@@ -540,7 +542,7 @@
option.req_num_threads = num_threads;
option.verbose = true;
- bool ret = parseObj(&attrib, &shapes, data, data_len, option);
+ bool ret = parseObj(&attrib, &shapes, &materials, data, data_len, option);
return ret;
}