Parse multiple group names. Fixes #146
This commit is contained in:
@@ -13,6 +13,7 @@ v 2.000000 2.000000 0.000000
|
|||||||
g front cube
|
g front cube
|
||||||
usemtl white
|
usemtl white
|
||||||
f 1 2 3 4
|
f 1 2 3 4
|
||||||
|
# two white spaces between 'back' and 'cube'
|
||||||
g back cube
|
g back cube
|
||||||
# expects white material
|
# expects white material
|
||||||
f 8 7 6 5
|
f 8 7 6 5
|
||||||
|
|||||||
@@ -807,6 +807,24 @@ TEST_CASE("line-primitive", "[line]") {
|
|||||||
REQUIRE(6 == shapes[0].path.indices.size());
|
REQUIRE(6 == shapes[0].path.indices.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("multiple-group-names", "[group]") {
|
||||||
|
tinyobj::attrib_t attrib;
|
||||||
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
|
||||||
|
std::string err;
|
||||||
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/cube.obj", gMtlBasePath);
|
||||||
|
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << "[group] " << err << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE(true == ret);
|
||||||
|
REQUIRE(6 == shapes.size());
|
||||||
|
REQUIRE(0 == shapes[0].name.compare("front cube"));
|
||||||
|
REQUIRE(0 == shapes[1].name.compare("back cube")); // multiple whitespaces are aggregated as single white space.
|
||||||
|
}
|
||||||
|
|
||||||
// Fuzzer test.
|
// Fuzzer test.
|
||||||
// Just check if it does not crash.
|
// Just check if it does not crash.
|
||||||
// Disable by default since Windows filesystem can't create filename of afl testdata
|
// Disable by default since Windows filesystem can't create filename of afl testdata
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ THE SOFTWARE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//
|
//
|
||||||
|
// version 1.2.2 : Parse multiple group names.
|
||||||
// version 1.2.1 : Added initial support for line('l') primitive(PR #178)
|
// version 1.2.1 : Added initial support for line('l') primitive(PR #178)
|
||||||
// version 1.2.0 : Hardened implementation(#175)
|
// version 1.2.0 : Hardened implementation(#175)
|
||||||
// version 1.1.1 : Support smoothing groups(#162)
|
// version 1.1.1 : Support smoothing groups(#162)
|
||||||
@@ -1790,10 +1791,13 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
|
|
||||||
shape_t shape;
|
shape_t shape;
|
||||||
|
|
||||||
|
size_t line_num = 0;
|
||||||
std::string linebuf;
|
std::string linebuf;
|
||||||
while (inStream->peek() != -1) {
|
while (inStream->peek() != -1) {
|
||||||
safeGetline(*inStream, linebuf);
|
safeGetline(*inStream, linebuf);
|
||||||
|
|
||||||
|
line_num++;
|
||||||
|
|
||||||
// Trim newline '\r\n' or '\n'
|
// Trim newline '\r\n' or '\n'
|
||||||
if (linebuf.size() > 0) {
|
if (linebuf.size() > 0) {
|
||||||
if (linebuf[linebuf.size() - 1] == '\n')
|
if (linebuf[linebuf.size() - 1] == '\n')
|
||||||
@@ -2001,7 +2005,6 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
faceGroup.clear();
|
faceGroup.clear();
|
||||||
|
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
names.reserve(2);
|
|
||||||
|
|
||||||
while (!IS_NEW_LINE(token[0])) {
|
while (!IS_NEW_LINE(token[0])) {
|
||||||
std::string str = parseString(&token);
|
std::string str = parseString(&token);
|
||||||
@@ -2009,14 +2012,32 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
token += strspn(token, " \t\r"); // skip tag
|
token += strspn(token, " \t\r"); // skip tag
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(names.size() > 0);
|
// names[0] must be 'g'
|
||||||
|
|
||||||
// names[0] must be 'g', so skip the 0th element.
|
if (names.size() < 2) {
|
||||||
if (names.size() > 1) {
|
// 'g' with empty names
|
||||||
name = names[1];
|
if (err) {
|
||||||
} else {
|
std::stringstream ss;
|
||||||
|
ss << "WARN: Empty group name. line: " << line_num << "\n";
|
||||||
|
(*err) += ss.str();
|
||||||
name = "";
|
name = "";
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << names[1];
|
||||||
|
|
||||||
|
// tinyobjloader does not support multiple groups for a primitive.
|
||||||
|
// Currently we concatinate multiple group names with a space to get
|
||||||
|
// single group name.
|
||||||
|
|
||||||
|
for (size_t i = 2; i < names.size(); i++) {
|
||||||
|
ss << " " << names[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
name = ss.str();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2169,7 +2190,6 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
std::vector<material_t> materials;
|
std::vector<material_t> materials;
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
names.reserve(2);
|
names.reserve(2);
|
||||||
std::string name;
|
|
||||||
std::vector<const char *> names_out;
|
std::vector<const char *> names_out;
|
||||||
|
|
||||||
std::string linebuf;
|
std::string linebuf;
|
||||||
@@ -2346,13 +2366,6 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
|
|
||||||
assert(names.size() > 0);
|
assert(names.size() > 0);
|
||||||
|
|
||||||
// names[0] must be 'g', so skip the 0th element.
|
|
||||||
if (names.size() > 1) {
|
|
||||||
name = names[1];
|
|
||||||
} else {
|
|
||||||
name.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback.group_cb) {
|
if (callback.group_cb) {
|
||||||
if (names.size() > 1) {
|
if (names.size() > 1) {
|
||||||
// create const char* array.
|
// create const char* array.
|
||||||
|
|||||||
Reference in New Issue
Block a user