diff --git a/examples/obj_sticher/obj_sticher.cc b/examples/obj_sticher/obj_sticher.cc index 8ec7a28..f59fee4 100644 --- a/examples/obj_sticher/obj_sticher.cc +++ b/examples/obj_sticher/obj_sticher.cc @@ -86,9 +86,12 @@ main( for (int i = 0; i < num_objfiles; i++) { std::cout << "Loading " << argv[i+1] << " ... " << std::flush; - std::string err = tinyobj::LoadObj(shapes[i], materials[i], argv[i+1]); + std::string err; + bool ret = tinyobj::LoadObj(shapes[i], materials[i], err, argv[i+1]); if (!err.empty()) { std::cerr << err << std::endl; + } + if (!ret) { exit(1); } diff --git a/missing_material_file.obj b/missing_material_file.obj new file mode 100644 index 0000000..9e1d98c --- /dev/null +++ b/missing_material_file.obj @@ -0,0 +1,145 @@ +# cornell_box.obj and cornell_box.mtl are grabbed from Intel's embree project. +# original cornell box data + # comment + +# empty line including some space + + +#mtllib no_material.mtl + +o floor +usemtl white +v 552.8 0.0 0.0 +v 0.0 0.0 0.0 +v 0.0 0.0 559.2 +v 549.6 0.0 559.2 + +v 130.0 0.0 65.0 +v 82.0 0.0 225.0 +v 240.0 0.0 272.0 +v 290.0 0.0 114.0 + +v 423.0 0.0 247.0 +v 265.0 0.0 296.0 +v 314.0 0.0 456.0 +v 472.0 0.0 406.0 + +f 1 2 3 4 +f 8 7 6 5 +f 12 11 10 9 + +o light +usemtl light +v 343.0 548.0 227.0 +v 343.0 548.0 332.0 +v 213.0 548.0 332.0 +v 213.0 548.0 227.0 +f -4 -3 -2 -1 + +o ceiling +usemtl white +v 556.0 548.8 0.0 +v 556.0 548.8 559.2 +v 0.0 548.8 559.2 +v 0.0 548.8 0.0 +f -4 -3 -2 -1 + +o back_wall +usemtl white +v 549.6 0.0 559.2 +v 0.0 0.0 559.2 +v 0.0 548.8 559.2 +v 556.0 548.8 559.2 +f -4 -3 -2 -1 + +o front_wall +usemtl blue +v 549.6 0.0 0 +v 0.0 0.0 0 +v 0.0 548.8 0 +v 556.0 548.8 0 +#f -1 -2 -3 -4 + +o green_wall +usemtl green +v 0.0 0.0 559.2 +v 0.0 0.0 0.0 +v 0.0 548.8 0.0 +v 0.0 548.8 559.2 +f -4 -3 -2 -1 + +o red_wall +usemtl red +v 552.8 0.0 0.0 +v 549.6 0.0 559.2 +v 556.0 548.8 559.2 +v 556.0 548.8 0.0 +f -4 -3 -2 -1 + +o short_block +usemtl white + +v 130.0 165.0 65.0 +v 82.0 165.0 225.0 +v 240.0 165.0 272.0 +v 290.0 165.0 114.0 +f -4 -3 -2 -1 + +v 290.0 0.0 114.0 +v 290.0 165.0 114.0 +v 240.0 165.0 272.0 +v 240.0 0.0 272.0 +f -4 -3 -2 -1 + +v 130.0 0.0 65.0 +v 130.0 165.0 65.0 +v 290.0 165.0 114.0 +v 290.0 0.0 114.0 +f -4 -3 -2 -1 + +v 82.0 0.0 225.0 +v 82.0 165.0 225.0 +v 130.0 165.0 65.0 +v 130.0 0.0 65.0 +f -4 -3 -2 -1 + +v 240.0 0.0 272.0 +v 240.0 165.0 272.0 +v 82.0 165.0 225.0 +v 82.0 0.0 225.0 +f -4 -3 -2 -1 + +o tall_block +usemtl white + +v 423.0 330.0 247.0 +v 265.0 330.0 296.0 +v 314.0 330.0 456.0 +v 472.0 330.0 406.0 +f -4 -3 -2 -1 + +usemtl white +v 423.0 0.0 247.0 +v 423.0 330.0 247.0 +v 472.0 330.0 406.0 +v 472.0 0.0 406.0 +f -4 -3 -2 -1 + +v 472.0 0.0 406.0 +v 472.0 330.0 406.0 +v 314.0 330.0 456.0 +v 314.0 0.0 456.0 +f -4 -3 -2 -1 + +v 314.0 0.0 456.0 +v 314.0 330.0 456.0 +v 265.0 330.0 296.0 +v 265.0 0.0 296.0 +f -4 -3 -2 -1 + +v 265.0 0.0 296.0 +v 265.0 330.0 296.0 +v 423.0 330.0 247.0 +v 423.0 0.0 247.0 +f -4 -3 -2 -1 + diff --git a/no_material.obj b/no_material.obj new file mode 100644 index 0000000..6f3688f --- /dev/null +++ b/no_material.obj @@ -0,0 +1,133 @@ +# cornell_box.obj and cornell_box.mtl are grabbed from Intel's embree project. +# original cornell box data + # comment + +# empty line including some space + + +o floor +v 552.8 0.0 0.0 +v 0.0 0.0 0.0 +v 0.0 0.0 559.2 +v 549.6 0.0 559.2 + +v 130.0 0.0 65.0 +v 82.0 0.0 225.0 +v 240.0 0.0 272.0 +v 290.0 0.0 114.0 + +v 423.0 0.0 247.0 +v 265.0 0.0 296.0 +v 314.0 0.0 456.0 +v 472.0 0.0 406.0 + +f 1 2 3 4 +f 8 7 6 5 +f 12 11 10 9 + +o light +v 343.0 548.0 227.0 +v 343.0 548.0 332.0 +v 213.0 548.0 332.0 +v 213.0 548.0 227.0 +f -4 -3 -2 -1 + +o ceiling +v 556.0 548.8 0.0 +v 556.0 548.8 559.2 +v 0.0 548.8 559.2 +v 0.0 548.8 0.0 +f -4 -3 -2 -1 + +o back_wall +v 549.6 0.0 559.2 +v 0.0 0.0 559.2 +v 0.0 548.8 559.2 +v 556.0 548.8 559.2 +f -4 -3 -2 -1 + +o front_wall +v 549.6 0.0 0 +v 0.0 0.0 0 +v 0.0 548.8 0 +v 556.0 548.8 0 +#f -1 -2 -3 -4 + +o green_wall +v 0.0 0.0 559.2 +v 0.0 0.0 0.0 +v 0.0 548.8 0.0 +v 0.0 548.8 559.2 +f -4 -3 -2 -1 + +o red_wall +v 552.8 0.0 0.0 +v 549.6 0.0 559.2 +v 556.0 548.8 559.2 +v 556.0 548.8 0.0 +f -4 -3 -2 -1 + +o short_block + +v 130.0 165.0 65.0 +v 82.0 165.0 225.0 +v 240.0 165.0 272.0 +v 290.0 165.0 114.0 +f -4 -3 -2 -1 + +v 290.0 0.0 114.0 +v 290.0 165.0 114.0 +v 240.0 165.0 272.0 +v 240.0 0.0 272.0 +f -4 -3 -2 -1 + +v 130.0 0.0 65.0 +v 130.0 165.0 65.0 +v 290.0 165.0 114.0 +v 290.0 0.0 114.0 +f -4 -3 -2 -1 + +v 82.0 0.0 225.0 +v 82.0 165.0 225.0 +v 130.0 165.0 65.0 +v 130.0 0.0 65.0 +f -4 -3 -2 -1 + +v 240.0 0.0 272.0 +v 240.0 165.0 272.0 +v 82.0 165.0 225.0 +v 82.0 0.0 225.0 +f -4 -3 -2 -1 + +o tall_block + +v 423.0 330.0 247.0 +v 265.0 330.0 296.0 +v 314.0 330.0 456.0 +v 472.0 330.0 406.0 +f -4 -3 -2 -1 + +v 423.0 0.0 247.0 +v 423.0 330.0 247.0 +v 472.0 330.0 406.0 +v 472.0 0.0 406.0 +f -4 -3 -2 -1 + +v 472.0 0.0 406.0 +v 472.0 330.0 406.0 +v 314.0 330.0 456.0 +v 314.0 0.0 456.0 +f -4 -3 -2 -1 + +v 314.0 0.0 456.0 +v 314.0 330.0 456.0 +v 265.0 330.0 296.0 +v 265.0 0.0 296.0 +f -4 -3 -2 -1 + +v 265.0 0.0 296.0 +v 265.0 330.0 296.0 +v 423.0 330.0 247.0 +v 423.0 0.0 247.0 +f -4 -3 -2 -1 + diff --git a/test-nan.obj b/test-nan.obj new file mode 100644 index 0000000..3c68925 --- /dev/null +++ b/test-nan.obj @@ -0,0 +1,145 @@ +# cornell_box.obj and cornell_box.mtl are grabbed from Intel's embree project. +# original cornell box data + # comment + +# empty line including some space + + +mtllib cornell_box.mtl + +o floor +usemtl white +v nan -nan nan +v inf -inf inf +v 1.#IND -1.#IND 1.#IND +v 1.#INF -1.#INF 1.#INF + +v 130.0 0.0 65.0 +v 82.0 0.0 225.0 +v 240.0 0.0 272.0 +v 290.0 0.0 114.0 + +v 423.0 0.0 247.0 +v 265.0 0.0 296.0 +v 314.0 0.0 456.0 +v 472.0 0.0 406.0 + +f 1 2 3 4 +f 8 7 6 5 +f 12 11 10 9 + +o light +usemtl light +v 343.0 548.0 227.0 +v 343.0 548.0 332.0 +v 213.0 548.0 332.0 +v 213.0 548.0 227.0 +f -4 -3 -2 -1 + +o ceiling +usemtl white +v 556.0 548.8 0.0 +v 556.0 548.8 559.2 +v 0.0 548.8 559.2 +v 0.0 548.8 0.0 +f -4 -3 -2 -1 + +o back_wall +usemtl white +v 549.6 0.0 559.2 +v 0.0 0.0 559.2 +v 0.0 548.8 559.2 +v 556.0 548.8 559.2 +f -4 -3 -2 -1 + +o front_wall +usemtl blue +v 549.6 0.0 0 +v 0.0 0.0 0 +v 0.0 548.8 0 +v 556.0 548.8 0 +#f -1 -2 -3 -4 + +o green_wall +usemtl green +v 0.0 0.0 559.2 +v 0.0 0.0 0.0 +v 0.0 548.8 0.0 +v 0.0 548.8 559.2 +f -4 -3 -2 -1 + +o red_wall +usemtl red +v 552.8 0.0 0.0 +v 549.6 0.0 559.2 +v 556.0 548.8 559.2 +v 556.0 548.8 0.0 +f -4 -3 -2 -1 + +o short_block +usemtl white + +v 130.0 165.0 65.0 +v 82.0 165.0 225.0 +v 240.0 165.0 272.0 +v 290.0 165.0 114.0 +f -4 -3 -2 -1 + +v 290.0 0.0 114.0 +v 290.0 165.0 114.0 +v 240.0 165.0 272.0 +v 240.0 0.0 272.0 +f -4 -3 -2 -1 + +v 130.0 0.0 65.0 +v 130.0 165.0 65.0 +v 290.0 165.0 114.0 +v 290.0 0.0 114.0 +f -4 -3 -2 -1 + +v 82.0 0.0 225.0 +v 82.0 165.0 225.0 +v 130.0 165.0 65.0 +v 130.0 0.0 65.0 +f -4 -3 -2 -1 + +v 240.0 0.0 272.0 +v 240.0 165.0 272.0 +v 82.0 165.0 225.0 +v 82.0 0.0 225.0 +f -4 -3 -2 -1 + +o tall_block +usemtl white + +v 423.0 330.0 247.0 +v 265.0 330.0 296.0 +v 314.0 330.0 456.0 +v 472.0 330.0 406.0 +f -4 -3 -2 -1 + +usemtl white +v 423.0 0.0 247.0 +v 423.0 330.0 247.0 +v 472.0 330.0 406.0 +v 472.0 0.0 406.0 +f -4 -3 -2 -1 + +v 472.0 0.0 406.0 +v 472.0 330.0 406.0 +v 314.0 330.0 456.0 +v 314.0 0.0 456.0 +f -4 -3 -2 -1 + +v 314.0 0.0 456.0 +v 314.0 330.0 456.0 +v 265.0 330.0 296.0 +v 265.0 0.0 296.0 +f -4 -3 -2 -1 + +v 265.0 0.0 296.0 +v 265.0 330.0 296.0 +v 423.0 330.0 247.0 +v 423.0 0.0 247.0 +f -4 -3 -2 -1 + diff --git a/test.cc b/test.cc index 3f16e3e..e012623 100644 --- a/test.cc +++ b/test.cc @@ -67,10 +67,15 @@ TestLoadObj( std::vector shapes; std::vector materials; - std::string err = tinyobj::LoadObj(shapes, materials, filename, basepath); + + std::string err; + bool ret = tinyobj::LoadObj(shapes, materials, err, filename, basepath); if (!err.empty()) { std::cerr << err << std::endl; + } + + if (!ret) { return false; } @@ -152,12 +157,14 @@ std::string matStream( public: MaterialStringStreamReader(const std::string& matSStream): m_matSStream(matSStream) {} virtual ~MaterialStringStreamReader() {} - virtual std::string operator() ( + virtual bool operator() ( const std::string& matId, std::vector& materials, - std::map& matMap) + std::map& matMap, + std::string& err) { - return LoadMtl(matMap, materials, m_matSStream); + LoadMtl(matMap, materials, m_matSStream); + return true; } private: @@ -167,10 +174,14 @@ std::string matStream( MaterialStringStreamReader matSSReader(matStream); std::vector shapes; std::vector materials; - std::string err = tinyobj::LoadObj(shapes, materials, objStream, matSSReader); + std::string err; + bool ret = tinyobj::LoadObj(shapes, materials, err, objStream, matSSReader); if (!err.empty()) { std::cerr << err << std::endl; + } + + if (!ret) { return false; } diff --git a/tiny_obj_loader.cc b/tiny_obj_loader.cc index 067f642..84c1a77 100644 --- a/tiny_obj_loader.cc +++ b/tiny_obj_loader.cc @@ -5,6 +5,7 @@ // // +// version 0.9.15: Change API to handle no mtl file case correctly(#58) // version 0.9.14: Support specular highlight, bump, displacement and alpha map(#53) // version 0.9.13: Report "Material file not found message" in `err`(#46) // version 0.9.12: Fix groups being ignored if they have 'usemtl' just before 'g' (#44) @@ -415,10 +416,9 @@ static bool exportFaceGroupToShape( return true; } -std::string LoadMtl(std::map &material_map, - std::vector &materials, - std::istream &inStream) { - std::stringstream err; +void LoadMtl(std::map &material_map, + std::vector &materials, + std::istream &inStream) { // Create a default material anyway. material_t material; @@ -643,13 +643,12 @@ std::string LoadMtl(std::map &material_map, material_map.insert( std::pair(material.name, static_cast(materials.size()))); materials.push_back(material); - - return err.str(); } -std::string MaterialFileReader::operator()(const std::string &matId, - std::vector &materials, - std::map &matMap) { +bool MaterialFileReader::operator()(const std::string &matId, + std::vector &materials, + std::map &matMap, + std::string& err) { std::string filepath; if (!m_mtlBasePath.empty()) { @@ -659,27 +658,29 @@ std::string MaterialFileReader::operator()(const std::string &matId, } std::ifstream matIStream(filepath.c_str()); - std::string err = LoadMtl(matMap, materials, matIStream); + LoadMtl(matMap, materials, matIStream); if (!matIStream) { std::stringstream ss; ss << "WARN: Material file [ " << filepath << " ] not found. Created a default material."; err += ss.str(); } - return err; + return true; } -std::string LoadObj(std::vector &shapes, - std::vector &materials, // [output] - const char *filename, const char *mtl_basepath) { +bool LoadObj(std::vector &shapes, // [output] + std::vector &materials, // [output] + std::string &err, + const char *filename, const char *mtl_basepath) { shapes.clear(); - std::stringstream err; + std::stringstream errss; std::ifstream ifs(filename); if (!ifs) { - err << "Cannot open file [" << filename << "]" << std::endl; - return err.str(); + errss << "Cannot open file [" << filename << "]" << std::endl; + err = errss.str(); + return false; } std::string basePath; @@ -688,13 +689,14 @@ std::string LoadObj(std::vector &shapes, } MaterialFileReader matFileReader(basePath); - return LoadObj(shapes, materials, ifs, matFileReader); + return LoadObj(shapes, materials, err, ifs, matFileReader); } -std::string LoadObj(std::vector &shapes, - std::vector &materials, // [output] - std::istream &inStream, MaterialReader &readMatFn) { - std::stringstream err; +bool LoadObj(std::vector &shapes, // [output] + std::vector &materials, // [output] + std::string& err, + std::istream &inStream, MaterialReader &readMatFn) { + std::stringstream errss; std::vector v; std::vector vn; @@ -833,10 +835,13 @@ std::string LoadObj(std::vector &shapes, sscanf(token, "%s", namebuf); #endif - std::string err_mtl = readMatFn(namebuf, materials, material_map); - if (!err_mtl.empty()) { + std::string err_mtl; + bool ok = readMatFn(namebuf, materials, material_map, err_mtl); + err += err_mtl; + + if (!ok) { faceGroup.clear(); // for safety - return err_mtl; + return false; } continue; @@ -913,6 +918,8 @@ std::string LoadObj(std::vector &shapes, } faceGroup.clear(); // for safety - return err.str(); -} + err += errss.str(); + return true; } + +} // namespace diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index 00259e7..0a65b3a 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -54,9 +54,10 @@ public: MaterialReader() {} virtual ~MaterialReader() {} - virtual std::string operator()(const std::string &matId, - std::vector &materials, - std::map &matMap) = 0; + virtual bool operator()(const std::string &matId, + std::vector &materials, + std::map &matMap, + std::string &err) = 0; }; class MaterialFileReader : public MaterialReader { @@ -64,9 +65,10 @@ public: MaterialFileReader(const std::string &mtl_basepath) : m_mtlBasePath(mtl_basepath) {} virtual ~MaterialFileReader() {} - virtual std::string operator()(const std::string &matId, - std::vector &materials, - std::map &matMap); + virtual bool operator()(const std::string &matId, + std::vector &materials, + std::map &matMap, + std::string &err); private: std::string m_mtlBasePath; @@ -75,23 +77,27 @@ private: /// Loads .obj from a file. /// 'shapes' will be filled with parsed shape data /// The function returns error string. -/// Returns empty string when loading .obj success. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` /// 'mtl_basepath' is optional, and used for base path for .mtl file. -std::string LoadObj(std::vector &shapes, // [output] - std::vector &materials, // [output] - const char *filename, const char *mtl_basepath = NULL); +bool LoadObj(std::vector &shapes, // [output] + std::vector &materials, // [output] + std::string& err, // [output] + const char *filename, const char *mtl_basepath = NULL); /// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve /// std::istream for materials. -/// Returns empty string when loading .obj success. -std::string LoadObj(std::vector &shapes, // [output] - std::vector &materials, // [output] - std::istream &inStream, MaterialReader &readMatFn); +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(std::vector &shapes, // [output] + std::vector &materials, // [output] + std::string& err, // [output] + std::istream &inStream, MaterialReader &readMatFn); /// Loads materials into std::map -/// Returns an empty string if successful -std::string LoadMtl(std::map &material_map, - std::vector &materials, std::istream &inStream); +void LoadMtl(std::map &material_map, // [output] + std::vector &materials, // [output] + std::istream &inStream); } #endif // _TINY_OBJ_LOADER_H