Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 08ff49d

Browse files
committed
Added a LoadObj function that reads from a std::istream.
+ Added a LoadObj function that reads from a std::istream. This should allow more generic usage and possibly make testing a little easier. o This LoadObj accepts a function that returns a std::unique_ptr<std::istream> for a material. + Modified LoadMtl to read from a std::istream to allow more generic usage. + Modified test.cc to check that the changes work as expected and nothing was broken. Tests: + Compiled test.cc, checked diff of output against pre change output. Same output where expected.
1 parent c33b0cf commit 08ff49d

File tree

3 files changed

+179
-42
lines changed

3 files changed

+179
-42
lines changed

test.cc

Lines changed: 120 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,15 @@
33
#include <cstdio>
44
#include <cstdlib>
55
#include <cassert>
6+
#include <cstddef>
67
#include <iostream>
8+
#include <sstream>
9+
#include <fstream>
10+
#include <functional>
11+
#include <memory>
712

8-
static bool
9-
TestLoadObj(
10-
const char* filename,
11-
const char* basepath = NULL)
13+
static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes)
1214
{
13-
std::cout << "Loading " << filename << std::endl;
14-
15-
std::vector<tinyobj::shape_t> shapes;
16-
std::string err = tinyobj::LoadObj(shapes, filename, basepath);
17-
18-
if (!err.empty()) {
19-
std::cerr << err << std::endl;
20-
return false;
21-
}
22-
2315
std::cout << "# of shapes : " << shapes.size() << std::endl;
2416

2517
for (size_t i = 0; i < shapes.size(); i++) {
@@ -53,14 +45,124 @@ TestLoadObj(
5345
printf(" material.map_Kd = %s\n", shapes[i].material.diffuse_texname.c_str());
5446
printf(" material.map_Ks = %s\n", shapes[i].material.specular_texname.c_str());
5547
printf(" material.map_Ns = %s\n", shapes[i].material.normal_texname.c_str());
56-
std::map<std::string, std::string>::iterator it(shapes[i].material.unknown_parameter.begin());
57-
std::map<std::string, std::string>::iterator itEnd(shapes[i].material.unknown_parameter.end());
48+
auto it = shapes[i].material.unknown_parameter.begin();
49+
auto itEnd = shapes[i].material.unknown_parameter.end();
5850
for (; it != itEnd; it++) {
5951
printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str());
6052
}
6153
printf("\n");
6254
}
55+
}
56+
57+
static bool
58+
TestLoadObj(
59+
const char* filename,
60+
const char* basepath = NULL)
61+
{
62+
std::cout << "Loading " << filename << std::endl;
63+
64+
std::vector<tinyobj::shape_t> shapes;
65+
std::string err = tinyobj::LoadObj(shapes, filename, basepath);
6366

67+
if (!err.empty()) {
68+
std::cerr << err << std::endl;
69+
return false;
70+
}
71+
72+
PrintInfo(shapes);
73+
74+
return true;
75+
}
76+
77+
78+
static bool
79+
TestStreamLoadObj()
80+
{
81+
std::cout << "Stream Loading " << std::endl;
82+
83+
std::stringstream objStream;
84+
objStream
85+
<< "mtllib cube.mtl\n"
86+
"\n"
87+
"v 0.000000 2.000000 2.000000\n"
88+
"v 0.000000 0.000000 2.000000\n"
89+
"v 2.000000 0.000000 2.000000\n"
90+
"v 2.000000 2.000000 2.000000\n"
91+
"v 0.000000 2.000000 0.000000\n"
92+
"v 0.000000 0.000000 0.000000\n"
93+
"v 2.000000 0.000000 0.000000\n"
94+
"v 2.000000 2.000000 0.000000\n"
95+
"# 8 vertices\n"
96+
"\n"
97+
"g front cube\n"
98+
"usemtl white\n"
99+
"f 1 2 3 4\n"
100+
"g back cube\n"
101+
"# expects white material\n"
102+
"f 8 7 6 5\n"
103+
"g right cube\n"
104+
"usemtl red\n"
105+
"f 4 3 7 8\n"
106+
"g top cube\n"
107+
"usemtl white\n"
108+
"f 5 1 4 8\n"
109+
"g left cube\n"
110+
"usemtl green\n"
111+
"f 5 6 2 1\n"
112+
"g bottom cube\n"
113+
"usemtl white\n"
114+
"f 2 6 7 3\n"
115+
"# 6 elements";
116+
117+
auto getMatFileIStreamFunc =
118+
[](const std::string& matId)
119+
{
120+
if (matId == "cube.mtl") {
121+
122+
std::unique_ptr<std::stringstream> matStream(
123+
new std::stringstream(
124+
"newmtl white\n"
125+
"Ka 0 0 0\n"
126+
"Kd 1 1 1\n"
127+
"Ks 0 0 0\n"
128+
"\n"
129+
"newmtl red\n"
130+
"Ka 0 0 0\n"
131+
"Kd 1 0 0\n"
132+
"Ks 0 0 0\n"
133+
"\n"
134+
"newmtl green\n"
135+
"Ka 0 0 0\n"
136+
"Kd 0 1 0\n"
137+
"Ks 0 0 0\n"
138+
"\n"
139+
"newmtl blue\n"
140+
"Ka 0 0 0\n"
141+
"Kd 0 0 1\n"
142+
"Ks 0 0 0\n"
143+
"\n"
144+
"newmtl light\n"
145+
"Ka 20 20 20\n"
146+
"Kd 1 1 1\n"
147+
"Ks 0 0 0"));
148+
149+
return matStream;
150+
}
151+
152+
std::unique_ptr<std::stringstream> emptyUP( nullptr );
153+
return emptyUP;
154+
};
155+
156+
std::vector<tinyobj::shape_t> shapes;
157+
std::string err = tinyobj::LoadObj(shapes, objStream, getMatFileIStreamFunc);
158+
159+
if (!err.empty()) {
160+
std::cerr << err << std::endl;
161+
return false;
162+
}
163+
164+
PrintInfo(shapes);
165+
64166
return true;
65167
}
66168

@@ -79,7 +181,8 @@ main(
79181
} else {
80182
assert(true == TestLoadObj("cornell_box.obj"));
81183
assert(true == TestLoadObj("cube.obj"));
184+
assert(true == TestStreamLoadObj());
82185
}
83-
186+
84187
return 0;
85188
}

tiny_obj_loader.cc

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -290,35 +290,19 @@ exportFaceGroupToShape(
290290

291291
}
292292

293-
294293
std::string LoadMtl (
295294
std::map<std::string, material_t>& material_map,
296-
const char* filename,
297-
const char* mtl_basepath)
295+
std::istream& inStream)
298296
{
299297
material_map.clear();
300298
std::stringstream err;
301299

302-
std::string filepath;
303-
304-
if (mtl_basepath) {
305-
filepath = std::string(mtl_basepath) + std::string(filename);
306-
} else {
307-
filepath = std::string(filename);
308-
}
309-
310-
std::ifstream ifs(filepath.c_str());
311-
if (!ifs) {
312-
err << "Cannot open file [" << filepath << "]" << std::endl;
313-
return err.str();
314-
}
315-
316300
material_t material;
317301

318302
int maxchars = 8192; // Alloc enough size.
319303
std::vector<char> buf(maxchars); // Alloc enough size.
320-
while (ifs.peek() != -1) {
321-
ifs.getline(&buf[0], maxchars);
304+
while (inStream.peek() != -1) {
305+
inStream.getline(&buf[0], maxchars);
322306

323307
std::string linebuf(&buf[0]);
324308

@@ -511,6 +495,31 @@ LoadObj(
511495
return err.str();
512496
}
513497

498+
auto getMatFileIStreamFunc =
499+
[&](const std::string& matId)
500+
{
501+
std::string filepath;
502+
503+
if (mtl_basepath) {
504+
filepath = std::string(mtl_basepath) + matId;
505+
} else {
506+
filepath = matId;
507+
}
508+
509+
std::unique_ptr<std::ifstream> ifs( new std::ifstream(filepath.c_str()) );
510+
return ifs;
511+
};
512+
513+
return LoadObj(shapes, ifs, getMatFileIStreamFunc);
514+
}
515+
516+
std::string LoadObj(
517+
std::vector<shape_t>& shapes,
518+
std::istream& inStream,
519+
GetMtlIStreamFn getMatFn)
520+
{
521+
std::stringstream err;
522+
514523
std::vector<float> v;
515524
std::vector<float> vn;
516525
std::vector<float> vt;
@@ -524,8 +533,8 @@ LoadObj(
524533

525534
int maxchars = 8192; // Alloc enough size.
526535
std::vector<char> buf(maxchars); // Alloc enough size.
527-
while (ifs.peek() != -1) {
528-
ifs.getline(&buf[0], maxchars);
536+
while (inStream.peek() != -1) {
537+
inStream.getline(&buf[0], maxchars);
529538

530539
std::string linebuf(&buf[0]);
531540

@@ -625,11 +634,20 @@ LoadObj(
625634
token += 7;
626635
sscanf(token, "%s", namebuf);
627636

628-
std::string err_mtl = LoadMtl(material_map, namebuf, mtl_basepath);
629-
if (!err_mtl.empty()) {
630-
faceGroup.clear(); // for safety
631-
return err_mtl;
637+
if (!getMatFn) {
638+
err << "Could not read material, no callable function target.";
639+
return err.str();
640+
}
641+
642+
std::unique_ptr<std::istream> matIStream = getMatFn(namebuf);
643+
if (matIStream) {
644+
std::string err_mtl = LoadMtl(material_map, *matIStream);
645+
if (!err_mtl.empty()) {
646+
faceGroup.clear(); // for safety
647+
return err_mtl;
648+
}
632649
}
650+
633651
continue;
634652
}
635653

tiny_obj_loader.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <string>
1010
#include <vector>
1111
#include <map>
12+
#include <functional>
13+
#include <memory>
1214

1315
namespace tinyobj {
1416

@@ -49,6 +51,13 @@ typedef struct
4951
mesh_t mesh;
5052
} shape_t;
5153

54+
/// typedef for a function that returns a pointer to an istream for
55+
/// the material identified by the const std::string&
56+
typedef std::function<
57+
std::unique_ptr<std::istream>(
58+
const std::string&)
59+
> GetMtlIStreamFn;
60+
5261
/// Loads .obj from a file.
5362
/// 'shapes' will be filled with parsed shape data
5463
/// The function returns error string.
@@ -59,6 +68,13 @@ std::string LoadObj(
5968
const char* filename,
6069
const char* mtl_basepath = NULL);
6170

71+
/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve
72+
/// std::istream for materials.
73+
/// Returns empty string when loading .obj success.
74+
std::string LoadObj(
75+
std::vector<shape_t>& shapes, // [output]
76+
std::istream& inStream,
77+
GetMtlIStreamFn getMatFn);
6278
};
6379

6480
#endif // _TINY_OBJ_LOADER_H

0 commit comments

Comments
 (0)