diff --git a/test.cc b/test.cc index 4de4cc2..7148135 100644 --- a/test.cc +++ b/test.cc @@ -6,12 +6,14 @@ #include static bool -TestLoadObj(const char* filename) +TestLoadObj( + const char* filename, + const char* basepath = NULL) { std::cout << "Loading " << filename << std::endl; std::vector shapes; - std::string err = tinyobj::LoadObj(shapes, filename); + std::string err = tinyobj::LoadObj(shapes, filename, basepath); if (!err.empty()) { std::cerr << err << std::endl; @@ -66,7 +68,11 @@ main( { if (argc > 1) { - assert(true == TestLoadObj(argv[1])); + const char* basepath = NULL; + if (argc > 2) { + basepath = argv[2]; + } + assert(true == TestLoadObj(argv[1], basepath)); } else { assert(true == TestLoadObj("cornell_box.obj")); assert(true == TestLoadObj("cube.obj")); diff --git a/tiny_obj_loader.cc b/tiny_obj_loader.cc index 7988fab..0cc9e29 100644 --- a/tiny_obj_loader.cc +++ b/tiny_obj_loader.cc @@ -5,6 +5,8 @@ // // +// version 0.9.5: Parse multiple group name. +// Add support of specifying the base path to load material file. // version 0.9.4: Initial suupport of group tag(g) // version 0.9.3: Fix parsing triple 'x/y/z' // version 0.9.2: Add more .mtl load support @@ -73,6 +75,17 @@ static inline int fixIndex(int idx, int n) return i; } +static inline std::string parseString(const char*& token) +{ + std::string s; + int b = strspn(token, " \t"); + int e = strcspn(token, " \t\r"); + s = std::string(&token[b], &token[e]); + + token += (e - b); + return s; +} + static inline float parseFloat(const char*& token) { token += strspn(token, " \t"); @@ -259,14 +272,23 @@ void InitMaterial(material_t& material) { std::string LoadMtl ( std::map& material_map, - const char* filename) + const char* filename, + const char* mtl_basepath) { material_map.clear(); std::stringstream err; - std::ifstream ifs(filename); + std::string filepath; + + if (mtl_basepath) { + filepath = std::string(mtl_basepath) + std::string(filename); + } else { + filepath = std::string(filename); + } + + std::ifstream ifs(filepath.c_str()); if (!ifs) { - err << "Cannot open file [" << filename << "]" << std::endl; + err << "Cannot open file [" << filepath << "]" << std::endl; return err.str(); } @@ -428,7 +450,8 @@ std::string LoadMtl ( std::string LoadObj( std::vector& shapes, - const char* filename) + const char* filename, + const char* mtl_basepath) { shapes.clear(); @@ -553,7 +576,7 @@ LoadObj( token += 7; sscanf(token, "%s", namebuf); - std::string err_mtl = LoadMtl(material_map, namebuf); + std::string err_mtl = LoadMtl(material_map, namebuf, mtl_basepath); if (!err_mtl.empty()) { faceGroup.clear(); // for safety return err_mtl; @@ -564,8 +587,6 @@ LoadObj( // group name if (token[0] == 'g' && isSpace((token[1]))) { - printf("group\n"); - // flush previous face group. shape_t shape; bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name); @@ -575,11 +596,21 @@ LoadObj( faceGroup.clear(); - // @todo { multiple group name. } - char namebuf[4096]; - token += 2; - sscanf(token, "%s", namebuf); - name = std::string(namebuf); + std::vector names; + while (!isNewLine(token[0])) { + std::string str = parseString(token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skipt 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } continue; } @@ -596,6 +627,7 @@ LoadObj( faceGroup.clear(); + // @todo { multiple object name? } char namebuf[4096]; token += 2; sscanf(token, "%s", namebuf); diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index 6c1adcc..bc3ad2e 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -1,5 +1,5 @@ // -// Copyright 2012, Syoyo Fujita. +// Copyright 2012-2013, Syoyo Fujita. // // Licensed under 2-clause BSD liecense. // @@ -49,9 +49,11 @@ typedef struct /// 'shapes' will be filled with parsed shape data /// The function returns error string. /// Returns empty string when loading .obj success. +/// 'mtl_basepath' is optional, and used for base path for .mtl file. std::string LoadObj( std::vector& shapes, // [output] - const char* filename); + const char* filename, + const char* mtl_basepath = NULL); };