@@ -421,6 +421,8 @@ struct attrib_t {
421421struct callback_t {
422422 // W is optional and set to 1 if there is no `w` item in `v` line
423423 void (*vertex_cb)(void *user_data, real_t x, real_t y, real_t z, real_t w);
424+ void (*vertex_color_cb)(void *user_data, real_t x, real_t y, real_t z,
425+ real_t r, real_t g, real_t b, bool has_color);
424426 void (*normal_cb)(void *user_data, real_t x, real_t y, real_t z);
425427
426428 // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in
@@ -796,8 +798,21 @@ static std::istream &safeGetline(std::istream &is, std::string &t) {
796798 (static_cast <unsigned int >((x) - ' 0' ) < static_cast <unsigned int >(10 ))
797799#define IS_NEW_LINE (x ) (((x) == ' \r ' ) || ((x) == ' \n ' ) || ((x) == ' \0 ' ))
798800
801+ template <typename T>
802+ static inline std::string toString (const T &t) {
803+ std::stringstream ss;
804+ ss << t;
805+ return ss.str ();
806+ }
807+
808+ struct warning_context
809+ {
810+ std::string *warn;
811+ size_t line_number;
812+ };
813+
799814// Make index zero-base, and also support relative index.
800- static inline bool fixIndex (int idx, int n, int *ret) {
815+ static inline bool fixIndex (int idx, int n, int *ret, bool allow_zero, const warning_context &context ) {
801816 if (!ret) {
802817 return false ;
803818 }
@@ -809,7 +824,13 @@ static inline bool fixIndex(int idx, int n, int *ret) {
809824
810825 if (idx == 0 ) {
811826 // zero is not allowed according to the spec.
812- return false ;
827+ if (context.warn ) {
828+ (*context.warn ) += " A zero value index found (will have a value of -1 for normal and tex indices. Line "
829+ + toString (context.line_number ) + " ).\n " ;
830+ }
831+
832+ (*ret) = idx - 1 ;
833+ return allow_zero;
813834 }
814835
815836 if (idx < 0 ) {
@@ -1134,14 +1155,14 @@ static tag_sizes parseTagTriple(const char **token) {
11341155
11351156// Parse triples with index offsets: i, i/j/k, i//k, i/j
11361157static bool parseTriple (const char **token, int vsize, int vnsize, int vtsize,
1137- vertex_index_t *ret) {
1158+ vertex_index_t *ret, const warning_context &context ) {
11381159 if (!ret) {
11391160 return false ;
11401161 }
11411162
11421163 vertex_index_t vi (-1 );
11431164
1144- if (!fixIndex (atoi ((*token)), vsize, &( vi.v_idx ) )) {
1165+ if (!fixIndex (atoi ((*token)), vsize, &vi.v_idx , false , context )) {
11451166 return false ;
11461167 }
11471168
@@ -1155,7 +1176,7 @@ static bool parseTriple(const char **token, int vsize, int vnsize, int vtsize,
11551176 // i//k
11561177 if ((*token)[0 ] == ' /' ) {
11571178 (*token)++;
1158- if (!fixIndex (atoi ((*token)), vnsize, &( vi.vn_idx ) )) {
1179+ if (!fixIndex (atoi ((*token)), vnsize, &vi.vn_idx , true , context )) {
11591180 return false ;
11601181 }
11611182 (*token) += strcspn ((*token), " / \t\r " );
@@ -1164,7 +1185,7 @@ static bool parseTriple(const char **token, int vsize, int vnsize, int vtsize,
11641185 }
11651186
11661187 // i/j/k or i/j
1167- if (!fixIndex (atoi ((*token)), vtsize, &( vi.vt_idx ) )) {
1188+ if (!fixIndex (atoi ((*token)), vtsize, &vi.vt_idx , true , context )) {
11681189 return false ;
11691190 }
11701191
@@ -1176,7 +1197,7 @@ static bool parseTriple(const char **token, int vsize, int vnsize, int vtsize,
11761197
11771198 // i/j/k
11781199 (*token)++; // skip '/'
1179- if (!fixIndex (atoi ((*token)), vnsize, &( vi.vn_idx ) )) {
1200+ if (!fixIndex (atoi ((*token)), vnsize, &vi.vn_idx , true , context )) {
11801201 return false ;
11811202 }
11821203 (*token) += strcspn ((*token), " / \t\r " );
@@ -1419,7 +1440,7 @@ inline real_t GetLength(TinyObjPoint &e) {
14191440}
14201441
14211442inline TinyObjPoint Normalize (TinyObjPoint e) {
1422- real_t inv_length = 1.0 / GetLength (e);
1443+ real_t inv_length = real_t ( 1 ) / GetLength (e);
14231444 return TinyObjPoint (e.x * inv_length, e.y * inv_length, e.z * inv_length );
14241445}
14251446
@@ -2678,6 +2699,10 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
26782699 vw.push_back (sw);
26792700 }
26802701
2702+ warning_context context;
2703+ context.warn = warn;
2704+ context.line_number = line_num;
2705+
26812706 // line
26822707 if (token[0 ] == ' l' && IS_SPACE ((token[1 ]))) {
26832708 token += 2 ;
@@ -2688,13 +2713,10 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
26882713 vertex_index_t vi;
26892714 if (!parseTriple (&token, static_cast <int >(v.size () / 3 ),
26902715 static_cast <int >(vn.size () / 3 ),
2691- static_cast <int >(vt.size () / 2 ), &vi)) {
2716+ static_cast <int >(vt.size () / 2 ), &vi, context )) {
26922717 if (err) {
2693- std::stringstream ss;
2694- ss << " Failed parse `l' line(e.g. zero value for vertex index. "
2695- " line "
2696- << line_num << " .)\n " ;
2697- (*err) += ss.str ();
2718+ (*err) += " Failed to parse `l' line (e.g. a zero value for vertex index. Line " +
2719+ toString (line_num) + " ).\n " ;
26982720 }
26992721 return false ;
27002722 }
@@ -2720,13 +2742,10 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
27202742 vertex_index_t vi;
27212743 if (!parseTriple (&token, static_cast <int >(v.size () / 3 ),
27222744 static_cast <int >(vn.size () / 3 ),
2723- static_cast <int >(vt.size () / 2 ), &vi)) {
2745+ static_cast <int >(vt.size () / 2 ), &vi, context )) {
27242746 if (err) {
2725- std::stringstream ss;
2726- ss << " Failed parse `p' line(e.g. zero value for vertex index. "
2727- " line "
2728- << line_num << " .)\n " ;
2729- (*err) += ss.str ();
2747+ (*err) += " Failed to parse `p' line (e.g. a zero value for vertex index. Line " +
2748+ toString (line_num) + " ).\n " ;
27302749 }
27312750 return false ;
27322751 }
@@ -2756,12 +2775,10 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
27562775 vertex_index_t vi;
27572776 if (!parseTriple (&token, static_cast <int >(v.size () / 3 ),
27582777 static_cast <int >(vn.size () / 3 ),
2759- static_cast <int >(vt.size () / 2 ), &vi)) {
2778+ static_cast <int >(vt.size () / 2 ), &vi, context )) {
27602779 if (err) {
2761- std::stringstream ss;
2762- ss << " Failed parse `f' line(e.g. zero value for face index. line "
2763- << line_num << " .)\n " ;
2764- (*err) += ss.str ();
2780+ (*err) += " Failed to parse `f' line (e.g. a zero value for vertex index. Line " +
2781+ toString (line_num) + " ).\n " ;
27652782 }
27662783 return false ;
27672784 }
@@ -3138,11 +3155,15 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
31383155 // vertex
31393156 if (token[0 ] == ' v' && IS_SPACE ((token[1 ]))) {
31403157 token += 2 ;
3141- // TODO(syoyo): Support parsing vertex color extension.
3142- real_t x, y, z, w; // w is optional. default = 1.0
3143- parseV (&x, &y, &z, &w, &token);
3158+ real_t x, y, z;
3159+ real_t r, g, b;
3160+
3161+ bool found_color = parseVertexWithColor (&x, &y, &z, &r, &g, &b, &token);
31443162 if (callback.vertex_cb ) {
3145- callback.vertex_cb (user_data, x, y, z, w);
3163+ callback.vertex_cb (user_data, x, y, z, r); // r=w is optional
3164+ }
3165+ if (callback.vertex_color_cb ) {
3166+ callback.vertex_color_cb (user_data, x, y, z, r, g, b, found_color);
31463167 }
31473168 continue ;
31483169 }
0 commit comments