Ignore Tr parameter when d exists in MTL(#43)

This commit is contained in:
Syoyo Fujita
2016-12-31 21:05:37 +09:00
parent 4886eebbf4
commit 7c3206f919
5 changed files with 948 additions and 40 deletions

View File

@@ -23,6 +23,7 @@ THE SOFTWARE.
*/
//
// version 1.0.5 : Ignore `Tr` when `d` exists in MTL(#43)
// version 1.0.4 : Support multiple filenames for 'mtllib'(#112)
// version 1.0.3 : Support parsing texture options(#85)
// version 1.0.2 : Improve parsing speed by about a factor of 2 for large
@@ -268,7 +269,7 @@ class MaterialReader {
class MaterialFileReader : public MaterialReader {
public:
explicit MaterialFileReader(const std::string &mtl_basedir)
: m_mtlBaseDir(mtl_basedir) {}
: m_mtlBaseDir(mtl_basedir) {}
virtual ~MaterialFileReader() {}
virtual bool operator()(const std::string &matId,
std::vector<material_t> *materials,
@@ -297,7 +298,8 @@ class MaterialStreamReader : public MaterialReader {
/// Returns true when loading .obj become success.
/// Returns warning 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.
/// In default(`NULL'), .mtl file is searched from an application's working
/// directory.
/// 'triangulate' is optional, and used whether triangulate polygon face in .obj
/// or not.
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
@@ -327,7 +329,8 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
/// Loads materials into std::map
void LoadMtl(std::map<std::string, int> *material_map,
std::vector<material_t> *materials, std::istream *inStream);
std::vector<material_t> *materials, std::istream *inStream,
std::string *warning);
} // namespace tinyobj
@@ -938,22 +941,29 @@ static bool exportFaceGroupToShape(
// Split a string with specified delimiter character.
// http://stackoverflow.com/questions/236129/split-a-string-in-c
static void SplitString(const std::string &s, char delim, std::vector<std::string> &elems)
{
std::stringstream ss;
ss.str(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
}
static void SplitString(const std::string &s, char delim,
std::vector<std::string> &elems) {
std::stringstream ss;
ss.str(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
}
}
void LoadMtl(std::map<std::string, int> *material_map,
std::vector<material_t> *materials, std::istream *inStream) {
std::vector<material_t> *materials, std::istream *inStream,
std::string *warning) {
// Create a default material anyway.
material_t material;
InitMaterial(&material);
// Issue 43. `d` wins against `Tr` since `Tr` is not in the MTL specification.
bool has_d = false;
bool has_tr = false;
std::stringstream ss;
std::string linebuf;
while (inStream->peek() != -1) {
safeGetline(*inStream, linebuf);
@@ -999,6 +1009,9 @@ void LoadMtl(std::map<std::string, int> *material_map,
// initial temporary material
InitMaterial(&material);
has_d = false;
has_tr = false;
// set new mtl name
char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE];
token += 7;
@@ -1092,12 +1105,29 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((token[0] == 'd' && IS_SPACE(token[1]))) {
token += 1;
material.dissolve = parseFloat(&token);
if (has_tr) {
ss << "WARN: Both `d` and `Tr` parameters defined for \""
<< material.name << "\". Use the value of `d` for dissolve."
<< std::endl;
}
has_d = true;
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])
material.dissolve = 1.0f - parseFloat(&token);
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;
} else {
// We invert value of Tr(assume Tr is in range [0, 1])
// NOTE: Interpretation of Tr is application(exporter) dependent. For
// some application(e.g. 3ds max obj exporter), Tr = d(Issue 43)
material.dissolve = 1.0f - parseFloat(&token);
}
has_tr = true;
continue;
}
@@ -1285,6 +1315,10 @@ void LoadMtl(std::map<std::string, int> *material_map,
material_map->insert(std::pair<std::string, int>(
material.name, static_cast<int>(materials->size())));
materials->push_back(material);
if (warning) {
(*warning) = ss.str();
}
}
bool MaterialFileReader::operator()(const std::string &matId,
@@ -1302,15 +1336,22 @@ 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;
ss << "WARN: Material file [ " << filepath << " ] not found." << std::endl;
if (err) {
(*err) += ss.str();
}
return false;
}
LoadMtl(matMap, materials, &matIStream);
std::string warning;
LoadMtl(matMap, materials, &matIStream, &warning);
if (!warning.empty()) {
if (err) {
(*err) += warning;
}
}
return true;
}
@@ -1328,14 +1369,21 @@ bool MaterialStreamReader::operator()(const std::string &matId,
return false;
}
LoadMtl(matMap, materials, &m_inStream);
std::string warning;
LoadMtl(matMap, materials, &m_inStream, &warning);
if (!warning.empty()) {
if (err) {
(*err) += warning;
}
}
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,
bool trianglulate) {
const char *filename, const char *mtl_basedir, bool trianglulate) {
attrib->vertices.clear();
attrib->normals.clear();
attrib->texcoords.clear();
@@ -1505,17 +1553,18 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
if (filenames.empty()) {
if (err) {
(*err) += "WARN: Looks like empty filename for mtllib. Use default material. \n";
(*err) +=
"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 err_mtl;
bool ok = (*readMatFn)(filenames[s].c_str(), materials, &material_map, &err_mtl);
if (err && (!err_mtl.empty())) {
(*err) += err_mtl; // This should be warn message.
bool ok = (*readMatFn)(filenames[s].c_str(), materials,
&material_map, &err_mtl);
if (err && (!err_mtl.empty())) {
(*err) += err_mtl; // This should be warn message.
}
if (ok) {
@@ -1525,8 +1574,10 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
}
if (!found) {
if (err) {
(*err) += "WARN: Failed to load material file(s). Use default material.\n";
if (err) {
(*err) +=
"WARN: Failed to load material file(s). Use default "
"material.\n";
}
}
}
@@ -1811,17 +1862,18 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
if (filenames.empty()) {
if (err) {
(*err) += "WARN: Looks like empty filename for mtllib. Use default material. \n";
(*err) +=
"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 err_mtl;
bool ok = (*readMatFn)(filenames[s].c_str(), &materials, &material_map, &err_mtl);
if (err && (!err_mtl.empty())) {
(*err) += err_mtl; // This should be warn message.
bool ok = (*readMatFn)(filenames[s].c_str(), &materials,
&material_map, &err_mtl);
if (err && (!err_mtl.empty())) {
(*err) += err_mtl; // This should be warn message.
}
if (ok) {
@@ -1831,11 +1883,12 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
}
if (!found) {
if (err) {
(*err) += "WARN: Failed to load material file(s). Use default material.\n";
if (err) {
(*err) +=
"WARN: Failed to load material file(s). Use default "
"material.\n";
}
} else {
if (callback.mtllib_cb) {
callback.mtllib_cb(user_data, &materials.at(0),
static_cast<int>(materials.size()));