From 94fc413466581c53c13015cf3b959d744abf5932 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Fri, 13 Oct 2017 18:13:36 +0900 Subject: Fix parsing of crease tags(`t`) Support parsing texture filename containing whitespace. --- models/texture-filename-with-whitespace.mtl | 28 ++++++++++++++++++++++++++ models/texture-filename-with-whitespace.obj | 31 +++++++++++++++++++++++++++++ tests/tester.cc | 23 +++++++++++++++++++++ tiny_obj_loader.h | 31 +++++++++++++++-------------- 4 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 models/texture-filename-with-whitespace.mtl create mode 100644 models/texture-filename-with-whitespace.obj diff --git a/models/texture-filename-with-whitespace.mtl b/models/texture-filename-with-whitespace.mtl new file mode 100644 index 0000000..70b1a4e --- /dev/null +++ b/models/texture-filename-with-whitespace.mtl @@ -0,0 +1,28 @@ +newmtl white +Ka 0 0 0 +Kd 1 1 1 +Ks 0 0 0 +# filename with white space. +map_Kd texture 01.png + +newmtl red +Ka 0 0 0 +Kd 1 0 0 +Ks 0 0 0 +# texture option + filename with white space. +bump -bm 2 bump 01.png + +newmtl green +Ka 0 0 0 +Kd 0 1 0 +Ks 0 0 0 + +newmtl blue +Ka 0 0 0 +Kd 0 0 1 +Ks 0 0 0 + +newmtl light +Ka 20 20 20 +Kd 1 1 1 +Ks 0 0 0 diff --git a/models/texture-filename-with-whitespace.obj b/models/texture-filename-with-whitespace.obj new file mode 100644 index 0000000..46e61e7 --- /dev/null +++ b/models/texture-filename-with-whitespace.obj @@ -0,0 +1,31 @@ +mtllib texture-filename-with-whitespace.mtl + +v 0.000000 2.000000 2.000000 +v 0.000000 0.000000 2.000000 +v 2.000000 0.000000 2.000000 +v 2.000000 2.000000 2.000000 +v 0.000000 2.000000 0.000000 +v 0.000000 0.000000 0.000000 +v 2.000000 0.000000 0.000000 +v 2.000000 2.000000 0.000000 +# 8 vertices + +g front cube +usemtl white +f 1 2 3 4 +g back cube +# expects white material +f 8 7 6 5 +g right cube +usemtl red +f 4 3 7 8 +g top cube +usemtl white +f 5 1 4 8 +g left cube +usemtl green +f 5 6 2 1 +g bottom cube +usemtl white +f 2 6 7 3 +# 6 elements diff --git a/tests/tester.cc b/tests/tester.cc index 811dfbf..cd972f8 100644 --- a/tests/tester.cc +++ b/tests/tester.cc @@ -694,6 +694,29 @@ TEST_CASE("zero-face-idx-value", "[Issue140]") { } +TEST_CASE("texture-name-whitespace", "[Issue145]") { + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + + std::string err; + bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/texture-filename-with-whitespace.obj", gMtlBasePath); + + + if (!err.empty()) { + std::cerr << "[Issue145] " << err << std::endl; + } + + REQUIRE(true == ret); + REQUIRE(err.empty()); + REQUIRE(2 < materials.size()); + + REQUIRE(0 == materials[0].diffuse_texname.compare("texture 01.png")); + REQUIRE(0 == materials[1].bump_texname.compare("bump 01.png")); + REQUIRE(2 == Approx(materials[1].bump_texopt.bump_multiplier)); + +} + #if 0 int main( diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index 591d236..65a9d62 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -721,22 +721,24 @@ static inline texture_type_t parseTextureType( static tag_sizes parseTagTriple(const char **token) { tag_sizes ts; + (*token) += strspn((*token), " \t"); ts.num_ints = atoi((*token)); (*token) += strcspn((*token), "/ \t\r"); if ((*token)[0] != '/') { return ts; } - (*token)++; + (*token)++; // Skip '/' + + (*token) += strspn((*token), " \t"); ts.num_reals = atoi((*token)); (*token) += strcspn((*token), "/ \t\r"); if ((*token)[0] != '/') { return ts; } - (*token)++; + (*token)++; // Skip '/' - ts.num_strings = atoi((*token)); - (*token) += strcspn((*token), "/ \t\r") + 1; + ts.num_strings = parseInt(token); return ts; } @@ -906,11 +908,18 @@ static bool ParseTextureNameAndOption(std::string *texname, parseReal2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); } else { // Assume texture filename +#if 0 size_t len = strcspn(token, " \t\r"); // untile next space texture_name = std::string(token, token + len); token += len; token += strspn(token, " \t"); // skip space +#else + // Read filename until line end to parse filename containing whitespace + // TODO(syoyo): Support parsing texture option flag after the filename. + texture_name = std::string(token); + token += texture_name.length(); +#endif found_texname = true; } @@ -1762,33 +1771,25 @@ bool LoadObj(attrib_t *attrib, std::vector *shapes, tag_t tag; token += 2; - std::stringstream ss; - ss << token; - tag.name = ss.str(); - token += tag.name.size() + 1; + tag.name = parseString(&token); tag_sizes ts = parseTagTriple(&token); tag.intValues.resize(static_cast(ts.num_ints)); for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { - tag.intValues[i] = atoi(token); - token += strcspn(token, "/ \t\r") + 1; + tag.intValues[i] = parseInt(&token); } tag.floatValues.resize(static_cast(ts.num_reals)); for (size_t i = 0; i < static_cast(ts.num_reals); ++i) { tag.floatValues[i] = parseReal(&token); - token += strcspn(token, "/ \t\r") + 1; } tag.stringValues.resize(static_cast(ts.num_strings)); for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { - std::stringstream sstr; - sstr << token; - tag.stringValues[i] = sstr.str(); - token += tag.stringValues[i].size() + 1; + tag.stringValues[i] = parseString(&token); } tags.push_back(tag); -- cgit v1.2.3