Skip to content

Commit 51d1370

Browse files
committed
Skip trailing whitespace in mtl. Fixes #92.
1 parent d5c7221 commit 51d1370

File tree

2 files changed

+118
-111
lines changed

2 files changed

+118
-111
lines changed

test.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,8 @@ std::string matStream(
302302
"newmtl light\n"
303303
"Ka 20 20 20\n"
304304
"Kd 1 1 1\n"
305-
"Ks 0 0 0");
305+
"Ks 0 0 0\n"
306+
"map_Kd tmp.png \n"); // #92(whitespace after filename)
306307

307308
using namespace tinyobj;
308309
class MaterialStringStreamReader:
@@ -342,6 +343,13 @@ std::string matStream(
342343
}
343344

344345
PrintInfo(shapes, materials);
346+
347+
// #92
348+
for (size_t i = 0; i < materials.size(); i++) {
349+
if (materials[i].name.compare("light") == 0) {
350+
assert(materials[i].diffuse_texname.compare("tmp.png") == 0);
351+
}
352+
}
345353

346354
return true;
347355
}

tiny_obj_loader.h

Lines changed: 109 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@
4242
#ifndef TINY_OBJ_LOADER_H_
4343
#define TINY_OBJ_LOADER_H_
4444

45+
#include <cmath>
46+
#include <map>
4547
#include <string>
4648
#include <vector>
47-
#include <map>
48-
#include <cmath>
4949

5050
namespace tinyobj {
5151

@@ -99,65 +99,48 @@ typedef struct {
9999
mesh_t mesh;
100100
} shape_t;
101101

102-
typedef enum
103-
{
104-
triangulation = 1, // used whether triangulate polygon face in .obj
105-
calculate_normals = 2, // used whether calculate the normals if the .obj normals are empty
102+
typedef enum {
103+
triangulation = 1, // used whether triangulate polygon face in .obj
104+
calculate_normals =
105+
2, // used whether calculate the normals if the .obj normals are empty
106106
// Some nice stuff here
107107
} load_flags_t;
108108

109-
class float3
110-
{
109+
class float3 {
111110
public:
112-
float3()
113-
: x( 0.0f )
114-
, y( 0.0f )
115-
, z( 0.0f )
116-
{
117-
}
111+
float3() : x(0.0f), y(0.0f), z(0.0f) {}
118112

119113
float3(float coord_x, float coord_y, float coord_z)
120-
: x( coord_x )
121-
, y( coord_y )
122-
, z( coord_z )
123-
{
124-
}
114+
: x(coord_x), y(coord_y), z(coord_z) {}
125115

126-
float3(const float3& from, const float3& to)
127-
{
116+
float3(const float3 &from, const float3 &to) {
128117
coord[0] = to.coord[0] - from.coord[0];
129118
coord[1] = to.coord[1] - from.coord[1];
130119
coord[2] = to.coord[2] - from.coord[2];
131120
}
132121

133-
float3 crossproduct ( const float3 & vec )
134-
{
135-
float a = y * vec.z - z * vec.y ;
136-
float b = z * vec.x - x * vec.z ;
137-
float c = x * vec.y - y * vec.x ;
138-
return float3( a , b , c );
122+
float3 crossproduct(const float3 &vec) {
123+
float a = y * vec.z - z * vec.y;
124+
float b = z * vec.x - x * vec.z;
125+
float c = x * vec.y - y * vec.x;
126+
return float3(a, b, c);
139127
}
140128

141-
void normalize()
142-
{
143-
const float length = std::sqrt( ( coord[0] * coord[0] ) +
144-
( coord[1] * coord[1] ) +
145-
( coord[2] * coord[2] ) );
146-
if( length != 1 )
147-
{
129+
void normalize() {
130+
const float length = std::sqrt(
131+
(coord[0] * coord[0]) + (coord[1] * coord[1]) + (coord[2] * coord[2]));
132+
if (length != 1) {
148133
coord[0] = (coord[0] / length);
149134
coord[1] = (coord[1] / length);
150135
coord[2] = (coord[2] / length);
151136
}
152137
}
153138

154139
private:
155-
union
156-
{
140+
union {
157141
float coord[3];
158-
struct
159-
{
160-
float x,y,z;
142+
struct {
143+
float x, y, z;
161144
};
162145
};
163146
};
@@ -197,7 +180,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
197180
std::vector<material_t> &materials, // [output]
198181
std::string &err, // [output]
199182
const char *filename, const char *mtl_basepath = NULL,
200-
unsigned int flags = 1 );
183+
unsigned int flags = 1);
201184

202185
/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve
203186
/// std::istream for materials.
@@ -216,12 +199,12 @@ void LoadMtl(std::map<std::string, int> &material_map, // [output]
216199
}
217200

218201
#ifdef TINYOBJLOADER_IMPLEMENTATION
219-
#include <cstdlib>
220-
#include <cstring>
221202
#include <cassert>
203+
#include <cctype>
222204
#include <cmath>
223205
#include <cstddef>
224-
#include <cctype>
206+
#include <cstdlib>
207+
#include <cstring>
225208

226209
#include <fstream>
227210
#include <sstream>
@@ -267,43 +250,43 @@ struct obj_shape {
267250
std::vector<float> vt;
268251
};
269252

270-
//See http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf
271-
std::istream& safeGetline(std::istream& is, std::string& t)
272-
{
273-
t.clear();
274-
275-
// The characters in the stream are read one-by-one using a std::streambuf.
276-
// That is faster than reading them one-by-one using the std::istream.
277-
// Code that uses streambuf this way must be guarded by a sentry object.
278-
// The sentry object performs various tasks,
279-
// such as thread synchronization and updating the stream state.
280-
281-
std::istream::sentry se(is, true);
282-
std::streambuf* sb = is.rdbuf();
283-
284-
for(;;) {
285-
int c = sb->sbumpc();
286-
switch (c) {
287-
case '\n':
288-
return is;
289-
case '\r':
290-
if(sb->sgetc() == '\n')
291-
sb->sbumpc();
292-
return is;
293-
case EOF:
294-
// Also handle the case when the last line has no line ending
295-
if(t.empty())
296-
is.setstate(std::ios::eofbit);
297-
return is;
298-
default:
299-
t += (char)c;
300-
}
253+
// See
254+
// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf
255+
std::istream &safeGetline(std::istream &is, std::string &t) {
256+
t.clear();
257+
258+
// The characters in the stream are read one-by-one using a std::streambuf.
259+
// That is faster than reading them one-by-one using the std::istream.
260+
// Code that uses streambuf this way must be guarded by a sentry object.
261+
// The sentry object performs various tasks,
262+
// such as thread synchronization and updating the stream state.
263+
264+
std::istream::sentry se(is, true);
265+
std::streambuf *sb = is.rdbuf();
266+
267+
for (;;) {
268+
int c = sb->sbumpc();
269+
switch (c) {
270+
case '\n':
271+
return is;
272+
case '\r':
273+
if (sb->sgetc() == '\n')
274+
sb->sbumpc();
275+
return is;
276+
case EOF:
277+
// Also handle the case when the last line has no line ending
278+
if (t.empty())
279+
is.setstate(std::ios::eofbit);
280+
return is;
281+
default:
282+
t += (char)c;
301283
}
284+
}
302285
}
303286

304-
#define IS_SPACE( x ) ( ( (x) == ' ') || ( (x) == '\t') )
305-
#define IS_DIGIT( x ) ( (unsigned int)( (x) - '0' ) < (unsigned int)10 )
306-
#define IS_NEW_LINE( x ) ( ( (x) == '\r') || ( (x) == '\n') || ( (x) == '\0') )
287+
#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t'))
288+
#define IS_DIGIT(x) ((unsigned int)((x) - '0') < (unsigned int)10)
289+
#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0'))
307290

308291
// Make index zero-base, and also support relative index.
309292
static inline int fixIndex(int idx, int n) {
@@ -614,13 +597,13 @@ static bool exportFaceGroupToShape(
614597
const std::vector<float> &in_texcoords,
615598
const std::vector<std::vector<vertex_index> > &faceGroup,
616599
std::vector<tag_t> &tags, const int material_id, const std::string &name,
617-
bool clearCache, unsigned int flags, std::string& err ) {
600+
bool clearCache, unsigned int flags, std::string &err) {
618601
if (faceGroup.empty()) {
619602
return false;
620603
}
621604

622-
bool triangulate( ( flags & triangulation ) == triangulation );
623-
bool normals_calculation( ( flags & calculate_normals ) == calculate_normals );
605+
bool triangulate((flags & triangulation) == triangulation);
606+
bool normals_calculation((flags & calculate_normals) == calculate_normals);
624607

625608
// Flatten vertices and indices
626609
for (size_t i = 0; i < faceGroup.size(); i++) {
@@ -673,31 +656,41 @@ static bool exportFaceGroupToShape(
673656
}
674657

675658
if (normals_calculation && shape.mesh.normals.empty()) {
676-
const size_t nIndexs = shape.mesh.indices.size();
677-
if (nIndexs % 3 == 0) {
678-
shape.mesh.normals.resize(shape.mesh.positions.size());
679-
for (register size_t iIndices = 0; iIndices < nIndexs; iIndices += 3) {
680-
float3 v1, v2, v3;
681-
memcpy(&v1, &shape.mesh.positions[shape.mesh.indices[iIndices] * 3], sizeof(float3));
682-
memcpy(&v2, &shape.mesh.positions[shape.mesh.indices[iIndices + 1] * 3], sizeof(float3));
683-
memcpy(&v3, &shape.mesh.positions[shape.mesh.indices[iIndices + 2] * 3], sizeof(float3));
684-
685-
float3 v12(v1, v2);
686-
float3 v13(v1, v3);
687-
688-
float3 normal = v12.crossproduct(v13);
689-
normal.normalize();
690-
691-
memcpy(&shape.mesh.normals[shape.mesh.indices[iIndices] * 3], &normal, sizeof(float3));
692-
memcpy(&shape.mesh.normals[shape.mesh.indices[iIndices + 1] * 3], &normal, sizeof(float3));
693-
memcpy(&shape.mesh.normals[shape.mesh.indices[iIndices + 2] * 3], &normal, sizeof(float3));
694-
}
695-
} else {
696-
697-
std::stringstream ss;
698-
ss << "WARN: The shape " << name << " does not have a topology of triangles, therfore the normals calculation could not be performed. Select the tinyobj::triangulation flag for this object." << std::endl;
699-
err += ss.str();
700-
}
659+
const size_t nIndexs = shape.mesh.indices.size();
660+
if (nIndexs % 3 == 0) {
661+
shape.mesh.normals.resize(shape.mesh.positions.size());
662+
for (register size_t iIndices = 0; iIndices < nIndexs; iIndices += 3) {
663+
float3 v1, v2, v3;
664+
memcpy(&v1, &shape.mesh.positions[shape.mesh.indices[iIndices] * 3],
665+
sizeof(float3));
666+
memcpy(&v2, &shape.mesh.positions[shape.mesh.indices[iIndices + 1] * 3],
667+
sizeof(float3));
668+
memcpy(&v3, &shape.mesh.positions[shape.mesh.indices[iIndices + 2] * 3],
669+
sizeof(float3));
670+
671+
float3 v12(v1, v2);
672+
float3 v13(v1, v3);
673+
674+
float3 normal = v12.crossproduct(v13);
675+
normal.normalize();
676+
677+
memcpy(&shape.mesh.normals[shape.mesh.indices[iIndices] * 3], &normal,
678+
sizeof(float3));
679+
memcpy(&shape.mesh.normals[shape.mesh.indices[iIndices + 1] * 3],
680+
&normal, sizeof(float3));
681+
memcpy(&shape.mesh.normals[shape.mesh.indices[iIndices + 2] * 3],
682+
&normal, sizeof(float3));
683+
}
684+
} else {
685+
686+
std::stringstream ss;
687+
ss << "WARN: The shape " << name
688+
<< " does not have a topology of triangles, therfore the normals "
689+
"calculation could not be performed. Select the "
690+
"tinyobj::triangulation flag for this object."
691+
<< std::endl;
692+
err += ss.str();
693+
}
701694
}
702695

703696
shape.name = name;
@@ -720,6 +713,11 @@ void LoadMtl(std::map<std::string, int> &material_map,
720713
std::string linebuf;
721714
safeGetline(inStream, linebuf);
722715

716+
// Trim trailing whitespace
717+
if (linebuf.size() > 0) {
718+
linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1);
719+
}
720+
723721
// Trim newline '\r\n' or '\n'
724722
if (linebuf.size() > 0) {
725723
if (linebuf[linebuf.size() - 1] == '\n')
@@ -1110,7 +1108,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
11101108
if (newMaterialId != material) {
11111109
// Create per-face material
11121110
exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags,
1113-
material, name, true, flags, err );
1111+
material, name, true, flags, err);
11141112
faceGroup.clear();
11151113
material = newMaterialId;
11161114
}
@@ -1146,7 +1144,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
11461144
// flush previous face group.
11471145
bool ret =
11481146
exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags,
1149-
material, name, true, flags, err );
1147+
material, name, true, flags, err);
11501148
if (ret) {
11511149
shapes.push_back(shape);
11521150
}
@@ -1183,7 +1181,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
11831181
// flush previous face group.
11841182
bool ret =
11851183
exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags,
1186-
material, name, true, flags, err );
1184+
material, name, true, flags, err);
11871185
if (ret) {
11881186
shapes.push_back(shape);
11891187
}
@@ -1239,7 +1237,8 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
12391237
char stringValueBuffer[4096];
12401238

12411239
#ifdef _MSC_VER
1242-
sscanf_s(token, "%s", stringValueBuffer, (unsigned)_countof(stringValueBuffer));
1240+
sscanf_s(token, "%s", stringValueBuffer,
1241+
(unsigned)_countof(stringValueBuffer));
12431242
#else
12441243
sscanf(token, "%s", stringValueBuffer);
12451244
#endif
@@ -1254,7 +1253,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
12541253
}
12551254

12561255
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup,
1257-
tags, material, name, true, flags, err );
1256+
tags, material, name, true, flags, err);
12581257
if (ret) {
12591258
shapes.push_back(shape);
12601259
}

0 commit comments

Comments
 (0)