From 039d4a6c54f7650a55b53a2fd68c38765867ad80 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 18 Oct 2016 17:33:28 +0900 Subject: [PATCH] Fix a shape is lost if obj ends with a 'usemtl'. Fixes #104 --- models/usemtl-issue-104.obj | 30 ++++++++++++++++++++++++++++++ tests/tester.cc | 16 ++++++++++++++++ tiny_obj_loader.h | 11 +++++++++-- 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 models/usemtl-issue-104.obj diff --git a/models/usemtl-issue-104.obj b/models/usemtl-issue-104.obj new file mode 100644 index 0000000..5183676 --- /dev/null +++ b/models/usemtl-issue-104.obj @@ -0,0 +1,30 @@ +# 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 +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 + +usemtl white diff --git a/tests/tester.cc b/tests/tester.cc index 5573bb6..f38238d 100644 --- a/tests/tester.cc +++ b/tests/tester.cc @@ -402,6 +402,7 @@ TEST_CASE("transmittance_filter_Tf", "[Issue95-Tf]") { REQUIRE(0.2 == Approx(materials[0].transmittance[1])); REQUIRE(0.3 == Approx(materials[0].transmittance[2])); } + TEST_CASE("transmittance_filter_Kt", "[Issue95-Kt]") { tinyobj::attrib_t attrib; std::vector shapes; @@ -420,6 +421,21 @@ TEST_CASE("transmittance_filter_Kt", "[Issue95-Kt]") { REQUIRE(0.3 == Approx(materials[0].transmittance[2])); } +TEST_CASE("usemtl_at_last_line", "[Issue104]") { + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + + std::string err; + bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/usemtl-issue-104.obj", gMtlBasePath); + + if (!err.empty()) { + std::cerr << err << std::endl; + } + REQUIRE(true == ret); + REQUIRE(1 == shapes.size()); +} + #if 0 int main( diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index 0200ff5..6ee59c1 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -23,6 +23,7 @@ THE SOFTWARE. */ // +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) // version 1.0.0 : Change data structure. Change license from BSD to MIT. // @@ -1161,7 +1162,9 @@ bool LoadObj(attrib_t *attrib, std::vector *shapes, } if (newMaterialId != material) { - // Create per-face material + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. exportFaceGroupToShape(&shape, faceGroup, tags, material, name, triangulate); faceGroup.clear(); @@ -1307,7 +1310,11 @@ bool LoadObj(attrib_t *attrib, std::vector *shapes, bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, triangulate); - if (ret) { + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { shapes->push_back(shape); } faceGroup.clear(); // for safety