1 /*
2 * File: fmt_ac3d.c
3 *
4 * Description: handles loading and saving of model data in AC3D format
5 *
6 * This source code is part of kludge3d, and is released under the
7 * GNU General Public License.
8 *
9 *
10 */
11
12 /*
13 * Portions of this file were ripped from:
14 * - ac3d.c from the "orbit" space combat game.
15 * "orbit" took the code from the ac_to_gl program.
16 *
17 */
18
19
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <math.h>
25
26 #include "transform.h"
27 #include "globals.h"
28 #include "mesh.h"
29 #include "model.h"
30 #include "group.h"
31 #include "polygon.h"
32 #include "vertex.h"
33 #include "texture.h"
34 #include "bottombar.h"
35 #include "vector.h"
36
37 #include "model_load_save.h"
38
39 #ifdef MEMWATCH
40 #include "memwatch.h"
41 #endif
42
43
44 /* This number is the latest version of the ac3d file format that this module
45 can load/save. */
46 #define AC3D_FORMAT_VERSION 0xb
47
48
49 gint ac3d_load_doc(struct fu_file *file, Model *doc);
50 gint ac3d_save_doc(struct fu_file *file, Model *doc);
51 void ac3d_destroy_priv_data(Model *doc);
52
53 struct doc_file_fmt fmt_ac3d = {
54 "AC3D Format (ac)",
55 "ac",
56 ac3d_load_doc,
57 ac3d_save_doc,
58 NULL /* <-- replace with NULL if not used */
59 };
60
61 /* FILE-SCOPE VARS ******************************************************/
62
63 Model *ac3dModel = NULL;
64
65
66 /* STRUCTS **************************************************************/
67
68 struct Tag {
69 char *token;
70 int ( *func ) ( char *s, GNode * node );
71 };
72
73
74 /* PROTOTYPES ***********************************************************/
75
76 void ac3d_write_materials( struct fu_file *file, Model *model );
77 void ac3d_write_mesh( Mesh *m, FILE *fp ) ;
78 void ac3d_write_child( GNode *n, FILE *fp );
79
80 GNode * ac3d_load ( FILE *fp );
81
82 int Search ( struct Tag *tags, char *s, GNode * );
83 int DoMaterial ( char *s, GNode * );
84 int DoObject ( char *s, GNode * );
85 int DoACName ( char *s, GNode * );
86 int DoData ( char *s, GNode * );
87 int DoTexture ( char *s, GNode * );
88 int DoTexrep ( char *s, GNode * );
89 int DoTexoff ( char *s, GNode * );
90 int DoRot ( char *s, GNode * );
91 int DoLoc ( char *s, GNode * );
92 int DoUrl ( char *s, GNode * );
93 int DoNumvert ( char *s, GNode * );
94 int DoNumsurf ( char *s, GNode * );
95 int DoSurf ( char *s, GNode * );
96 int DoMat ( char *s, GNode * );
97 int DoRefs ( char *s, GNode * );
98 int DoKids ( char *s, GNode * );
99
100 int DoObjWorld ( char *s, GNode * );
101 int DoObjPoly ( char *s, GNode * );
102 int DoObjGroup ( char *s, GNode * );
103
104 void SkipSpaces ( char **s );
105 void SkipQuotes ( char **s );
106 void RemoveQuotes ( char *s );
107
108
109 /* FUNCS ****************************************************************/
110
111
112 /* Load the document from fu_file and set the root member of doc */
ac3d_load_doc(struct fu_file * file,Model * model)113 gint ac3d_load_doc(struct fu_file *file, Model *model)
114 {
115
116 if( model == NULL ) return FALSE;
117
118 /* Note - model_new has already created an empty mesh and groupnode.
119 We don't need either, so we'll delete them here. */
120 if( model->root )
121 group_delete( model->root );
122
123 ac3dModel = model;
124
125 model->root = ac3d_load( file->fp );
126
127 if( model->root == NULL )
128 return FALSE;
129
130 return TRUE;
131 }
132
133
134 /* Save the document to fu_file */
ac3d_save_doc(struct fu_file * file,Model * model)135 gint ac3d_save_doc(struct fu_file *file, Model *model)
136 {
137 GNode *n;
138
139 if( model == NULL ) return FALSE;
140
141 n = model->root;
142
143 fu_truncate(file, 0); /* it's a good idea to truncate first */
144 /* unless you have a more complex format */
145
146 /* header */
147 fu_printf( file, "AC3D%x\n", AC3D_FORMAT_VERSION );
148 ac3d_write_materials( file, model );
149
150 /* world object (root node) */
151 fu_printf( file, "OBJECT world\n" );
152 fu_printf( file, "kids %i\n", g_node_n_children( n ) );
153
154 ac3d_write_child( n->children, file->fp );
155
156 return TRUE;
157 }
158
159
160 /* Destroy the contents of model->fmt_data */
ac3d_destroy_priv_data(Model * model)161 void ac3d_destroy_priv_data(Model *model)
162 {
163 /* nothing to do */
164 }
165
166
167
168
169 /***************************************************************************
170 *
171 * OUTPUT FUNCS
172 *
173 ***************************************************************************/
174
ac3d_write_materials(struct fu_file * file,Model * model)175 void ac3d_write_materials( struct fu_file *file, Model *model ) {
176 fu_printf( file, "MATERIAL \"\" rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0\n" );
177 }
178
179
ac3d_write_mesh(Mesh * m,FILE * fp)180 void ac3d_write_mesh( Mesh *m, FILE *fp ) {
181
182 GSList * c;
183 Poly *p;
184 Vertex *v;
185 int num_vertices, num_polygons;
186
187
188 num_vertices = g_slist_length( m->vertices );
189 num_polygons = g_slist_length( m->polygons );
190
191 fprintf( fp, "OBJECT poly\n" );
192
193 if( m->name != NULL )
194 fprintf( fp, "name \"%s\"\n", m->name );
195
196 if( m->texture != NULL ) {
197 fprintf( fp, "texture \"%s\"\n", m->texture->filename );
198 fprintf( fp, "texrep %f %f\n", m->texrep_x, m->texrep_y );
199 }
200
201 #if 0
202 if( m->location != NULL ) {
203 v = m->location;
204 #ifdef NO_SWAP_YZ
205 fprintf( fp, "loc %f %f %f\n", v->v[0], v->v[1], v->v[2] );
206 #else
207 fprintf( fp, "loc %f %f %f\n", v->v[0], v->v[2], -1.0 * v->v[1] );
208 #endif
209 }
210 #endif
211
212 fprintf( fp, "numvert %i\n", num_vertices );
213
214 for ( c = m->vertices; c != NULL; c = c->next ) {
215 v = ( Vertex * ) c->data;
216 #ifdef NO_SWAP_YZ
217 fprintf( fp, "%f %f %f\n", v->v[ 0 ], v->v[ 1 ], v->v[ 2 ] );
218 #else
219 fprintf( fp, "%f %f %f\n", v->v[ 0 ], v->v[ 2 ], -1.0 * v->v[ 1 ] );
220 #endif
221 }
222
223 fprintf( fp, "numsurf %i\n", num_polygons );
224
225 for ( c = m->polygons; c != NULL; c = c->next ) {
226 int i;
227 p = ( Poly * ) c->data;
228
229 fprintf( fp, "SURF 0x0\n" );
230 fprintf( fp, "mat 0\n" );
231 fprintf( fp, "refs %i\n", p->num_verts );
232
233
234 for ( i = 0; i < p->num_verts; i++ ) {
235
236 fprintf( fp, "%d %f %f\n",
237 g_slist_index( m->vertices, p->verts[ i ] ),
238 p->tc[ i ]->x,
239 p->tc[ i ]->y );
240 }
241
242 }
243 }
244
245
ac3d_write_child(GNode * n,FILE * fp)246 void ac3d_write_child( GNode *n, FILE *fp ) {
247
248 for( ; n != NULL; n = n->next ) {
249 int kids = g_node_n_children( n );
250 ac3d_write_mesh( (Mesh*)(n->data), fp );
251 fprintf( fp, "kids %i\n", kids );
252 if( kids > 0 )
253 ac3d_write_child( n->children, fp );
254 }
255
256 }
257
258
259
260 /***************************************************************************
261 *
262 * INPUT FUNCS
263 *
264 ***************************************************************************/
265
266
267 int acsmooth; /* Smooth surface? */
268 int acsurfpass; /* Pass through surface */
269 #define PASS_NORMAL (0) /* Get normals */
270 #define PASS_RENDER (1) /* Render */
271
272
273 int num_materials = 0;
274 int num_textures = 0;
275 int ntex = 0;
276
277 int last_flags = -1;
278 int last_mat;
279 int last_num_kids = -1;
280 int current_flags = -1;
281 int texture_enabled = 0;
282 int need_texture = 0;
283
284 #define PARSE_CONT 0
285 #define PARSE_POP 1
286 /*FIXME - should have a PARSE_ERROR so that we can gracefully back out
287 of all these funcs */
288
289 FILE *acfp;
290
291 struct Tag top_tags [] = {
292 {"MATERIAL", DoMaterial },
293 {"OBJECT" , DoObject },
294 {NULL, NULL }
295 };
296
297
298
ac3d_load(FILE * fp)299 GNode * ac3d_load ( FILE *fp ) {
300
301 char buffer[ 1024 ], *s;
302 int firsttime;
303 GNode *n;
304
305 printf( "LoadAC3D: Loading model \n" );
306
307 n = group_new( ac3dModel );
308
309 acfp = fp;
310 if ( acfp == NULL ) {
311 printf( "LoadAC3D: Can't open , giving up!\n" );
312 return ( NULL );
313 }
314
315 firsttime = 1;
316
317 num_materials = 0;
318 num_textures = 0;
319 last_flags = -1 ;
320 last_num_kids = -1 ;
321 current_flags = -1 ;
322 texture_enabled = 0;
323 need_texture = 0;
324 last_mat = -1;
325
326 while ( fgets ( buffer, 1024, acfp ) != NULL ) {
327
328 s = buffer ;
329
330 /* Skip leading whitespace */
331 SkipSpaces ( &s );
332
333 /* Skip blank lines and comments */
334 if ( *s < ' ' && *s != '\t' ) continue;
335 if ( *s == '#' || *s == ';' ) continue;
336
337 if ( firsttime ) {
338 int version;
339 firsttime = 0;
340
341 if ( strncmp ( s, "AC3D", 4 ) != 0 ) {
342 printf( "LoadAC3d: is not an AC3D format file\n" );
343 return ( NULL );
344 }
345 sscanf( s, "AC3D%x", &version );
346 #ifdef VERBOSE
347 printf( "LoadAC3d: file is in format version %x\n", version );
348 #endif
349 if( version > AC3D_FORMAT_VERSION ) {
350 printf( "LoadAC3d: file is in AC3D file format version %i, and "
351 "this program can\nonly read files up to version %i\n",
352 version, AC3D_FORMAT_VERSION );
353 return ( NULL );
354 }
355 } else {
356 Search( top_tags, s, n );
357 }
358 }
359
360 return n;
361 }
362
363
SkipSpaces(char ** s)364 void SkipSpaces ( char **s ) {
365 while ( **s == ' ' || **s == '\t' ) ( *s ) ++;
366 }
367
SkipQuotes(char ** s)368 void SkipQuotes ( char **s ) {
369 char * t;
370
371 SkipSpaces ( s );
372
373 if ( **s == '\"' ) {
374 ( *s ) ++;
375 t = *s;
376 while ( *t != '\0' && *t != '\"' ) t++;
377
378 if ( *t != '\"' )
379 printf( "SkipQuotes: Mismatched double-quote in '%s'\n", *s );
380
381 *t = '\0';
382 } else {
383 printf( "SkipQuotes: Expected double-quote in '%s'\n", *s );
384 }
385 }
386
RemoveQuotes(char * s)387 void RemoveQuotes ( char *s ) {
388 /*
389 * Remove quotes from string
390 */
391
392 char * t;
393 int i, j, len;
394
395 len = strlen ( s );
396 t = ( char * ) malloc ( len + 1 );
397 strcpy ( t, s );
398 j = 0;
399
400 for ( i = 0; i < len; i++ ) {
401 if ( t[ i ] != '"' ) {
402 s[ j++ ] = t[ i ];
403 }
404 }
405 s[ j ] = 0;
406
407 free ( t );
408 }
409
Search(struct Tag * tags,char * s,GNode * node)410 int Search ( struct Tag *tags, char *s, GNode *node ) {
411 int i;
412
413 SkipSpaces ( &s );
414
415 /*printf( "Search has been handed: %s", s ); */
416
417 for ( i = 0; tags[ i ].token != NULL; i++ ) {
418 if ( !strncasecmp ( tags[ i ].token, s, strlen ( tags[ i ].token ) ) ) {
419 s += strlen ( tags[ i ].token );
420 SkipSpaces ( &s );
421 return ( *( tags[ i ].func ) ) ( s, node );
422 }
423 }
424
425 printf( "Search: Unrecognised token '%s'\n", s );
426
427 return PARSE_POP;
428 }
429
430
431 /*****************************************
432 *
433 * OBJECT-LEVEL FUNCTIONS AND STRUCTS
434 *
435 *****************************************/
436
437
438 struct Tag object_tags[] = {
439 {"name" , DoACName },
440 {"data" , DoData},
441 {"texture", DoTexture},
442 {"texrep" , DoTexrep},
443 {"texoff" , DoTexoff},
444 {"rot" , DoRot},
445 {"loc" , DoLoc},
446 {"url" , DoUrl},
447 {"numvert", DoNumvert},
448 {"numsurf", DoNumsurf},
449 {"kids" , DoKids},
450 {NULL, NULL }
451 };
452
453 struct Tag surf_tag[] = {
454 {"SURF", DoSurf },
455 {NULL, NULL}
456 };
457
458 struct Tag surface_tags[] = {
459 {"mat" , DoMat },
460 {"refs", DoRefs},
461 {NULL, NULL}
462 };
463
464 struct Tag obj_type_tags[] = {
465 {"world", DoObjWorld },
466 {"poly" , DoObjPoly },
467 {"group", DoObjGroup},
468 {NULL, NULL}
469 };
470
471 #define OBJ_WORLD 0
472 #define OBJ_POLY 1
473 #define OBJ_GROUP 2
474
DoObjWorld(char * s,GNode * node)475 int DoObjWorld ( char *s, GNode * node ) {
476 return OBJ_WORLD;
477 }
478
DoObjPoly(char * s,GNode * node)479 int DoObjPoly ( char *s, GNode * node ) {
480 return OBJ_POLY;
481 }
482
DoObjGroup(char * s,GNode * node)483 int DoObjGroup ( char *s, GNode * node ) {
484 return OBJ_GROUP;
485 }
486
DoMaterial(char * s,GNode * node)487 int DoMaterial ( char *s, GNode * node ) {
488 char name[ 1024 ], *nm;
489 float rgb[ 3 ], amb[ 3 ], emis[ 3 ], spec[ 3 ], trans;
490 int shi;
491
492 if ( 15 != sscanf ( s,
493 "%s rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f",
494 name, &rgb[ 0 ], &rgb[ 1 ], &rgb[ 2 ], &amb[ 0 ], &amb[ 1 ], &amb[ 2 ],
495 &emis[ 0 ], &emis[ 1 ], &emis[ 2 ], &spec[ 0 ], &spec[ 1 ], &spec[ 2 ], &shi, &trans ) ) {
496 printf( "DoMaterial: Can't parse this MATERIAL: %s\n", s );
497 } else {
498 nm = name;
499 SkipQuotes ( &nm );
500
501 #if 0
502 /* Get a list for this material */
503 matlist[ num_materials ] = glGenLists ( 1 );
504
505 glNewList ( matlist[ num_materials ], GL_COMPILE );
506 glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, amb );
507 glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, rgb );
508 glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, spec );
509 glMaterialfv ( GL_FRONT_AND_BACK, GL_EMISSION, emis );
510 glMaterialf ( GL_FRONT_AND_BACK, GL_SHININESS, shi );
511 glEndList();
512 #endif
513 }
514 /* num_materials++; */
515
516 return PARSE_CONT;
517 }
518
DoObject(char * s,GNode * node)519 int DoObject ( char *s, GNode * node ) {
520 int i, obj_type, num_kids;
521 char buffer[ 1024 ];
522
523
524 obj_type = Search ( obj_type_tags, s, node );
525
526 switch ( obj_type ) {
527 case OBJ_WORLD:
528 if( node->data != NULL ) {
529 mesh_set_name( (Mesh*)node->data, TOP_GROUP_NAME );
530 }
531 break;
532
533 case OBJ_POLY:
534 if( node->data != NULL ) {
535 if( ((Mesh*)node->data)->name == NULL )
536 mesh_set_name( (Mesh*)node->data, "Poly with no name" );
537 }
538 break;
539
540 case OBJ_GROUP:
541 if( node->data != NULL ) {
542 mesh_set_name( (Mesh*)node->data, "Group" );
543 }
544 break;
545 }
546
547 need_texture = 0;
548
549 /* for each line of input that pertains to this object... */
550 while ( NULL != fgets ( buffer, 1024, acfp ) ) {
551 if ( Search ( object_tags, buffer, node ) == PARSE_POP ) break;
552 }
553
554 num_kids = last_num_kids;
555
556 /* now do each of the object's children */
557 for ( i = 0; i < num_kids; i++ ) {
558 g_node_append_data( node, mesh_new( ac3dModel ) );
559
560 fgets ( buffer, 1024, acfp );
561 Search ( top_tags, buffer, g_node_last_child( node ) );
562 }
563
564 return PARSE_CONT;
565 }
566
DoACName(char * s,GNode * node)567 int DoACName ( char *s, GNode * node ) {
568
569 SkipQuotes ( &s );
570 /*printf( "DoACName: obj name %s\n", s ); */
571
572 mesh_set_name( (Mesh*)node->data, s );
573
574 return PARSE_CONT;
575 }
576
DoData(char * s,GNode * node)577 int DoData ( char *s, GNode * node ) {
578 int i, len;
579
580 len = strtol ( s, NULL, 0 );
581 printf( "DoData: WARNING - data string encountered\n" );
582
583 /* len plus one for the newline character at the end of the next line */
584 for ( i = 0; i < len +1; i++ )
585 fgetc ( acfp );
586
587 return PARSE_CONT;
588 }
589
590
DoTexture(char * s,GNode * node)591 int DoTexture ( char *s, GNode * node ) {
592
593 Texture *t = NULL;
594
595 SkipQuotes ( &s );
596
597 t = model_get_texture_by_filename( ac3dModel, s );
598 if( t != NULL ) {
599 mesh_set_texture( (Mesh*)node->data, t );
600 } else {
601 t = tex_load( s, TEXTURE_FORMAT_UNKNOWN, ac3dModel->fname );
602 if( t == NULL ) {
603 /* there was an error loading the texture file */
604 bb_push_message_f( 3.0, "Texture '%s' could not be loaded", s );
605 } else {
606 model_add_texture( ac3dModel, t );
607 mesh_set_texture( (Mesh*)node->data, t );
608 }
609 }
610
611
612 return PARSE_CONT;
613 }
614
DoTexrep(char * s,GNode * node)615 int DoTexrep ( char *s, GNode * node ) {
616 float texrep[ 2 ];
617
618 if ( 2 != sscanf ( s, "%f %f", &texrep[ 0 ], &texrep[ 1 ] ) ) {
619 printf( "DoTexrep: Illegal texrep record: %s\n", s );
620 } else {
621 mesh_set_texrep( (Mesh*)node->data, texrep[0], texrep[1] );
622 }
623
624 return PARSE_CONT;
625 }
626
DoTexoff(char * s,GNode * node)627 int DoTexoff ( char *s, GNode * node ) {
628 float texrep[ 2 ];
629
630 if ( 2 != sscanf ( s, "%f %f", &texrep[ 0 ], &texrep[ 1 ] ) ) {
631 printf( "DoTexoff: Illegal texoff record: %s\n", s );
632 } else {
633 printf( "DoTexoff: texture offsets aren't implemented yet...\n" );
634 }
635
636 return PARSE_CONT;
637 }
638
DoRot(char * s,GNode * node)639 int DoRot ( char *s, GNode * node ) {
640 float mat[ 4 ][ 4 ];
641
642 mat[ 0 ][ 3 ] = mat[ 1 ][ 3 ] = mat[ 2 ][ 3 ] = mat[ 3 ][ 0 ] = mat[ 3 ][ 1 ] = mat[ 3 ][ 2 ] = 0.0f;
643 mat[ 3 ][ 3 ] = 1.0f;
644
645 if ( 9 != sscanf ( s, "%f %f %f %f %f %f %f %f %f",
646 &mat[ 0 ][ 0 ], &mat[ 0 ][ 1 ], &mat[ 0 ][ 2 ],
647 &mat[ 1 ][ 0 ], &mat[ 1 ][ 1 ], &mat[ 1 ][ 2 ],
648 &mat[ 2 ][ 0 ], &mat[ 2 ][ 1 ], &mat[ 2 ][ 2 ] ) ) {
649 printf( "DoRot: Illegal rot record: %s\n", s );
650 }
651
652 /* glMultMatrixf (mat); */
653
654 return PARSE_CONT ;
655 }
656
DoLoc(char * s,GNode * node)657 int DoLoc ( char *s, GNode * node ) {
658 float loc[ 3 ];
659 Mesh *mesh;
660
661 mesh = (Mesh*)node->data;
662
663 if ( 3 != sscanf ( s, "%f %f %f", &loc[ 0 ], &loc[ 1 ], &loc[ 2 ] ) ) {
664 printf( "DoLoc: Illegal loc record: %s\n", s );
665 }
666
667 #ifdef NO_SWAP_YZ
668 vector_copy( mesh->loc, loc );
669 #else
670 mesh->loc[0] = loc[0];
671 mesh->loc[1] = -1.0 * loc[2];
672 mesh->loc[2] = loc[1];
673 #endif
674
675 if( node->parent && node->parent->data ) {
676 vector_add( mesh->loc, mesh->loc, ((Mesh*)node->parent->data)->loc );
677 }
678
679 return PARSE_CONT;
680 }
681
DoUrl(char * s,GNode * node)682 int DoUrl ( char *s, GNode * node ) {
683 SkipQuotes ( &s );
684 return PARSE_CONT;
685 }
686
DoNumvert(char * s,GNode * node)687 int DoNumvert ( char *s, GNode * node ) {
688 char buffer[ 1024 ];
689 int i;
690 Vertex * vertex;
691 float thisX;
692 float thisY;
693 float thisZ;
694
695 int numVertices = strtol ( s, NULL, 0 );
696
697 for ( i = 0; i < numVertices; i++ ) {
698 fgets ( buffer, 1024, acfp );
699
700 /*printf( "DoNumvert: buffer is: %s", buffer ); */
701 vertex = vertex_new();
702
703 thisX = thisY = thisZ = 0.0f;
704
705 if ( 3 != sscanf( buffer, "%f %f %f", &thisX, &thisY, &thisZ ) ) {
706 printf( "DoNumvert: Illegal vertex record: %s\n", buffer );
707 free( vertex );
708 }
709 else {
710 /*printf( "\tconverted to: %f %f %f\n", thisX, thisY, thisZ ); */
711 /* add a new vertex to the model */
712 #ifdef NO_SWAP_YZ
713 vertex->v[ 0 ] = thisX;
714 vertex->v[ 1 ] = thisY;
715 vertex->v[ 2 ] = thisZ;
716 #else
717 vertex->v[ 0 ] = thisX;
718 vertex->v[ 1 ] = -1.0 * thisZ;
719 vertex->v[ 2 ] = thisY;
720 #endif
721 /* translate according to the mesh's loc */
722 vector_add( vertex->v, vertex->v, ((Mesh*)node->data)->loc );
723
724 model_vertex_add( ac3dModel, vertex );
725 mesh_vertex_add( (Mesh*)node->data, vertex );
726 }
727
728 }
729
730 return PARSE_CONT;
731 }
732
DoNumsurf(char * s,GNode * node)733 int DoNumsurf ( char *s, GNode * node ) {
734 int i, ns;
735 char buffer[ 1024 ];
736
737 ns = strtol ( s, NULL, 0 );
738
739 #if 0
740 /* Do first pass to average normals */
741 pos = ftell ( acfp );
742 acsurfpass = PASS_NORMAL;
743 for ( i = 0; i < ns; i++ ) {
744 p = ftell ( acfp );
745 fgets ( buffer, 1024, acfp );
746 Search ( surf_tag, buffer );
747 }
748
749 /* Back to beginning of object */
750 fseek ( acfp, pos, SEEK_SET, HUH? );
751
752 /* Average normals */
753 for ( v = 0; v < nv; v++ ) {
754 // vtab[ v ].normal[ 0 ] /= vtab[ v ].n;
755 // vtab[ v ].normal[ 1 ] /= vtab[ v ].n;
756 // vtab[ v ].normal[ 2 ] /= vtab[ v ].n;
757 }
758
759 /* Now render */
760 acsurfpass = PASS_RENDER;
761 last_mat = ( -1 );
762 #endif
763
764 for ( i = 0; i < ns; i++ ) {
765 fgets ( buffer, 1024, acfp );
766 Search ( surf_tag, buffer, node );
767 }
768
769 return PARSE_CONT;
770 }
771
DoSurf(char * s,GNode * node)772 int DoSurf ( char *s, GNode * node ) {
773 char buffer[ 1024 ];
774
775 current_flags = strtol ( s, NULL, 0 );
776
777 while ( NULL != fgets ( buffer, 1024, acfp ) ) {
778 if ( Search ( surface_tags, buffer, node ) == PARSE_POP ) break;
779 }
780
781 return PARSE_CONT ;
782 }
783
DoMat(char * s,GNode * node)784 int DoMat ( char *s, GNode * node ) {
785 int mat;
786
787 mat = strtol ( s, NULL, 0 );
788
789 /* if ( mat != last_mat ) {
790 if ( acsurfpass == PASS_RENDER ) glCallList ( matlist[ mat ] );
791 last_mat = mat;
792 }
793 */
794
795 return PARSE_CONT ;
796 }
797
798
DoRefs(char * s,GNode * node)799 int DoRefs ( char *s, GNode * node ) {
800 int i;
801 int nrefs;
802 char buffer[ 1024 ] ;
803 int *vlist;
804 float *tlistu, *tlistv;
805
806 int vertNum;
807 float texCoordU;
808 float texCoordV;
809 int error = 0;
810
811 Mesh *mesh = (Mesh*)node->data;
812
813 nrefs = strtol ( s, NULL, 0 );
814
815 if ( nrefs <= 0 ) return PARSE_POP;
816
817 vlist = ( int * ) malloc ( sizeof( int ) * nrefs );
818 tlistu = ( float * ) malloc ( sizeof( float ) * nrefs ) ;
819 tlistv = ( float * ) malloc ( sizeof( float ) * nrefs ) ;
820
821 for ( i = 0; i < nrefs; i++ ) {
822 fgets ( buffer, 1024, acfp );
823
824
825 vlist[ i ] = vertNum = 0;
826 tlistu[ i ] = texCoordU = 0.0f;
827 tlistv[ i ] = texCoordV = 0.0f;
828
829 if( 3 != sscanf( buffer, "%u %f %f", &vertNum, &texCoordU, &texCoordV ) ) {
830 printf( "DoRefs: Illegal ref record: %s\n", buffer );
831 if( mesh->name != NULL )
832 printf( "DoRefs: in object: %s\n", mesh->name );
833 error = 1;
834 }
835
836 vlist[ i ] = vertNum;
837 tlistu[ i ] = texCoordU;
838 tlistv[ i ] = texCoordV;
839
840 }
841
842
843 if ( nrefs >= 2 && !error ) {
844 int i;
845 Poly * newPoly;
846
847 newPoly = poly_new();
848
849 for( i = 0; i < nrefs; i++ ) {
850 poly_add_vertex( newPoly,
851 g_slist_nth_data( mesh->vertices, vlist[i] ) );
852
853 /* if there was some error in adding the vertex... */
854 if( newPoly->num_verts != i+1 ){
855 poly_delete( newPoly );
856 goto error;
857 }
858
859 /* fabs? ----------v */
860 newPoly->tc[ i ]->x = ( tlistu[ i ] );
861 newPoly->tc[ i ]->y = ( tlistv[ i ] );
862 }
863
864 mesh_polygon_add( mesh, newPoly );
865 }
866 error:
867 free ( vlist );
868 free ( tlistu );
869 free ( tlistv );
870
871 return PARSE_POP;
872 }
873
DoKids(char * s,GNode * node)874 int DoKids ( char *s, GNode * node ) {
875 last_num_kids = strtol ( s, NULL, 0 );
876 return PARSE_POP;
877 }
878
879
880
881
882
883
884
885