diff --git a/test.cc b/test.cc index b5e7d0c..82b6178 100644 --- a/test.cc +++ b/test.cc @@ -3,12 +3,9 @@ #include #include #include -#include #include #include #include -#include -#include static void PrintInfo(const std::vector& shapes) { @@ -45,8 +42,8 @@ static void PrintInfo(const std::vector& shapes) printf(" material.map_Kd = %s\n", shapes[i].material.diffuse_texname.c_str()); printf(" material.map_Ks = %s\n", shapes[i].material.specular_texname.c_str()); printf(" material.map_Ns = %s\n", shapes[i].material.normal_texname.c_str()); - auto it = shapes[i].material.unknown_parameter.begin(); - auto itEnd = shapes[i].material.unknown_parameter.end(); + std::map::const_iterator it(shapes[i].material.unknown_parameter.begin()); + std::map::const_iterator itEnd(shapes[i].material.unknown_parameter.end()); for (; it != itEnd; it++) { printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str()); } @@ -113,48 +110,54 @@ TestStreamLoadObj() "usemtl white\n" "f 2 6 7 3\n" "# 6 elements"; - - auto getMatFileIStreamFunc = - [](const std::string& matId) - { - if (matId == "cube.mtl") { - - std::unique_ptr matStream( - new std::stringstream( - "newmtl white\n" - "Ka 0 0 0\n" - "Kd 1 1 1\n" - "Ks 0 0 0\n" - "\n" - "newmtl red\n" - "Ka 0 0 0\n" - "Kd 1 0 0\n" - "Ks 0 0 0\n" - "\n" - "newmtl green\n" - "Ka 0 0 0\n" - "Kd 0 1 0\n" - "Ks 0 0 0\n" - "\n" - "newmtl blue\n" - "Ka 0 0 0\n" - "Kd 0 0 1\n" - "Ks 0 0 0\n" - "\n" - "newmtl light\n" - "Ka 20 20 20\n" - "Kd 1 1 1\n" - "Ks 0 0 0")); - return matStream; - } +std::string matStream( + "newmtl white\n" + "Ka 0 0 0\n" + "Kd 1 1 1\n" + "Ks 0 0 0\n" + "\n" + "newmtl red\n" + "Ka 0 0 0\n" + "Kd 1 0 0\n" + "Ks 0 0 0\n" + "\n" + "newmtl green\n" + "Ka 0 0 0\n" + "Kd 0 1 0\n" + "Ks 0 0 0\n" + "\n" + "newmtl blue\n" + "Ka 0 0 0\n" + "Kd 0 0 1\n" + "Ks 0 0 0\n" + "\n" + "newmtl light\n" + "Ka 20 20 20\n" + "Kd 1 1 1\n" + "Ks 0 0 0"); - std::unique_ptr emptyUP( nullptr ); - return emptyUP; - }; - + using namespace tinyobj; + class MaterialStringStreamReader: + public MaterialReader + { + public: + MaterialStringStreamReader(const std::string& matSStream): m_matSStream(matSStream) {} + virtual ~MaterialStringStreamReader() {} + virtual std::string operator() ( + const std::string& matId, + std::map& matMap) + { + return LoadMtl(matMap, m_matSStream); + } + + private: + std::stringstream m_matSStream; + }; + + MaterialStringStreamReader matSSReader(matStream); std::vector shapes; - std::string err = tinyobj::LoadObj(shapes, objStream, getMatFileIStreamFunc); + std::string err = tinyobj::LoadObj(shapes, objStream, matSSReader); if (!err.empty()) { std::cerr << err << std::endl; diff --git a/tiny_obj_loader.cc b/tiny_obj_loader.cc index e7c2346..51de34b 100644 --- a/tiny_obj_loader.cc +++ b/tiny_obj_loader.cc @@ -478,6 +478,22 @@ std::string LoadMtl ( return err.str(); } +std::string MaterialFileReader::operator() ( + const std::string& matId, + std::map& matMap) +{ + std::string filepath; + + if (!m_mtlBasePath.empty()) { + filepath = std::string(m_mtlBasePath) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + return LoadMtl(matMap, matIStream); +} + std::string LoadObj( std::vector& shapes, @@ -495,28 +511,19 @@ LoadObj( return err.str(); } - auto getMatFileIStreamFunc = - [&](const std::string& matId) - { - std::string filepath; - - if (mtl_basepath) { - filepath = std::string(mtl_basepath) + matId; - } else { - filepath = matId; - } - - std::unique_ptr ifs( new std::ifstream(filepath.c_str()) ); - return ifs; - }; + std::string basePath; + if (mtl_basepath) { + basePath = mtl_basepath; + } + MaterialFileReader matFileReader( basePath ); - return LoadObj(shapes, ifs, getMatFileIStreamFunc); + return LoadObj(shapes, ifs, matFileReader); } std::string LoadObj( std::vector& shapes, std::istream& inStream, - GetMtlIStreamFn getMatFn) + MaterialReader& readMatFn) { std::stringstream err; @@ -633,19 +640,11 @@ std::string LoadObj( char namebuf[4096]; token += 7; sscanf(token, "%s", namebuf); - - if (!getMatFn) { - err << "Could not read material, no callable function target."; - return err.str(); - } - std::unique_ptr matIStream = getMatFn(namebuf); - if (matIStream) { - std::string err_mtl = LoadMtl(material_map, *matIStream); - if (!err_mtl.empty()) { - faceGroup.clear(); // for safety - return err_mtl; - } + std::string err_mtl = readMatFn(namebuf, material_map); + if (!err_mtl.empty()) { + faceGroup.clear(); // for safety + return err_mtl; } continue; diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index c4a0a30..c275a88 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -9,8 +9,6 @@ #include #include #include -#include -#include namespace tinyobj { @@ -51,12 +49,30 @@ typedef struct mesh_t mesh; } shape_t; -/// typedef for a function that returns a pointer to an istream for -/// the material identified by the const std::string& -typedef std::function< - std::unique_ptr( - const std::string&) - > GetMtlIStreamFn; +class MaterialReader +{ +public: + MaterialReader(){} + virtual ~MaterialReader(){} + + virtual std::string operator() ( + const std::string& matId, + std::map& matMap) = 0; +}; + +class MaterialFileReader: + public MaterialReader +{ + public: + MaterialFileReader(const std::string& mtl_basepath): m_mtlBasePath(mtl_basepath) {} + virtual ~MaterialFileReader() {} + virtual std::string operator() ( + const std::string& matId, + std::map& matMap); + + private: + std::string m_mtlBasePath; +}; /// Loads .obj from a file. /// 'shapes' will be filled with parsed shape data @@ -74,7 +90,13 @@ std::string LoadObj( std::string LoadObj( std::vector& shapes, // [output] std::istream& inStream, - GetMtlIStreamFn getMatFn); + MaterialReader& readMatFn); + +/// Loads materials into std::map +/// Returns an empty string if successful +std::string LoadMtl ( + std::map& material_map, + std::istream& inStream); }; #endif // _TINY_OBJ_LOADER_H