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