@@ -35,14 +35,19 @@ static char *parse_face_vert(char *ptr, struct facevertex *fv, int numv, int num
3535static int cmp_facevert (const void * ap , const void * bp );
3636static void free_rbnode_key (struct rbnode * n , void * cls );
3737
38+ struct vertex {
39+ float x , y , z , w ;
40+ float r , g , b , a ;
41+ int rgba_valid ;
42+ };
3843
3944int mf_load_obj (struct mf_meshfile * mf , const struct mf_userio * io )
4045{
4146 char buf [128 ];
4247 int result = -1 ;
4348 int i , line_num = 0 ;
44- mf_vec3 * varr = 0 , * narr = 0 ;
45- mf_vec4 * carr = 0 ;
49+ struct vertex * varr = 0 ;
50+ mf_vec3 * narr = 0 ;
4651 mf_vec2 * tarr = 0 ;
4752 struct rbtree * rbtree = 0 ;
4853 struct mf_mesh * mesh = 0 ;
@@ -58,24 +63,23 @@ int mf_load_obj(struct mf_meshfile *mf, const struct mf_userio *io)
5863 }
5964
6065 if (!(rbtree = rb_create (cmp_facevert ))) {
61- fprintf (stderr , "mf_load : failed to create rbtree\n" );
66+ fprintf (stderr , "load_obj : failed to create rbtree\n" );
6267 goto end ;
6368 }
6469 rb_set_delete_func (rbtree , free_rbnode_key , 0 );
6570
6671 if (!(varr = mf_dynarr_alloc (0 , sizeof * varr )) ||
6772 !(narr = mf_dynarr_alloc (0 , sizeof * narr )) ||
68- !(tarr = mf_dynarr_alloc (0 , sizeof * tarr )) ||
69- !(carr = mf_dynarr_alloc (0 , sizeof * carr ))) {
70- fprintf (stderr , "mf_load: failed to allocate vertex attribute arrays\n" );
73+ !(tarr = mf_dynarr_alloc (0 , sizeof * tarr ))) {
74+ fprintf (stderr , "load_obj: failed to allocate vertex attribute arrays\n" );
7175 goto end ;
7276 }
7377
7478 if (!(mesh = mf_alloc_mesh ())) {
7579 goto end ;
7680 }
7781 if (!(mesh -> name = strdup (mf -> name ))) {
78- fprintf (stderr , "mf_load : failed to allocate mesh name\n" );
82+ fprintf (stderr , "load_obj : failed to allocate mesh name\n" );
7983 goto end ;
8084 }
8185
@@ -89,32 +93,30 @@ int mf_load_obj(struct mf_meshfile *mf, const struct mf_userio *io)
8993 case 'v' :
9094 if (isspace (line [1 ])) {
9195 /* vertex */
92- mf_vec3 v ;
93- mf_vec4 col ;
96+ struct vertex v ;
9497 int num ;
9598
9699 num = sscanf (line + 2 , "%f %f %f %f %f %f %f" , & v .x , & v .y , & v .z ,
97- & col . x , & col . y , & col . z , & col . w );
100+ & v . w , & v . g , & v . b , & v . a );
98101 if (num < 3 ) {
99102 fprintf (stderr , "%s:%d: invalid vertex definition: \"%s\"\n" , mf -> name , line_num , line );
100103 goto end ;
101104 }
105+ switch (num ) {
106+ case 6 :
107+ v .a = 1.0f ;
108+ case 7 :
109+ v .r = v .w ;
110+ v .rgba_valid = 1 ;
111+ break ;
112+ default :
113+ v .rgba_valid = 0 ;
114+ v .r = v .g = v .b = v .a = 1.0f ;
115+ }
102116 if (!(varr = mf_dynarr_push (varr , & v ))) {
103- fprintf (stderr , "mf_load : failed to resize vertex buffer\n" );
117+ fprintf (stderr , "load_obj : failed to resize vertex buffer\n" );
104118 goto end ;
105119 }
106- if (num > 3 ) {
107- /* vertex color "extension" */
108- switch (num ) {
109- case 4 : col .y = col .x ;
110- case 5 : col .z = col .x ;
111- case 6 : col .w = 1.0f ;
112- }
113- if (!(carr = mf_dynarr_push (carr , & col ))) {
114- fprintf (stderr , "mf_load: failed to resize buffer\n" );
115- goto end ;
116- }
117- }
118120
119121 } else if (line [1 ] == 't' && isspace (line [2 ])) {
120122 /* texcoord */
@@ -125,7 +127,7 @@ int mf_load_obj(struct mf_meshfile *mf, const struct mf_userio *io)
125127 }
126128 tc .y = 1.0f - tc .y ;
127129 if (!(tarr = mf_dynarr_push (tarr , & tc ))) {
128- fprintf (stderr , "mf_load : failed to resize texcoord buffer\n" );
130+ fprintf (stderr , "load_obj : failed to resize texcoord buffer\n" );
129131 goto end ;
130132 }
131133
@@ -137,7 +139,7 @@ int mf_load_obj(struct mf_meshfile *mf, const struct mf_userio *io)
137139 goto end ;
138140 }
139141 if (!(narr = mf_dynarr_push (narr , & norm ))) {
140- fprintf (stderr , "mf_load : failed to resize normal buffer\n" );
142+ fprintf (stderr , "load_obj : failed to resize normal buffer\n" );
141143 goto end ;
142144 }
143145 }
@@ -175,29 +177,29 @@ int mf_load_obj(struct mf_meshfile *mf, const struct mf_userio *io)
175177 } else {
176178 unsigned int newidx = mesh -> num_verts ;
177179 struct facevertex * newfv ;
178- mf_vec3 * vptr = varr + fv .vidx ;
180+ struct vertex * vptr = varr + fv .vidx ;
179181
180182 if (mf_add_vertex (mesh , vptr -> x , vptr -> y , vptr -> z ) == -1 ) {
181- fprintf (stderr , "mf_load : failed to resize vertex array\n" );
183+ fprintf (stderr , "load_obj : failed to resize vertex array\n" );
182184 goto end ;
183185 }
184- if (! mf_dynarr_empty ( carr ) ) {
186+ if (vptr -> rgba_valid ) {
185187 /* vertex color extension */
186- if (mf_add_color (mesh , carr [fv .vidx ].x , carr [fv .vidx ].y ,
187- carr [fv .vidx ].z , carr [fv .vidx ].w ) == -1 ) {
188- fprintf (stderr , "mf_load : failed to resize color array\n" );
188+ if (mf_add_color (mesh , varr [fv .vidx ].r , varr [fv .vidx ].g ,
189+ varr [fv .vidx ].b , varr [fv .vidx ].a ) == -1 ) {
190+ fprintf (stderr , "load_obj : failed to resize color array\n" );
189191 goto end ;
190192 }
191193 }
192194 if (fv .nidx >= 0 ) {
193195 if (mf_add_normal (mesh , narr [fv .nidx ].x , narr [fv .nidx ].y , narr [fv .nidx ].z ) == -1 ) {
194- fprintf (stderr , "mf_load : failed to resize normal array\n" );
196+ fprintf (stderr , "load_obj : failed to resize normal array\n" );
195197 goto end ;
196198 }
197199 }
198200 if (fv .tidx >= 0 ) {
199201 if (mf_add_texcoord (mesh , tarr [fv .tidx ].x , tarr [fv .tidx ].y ) == -1 ) {
200- fprintf (stderr , "mf_load : failed to resize texcoord array\n" );
202+ fprintf (stderr , "load_obj : failed to resize texcoord array\n" );
201203 goto end ;
202204 }
203205 }
@@ -207,7 +209,7 @@ int mf_load_obj(struct mf_meshfile *mf, const struct mf_userio *io)
207209 * newfv = fv ;
208210 }
209211 if (!newfv || rb_insert (rbtree , newfv , (void * )(uintptr_t )newidx ) == -1 ) {
210- fprintf (stderr , "mf_load : failed to insert facevertex to the binary search tree\n" );
212+ fprintf (stderr , "load_obj : failed to insert facevertex to the binary search tree\n" );
211213 goto end ;
212214 }
213215 }
@@ -219,7 +221,7 @@ int mf_load_obj(struct mf_meshfile *mf, const struct mf_userio *io)
219221 res = mf_add_triangle (mesh , vidx [0 ], vidx [1 ], vidx [2 ]);
220222 }
221223 if (res == -1 ) {
222- fprintf (stderr , "mf_load : failed to resize index array\n" );
224+ fprintf (stderr , "load_obj : failed to resize index array\n" );
223225 goto end ;
224226 }
225227 }
@@ -228,12 +230,12 @@ int mf_load_obj(struct mf_meshfile *mf, const struct mf_userio *io)
228230 case 'o' :
229231 case 'g' :
230232 if (mesh_done (mf , mesh ) != -1 && !(mesh = mf_alloc_mesh ())) {
231- fprintf (stderr , "mf_load : failed to allocate mesh\n" );
233+ fprintf (stderr , "load_obj : failed to allocate mesh\n" );
232234 goto end ;
233235 }
234236 mesh -> name = clean_line (line + 1 );
235237 if (!(mesh -> name = strdup (mesh -> name ? mesh -> name : "unnamed mesh" ))) {
236- fprintf (stderr , "mf_load : failed to allocate mesh name\n" );
238+ fprintf (stderr , "load_obj : failed to allocate mesh name\n" );
237239 goto end ;
238240 }
239241 break ;
@@ -242,7 +244,7 @@ int mf_load_obj(struct mf_meshfile *mf, const struct mf_userio *io)
242244 if (memcmp (line , "mtllib" , 6 ) == 0 ) {
243245 const char * mtlfile = clean_line (line + 6 );
244246 if (!mtlfile ) {
245- fprintf (stderr , "mf_load : ignoring invalid mtllib\n" );
247+ fprintf (stderr , "load_obj : ignoring invalid mtllib\n" );
246248 continue ;
247249 }
248250 mtlfile = mf_find_asset (mf , mtlfile );
@@ -251,7 +253,7 @@ int mf_load_obj(struct mf_meshfile *mf, const struct mf_userio *io)
251253 load_mtl (mf , & subio );
252254 io -> close (subio .file );
253255 } else {
254- fprintf (stderr , "mf_load : failed to open material library: %s, ignoring\n" , mtlfile );
256+ fprintf (stderr , "load_obj : failed to open material library: %s, ignoring\n" , mtlfile );
255257 }
256258
257259 } else if (memcmp (line , "usemtl" , 6 ) == 0 ) {
@@ -273,7 +275,6 @@ int mf_load_obj(struct mf_meshfile *mf, const struct mf_userio *io)
273275 mf_dynarr_free (varr );
274276 mf_dynarr_free (narr );
275277 mf_dynarr_free (tarr );
276- mf_dynarr_free (carr );
277278 mf_free_mesh (mesh );
278279 rb_free (rbtree );
279280 return result ;
@@ -287,22 +288,33 @@ static int mesh_done(struct mf_meshfile *mf, struct mf_mesh *mesh)
287288 return -1 ;
288289 }
289290
291+ if (mesh -> color && mf_dynarr_size (mesh -> color ) != mf_dynarr_size (mesh -> vertex )) {
292+ /* we can end up with short color arrays in a mesh if some of its
293+ * vertices didn't have valid vertex colors. We don't support that, so
294+ * we'll just discard the color array altogether.
295+ */
296+ mf_dynarr_free (mesh -> color );
297+ mesh -> color = 0 ;
298+ fprintf (stderr , "load_obj: ignoring partial vertex colors in mesh %s\n" ,
299+ mesh -> name );
300+ }
301+
290302 if (mesh -> normal ) {
291303 if (mf_dynarr_size (mesh -> normal ) != mf_dynarr_size (mesh -> vertex )) {
292- fprintf (stderr , "mf_load : ignoring mesh with inconsistent attributes\n" );
304+ fprintf (stderr , "load_obj : ignoring mesh with inconsistent attributes\n" );
293305 goto reset_mesh ;
294306 }
295307 }
296308 if (mesh -> texcoord ) {
297309 if (mf_dynarr_size (mesh -> texcoord ) != mf_dynarr_size (mesh -> vertex )) {
298- fprintf (stderr , "mf_load : ignoring mesh with inconsistent attributes\n" );
310+ fprintf (stderr , "load_obj : ignoring mesh with inconsistent attributes\n" );
299311 goto reset_mesh ;
300312 }
301313 }
302314
303315 /* also allocate a node for it */
304316 if (!(node = mf_alloc_node ())) {
305- fprintf (stderr , "mf_load : failed to allocate mesh node\n" );
317+ fprintf (stderr , "load_obj : failed to allocate mesh node\n" );
306318 goto reset_mesh ;
307319 }
308320 if (!(node -> name = strdup (mesh -> name ))) {
@@ -311,12 +323,12 @@ static int mesh_done(struct mf_meshfile *mf, struct mf_mesh *mesh)
311323 }
312324
313325 if (mf_node_add_mesh (node , mesh ) == -1 ) {
314- fprintf (stderr , "mf_load : failed to add mesh to node\n" );
326+ fprintf (stderr , "load_obj : failed to add mesh to node\n" );
315327 goto reset_mesh ;
316328 }
317329
318330 if (mf_add_mesh (mf , mesh ) == -1 ) {
319- fprintf (stderr , "mf_load : failed to add mesh\n" );
331+ fprintf (stderr , "load_obj : failed to add mesh\n" );
320332 goto reset_mesh ;
321333 }
322334 mf_add_node (mf , node );
0 commit comments