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
5050namespace 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 {
111110public:
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
154139private:
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.
309292static 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