Separate error message into warning and error. Breaks API, so bump to version 1.3.0

This commit is contained in:
Syoyo Fujita
2018-10-10 01:56:07 +09:00
parent 1cdfd786d8
commit e07a835f02
7 changed files with 568 additions and 378 deletions

View File

@@ -23,6 +23,7 @@ THE SOFTWARE.
*/
//
// version 1.3.0 : Separate warning and error message(breaking API of LoadObj)
// version 1.2.3 : Added color space extension('-colorspace') to tex opts.
// version 1.2.2 : Parse multiple group names.
// version 1.2.1 : Added initial support for line('l') primitive(PR #178)
@@ -117,8 +118,9 @@ namespace tinyobj {
//
// TinyObjLoader extension.
//
// -colorspace SPACE # Color space of the texture. e.g. 'sRGB` or 'linear'
//
// -colorspace SPACE # Color space of the texture. e.g.
// 'sRGB` or 'linear'
//
#ifdef TINYOBJLOADER_USE_DOUBLE
//#pragma message "using double"
@@ -153,9 +155,10 @@ typedef struct {
bool blendu; // -blendu (default on)
bool blendv; // -blendv (default on)
real_t bump_multiplier; // -bm (for bump maps only, default 1.0)
// extension
std::string colorspace; // Explicitly specify color space of stored value. Usually `sRGB` or `linear` (default empty).
std::string colorspace; // Explicitly specify color space of stored value.
// Usually `sRGB` or `linear` (default empty).
} texture_option_t;
typedef struct {
@@ -307,7 +310,7 @@ class MaterialReader {
virtual bool operator()(const std::string &matId,
std::vector<material_t> *materials,
std::map<std::string, int> *matMap,
std::map<std::string, int> *matMap, std::string *warn,
std::string *err) = 0;
};
@@ -318,7 +321,8 @@ class MaterialFileReader : public MaterialReader {
virtual ~MaterialFileReader() {}
virtual bool operator()(const std::string &matId,
std::vector<material_t> *materials,
std::map<std::string, int> *matMap, std::string *err);
std::map<std::string, int> *matMap, std::string *warn,
std::string *err);
private:
std::string m_mtlBaseDir;
@@ -331,7 +335,8 @@ class MaterialStreamReader : public MaterialReader {
virtual ~MaterialStreamReader() {}
virtual bool operator()(const std::string &matId,
std::vector<material_t> *materials,
std::map<std::string, int> *matMap, std::string *err);
std::map<std::string, int> *matMap, std::string *warn,
std::string *err);
private:
std::istream &m_inStream;
@@ -341,7 +346,7 @@ class MaterialStreamReader : public MaterialReader {
/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data
/// 'shapes' will be filled with parsed shape data
/// Returns true when loading .obj become success.
/// Returns warning and error message into `err`
/// Returns warning message into `warn`, and error message into `err`
/// 'mtl_basedir' is optional, and used for base directory for .mtl file.
/// In default(`NULL'), .mtl file is searched from an application's working
/// directory.
@@ -350,34 +355,36 @@ class MaterialStreamReader : public MaterialReader {
/// Option 'default_vcols_fallback' specifies whether vertex colors should
/// always be defined, even if no colors are given (fallback to white).
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
std::vector<material_t> *materials, std::string *err,
const char *filename, const char *mtl_basedir = NULL,
bool triangulate = true, bool default_vcols_fallback = true);
std::vector<material_t> *materials, std::string *warn,
std::string *err, const char *filename,
const char *mtl_basedir = NULL, bool triangulate = true,
bool default_vcols_fallback = true);
/// Loads .obj from a file with custom user callback.
/// .mtl is loaded as usual and parsed material_t data will be passed to
/// `callback.mtllib_cb`.
/// Returns true when loading .obj/.mtl become success.
/// Returns warning and error message into `err`
/// Returns warning message into `warn`, and error message into `err`
/// See `examples/callback_api/` for how to use this function.
bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
void *user_data = NULL,
MaterialReader *readMatFn = NULL,
std::string *err = NULL);
std::string *warn = NULL, std::string *err = NULL);
/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve
/// std::istream for materials.
/// Returns true when loading .obj become success.
/// Returns warning and error message into `err`
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
std::vector<material_t> *materials, std::string *err,
std::istream *inStream, MaterialReader *readMatFn = NULL,
bool triangulate = true, bool default_vcols_fallback = true);
std::vector<material_t> *materials, std::string *warn,
std::string *err, std::istream *inStream,
MaterialReader *readMatFn = NULL, bool triangulate = true,
bool default_vcols_fallback = true);
/// Loads materials into std::map
void LoadMtl(std::map<std::string, int> *material_map,
std::vector<material_t> *materials, std::istream *inStream,
std::string *warning);
std::string *warning, std::string *err);
} // namespace tinyobj
@@ -721,12 +728,13 @@ static inline bool parseVertexWithColor(real_t *x, real_t *y, real_t *z,
(*y) = parseReal(token, default_y);
(*z) = parseReal(token, default_z);
const bool found_color = parseReal(token, r) && parseReal(token, g) && parseReal(token, b);
const bool found_color =
parseReal(token, r) && parseReal(token, g) && parseReal(token, b);
if (!found_color) {
(*r) = (*g) = (*b) = 1.0;
}
return found_color;
}
@@ -959,11 +967,12 @@ static bool ParseTextureNameAndOption(std::string *texname,
} else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) {
token += 4;
parseReal2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0);
} else if ((0 == strncmp(token, "-colorspace", 11)) && IS_SPACE((token[11]))) {
} else if ((0 == strncmp(token, "-colorspace", 11)) &&
IS_SPACE((token[11]))) {
token += 12;
texopt->colorspace = parseString(&token);
} else {
// Assume texture filename
// Assume texture filename
#if 0
size_t len = strcspn(token, " \t\r"); // untile next space
texture_name = std::string(token, token + len);
@@ -1303,7 +1312,9 @@ static void SplitString(const std::string &s, char delim,
void LoadMtl(std::map<std::string, int> *material_map,
std::vector<material_t> *materials, std::istream *inStream,
std::string *warning) {
std::string *warning, std::string *err) {
(void)err;
// Create a default material anyway.
material_t material;
InitMaterial(&material);
@@ -1312,7 +1323,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
bool has_d = false;
bool has_tr = false;
std::stringstream ss;
std::stringstream warn_ss;
std::string linebuf;
while (inStream->peek() != -1) {
@@ -1455,9 +1466,9 @@ void LoadMtl(std::map<std::string, int> *material_map,
material.dissolve = parseReal(&token);
if (has_tr) {
ss << "WARN: Both `d` and `Tr` parameters defined for \""
<< material.name << "\". Use the value of `d` for dissolve."
<< std::endl;
warn_ss << "Both `d` and `Tr` parameters defined for \""
<< material.name << "\". Use the value of `d` for dissolve."
<< std::endl;
}
has_d = true;
continue;
@@ -1466,9 +1477,9 @@ void LoadMtl(std::map<std::string, int> *material_map,
token += 2;
if (has_d) {
// `d` wins. Ignore `Tr` value.
ss << "WARN: Both `d` and `Tr` parameters defined for \""
<< material.name << "\". Use the value of `d` for dissolve."
<< std::endl;
warn_ss << "Both `d` and `Tr` parameters defined for \""
<< material.name << "\". Use the value of `d` for dissolve."
<< std::endl;
} else {
// We invert value of Tr(assume Tr is in range [0, 1])
// NOTE: Interpretation of Tr is application(exporter) dependent. For
@@ -1683,14 +1694,14 @@ void LoadMtl(std::map<std::string, int> *material_map,
materials->push_back(material);
if (warning) {
(*warning) = ss.str();
(*warning) = warn_ss.str();
}
}
bool MaterialFileReader::operator()(const std::string &matId,
std::vector<material_t> *materials,
std::map<std::string, int> *matMap,
std::string *err) {
std::string *warn, std::string *err) {
std::string filepath;
if (!m_mtlBaseDir.empty()) {
@@ -1702,21 +1713,14 @@ bool MaterialFileReader::operator()(const std::string &matId,
std::ifstream matIStream(filepath.c_str());
if (!matIStream) {
std::stringstream ss;
ss << "WARN: Material file [ " << filepath << " ] not found." << std::endl;
if (err) {
(*err) += ss.str();
ss << "Material file [ " << filepath << " ] not found." << std::endl;
if (warn) {
(*warn) += ss.str();
}
return false;
}
std::string warning;
LoadMtl(matMap, materials, &matIStream, &warning);
if (!warning.empty()) {
if (err) {
(*err) += warning;
}
}
LoadMtl(matMap, materials, &matIStream, warn, err);
return true;
}
@@ -1724,32 +1728,26 @@ bool MaterialFileReader::operator()(const std::string &matId,
bool MaterialStreamReader::operator()(const std::string &matId,
std::vector<material_t> *materials,
std::map<std::string, int> *matMap,
std::string *err) {
std::string *warn, std::string *err) {
(void)err;
(void)matId;
if (!m_inStream) {
std::stringstream ss;
ss << "WARN: Material stream in error state. " << std::endl;
if (err) {
(*err) += ss.str();
ss << "Material stream in error state. " << std::endl;
if (warn) {
(*warn) += ss.str();
}
return false;
}
std::string warning;
LoadMtl(matMap, materials, &m_inStream, &warning);
if (!warning.empty()) {
if (err) {
(*err) += warning;
}
}
LoadMtl(matMap, materials, &m_inStream, warn, err);
return true;
}
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
std::vector<material_t> *materials, std::string *err,
const char *filename, const char *mtl_basedir,
std::vector<material_t> *materials, std::string *warn,
std::string *err, const char *filename, const char *mtl_basedir,
bool trianglulate, bool default_vcols_fallback) {
attrib->vertices.clear();
attrib->normals.clear();
@@ -1779,14 +1777,15 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
}
MaterialFileReader matFileReader(baseDir);
return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader,
return LoadObj(attrib, shapes, materials, warn, err, &ifs, &matFileReader,
trianglulate, default_vcols_fallback);
}
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
std::vector<material_t> *materials, std::string *err,
std::istream *inStream, MaterialReader *readMatFn /*= NULL*/,
bool triangulate, bool default_vcols_fallback) {
std::vector<material_t> *materials, std::string *warn,
std::string *err, std::istream *inStream,
MaterialReader *readMatFn /*= NULL*/, bool triangulate,
bool default_vcols_fallback) {
std::stringstream errss;
std::vector<real_t> v;
@@ -1813,7 +1812,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
shape_t shape;
bool found_all_colors = true;
size_t line_num = 0;
std::string linebuf;
while (inStream->peek() != -1) {
@@ -1850,9 +1849,9 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
token += 2;
real_t x, y, z;
real_t r, g, b;
found_all_colors &= parseVertexWithColor(&x, &y, &z, &r, &g, &b, &token);
v.push_back(x);
v.push_back(y);
v.push_back(z);
@@ -1862,7 +1861,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
vc.push_back(g);
vc.push_back(b);
}
continue;
}
@@ -1936,8 +1935,10 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
}
greatest_v_idx = greatest_v_idx > vi.v_idx ? greatest_v_idx : vi.v_idx;
greatest_vn_idx = greatest_vn_idx > vi.vn_idx ? greatest_vn_idx : vi.vn_idx;
greatest_vt_idx = greatest_vt_idx > vi.vt_idx ? greatest_vt_idx : vi.vt_idx;
greatest_vn_idx =
greatest_vn_idx > vi.vn_idx ? greatest_vn_idx : vi.vn_idx;
greatest_vt_idx =
greatest_vt_idx > vi.vt_idx ? greatest_vt_idx : vi.vt_idx;
face.vertex_indices.push_back(vi);
size_t n = strspn(token, " \t\r");
@@ -1949,7 +1950,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
continue;
}
// use mtl
if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) {
token += 7;
@@ -1986,19 +1987,24 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
SplitString(std::string(token), ' ', filenames);
if (filenames.empty()) {
if (err) {
(*err) +=
"WARN: Looks like empty filename for mtllib. Use default "
if (warn) {
(*warn) +=
"Looks like empty filename for mtllib. Use default "
"material. \n";
}
} else {
bool found = false;
for (size_t s = 0; s < filenames.size(); s++) {
std::string warn_mtl;
std::string err_mtl;
bool ok = (*readMatFn)(filenames[s].c_str(), materials,
&material_map, &err_mtl);
&material_map, &warn_mtl, &err_mtl);
if (warn && (!warn_mtl.empty())) {
(*warn) += warn_mtl;
}
if (err && (!err_mtl.empty())) {
(*err) += err_mtl; // This should be warn message.
(*err) += err_mtl;
}
if (ok) {
@@ -2008,9 +2014,9 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
}
if (!found) {
if (err) {
(*err) +=
"WARN: Failed to load material file(s). Use default "
if (warn) {
(*warn) +=
"Failed to load material file(s). Use default "
"material.\n";
}
}
@@ -2048,14 +2054,13 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
if (names.size() < 2) {
// 'g' with empty names
if (err) {
if (warn) {
std::stringstream ss;
ss << "WARN: Empty group name. line: " << line_num << "\n";
(*err) += ss.str();
ss << "Empty group name. line: " << line_num << "\n";
(*warn) += ss.str();
name = "";
}
} else {
std::stringstream ss;
ss << names[1];
@@ -2068,7 +2073,6 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
}
name = ss.str();
}
continue;
@@ -2184,34 +2188,31 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
// Ignore unknown command.
}
// not all vertices have colors, no default colors desired? -> clear colors
if (!found_all_colors && !default_vcols_fallback) {
if (!found_all_colors && !default_vcols_fallback) {
vc.clear();
}
if (greatest_v_idx >= static_cast<int>(v.size() / 3))
{
if (err) {
if (greatest_v_idx >= static_cast<int>(v.size() / 3)) {
if (warn) {
std::stringstream ss;
ss << "WARN: Vertex indices out of bounds.\n" << std::endl;
(*err) += ss.str();
ss << "Vertex indices out of bounds.\n" << std::endl;
(*warn) += ss.str();
}
}
if (greatest_vn_idx >= static_cast<int>(vn.size() / 3))
{
if (err) {
if (greatest_vn_idx >= static_cast<int>(vn.size() / 3)) {
if (warn) {
std::stringstream ss;
ss << "WARN: Vertex normal indices out of bounds.\n" << std::endl;
(*err) += ss.str();
ss << "Vertex normal indices out of bounds.\n" << std::endl;
(*warn) += ss.str();
}
}
if (greatest_vt_idx >= static_cast<int>(vt.size() / 2))
{
if (err) {
if (greatest_vt_idx >= static_cast<int>(vt.size() / 2)) {
if (warn) {
std::stringstream ss;
ss << "WARN: Vertex texcoord indices out of bounds.\n" << std::endl;
(*err) += ss.str();
ss << "Vertex texcoord indices out of bounds.\n" << std::endl;
(*warn) += ss.str();
}
}
@@ -2241,6 +2242,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
void *user_data /*= NULL*/,
MaterialReader *readMatFn /*= NULL*/,
std::string *warn, /* = NULL*/
std::string *err /*= NULL*/) {
std::stringstream errss;
@@ -2377,19 +2379,25 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
SplitString(std::string(token), ' ', filenames);
if (filenames.empty()) {
if (err) {
(*err) +=
"WARN: Looks like empty filename for mtllib. Use default "
if (warn) {
(*warn) +=
"Looks like empty filename for mtllib. Use default "
"material. \n";
}
} else {
bool found = false;
for (size_t s = 0; s < filenames.size(); s++) {
std::string warn_mtl;
std::string err_mtl;
bool ok = (*readMatFn)(filenames[s].c_str(), &materials,
&material_map, &err_mtl);
&material_map, &warn_mtl, &err_mtl);
if (warn && (!warn_mtl.empty())) {
(*warn) += warn_mtl; // This should be warn message.
}
if (err && (!err_mtl.empty())) {
(*err) += err_mtl; // This should be warn message.
(*err) += err_mtl;
}
if (ok) {
@@ -2399,9 +2407,9 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
}
if (!found) {
if (err) {
(*err) +=
"WARN: Failed to load material file(s). Use default "
if (warn) {
(*warn) +=
"Failed to load material file(s). Use default "
"material.\n";
}
} else {