Skip to content

Commit b46cd46

Browse files
committed
Support MTL files with escaped whitespace
Signed-off-by: Louise Poubel <louise@openrobotics.org>
1 parent a40e9c2 commit b46cd46

File tree

5 files changed

+87
-10
lines changed

5 files changed

+87
-10
lines changed

examples/viewer/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* premake5
66
* glfw3
77
* glew
8+
* xcursor
9+
* xinerama
810

911
## Build on MaCOSX
1012

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
newmtl green
2+
Ka 0 0 0
3+
Kd 0 1 0
4+
Ks 0 0 0
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
mtllib invalid-file-without-spaces.mtl invalid\ file\ with\ spaces.mtl mtl\ filename\ with\ whitespace\ issue46.mtl
2+
3+
v 0.000000 2.000000 2.000000
4+
v 0.000000 0.000000 2.000000
5+
v 2.000000 0.000000 2.000000
6+
v 2.000000 2.000000 2.000000
7+
v 0.000000 2.000000 0.000000
8+
v 0.000000 0.000000 0.000000
9+
v 2.000000 0.000000 0.000000
10+
v 2.000000 2.000000 0.000000
11+
# 8 vertices
12+
13+
g front cube
14+
usemtl green
15+
f 1 2 3 4
16+
g back cube
17+
usemtl green
18+
f 8 7 6 5
19+
g right cube
20+
usemtl green
21+
f 4 3 7 8
22+
g left cube
23+
usemtl green
24+
f 5 6 2 1
25+
g top cube
26+
usemtl green
27+
f 5 1 4 8
28+
g bottom cube
29+
usemtl green
30+
f 2 6 7 3
31+
# 6 elements

tests/tester.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,30 @@ void test_texres_texopt_issue248() {
13081308
TEST_CHECK("input.jpg" == materials[0].diffuse_texname);
13091309
}
13101310

1311+
void test_mtl_filename_with_whitespace_issue46() {
1312+
tinyobj::attrib_t attrib;
1313+
std::vector<tinyobj::shape_t> shapes;
1314+
std::vector<tinyobj::material_t> materials;
1315+
1316+
std::string warn;
1317+
std::string err;
1318+
bool ret =
1319+
tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err,
1320+
"../models/mtl filename with whitespace issue46.obj",
1321+
gMtlBasePath);
1322+
1323+
if (!warn.empty()) {
1324+
std::cout << "WARN: " << warn << std::endl;
1325+
}
1326+
1327+
if (!err.empty()) {
1328+
std::cerr << "ERR: " << err << std::endl;
1329+
}
1330+
TEST_CHECK(true == ret);
1331+
TEST_CHECK(1 == materials.size());
1332+
TEST_CHECK("green" == materials[0].name);
1333+
}
1334+
13111335
// Fuzzer test.
13121336
// Just check if it does not crash.
13131337
// Disable by default since Windows filesystem can't create filename of afl
@@ -1407,4 +1431,6 @@ TEST_LIST = {
14071431
test_usemtl_whitespace_issue246},
14081432
{"texres_texopt_issue248",
14091433
test_texres_texopt_issue248},
1434+
{"test_mtl_filename_with_whitespace_issue46",
1435+
test_mtl_filename_with_whitespace_issue46},
14101436
{NULL, NULL}};

tiny_obj_loader.h

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,16 +1658,30 @@ static bool exportGroupsToShape(shape_t *shape, const PrimGroup &prim_group,
16581658
return true;
16591659
}
16601660

1661-
// Split a string with specified delimiter character.
1662-
// http://stackoverflow.com/questions/236129/split-a-string-in-c
1663-
static void SplitString(const std::string &s, char delim,
1661+
// Split a string with specified delimiter character and escape character.
1662+
// https://rosettacode.org/wiki/Tokenize_a_string_with_escaping#C.2B.2B
1663+
static void SplitString(const std::string &s, char delim, char escape,
16641664
std::vector<std::string> &elems) {
1665-
std::stringstream ss;
1666-
ss.str(s);
1667-
std::string item;
1668-
while (std::getline(ss, item, delim)) {
1669-
elems.push_back(item);
1665+
std::string token;
1666+
1667+
bool escaping = false;
1668+
for (char ch : s) {
1669+
if (escaping) {
1670+
escaping = false;
1671+
} else if (ch == escape) {
1672+
escaping = true;
1673+
continue;
1674+
} else if (ch == delim) {
1675+
if (!token.empty()) {
1676+
elems.push_back(token);
1677+
}
1678+
token.clear();
1679+
continue;
1680+
}
1681+
token += ch;
16701682
}
1683+
1684+
elems.push_back(token);
16711685
}
16721686

16731687
static std::string JoinPath(const std::string &dir,
@@ -2483,7 +2497,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
24832497
token += 7;
24842498

24852499
std::vector<std::string> filenames;
2486-
SplitString(std::string(token), ' ', filenames);
2500+
SplitString(std::string(token), ' ', '\\', filenames);
24872501

24882502
if (filenames.empty()) {
24892503
if (warn) {
@@ -2891,7 +2905,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
28912905
token += 7;
28922906

28932907
std::vector<std::string> filenames;
2894-
SplitString(std::string(token), ' ', filenames);
2908+
SplitString(std::string(token), ' ', '\\', filenames);
28952909

28962910
if (filenames.empty()) {
28972911
if (warn) {

0 commit comments

Comments
 (0)