Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support MTL files with escaped whitespace #285

Merged
merged 2 commits into from
Nov 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/viewer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* premake5
* glfw3
* glew
* xcursor
* xinerama

## Build on MaCOSX

Expand Down
4 changes: 4 additions & 0 deletions models/mtl filename with whitespace issue46.mtl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
newmtl green
Ka 0 0 0
Kd 0 1 0
Ks 0 0 0
31 changes: 31 additions & 0 deletions models/mtl filename with whitespace issue46.obj
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
mtllib invalid-file-without-spaces.mtl invalid\ file\ with\ spaces.mtl mtl\ filename\ with\ whitespace\ issue46.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 green
f 1 2 3 4
g back cube
usemtl green
f 8 7 6 5
g right cube
usemtl green
f 4 3 7 8
g left cube
usemtl green
f 5 6 2 1
g top cube
usemtl green
f 5 1 4 8
g bottom cube
usemtl green
f 2 6 7 3
# 6 elements
26 changes: 26 additions & 0 deletions tests/tester.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1308,6 +1308,30 @@ void test_texres_texopt_issue248() {
TEST_CHECK("input.jpg" == materials[0].diffuse_texname);
}

void test_mtl_filename_with_whitespace_issue46() {
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/mtl filename with whitespace issue46.obj",
gMtlBasePath);

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 == materials.size());
TEST_CHECK("green" == materials[0].name);
}

// Fuzzer test.
// Just check if it does not crash.
// Disable by default since Windows filesystem can't create filename of afl
Expand Down Expand Up @@ -1407,4 +1431,6 @@ TEST_LIST = {
test_usemtl_whitespace_issue246},
{"texres_texopt_issue248",
test_texres_texopt_issue248},
{"test_mtl_filename_with_whitespace_issue46",
test_mtl_filename_with_whitespace_issue46},
{NULL, NULL}};
35 changes: 25 additions & 10 deletions tiny_obj_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -1658,16 +1658,31 @@ static bool exportGroupsToShape(shape_t *shape, const PrimGroup &prim_group,
return true;
}

// Split a string with specified delimiter character.
// http://stackoverflow.com/questions/236129/split-a-string-in-c
static void SplitString(const std::string &s, char delim,
// Split a string with specified delimiter character and escape character.
// https://rosettacode.org/wiki/Tokenize_a_string_with_escaping#C.2B.2B
static void SplitString(const std::string &s, char delim, char escape,
std::vector<std::string> &elems) {
std::stringstream ss;
ss.str(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
std::string token;

bool escaping = false;
for (int i = 0; i < s.size(); ++i) {
char ch = s[i];
if (escaping) {
escaping = false;
} else if (ch == escape) {
escaping = true;
continue;
} else if (ch == delim) {
if (!token.empty()) {
elems.push_back(token);
}
token.clear();
continue;
}
token += ch;
}

elems.push_back(token);
}

static std::string JoinPath(const std::string &dir,
Expand Down Expand Up @@ -2483,7 +2498,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
token += 7;

std::vector<std::string> filenames;
SplitString(std::string(token), ' ', filenames);
SplitString(std::string(token), ' ', '\\', filenames);

if (filenames.empty()) {
if (warn) {
Expand Down Expand Up @@ -2891,7 +2906,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
token += 7;

std::vector<std::string> filenames;
SplitString(std::string(token), ' ', filenames);
SplitString(std::string(token), ' ', '\\', filenames);

if (filenames.empty()) {
if (warn) {
Expand Down