diff options
author | Syoyo Fujita <syoyo@lighttransport.com> | 2021-03-08 15:32:47 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-08 15:32:47 +0900 |
commit | 7ba4b652ee0c5175ec8abf66199e84d88adf11f1 (patch) | |
tree | 39f6b41d1d58d5efa284d6f3228cadbbb181d851 | |
parent | 9173980d1de273b17eba5e10eb189e8b4be89425 (diff) | |
download | tinyobjloader-7ba4b652ee0c5175ec8abf66199e84d88adf11f1.tar.gz |
Use simple triangulation rule for the quad face when triangulation. This partially solves issue no. 295. (#296)
-rw-r--r-- | models/issue-295-trianguation-failure.obj | 38 | ||||
-rw-r--r-- | tests/tester.cc | 34 | ||||
-rw-r--r-- | tiny_obj_loader.h | 475 |
3 files changed, 368 insertions, 179 deletions
diff --git a/models/issue-295-trianguation-failure.obj b/models/issue-295-trianguation-failure.obj new file mode 100644 index 0000000..f3b2649 --- /dev/null +++ b/models/issue-295-trianguation-failure.obj @@ -0,0 +1,38 @@ +#mtllib invalid.mtl +v 14678.0 0.0 9605.0 +v 14678.0 1.0 9605.0 +v 14678.0 0.0 9606.0 +v 14678.0 1.0 9606.0 +v 14678.0 0.0 9607.0 +v 14678.0 1.0 9607.0 +v 14678.0 0.0 9608.0 +v 14678.0 1.0 9608.0 +v 14679.0 0.0 9605.0 +v 14679.0 1.0 9605.0 +v 14679.0 0.0 9606.0 +v 14679.0 1.0 9606.0 +v 14679.0 0.0 9607.0 +v 14679.0 1.0 9607.0 +v 14679.0 0.0 9608.0 +v 14679.0 1.0 9608.0 +# UV +vt 0.0 0.0 +vt 1.0 0.0 +vt 1.0 1.0 +vt 0.0 1.0 +#usemtl invalid +o invalid +f 9/4 11/1 3/2 1/3 +f 4/1 12/2 10/3 2/4 +f 2/3 10/4 9/1 1/2 +f 3/2 4/3 2/4 1/1 +f 10/3 12/4 11/1 9/2 +f 11/4 13/1 5/2 3/3 +f 6/1 14/2 12/3 4/4 +f 5/2 6/3 4/4 3/1 +f 12/3 14/4 13/1 11/2 +f 13/4 15/1 7/2 5/3 +f 8/1 16/2 14/3 6/4 +f 15/2 16/3 8/4 7/1 +f 7/2 8/3 6/4 5/1 +f 14/3 16/4 15/1 13/2 diff --git a/tests/tester.cc b/tests/tester.cc index 0fd0dbc..ebb5290 100644 --- a/tests/tester.cc +++ b/tests/tester.cc @@ -1332,6 +1332,38 @@ void test_mtl_filename_with_whitespace_issue46() { TEST_CHECK("green" == materials[0].name); } +void test_face_missing_issue295() { + tinyobj::attrib_t attrib; + std::vector<tinyobj::shape_t> shapes; + std::vector<tinyobj::material_t> materials; + + std::string warn; + std::string err; + bool ret = tinyobj::LoadObj( + &attrib, &shapes, &materials, &warn, &err, + "../models/issue-295-trianguation-failure.obj", + gMtlBasePath, /* triangualte */true); + + TEST_CHECK(warn.empty()); + + if (!warn.empty()) { + std::cout << "WARN: " << warn << std::endl; + } + + if (!err.empty()) { + std::cerr << "ERR: " << err << std::endl; + } + + TEST_CHECK(true == ret); + TEST_CHECK(1 == shapes.size()); + + // 14 quad faces are triangulated into 28 triangles. + TEST_CHECK(28 == shapes[0].mesh.num_face_vertices.size()); + TEST_CHECK(28 == shapes[0].mesh.smoothing_group_ids.size()); + TEST_CHECK(28 == shapes[0].mesh.material_ids.size()); + TEST_CHECK((3 * 28) == shapes[0].mesh.indices.size()); // 28 triangle faces x 3 +} + // Fuzzer test. // Just check if it does not crash. // Disable by default since Windows filesystem can't create filename of afl @@ -1433,4 +1465,6 @@ TEST_LIST = { test_texres_texopt_issue248}, {"test_mtl_filename_with_whitespace_issue46", test_mtl_filename_with_whitespace_issue46}, + {"test_face_missing_issue295", + test_face_missing_issue295}, {NULL, NULL}}; diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index 99213f6..4bfd7b7 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2012-2018 Syoyo Fujita and many contributors. +Copyright (c) 2012-Present, Syoyo Fujita and many contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -1366,8 +1366,8 @@ static int pnpoly(int nvert, T *vertx, T *verty, T testx, T testy) { static bool exportGroupsToShape(shape_t *shape, const PrimGroup &prim_group, const std::vector<tag_t> &tags, const int material_id, const std::string &name, - bool triangulate, - const std::vector<real_t> &v) { + bool triangulate, const std::vector<real_t> &v, + std::string *warn) { if (prim_group.IsEmpty()) { return false; } @@ -1384,30 +1384,34 @@ static bool exportGroupsToShape(shape_t *shape, const PrimGroup &prim_group, if (npolys < 3) { // Face must have 3+ vertices. + if (warn) { + (*warn) += "Degenerated face found\n."; + } continue; } - vertex_index_t i0 = face.vertex_indices[0]; - vertex_index_t i1(-1); - vertex_index_t i2 = face.vertex_indices[1]; - if (triangulate) { - // find the two axes to work in - size_t axes[2] = {1, 2}; - for (size_t k = 0; k < npolys; ++k) { - i0 = face.vertex_indices[(k + 0) % npolys]; - i1 = face.vertex_indices[(k + 1) % npolys]; - i2 = face.vertex_indices[(k + 2) % npolys]; + if (npolys == 4) { + vertex_index_t i0 = face.vertex_indices[0]; + vertex_index_t i1 = face.vertex_indices[1]; + vertex_index_t i2 = face.vertex_indices[2]; + vertex_index_t i3 = face.vertex_indices[3]; + size_t vi0 = size_t(i0.v_idx); size_t vi1 = size_t(i1.v_idx); size_t vi2 = size_t(i2.v_idx); + size_t vi3 = size_t(i3.v_idx); if (((3 * vi0 + 2) >= v.size()) || ((3 * vi1 + 2) >= v.size()) || - ((3 * vi2 + 2) >= v.size())) { + ((3 * vi2 + 2) >= v.size()) || ((3 * vi3 + 2) >= v.size())) { // Invalid triangle. // FIXME(syoyo): Is it ok to simply skip this invalid triangle? + if (warn) { + (*warn) += "Face with invalid vertex index found.\n"; + } continue; } + real_t v0x = v[vi0 * 3 + 0]; real_t v0y = v[vi0 * 3 + 1]; real_t v0z = v[vi0 * 3 + 2]; @@ -1417,186 +1421,297 @@ static bool exportGroupsToShape(shape_t *shape, const PrimGroup &prim_group, real_t v2x = v[vi2 * 3 + 0]; real_t v2y = v[vi2 * 3 + 1]; real_t v2z = v[vi2 * 3 + 2]; - real_t e0x = v1x - v0x; - real_t e0y = v1y - v0y; - real_t e0z = v1z - v0z; - real_t e1x = v2x - v1x; - real_t e1y = v2y - v1y; - real_t e1z = v2z - v1z; - real_t cx = std::fabs(e0y * e1z - e0z * e1y); - real_t cy = std::fabs(e0z * e1x - e0x * e1z); - real_t cz = std::fabs(e0x * e1y - e0y * e1x); - const real_t epsilon = std::numeric_limits<real_t>::epsilon(); - if (cx > epsilon || cy > epsilon || cz > epsilon) { - // found a corner - if (cx > cy && cx > cz) { - } else { - axes[0] = 0; - if (cz > cx && cz > cy) axes[1] = 1; - } - break; - } - } - - real_t area = 0; - for (size_t k = 0; k < npolys; ++k) { - i0 = face.vertex_indices[(k + 0) % npolys]; - i1 = face.vertex_indices[(k + 1) % npolys]; - size_t vi0 = size_t(i0.v_idx); - size_t vi1 = size_t(i1.v_idx); - if (((vi0 * 3 + axes[0]) >= v.size()) || - ((vi0 * 3 + axes[1]) >= v.size()) || - ((vi1 * 3 + axes[0]) >= v.size()) || - ((vi1 * 3 + axes[1]) >= v.size())) { - // Invalid index. - continue; - } - real_t v0x = v[vi0 * 3 + axes[0]]; - real_t v0y = v[vi0 * 3 + axes[1]]; - real_t v1x = v[vi1 * 3 + axes[0]]; - real_t v1y = v[vi1 * 3 + axes[1]]; - area += (v0x * v1y - v0y * v1x) * static_cast<real_t>(0.5); - } - - face_t remainingFace = face; // copy - size_t guess_vert = 0; - vertex_index_t ind[3]; - real_t vx[3]; - real_t vy[3]; - - // How many iterations can we do without decreasing the remaining - // vertices. - size_t remainingIterations = face.vertex_indices.size(); - size_t previousRemainingVertices = remainingFace.vertex_indices.size(); - - while (remainingFace.vertex_indices.size() > 3 && - remainingIterations > 0) { - npolys = remainingFace.vertex_indices.size(); - if (guess_vert >= npolys) { - guess_vert -= npolys; - } + real_t v3x = v[vi3 * 3 + 0]; + real_t v3y = v[vi3 * 3 + 1]; + real_t v3z = v[vi3 * 3 + 2]; + + // There are two candidates to split the quad into two triangles. + // + // Choose the shortest edge. + // TODO: Is it better to determine the edge to split by calculating + // the area of each triangle? + // + // +---+ + // |\ | + // | \ | + // | \| + // +---+ + // + // +---+ + // | /| + // | / | + // |/ | + // +---+ + + real_t e02x = v2x - v0x; + real_t e02y = v2y - v0y; + real_t e02z = v2z - v0z; + real_t e13x = v3x - v1x; + real_t e13y = v3y - v1y; + real_t e13z = v3z - v1z; + + real_t sqr02 = e02x * e02x + e02y * e02y + e02z * e02z; + real_t sqr13 = e13x * e13x + e13y * e13y + e13z * e13z; + + index_t idx0, idx1, idx2, idx3; + + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + idx3.vertex_index = i3.v_idx; + idx3.normal_index = i3.vn_idx; + idx3.texcoord_index = i3.vt_idx; + + if (sqr02 < sqr13) { + // [0, 1, 2], [0, 2, 3] + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); - if (previousRemainingVertices != npolys) { - // The number of remaining vertices decreased. Reset counters. - previousRemainingVertices = npolys; - remainingIterations = npolys; + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx2); + shape->mesh.indices.push_back(idx3); } else { - // We didn't consume a vertex on previous iteration, reduce the - // available iterations. - remainingIterations--; - } + // [0, 1, 3], [1, 2, 3] + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx3); - for (size_t k = 0; k < 3; k++) { - ind[k] = remainingFace.vertex_indices[(guess_vert + k) % npolys]; - size_t vi = size_t(ind[k].v_idx); - if (((vi * 3 + axes[0]) >= v.size()) || - ((vi * 3 + axes[1]) >= v.size())) { - // ??? - vx[k] = static_cast<real_t>(0.0); - vy[k] = static_cast<real_t>(0.0); - } else { - vx[k] = v[vi * 3 + axes[0]]; - vy[k] = v[vi * 3 + axes[1]]; - } - } - real_t e0x = vx[1] - vx[0]; - real_t e0y = vy[1] - vy[0]; - real_t e1x = vx[2] - vx[1]; - real_t e1y = vy[2] - vy[1]; - real_t cross = e0x * e1y - e0y * e1x; - // if an internal angle - if (cross * area < static_cast<real_t>(0.0)) { - guess_vert += 1; - continue; + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + shape->mesh.indices.push_back(idx3); } - // check all other verts in case they are inside this triangle - bool overlap = false; - for (size_t otherVert = 3; otherVert < npolys; ++otherVert) { - size_t idx = (guess_vert + otherVert) % npolys; + // Two triangle faces + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.num_face_vertices.push_back(3); - if (idx >= remainingFace.vertex_indices.size()) { - // ??? - continue; - } + shape->mesh.material_ids.push_back(material_id); + shape->mesh.material_ids.push_back(material_id); - size_t ovi = size_t(remainingFace.vertex_indices[idx].v_idx); + shape->mesh.smoothing_group_ids.push_back(face.smoothing_group_id); + shape->mesh.smoothing_group_ids.push_back(face.smoothing_group_id); - if (((ovi * 3 + axes[0]) >= v.size()) || - ((ovi * 3 + axes[1]) >= v.size())) { - // ??? + } else { + vertex_index_t i0 = face.vertex_indices[0]; + vertex_index_t i1(-1); + vertex_index_t i2 = face.vertex_indices[1]; + + // find the two axes to work in + size_t axes[2] = {1, 2}; + for (size_t k = 0; k < npolys; ++k) { + i0 = face.vertex_indices[(k + 0) % npolys]; + i1 = face.vertex_indices[(k + 1) % npolys]; + i2 = face.vertex_indices[(k + 2) % npolys]; + size_t vi0 = size_t(i0.v_idx); + size_t vi1 = size_t(i1.v_idx); + size_t vi2 = size_t(i2.v_idx); + + if (((3 * vi0 + 2) >= v.size()) || ((3 * vi1 + 2) >= v.size()) || + ((3 * vi2 + 2) >= v.size())) { + // Invalid triangle. + // FIXME(syoyo): Is it ok to simply skip this invalid triangle? continue; } - real_t tx = v[ovi * 3 + axes[0]]; - real_t ty = v[ovi * 3 + axes[1]]; - if (pnpoly(3, vx, vy, tx, ty)) { - overlap = true; + real_t v0x = v[vi0 * 3 + 0]; + real_t v0y = v[vi0 * 3 + 1]; + real_t v0z = v[vi0 * 3 + 2]; + real_t v1x = v[vi1 * 3 + 0]; + real_t v1y = v[vi1 * 3 + 1]; + real_t v1z = v[vi1 * 3 + 2]; + real_t v2x = v[vi2 * 3 + 0]; + real_t v2y = v[vi2 * 3 + 1]; + real_t v2z = v[vi2 * 3 + 2]; + real_t e0x = v1x - v0x; + real_t e0y = v1y - v0y; + real_t e0z = v1z - v0z; + real_t e1x = v2x - v1x; + real_t e1y = v2y - v1y; + real_t e1z = v2z - v1z; + real_t cx = std::fabs(e0y * e1z - e0z * e1y); + real_t cy = std::fabs(e0z * e1x - e0x * e1z); + real_t cz = std::fabs(e0x * e1y - e0y * e1x); + const real_t epsilon = std::numeric_limits<real_t>::epsilon(); + if (cx > epsilon || cy > epsilon || cz > epsilon) { + // found a corner + if (cx > cy && cx > cz) { + } else { + axes[0] = 0; + if (cz > cx && cz > cy) axes[1] = 1; + } break; } } - if (overlap) { - guess_vert += 1; - continue; + real_t area = 0; + for (size_t k = 0; k < npolys; ++k) { + i0 = face.vertex_indices[(k + 0) % npolys]; + i1 = face.vertex_indices[(k + 1) % npolys]; + size_t vi0 = size_t(i0.v_idx); + size_t vi1 = size_t(i1.v_idx); + if (((vi0 * 3 + axes[0]) >= v.size()) || + ((vi0 * 3 + axes[1]) >= v.size()) || + ((vi1 * 3 + axes[0]) >= v.size()) || + ((vi1 * 3 + axes[1]) >= v.size())) { + // Invalid index. + continue; + } + real_t v0x = v[vi0 * 3 + axes[0]]; + real_t v0y = v[vi0 * 3 + axes[1]]; + real_t v1x = v[vi1 * 3 + axes[0]]; + real_t v1y = v[vi1 * 3 + axes[1]]; + area += (v0x * v1y - v0y * v1x) * static_cast<real_t>(0.5); } - // this triangle is an ear - { - index_t idx0, idx1, idx2; - idx0.vertex_index = ind[0].v_idx; - idx0.normal_index = ind[0].vn_idx; - idx0.texcoord_index = ind[0].vt_idx; - idx1.vertex_index = ind[1].v_idx; - idx1.normal_index = ind[1].vn_idx; - idx1.texcoord_index = ind[1].vt_idx; - idx2.vertex_index = ind[2].v_idx; - idx2.normal_index = ind[2].vn_idx; - idx2.texcoord_index = ind[2].vt_idx; + face_t remainingFace = face; // copy + size_t guess_vert = 0; + vertex_index_t ind[3]; + real_t vx[3]; + real_t vy[3]; + + // How many iterations can we do without decreasing the remaining + // vertices. + size_t remainingIterations = face.vertex_indices.size(); + size_t previousRemainingVertices = + remainingFace.vertex_indices.size(); + + while (remainingFace.vertex_indices.size() > 3 && + remainingIterations > 0) { + npolys = remainingFace.vertex_indices.size(); + if (guess_vert >= npolys) { + guess_vert -= npolys; + } - shape->mesh.indices.push_back(idx0); - shape->mesh.indices.push_back(idx1); - shape->mesh.indices.push_back(idx2); + if (previousRemainingVertices != npolys) { + // The number of remaining vertices decreased. Reset counters. + previousRemainingVertices = npolys; + remainingIterations = npolys; + } else { + // We didn't consume a vertex on previous iteration, reduce the + // available iterations. + remainingIterations--; + } - shape->mesh.num_face_vertices.push_back(3); - shape->mesh.material_ids.push_back(material_id); - shape->mesh.smoothing_group_ids.push_back(face.smoothing_group_id); - } + for (size_t k = 0; k < 3; k++) { + ind[k] = remainingFace.vertex_indices[(guess_vert + k) % npolys]; + size_t vi = size_t(ind[k].v_idx); + if (((vi * 3 + axes[0]) >= v.size()) || + ((vi * 3 + axes[1]) >= v.size())) { + // ??? + vx[k] = static_cast<real_t>(0.0); + vy[k] = static_cast<real_t>(0.0); + } else { + vx[k] = v[vi * 3 + axes[0]]; + vy[k] = v[vi * 3 + axes[1]]; + } + } + real_t e0x = vx[1] - vx[0]; + real_t e0y = vy[1] - vy[0]; + real_t e1x = vx[2] - vx[1]; + real_t e1y = vy[2] - vy[1]; + real_t cross = e0x * e1y - e0y * e1x; + // if an internal angle + if (cross * area < static_cast<real_t>(0.0)) { + guess_vert += 1; + continue; + } - // remove v1 from the list - size_t removed_vert_index = (guess_vert + 1) % npolys; - while (removed_vert_index + 1 < npolys) { - remainingFace.vertex_indices[removed_vert_index] = - remainingFace.vertex_indices[removed_vert_index + 1]; - removed_vert_index += 1; - } - remainingFace.vertex_indices.pop_back(); - } + // check all other verts in case they are inside this triangle + bool overlap = false; + for (size_t otherVert = 3; otherVert < npolys; ++otherVert) { + size_t idx = (guess_vert + otherVert) % npolys; + + if (idx >= remainingFace.vertex_indices.size()) { + // ??? + continue; + } + + size_t ovi = size_t(remainingFace.vertex_indices[idx].v_idx); + + if (((ovi * 3 + axes[0]) >= v.size()) || + ((ovi * 3 + axes[1]) >= v.size())) { + // ??? + continue; + } + real_t tx = v[ovi * 3 + axes[0]]; + real_t ty = v[ovi * 3 + axes[1]]; + if (pnpoly(3, vx, vy, tx, ty)) { + overlap = true; + break; + } + } - if (remainingFace.vertex_indices.size() == 3) { - i0 = remainingFace.vertex_indices[0]; - i1 = remainingFace.vertex_indices[1]; - i2 = remainingFace.vertex_indices[2]; - { - index_t idx0, idx1, idx2; - idx0.vertex_index = i0.v_idx; - idx0.normal_index = i0.vn_idx; - idx0.texcoord_index = i0.vt_idx; - idx1.vertex_index = i1.v_idx; - idx1.normal_index = i1.vn_idx; - idx1.texcoord_index = i1.vt_idx; - idx2.vertex_index = i2.v_idx; - idx2.normal_index = i2.vn_idx; - idx2.texcoord_index = i2.vt_idx; + if (overlap) { + guess_vert += 1; + continue; + } - shape->mesh.indices.push_back(idx0); - shape->mesh.indices.push_back(idx1); - shape->mesh.indices.push_back(idx2); + // this triangle is an ear + { + index_t idx0, idx1, idx2; + idx0.vertex_index = ind[0].v_idx; + idx0.normal_index = ind[0].vn_idx; + idx0.texcoord_index = ind[0].vt_idx; + idx1.vertex_index = ind[1].v_idx; + idx1.normal_index = ind[1].vn_idx; + idx1.texcoord_index = ind[1].vt_idx; + idx2.vertex_index = ind[2].v_idx; + idx2.normal_index = ind[2].vn_idx; + idx2.texcoord_index = ind[2].vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + shape->mesh.smoothing_group_ids.push_back( + face.smoothing_group_id); + } - shape->mesh.num_face_vertices.push_back(3); - shape->mesh.material_ids.push_back(material_id); - shape->mesh.smoothing_group_ids.push_back(face.smoothing_group_id); + // remove v1 from the list + size_t removed_vert_index = (guess_vert + 1) % npolys; + while (removed_vert_index + 1 < npolys) { + remainingFace.vertex_indices[removed_vert_index] = + remainingFace.vertex_indices[removed_vert_index + 1]; + removed_vert_index += 1; + } + remainingFace.vertex_indices.pop_back(); } - } + + if (remainingFace.vertex_indices.size() == 3) { + i0 = remainingFace.vertex_indices[0]; + i1 = remainingFace.vertex_indices[1]; + i2 = remainingFace.vertex_indices[2]; + { + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + shape->mesh.smoothing_group_ids.push_back( + face.smoothing_group_id); + } + } + } // npolys } else { for (size_t k = 0; k < npolys; k++) { index_t idx; @@ -2174,7 +2289,7 @@ bool MaterialStreamReader::operator()(const std::string &matId, bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes, std::vector<material_t> *materials, std::string *warn, std::string *err, const char *filename, const char *mtl_basedir, - bool trianglulate, bool default_vcols_fallback) { + bool triangulate, bool default_vcols_fallback) { attrib->vertices.clear(); attrib->normals.clear(); attrib->texcoords.clear(); @@ -2204,7 +2319,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes, MaterialFileReader matFileReader(baseDir); return LoadObj(attrib, shapes, materials, warn, err, &ifs, &matFileReader, - trianglulate, default_vcols_fallback); + triangulate, default_vcols_fallback); } bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes, @@ -2470,7 +2585,8 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes, std::string namebuf = parseString(&token); int newMaterialId = -1; - std::map<std::string, int>::const_iterator it = material_map.find(namebuf); + std::map<std::string, int>::const_iterator it = + material_map.find(namebuf); if (it != material_map.end()) { newMaterialId = it->second; } else { @@ -2485,7 +2601,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes, // this time. // just clear `faceGroup` after `exportGroupsToShape()` call. exportGroupsToShape(&shape, prim_group, tags, material, name, - triangulate, v); + triangulate, v, warn); prim_group.faceGroup.clear(); material = newMaterialId; } @@ -2548,7 +2664,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes, if (token[0] == 'g' && IS_SPACE((token[1]))) { // flush previous face group. bool ret = exportGroupsToShape(&shape, prim_group, tags, material, name, - triangulate, v); + triangulate, v, warn); (void)ret; // return value not used. if (shape.mesh.indices.size() > 0) { @@ -2600,7 +2716,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes, if (token[0] == 'o' && IS_SPACE((token[1]))) { // flush previous face group. bool ret = exportGroupsToShape(&shape, prim_group, tags, material, name, - triangulate, v); + triangulate, v, warn); (void)ret; // return value not used. if (shape.mesh.indices.size() > 0 || shape.lines.indices.size() > 0 || @@ -2740,7 +2856,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes, } bool ret = exportGroupsToShape(&shape, prim_group, tags, material, name, - triangulate, v); + triangulate, v, warn); // exportGroupsToShape return false when `usemtl` is called in the last // line. // we also add `shape` to `shapes` when `shape.mesh` has already some @@ -2880,7 +2996,8 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, std::string namebuf = ss.str(); int newMaterialId = -1; - std::map<std::string, int>::const_iterator it = material_map.find(namebuf); + std::map<std::string, int>::const_iterator it = + material_map.find(namebuf); if (it != material_map.end()) { newMaterialId = it->second; } else { |