@@ -26,6 +26,7 @@ THE SOFTWARE.
2626// version 2.0.0 : Add new object oriented API. 1.x API is still provided.
2727// * Support line primitive.
2828// * Support points primitive.
29+ // * Support multiple search path for .mtl(v1 API).
2930// version 1.4.0 : Modifed ParseTextureNameAndOption API
3031// version 1.3.1 : Make ParseTextureNameAndOption API public
3132// version 1.3.0 : Separate warning and error message(breaking API of LoadObj)
@@ -436,6 +437,7 @@ class MaterialReader {
436437// /
437438class MaterialFileReader : public MaterialReader {
438439 public:
440+ // Path could contain separator(';' in Windows, ':' in Posix)
439441 explicit MaterialFileReader (const std::string &mtl_basedir)
440442 : m_mtlBaseDir(mtl_basedir) {}
441443 virtual ~MaterialFileReader () {}
@@ -1634,6 +1636,21 @@ static void SplitString(const std::string &s, char delim,
16341636 }
16351637}
16361638
1639+ static std::string JoinPath (const std::string &dir,
1640+ const std::string &filename) {
1641+ if (dir.empty ()) {
1642+ return filename;
1643+ } else {
1644+ // check '/'
1645+ char lastChar = *dir.rbegin ();
1646+ if (lastChar != ' /' ) {
1647+ return dir + std::string (" /" ) + filename;
1648+ } else {
1649+ return dir + filename;
1650+ }
1651+ }
1652+ }
1653+
16371654void LoadMtl (std::map<std::string, int > *material_map,
16381655 std::vector<material_t > *materials, std::istream *inStream,
16391656 std::string *warning, std::string *err) {
@@ -2015,27 +2032,59 @@ bool MaterialFileReader::operator()(const std::string &matId,
20152032 std::vector<material_t > *materials,
20162033 std::map<std::string, int > *matMap,
20172034 std::string *warn, std::string *err) {
2018- std::string filepath;
2019-
20202035 if (!m_mtlBaseDir.empty ()) {
2021- filepath = std::string (m_mtlBaseDir) + matId;
2022- } else {
2023- filepath = matId;
2024- }
2036+ #if _WIN32
2037+ char sep = ' ;' ;
2038+ #else
2039+ char sep = ' :' ;
2040+ #endif
2041+
2042+ // https://stackoverflow.com/questions/5167625/splitting-a-c-stdstring-using-tokens-e-g
2043+ std::vector<std::string> paths;
2044+ std::istringstream f (m_mtlBaseDir);
2045+
2046+ std::string s;
2047+ while (getline (f, s, sep)) {
2048+ paths.push_back (s);
2049+ }
2050+
2051+ for (size_t i = 0 ; i < paths.size (); i++) {
2052+ std::string filepath = JoinPath (paths[i], matId);
2053+
2054+ std::ifstream matIStream (filepath.c_str ());
2055+ if (matIStream) {
2056+ LoadMtl (matMap, materials, &matIStream, warn, err);
2057+
2058+ return true ;
2059+ }
2060+ }
20252061
2026- std::ifstream matIStream (filepath.c_str ());
2027- if (!matIStream) {
20282062 std::stringstream ss;
2029- ss << " Material file [ " << filepath << " ] not found." << std::endl;
2063+ ss << " Material file [ " << matId
2064+ << " ] not found in a path : " << m_mtlBaseDir << std::endl;
20302065 if (warn) {
20312066 (*warn) += ss.str ();
20322067 }
20332068 return false ;
2034- }
20352069
2036- LoadMtl (matMap, materials, &matIStream, warn, err);
2070+ } else {
2071+ std::string filepath = matId;
2072+ std::ifstream matIStream (filepath.c_str ());
2073+ if (matIStream) {
2074+ LoadMtl (matMap, materials, &matIStream, warn, err);
20372075
2038- return true ;
2076+ return true ;
2077+ }
2078+
2079+ std::stringstream ss;
2080+ ss << " Material file [ " << filepath
2081+ << " ] not found in a path : " << m_mtlBaseDir << std::endl;
2082+ if (warn) {
2083+ (*warn) += ss.str ();
2084+ }
2085+
2086+ return false ;
2087+ }
20392088}
20402089
20412090bool MaterialStreamReader::operator ()(const std::string &matId,
0 commit comments