1 /*
2      PLIB - A Suite of Portable Game Libraries
3      Copyright (C) 1998,2002  Steve Baker
4 
5      This library is free software; you can redistribute it and/or
6      modify it under the terms of the GNU Library General Public
7      License as published by the Free Software Foundation; either
8      version 2 of the License, or (at your option) any later version.
9 
10      This library is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Library General Public License for more details.
14 
15      You should have received a copy of the GNU Library General Public
16      License along with this library; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 
19      For further information visit http://plib.sourceforge.net
20 
21      $Id: ssgLoadASE.cxx 1988 2004-10-29 22:41:37Z wolfram_kuss $
22 */
23 
24 /****
25 * NAME
26 *   ssgLoadASE -- ASE model loader
27 *
28 * DESCRIPTION
29 *   ssgLoadASE will load an ASE model exported from 3dsmax using
30 *   the standard ascii export v2.00 plugin.
31 *
32 *   The material list and geometry objects are parsed and converted
33 *   into an SSG scene graph.  shape, light, camera, and helper
34 *   nodes are ignored.
35 *
36 *   If the geometry has vertex colours (pre-lit) then lighting is
37 *   disabled for that leaf.
38 *
39 *   mesh animation creates ssgSelector entities.  transform
40 *   animation creates ssgTransform entities with ssgTransformArray
41 *   user_data.  see the viewer example for details on controlling
42 *   animation.
43 *
44 *   NOTE: be sure you _reset the transform_ of the top-level object
45 *   in 3dsmax before exporting transform animation.
46 *
47 *   Please report any bugs to the author.  Complete information about
48 *   the ASE format can be found in the 3dsmax SDK source code.
49 *
50 * AUTHOR
51 *   Dave McClurg <dpm@efn.org>
52 *
53 * CREATION DATE
54 *   Feb-2000
55 *
56 * MODIFICATION HISTORY
57 *   November 2000 - v1.1, Dave McClurg <dpm@efn.org>
58 *     o support for transform animation samples
59 ****/
60 
61 #include "ssgLocal.h"
62 #include "ssgParser.h"
63 
64 
65 #define u32 unsigned int
66 #define f32 float
67 #define cchar const char
68 
69 
70 static ssgLoaderOptions* current_options = NULL ;
71 
72 struct aseVertexBuffer
73 {
74   bool use_flag ;
75   int index ;
76   sgVec3 v ;
77   sgVec2 tv ;
78   sgVec3 cv ;
79 } ;
80 
81 
82 struct aseFace
83 {
84   u32 v[3];
85   u32 tv[3];
86   u32 cv[3];
87   u32 sub_index;
88 
89 	// SAC: Additional vals to track normals for each face vertex.
90   // Since each vertex can supposedly have various normals if shared by two
91   // non-smoothed faces, we track them per face.  I haven't checked this as
92   // good as I should have with smoothed & unsmoothed shapes :)
93 	bool has_vertex_normals;
94 	sgVec3 vn [3];
95 };
96 
97 
98 struct aseTransform
99 {
100   sgVec3 pos ;
101   sgVec3 axis ;   // axis of rotation (unit vector)
102   f32 angle ;     // angle of rotation in radians (always >0)
103   sgVec3 scale ;
104 } ;
105 
106 
107 struct aseMesh
108 {
109   u32 num_faces ;
110   u32 num_verts ;
111   u32 num_tverts ;
112   u32 num_cverts ;
113 
114   aseFace* faces ;
115   sgVec3* verts ;
116   sgVec2* tverts ;
117   sgVec3* cverts ;
118 
119   aseMesh();
120   ~aseMesh();
121 };
122 
123 
124 struct aseObject
125 {
126   enum Type { GEOM, HELPER, CAMERA } ;
127   int type ;
128   char* name ;
129   char* parent ;
130   bool inherit_pos [3] ;
131   sgVec3 pos ;
132   sgVec3 target ;
133   u32 mat_index ;
134   u32 num_tkeys ;
135   aseTransform* tkeys ;
136 
137   enum { MAX_FRAMES = 256 };
138   aseMesh* mesh_list[ MAX_FRAMES ];
139   int mesh_count ;
140 
141   aseObject( Type type );
142   ~aseObject();
143 };
144 
145 struct aseMaterial
146 {
147   char* name ;
148   u32 mat_index ;
149   u32 sub_index ;
150   bool sub_flag ;
151 
152   sgVec4 amb ;
153   sgVec4 diff ;
154   sgVec4 spec ;
155   f32 shine ;
156   f32 transparency ;
157 
158   char* tfname ;
159   sgVec2 texrep ;
160   sgVec2 texoff ;
161 };
162 
163 
164 #define MAX_MATERIALS 1000
165 static aseMaterial** materials ;
166 static u32 num_materials ;
167 
168 static u32 first_frame ;
169 static u32 last_frame ;
170 static u32 frame_speed ;
171 static u32 ticks_per_frame ;
172 static u32 num_frames=0 ;
173 
174 static _ssgParserSpec parser_spec =
175 {
176    "\r\n\t ",  // delim_chars_skipable
177 	 0,          // delim_chars_non_skipable
178    NULL,      // pre_processor
179    "{",        // open_brace_chars
180    "}",        // close_brace_chars
181    '"',        // quote_char
182    0,          // comment_char
183 	 0           // comment_string
184 } ;
185 
186 static _ssgParser parser;
187 static ssgBranch* top_branch;
188 
aseMesh()189 aseMesh::aseMesh()
190 {
191   memset(this,0,sizeof(aseMesh));
192 }
193 
194 
~aseMesh()195 aseMesh::~aseMesh()
196 {
197   delete[] faces;
198   delete[] verts;
199   delete[] tverts;
200   delete[] cverts;
201 }
202 
203 
aseObject(aseObject::Type _type)204 aseObject::aseObject( aseObject::Type _type )
205 {
206   memset(this,0,sizeof(aseObject));
207   type = _type ;
208 }
209 
210 
~aseObject()211 aseObject::~aseObject()
212 {
213   delete[] name;
214   delete[] parent;
215   delete[] tkeys;
216   for ( int i=0; i<MAX_FRAMES; i++ )
217     delete mesh_list [ i ] ;
218   memset(this,0,sizeof(aseObject));
219 }
220 
221 
count_sub_materials(u32 mat_index)222 static u32 count_sub_materials( u32 mat_index )
223 {
224   u32 count = 0 ;
225   for ( u32 i=0; i<num_materials; i++ )
226   {
227     aseMaterial* mat = materials[ i ] ;
228     if ( mat->mat_index == mat_index && mat->sub_flag )
229       count ++;
230   }
231   return count ;
232 }
233 
234 
find_material(u32 mat_index,u32 sub_index)235 static aseMaterial* find_material( u32 mat_index, u32 sub_index )
236 {
237   u32 i;
238 
239   //find sub-material
240   for ( i=0; i<num_materials; i++ )
241   {
242     aseMaterial* mat = materials[ i ] ;
243     if ( mat->mat_index == mat_index && mat->sub_index == sub_index )
244       return(mat);
245   }
246 
247   //just match material #
248   for ( i=0; i<num_materials; i++ )
249   {
250     aseMaterial* mat = materials[ i ] ;
251     if ( mat->mat_index == mat_index )
252       return(mat);
253   }
254 
255   parser.error("unknown material #%d",mat_index);
256   return(0);
257 }
258 
259 
make_state(aseMaterial * mat,bool prelit)260 static ssgSimpleState* make_state( aseMaterial* mat, bool prelit )
261 {
262   if ( mat -> tfname  != NULL)
263   {
264     ssgSimpleState *st = current_options -> createSimpleState ( mat -> tfname ) ;
265     if ( st != NULL )
266       return st ;
267   }
268 
269   ssgSimpleState *st = new ssgSimpleState () ;
270 
271   bool has_alpha = false ;
272 
273   if (mat -> tfname != NULL)
274   {
275     ssgTexture* tex = current_options -> createTexture ( mat->tfname ) ;
276     has_alpha = tex -> hasAlpha () ;
277 
278     st -> setTexture ( tex ) ;
279     st -> enable ( GL_TEXTURE_2D ) ;
280   }
281   else
282   {
283     st -> disable( GL_TEXTURE_2D ) ;
284   }
285 
286   st -> disable ( GL_ALPHA_TEST ) ;
287 
288   if ( sgCompareFloat ( mat -> transparency, 0.0f, 0.01f ) > 0 || has_alpha )
289   {
290     st -> enable  ( GL_BLEND ) ;
291     st -> setTranslucent () ;
292   }
293   else
294   {
295     st -> disable ( GL_BLEND ) ;
296     st -> setOpaque () ;
297   }
298 
299   if ( prelit )
300   {
301     st -> disable ( GL_LIGHTING ) ;
302   }
303   else
304   {
305     st -> setMaterial ( GL_AMBIENT, mat -> amb ) ;
306     st -> setMaterial ( GL_DIFFUSE, mat -> diff ) ;
307     st -> setMaterial ( GL_SPECULAR, mat -> spec ) ;
308     st -> setShininess ( mat -> shine ) ;
309     st -> disable ( GL_COLOR_MATERIAL ) ;
310     st -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ;
311     st -> enable  ( GL_LIGHTING ) ;
312   }
313 
314   st -> setShadeModel ( GL_SMOOTH ) ;
315 
316   return st ;
317 }
318 
319 
get_state(aseMaterial * mat,bool prelit)320 static ssgSimpleState* get_state( aseMaterial* mat, bool prelit )
321 {
322   // is material an ifl (image file list)
323 #ifdef UL_WIN32
324   if ( strnicmp ( "ifl_", mat -> name, 4 ) == 0 )
325 #else
326   if ( strncasecmp ( "ifl_", mat -> name, 4 ) == 0 )
327 #endif
328   {
329     u32 num_subs = count_sub_materials ( mat -> mat_index );
330     if ( num_subs < 2 )
331       parser.error("ifl material only has <2 frames: %s",mat -> name);
332 
333     ssgStateSelector* selector = new ssgStateSelector ( num_subs ) ;
334     for ( u32 i=0; i<num_subs; i++ )
335     {
336       aseMaterial* mat2 = find_material ( mat -> mat_index, i ) ;
337       assert ( mat2 != NULL ) ;
338 
339       ssgSimpleState* st = make_state ( mat2, prelit ) ;
340       selector -> setStep ( i, st ) ;
341     }
342     selector -> selectStep ( 0 ) ;
343     return selector ;
344   }
345   return make_state ( mat, prelit ) ;
346 }
347 
348 
parse_map(aseMaterial * mat)349 static int parse_map( aseMaterial* mat )
350 // return TRUE on success
351 {
352   char* token;
353   int startLevel = parser.level;
354   while ((token = parser.getLine( startLevel )) != NULL)
355   {
356     if (!strcmp(token,"*BITMAP"))
357     {
358       if ( mat->tfname != NULL )
359         parser.error("multiple textures for material: %s",mat->name);
360       else
361       {
362         char* fname;
363 				if (! parser.parseString(fname, "bitmap filename") )
364 					return FALSE;
365 
366         //strip existing directory from fname
367         char* slash = strrchr ( fname, '/' ) ;
368         if ( !slash )
369           slash = strrchr ( fname, '\\' ) ; //for dos
370         if ( slash )
371           fname = slash + 1 ;
372 
373         mat->tfname = ulStrDup ( fname ) ;
374       }
375     }
376     else if (!strcmp(token,"*UVW_U_TILING"))
377     {
378       if (! parser.parseFloat(mat->texrep[0], "tiling.u"))
379 				return FALSE;
380     }
381     else if (!strcmp(token,"*UVW_V_TILING"))
382     {
383       if (! parser.parseFloat(mat->texrep[1], "tiling.v"))
384 				return FALSE;
385     }
386     else if (!strcmp(token,"*UVW_U_OFFSET"))
387     {
388       if (! parser.parseFloat(mat->texoff[0] , "offset.u"))
389 				return FALSE;
390     }
391     else if (!strcmp(token,"*UVW_V_OFFSET"))
392     {
393       if (! parser.parseFloat(mat->texoff[1] , "offset.v"))
394 				return FALSE;
395     }
396   }
397 	return TRUE;
398 }
399 
400 
parse_material(u32 mat_index,u32 sub_index,cchar * mat_name)401 static int parse_material( u32 mat_index, u32 sub_index, cchar* mat_name )
402 // return TRUE on success
403 {
404   if ( num_materials >= MAX_MATERIALS )
405   {
406     parser.error( "too many materials" );
407 
408     // skip material definition
409     int startLevel = parser.level;
410     while (parser.getLine( startLevel ) != NULL)
411       ;
412     return TRUE; // go on parsing
413   }
414   aseMaterial* mat = new aseMaterial;
415   materials [ num_materials++ ] = mat ;
416 
417   memset ( mat, 0, sizeof(aseMaterial) ) ;
418   mat->mat_index = mat_index ;
419   mat->sub_index = sub_index ;
420   mat->sub_flag = ( mat_name != 0 ) ;
421   mat->texrep[0] = 1.0f ;
422   mat->texrep[1] = 1.0f ;
423   mat->texoff[0] = 0.0f ;
424   mat->texoff[1] = 0.0f ;
425 
426   char* token;
427   int startLevel = parser.level;
428   while ((token = parser.getLine( startLevel )) != NULL)
429   {
430     if (!strcmp(token,"*MATERIAL_NAME"))
431     {
432       char* name;
433 			if (! parser.parseString(name, "mat name") )
434 				return FALSE;
435 
436       if ( mat->sub_flag )
437       {
438         char buff [ 256 ] ;
439         sprintf( buff, "%s, sub#%d", mat_name, sub_index );
440 
441         mat->name = ulStrDup ( buff ) ;
442       }
443       else
444         mat->name = ulStrDup ( name ) ;
445     }
446     else if (!strcmp(token,"*MATERIAL_AMBIENT"))
447     {
448       if (! parser.parseFloat(mat->amb[ 0 ], "amb.r"))
449 				return FALSE;
450       if (! parser.parseFloat(mat->amb[ 1 ], "amb.g"))
451 				return FALSE;
452       if (! parser.parseFloat(mat->amb[ 2 ], "amb.b"))
453 				return FALSE;
454       mat->amb[ 3 ] = 1.0f;
455     }
456     else if (!strcmp(token,"*MATERIAL_DIFFUSE"))
457     {
458       if (! parser.parseFloat(mat->diff[ 0 ], "diff.r"))
459 				return FALSE;
460       if (! parser.parseFloat(mat->diff[ 1 ], "diff.g"))
461 				return FALSE;
462       if (! parser.parseFloat(mat->diff[ 2 ], "diff.b"))
463 				return FALSE;
464       mat->diff[ 3 ] = 1.0f;
465     }
466     else if (!strcmp(token,"*MATERIAL_SPECULAR"))
467     {
468       if (! parser.parseFloat(mat->spec[ 0 ], "spec.r"))
469 				return FALSE;
470       if (! parser.parseFloat(mat->spec[ 1 ], "spec.g"))
471 				return FALSE;
472       if (! parser.parseFloat(mat->spec[ 2 ], "spec.b"))
473 				return FALSE;
474       mat->spec[ 3 ] = 1.0f;
475     }
476     else if (!strcmp(token,"*MATERIAL_SHINE"))
477     {
478       if (! parser.parseFloat(mat->shine, "shine"))
479 			  return FALSE;
480 
481 			// SAC: Shine seems off.  If I load a 3ds of the same shape
482       // the shine is 256x as much and works better, so I'll tweak
483       // the val here  :)    I couldn't clarify the range used by
484       // MAX SDK anywhere in the docs (though this assumes 0 - 0.5).
485       // OpenGL is 0-128.
486 			mat->shine = mat->shine * 256.0f;
487 			if ( mat->shine > 128 )
488 				mat->shine = 128;
489     }
490     else if (!strcmp(token,"*MATERIAL_TRANSPARENCY"))
491     {
492       if (! parser.parseFloat(mat->transparency, "transparency"))
493 				return FALSE;
494     }
495     else if (!strcmp(token,"*MAP_DIFFUSE"))
496     {
497       //Need: what about MAP_GENERIC, MAP_AMBIENT, etc??
498       if (! parse_map( mat ))
499 				return FALSE;
500     }
501     else if (!strcmp(token,"*SUBMATERIAL"))
502     {
503       u32 sub_index;
504 			if (! parser.parseUInt(sub_index, "sub mat #"))
505 				return FALSE;
506       if (! parse_material( mat_index, sub_index, mat->name ))
507 				return FALSE;
508     }
509   }
510 
511   //parser.message("material: %s (%s)",mat->name,mat->tfname);
512 	return TRUE;
513 }
514 
515 
parse_material_list()516 static int parse_material_list()
517 // return TRUE on success
518 {
519   if ( num_materials )
520     parser.error("multiple material lists");
521 
522   char* token;
523   int startLevel = parser.level;
524   while ((token = parser.getLine( startLevel )) != NULL)
525   {
526     if (!strcmp(token,"*MATERIAL"))
527     {
528       u32 mat_index;
529 			if (! parser.parseUInt(mat_index, "mat #"))
530 				return FALSE;
531       if (! parse_material( mat_index, 9999, NULL ))
532 				return FALSE;
533     }
534   }
535 	return TRUE;
536 }
537 
538 
parse_mesh(aseObject * obj)539 static int parse_mesh( aseObject* obj )
540 {
541   aseMesh* mesh = NULL ;
542 	u32 mesh_face_normal_index = 0x7fffffff;
543 	u32 mesh_face_normal_count = 0;
544 
545   char* token;
546   int startLevel = parser.level;
547   while ((token = parser.getLine( startLevel )) != NULL)
548   {
549     if ( mesh == NULL )
550     {
551       u32 frame = aseObject::MAX_FRAMES ;
552 
553       if (!strcmp(token,"*TIMEVALUE"))
554       {
555         u32 time;
556 				if (! parser.parseUInt(time, "time"))
557 					return FALSE;
558         frame = (time + (ticks_per_frame-1)) / ticks_per_frame - first_frame;
559       }
560       else
561       {
562         parser.error("missing *TIMEVALUE");
563         frame = aseObject::MAX_FRAMES ;
564       }
565 
566       if ( frame >= aseObject::MAX_FRAMES || obj->mesh_list [ frame ] != NULL )
567       {
568         //ignore this mesh
569         while (parser.getLine( startLevel )) ;
570         return TRUE; // go on parsing
571       }
572 
573       mesh = new aseMesh ;
574       obj->mesh_list [ frame ] = mesh ;
575       obj->mesh_count ++ ;
576     }
577     else if (!strcmp(token,"*MESH_NUMFACES"))
578     {
579       if (mesh -> faces)
580         parser.error("%s already seen",token);
581       else
582       {
583         if (! parser.parseUInt(mesh -> num_faces, "num_faces"))
584 					return FALSE;
585         mesh -> faces = new aseFace[ mesh -> num_faces ];
586 
587         // SAC: Help clear all the has_vertex_normals flags
588 				memset ( mesh -> faces, 0, mesh -> num_faces * sizeof (aseFace) );
589       }
590     }
591     else if (!strcmp(token,"*MESH_NUMTVFACES"))
592     {
593       u32 ntfaces;
594 			if (! parser.parseUInt(ntfaces, "ntfaces"))
595 			  return FALSE;
596       if (ntfaces != mesh -> num_faces)
597         parser.error("NUMTFACES(%d) != NUMFACES(%d)",ntfaces,mesh -> num_faces);
598     }
599     else if (!strcmp(token,"*MESH_NUMCVFACES"))
600     {
601       u32 ncfaces;
602 			if (! parser.parseUInt(ncfaces, "ncfaces"))
603 				return FALSE;
604       if (ncfaces != mesh -> num_faces)
605         parser.error("NUMCFACES(%d) != NUMFACES(%d)",ncfaces,mesh -> num_faces);
606     }
607     else if (!strcmp(token,"*MESH_NUMVERTEX"))
608     {
609       if (mesh -> verts)
610         parser.error("%s already seen",token);
611       else
612       {
613 				if (! parser.parseUInt(mesh -> num_verts, "num_verts"))
614 					return FALSE;
615         mesh -> verts = new sgVec3[ mesh -> num_verts ];
616       }
617     }
618     else if (!strcmp(token,"*MESH_NUMTVERTEX"))
619     {
620       if (mesh -> tverts)
621         parser.error("%s already seen",token);
622       else
623       {
624         if (! parser.parseUInt(mesh -> num_tverts, "num_tverts"))
625 					return FALSE;
626         if (mesh -> num_tverts)
627           mesh -> tverts = new sgVec2[ mesh -> num_tverts ];
628       }
629     }
630     else if (!strcmp(token,"*MESH_NUMCVERTEX"))
631     {
632       if (mesh -> cverts)
633         parser.error("%s already seen",token);
634       else
635       {
636         if (! parser.parseUInt(mesh -> num_cverts, "num_cverts"))
637 				  return FALSE;
638         if (mesh -> num_cverts)
639           mesh -> cverts = new sgVec3[ mesh -> num_cverts ];
640       }
641     }
642     else if (!strcmp(token,"*MESH_FACE"))
643     {
644       u32 index;
645 			// wk: The old parseInt converted a "3:" into 3,
646 			// the new would give an error. Therefore I had to change this code:
647 			char *my_endptr, *my_token = parser.parseToken("face #");
648 			if (my_token[strlen(my_token)-1]==':')
649 				my_token[strlen(my_token)-1]=0;
650 
651 			index = (unsigned int)(strtol( my_token, &my_endptr, 10));
652 			if ( (my_endptr != NULL) && (*my_endptr != 0))
653 			{ parser.error("The field face # should contain an integer number but contains %s", my_token) ;
654 				return FALSE;
655 			}
656 
657 
658 			if (index >= mesh -> num_faces)
659         parser.error("bad face #");
660       else
661       {
662         aseFace& face = mesh -> faces[ index ];
663 
664         parser.expect("A:");
665         if (! parser.parseUInt(face.v[0], "face.v[0]"))
666 					return FALSE;
667         parser.expect("B:");
668         if (! parser.parseUInt(face.v[1], "face.v[1]"))
669 					return FALSE;
670         parser.expect("C:");
671         if (! parser.parseUInt(face.v[2], "face.v[2]"))
672 					return FALSE;
673 
674         //search for other flags
675 				token = parser.parseToken(0);
676         while ( ! parser.eol )
677         {
678           if ( strcmp(token,"*MESH_MTLID") == 0 )
679           {
680             if (! parser.parseUInt(face.sub_index, "mat #"))
681 							return FALSE;
682           }
683 					token = parser.parseToken(0);
684         }
685       }
686     }
687     else if (!strcmp(token,"*MESH_TFACE"))
688     {
689       u32 index;
690 			if (! parser.parseUInt(index, "tface #"))
691 				return FALSE;
692       if (index >= mesh -> num_faces)
693         parser.error("bad tface #");
694       else
695       {
696         aseFace& face = mesh -> faces[ index ];
697 
698         if (! parser.parseUInt(face.tv[0], "tface.tv[0]"))
699 					return FALSE;
700         if (! parser.parseUInt(face.tv[1], "tface.tv[1]"))
701 					return FALSE;
702         if (! parser.parseUInt(face.tv[2], "tface.tv[2]"))
703 					return FALSE;
704       }
705     }
706     else if (!strcmp(token,"*MESH_CFACE"))
707     {
708       u32 index;
709 			if (! parser.parseUInt(index, "cface #"))
710 				return FALSE;
711       if (index >= mesh -> num_faces)
712         parser.error("bad cface #");
713       else
714       {
715         aseFace& face = mesh -> faces[ index ];
716 
717         if (! parser.parseUInt(face.cv[0], "tface.cv[0]"))
718 					return FALSE;
719         if (! parser.parseUInt(face.cv[1], "tface.cv[1]"))
720 					return FALSE;
721         if (! parser.parseUInt(face.cv[2], "tface.cv[2]"))
722 					return FALSE;
723       }
724     }
725 		// SAC: START OF VERTEX NORMAL PARSING SECTION
726 		// NOTE: Assumes that three correctly-ordered *MESH_VERTEXNORMAL lines
727     // come after each *MESH_FACENORMAL line.  Which seems to be the case
728     // in current exporter
729     else if (!strcmp(token,"*MESH_FACENORMAL"))
730 		{
731 			if (! parser.parseUInt(mesh_face_normal_index, "face normal #"))
732 				return FALSE;
733 			mesh_face_normal_count = 0;
734 		}
735     else if (!strcmp(token,"*MESH_VERTEXNORMAL"))
736     {
737 			//int nverts = mesh -> num_verts;
738 
739       if ( mesh_face_normal_index >= mesh -> num_faces )
740         parser.error("bad mesh_face_normal_index #");
741       if ( mesh_face_normal_count >= 3 )
742         parser.error("bad mesh_face_normal_count");
743 
744 			aseFace& face = mesh -> faces[ mesh_face_normal_index ];
745       sgVec3& vn = face . vn [ mesh_face_normal_count ];
746 			face.has_vertex_normals = true;
747 			u32 vertex_index;
748 			if (! parser.parseUInt(vertex_index, "vertex normal #"))
749 				return FALSE;
750 			if  ( face.v [mesh_face_normal_count] != vertex_index )
751         parser.error("bad MESH_VERTEXNORMAL entries out of order!");
752       if (! parser.parseFloat(vn[0], "vertexNormal.x"))
753 				return FALSE;
754       if (! parser.parseFloat(vn[1], "vertexNormal.y"))
755 				return FALSE;
756       if (! parser.parseFloat(vn[2], "vertexNormal.z"))
757 				return FALSE;
758 
759 			// sgNormaliseVec3 ( vn ) ;
760 			mesh_face_normal_count++;
761     }
762 		// SAC: END OF VERTEX NORMAL PARSING SECTION
763     else if (!strcmp(token,"*MESH_VERTEX"))
764     {
765       u32 index;
766 			if (! parser.parseUInt(index, "vertex #"))
767 				return FALSE;
768       if (index >= mesh -> num_verts)
769         parser.error("bad vertex #");
770       else
771       {
772         sgVec3& vert = mesh -> verts[ index ];
773 
774         if (! parser.parseFloat(vert[0], "vert.x"))
775 					return FALSE;
776         if (! parser.parseFloat(vert[1], "vert.y"))
777 					return FALSE;
778         if (! parser.parseFloat(vert[2], "vert.z"))
779 					return FALSE;
780       }
781     }
782     else if (!strcmp(token,"*MESH_TVERT"))
783     {
784       u32 index;
785 			if (! parser.parseUInt(index, "tvertex #"))
786 			  return FALSE;
787       if (index >= mesh -> num_tverts)
788         parser.error("bad tvertex #");
789       else
790       {
791         sgVec2& tvert = mesh -> tverts[ index ];
792 
793         if (! parser.parseFloat(tvert[0], "tvert.x"))
794 					return FALSE;
795         if (! parser.parseFloat(tvert[1], "tvert.y"))
796 					return FALSE;
797       }
798     }
799     else if (!strcmp(token,"*MESH_VERTCOL"))
800     {
801       u32 index;
802 			if (! parser.parseUInt(index, "cvertex #"))
803 				return FALSE;
804       if (index >= mesh -> num_cverts)
805         parser.error("bad cvertex #");
806       else
807       {
808         sgVec3& cvert = mesh -> cverts[ index ];
809 
810         if (! parser.parseFloat(cvert[0], "cvert.x"))
811 					return FALSE;
812         if (! parser.parseFloat(cvert[1], "cvert.y"))
813 					return FALSE;
814         if (! parser.parseFloat(cvert[2], "cvert.z"))
815 					return FALSE;
816       }
817     }
818   }
819 	return TRUE;
820 }
821 
822 
get_texcoord(aseMaterial * mat,sgVec2 tv)823 static void get_texcoord ( aseMaterial* mat, sgVec2 tv )
824 {
825   //invert Y coordinate
826   tv[1] = 1.0f - tv[1] ;
827 
828   tv[0] *= mat->texrep[0] ;
829   tv[1] *= mat->texrep[1] ;
830   tv[0] += mat->texoff[0] ;
831   tv[1] += mat->texoff[1] ;
832 }
833 
834 
add_points(aseObject * obj,aseMesh * mesh)835 static ssgLeaf* add_points( aseObject* obj, aseMesh* mesh )
836 {
837   ssgVertexArray* vl = NULL ;
838 
839   if ( obj->type == aseObject::CAMERA )
840   {
841     /* compute a normalized target vector */
842     sgVec3 target ;
843 		sgCopyVec3 ( target, obj->target ) ;
844 		sgSubVec3 ( target, obj->pos ) ;
845 
846     SGfloat len = sgLengthVec3 ( target ) ;
847     if ( len == SG_ZERO )
848     {
849       vl = new ssgVertexArray ( 1 ) ;
850       vl -> add ( obj->pos ) ;
851     }
852     else
853     {
854       vl = new ssgVertexArray ( 2 ) ;
855 
856       sgNormaliseVec3 ( target ) ;
857       sgAddVec3 ( target, obj->pos ) ;
858 
859       vl -> add ( obj->pos ) ;
860       vl -> add ( target ) ;
861     }
862   }
863   else if ( mesh != NULL )
864   {
865     u32 num_verts = mesh -> num_verts ;
866     if ( num_verts == 0 )
867       return NULL;
868 
869     vl = new ssgVertexArray ( num_verts ) ;
870 
871     //pass the data to ssg
872     sgVec3* vert = mesh -> verts ;
873     for ( u32 i=0; i < num_verts; i++, vert++ )
874       vl -> add ( *vert ) ;
875   }
876   else
877   {
878     return NULL ;
879   }
880 
881   ssgVtxTable* leaf = new ssgVtxTable ( GL_POINTS,
882     vl, NULL, NULL, NULL ) ;
883 
884   if ( leaf != NULL )
885   {
886     // leaves with no faces are used for game logic
887     // and should not be culled and rendered
888     leaf -> clrTraversalMaskBits ( SSGTRAV_CULL ) ;
889   }
890 
891   return ssgGetCurrentOptions () -> createLeaf ( leaf, obj -> name ) ;
892 }
893 
894 
add_mesh(aseObject * obj,aseMesh * mesh,u32 sub_index)895 static ssgLeaf* add_mesh( aseObject* obj, aseMesh* mesh, u32 sub_index )
896 {
897   u32 i ;
898 
899   aseMaterial* mat = find_material ( obj->mat_index, sub_index ) ;
900   if ( mat == NULL )
901     return NULL ;
902 
903   //compute number of faces for this sub-material
904   u32 num_faces = mesh -> num_faces ;
905   if ( mat->sub_flag )
906   {
907     num_faces = 0 ;
908     aseFace* face = mesh -> faces ;
909     for ( i=0; i<mesh -> num_faces; i++, face++ )
910     {
911       if ( face->sub_index == mat->sub_index )
912         num_faces ++ ;
913     }
914   }
915   if ( num_faces == 0 )
916     return NULL ;
917 
918   if ( mesh -> cverts == NULL )
919   {
920     u32 num_verts = num_faces * 3 ;
921 
922     //pass the data to ssg
923     ssgSimpleState* st = get_state ( mat, false ) ;
924     ssgColourArray* cl = new ssgColourArray ( 1 ) ;
925     ssgVertexArray* vl = new ssgVertexArray ( num_verts ) ;
926     ssgNormalArray* nl = new ssgNormalArray ( num_verts ) ;
927     ssgTexCoordArray* tl = 0 ;
928     if ( mesh -> tverts )
929       tl = new ssgTexCoordArray ( num_verts ) ;
930 
931     //set the material colour
932     sgVec4 c ;
933     sgCopyVec3 ( c, mat -> diff ) ;
934     c[3] = 1.0f - mat -> transparency ;
935     cl -> add ( c ) ;
936 
937     aseFace* face = mesh -> faces ;
938     for ( i=0; i<mesh -> num_faces; i++, face++ )
939     {
940       if ( mat->sub_flag && face->sub_index != mat->sub_index )
941         continue ;
942 
943       sgVec3 n ;
944       sgMakeNormal ( n,
945         mesh -> verts[ face->v[0] ] ,
946         mesh -> verts[ face->v[1] ] ,
947         mesh -> verts[ face->v[2] ] ) ;
948 
949       for ( u32 j=0; j<3; j++ )
950       {
951         vl -> add ( mesh -> verts[ face->v[j] ] ) ;
952 
953 				// SAC: If per-vertex normals were found, use 'em.
954         // Else use the face normal computed above
955 				if  ( face -> has_vertex_normals )
956 					nl -> add ( face->vn [j] ) ;
957 				else
958 					nl -> add ( n ) ;
959 
960         if ( mesh -> tverts )
961         {
962           sgVec2 tv ;
963           sgCopyVec2 ( tv, mesh -> tverts[ face->tv[j] ] ) ;
964           get_texcoord ( mat, tv ) ;
965           tl -> add ( tv ) ;
966         }
967       }
968     }
969 
970     ssgVtxTable* leaf = new ssgVtxTable ( GL_TRIANGLES,
971       vl, nl, tl, cl ) ;
972     leaf -> setCullFace ( TRUE ) ;
973     leaf -> setState ( st ) ;
974     return current_options -> createLeaf ( leaf, obj->name ) ;
975   }
976 
977   //allocate map_index array
978   int* map_index = new int [ mesh -> num_faces * 3 ] ;
979 
980   //allocate the vertex list
981   u32 max_verts = mesh -> num_verts + mesh -> num_faces * 3 ;
982   aseVertexBuffer* vert_list = new aseVertexBuffer [ max_verts ] ;
983 
984   //mark each vertex as *not* used
985   aseVertexBuffer* vert = vert_list ;
986   for ( i=0; i < max_verts; i++, vert++ )
987   {
988     vert -> use_flag = false ;
989   }
990 
991   u32 extra_verts = 0 ;
992 
993   //build the vertex list
994   aseFace* face = mesh -> faces ;
995   for ( i=0; i<mesh -> num_faces; i++, face++ )
996   {
997     if ( mat->sub_flag && face->sub_index != mat->sub_index )
998       continue ;
999 
1000     for ( u32 j=0; j<3; j++ )
1001     {
1002       int k = i*3+j;
1003 
1004       map_index [k] = face->v[j] ;
1005       vert = vert_list + map_index[k];
1006 
1007       if ( vert -> use_flag )
1008       {
1009         //check for match
1010         bool match = true ;
1011         if ( mesh -> tverts &&
1012           sgCompareVec2 ( vert -> tv, mesh -> tverts[ face->tv[j] ], 0.0f ) != 0 )
1013           match = false ;
1014         else if ( mesh -> cverts &&
1015           sgCompareVec3 ( vert -> cv, mesh -> cverts[ face->cv[j] ], 0.0f ) != 0 )
1016           match = false ;
1017         if ( match )
1018           continue ;  //texcoord and color matches other vertex
1019 
1020         extra_verts ++ ;
1021 
1022         map_index [k] = mesh -> num_verts + k ;
1023         vert = vert_list + map_index[k];
1024       }
1025 
1026       //add the vertex
1027       vert -> use_flag = true;
1028       sgCopyVec3 ( vert -> v, mesh -> verts[ face->v[j] ] ) ;
1029       if ( mesh -> tverts )
1030         sgCopyVec2 ( vert -> tv, mesh -> tverts[ face->tv[j] ] ) ;
1031       if ( mesh -> cverts )
1032         sgCopyVec3 ( vert -> cv, mesh -> cverts[ face->cv[j] ] ) ;
1033     }
1034   }
1035 
1036   //assign a unique index to each vertex
1037   int num_verts = 0 ;
1038   vert = vert_list;
1039   for ( i=0; i < max_verts; i++, vert++ )
1040   {
1041     if ( vert -> use_flag )
1042       vert -> index = num_verts ++;
1043   }
1044 
1045   //if ( extra_verts > 0 )
1046   //   ulSetError( UL_DEBUG, "%d verts; %d added", num_verts-extra_verts, extra_verts );
1047   //else
1048   //   ulSetError( UL_DEBUG, "%d verts", num_verts );
1049 
1050   //pass the data to ssg
1051   ssgSimpleState* st = get_state ( mat, ( mesh -> cverts != NULL ) ) ;
1052   ssgIndexArray* il = new ssgIndexArray ( num_faces * 3 ) ;
1053   ssgVertexArray* vl = new ssgVertexArray ( num_verts ) ;
1054   ssgTexCoordArray* tl = 0 ;
1055   ssgColourArray* cl = 0 ;
1056   if ( mesh -> tverts )
1057     tl = new ssgTexCoordArray ( num_verts ) ;
1058   if ( mesh -> cverts )
1059     cl = new ssgColourArray ( num_verts ) ;
1060 
1061   //build the index list
1062   face = mesh -> faces ;
1063   for ( i=0; i<mesh -> num_faces; i++, face++ )
1064   {
1065     if ( mat->sub_flag && face->sub_index != mat->sub_index )
1066       continue ;
1067 
1068     for ( u32 j=0; j<3; j++ )
1069     {
1070       int k = i*3+j;
1071       vert = vert_list + map_index[k];
1072 
1073       if ( ! vert -> use_flag )
1074         ulSetError ( UL_FATAL, "internal error" ) ;
1075 
1076       il -> add ( vert -> index ) ;
1077     }
1078   }
1079 
1080   //copy the vertex lists
1081   vert = vert_list;
1082   for ( i=0; i < max_verts; i++, vert++ )
1083   {
1084     if ( vert -> use_flag )
1085     {
1086       vl -> add ( vert -> v ) ;
1087 
1088       if ( mesh -> tverts )
1089       {
1090         sgVec2 tv ;
1091         sgCopyVec2 ( tv, vert -> tv ) ;
1092         get_texcoord ( mat, tv ) ;
1093         tl -> add ( tv ) ;
1094       }
1095 
1096       if ( mesh -> cverts )
1097       {
1098         sgVec4 c ;
1099         sgCopyVec3 ( c, vert -> cv ) ;
1100         c[3] = 1.0f - mat -> transparency ;
1101 
1102         cl -> add ( c ) ;
1103       }
1104     }
1105   }
1106 
1107   delete[] vert_list ;
1108   delete[] map_index ;
1109 
1110   ssgVtxArray* leaf = new ssgVtxArray ( GL_TRIANGLES,
1111     vl, NULL, tl, cl, il ) ;
1112   leaf -> setCullFace ( TRUE ) ;
1113   leaf -> setState ( st ) ;
1114   return current_options -> createLeaf ( leaf, obj -> name ) ;
1115 }
1116 
1117 
get_tkey(aseObject * obj,u32 time)1118 static aseTransform* get_tkey( aseObject* obj, u32 time )
1119 {
1120   if ( obj->tkeys == NULL )
1121   {
1122     obj->num_tkeys = 0;
1123     obj->tkeys = new aseTransform [ num_frames ] ;
1124 
1125     //initialize
1126     aseTransform* tkey = obj->tkeys ;
1127     for ( u32 i=0; i<num_frames; i++, tkey++ )
1128     {
1129       sgSetVec3 ( tkey->pos, 0, 0, 0 ) ;
1130       sgSetVec3 ( tkey->axis, 0, 0, 1 ) ;
1131       tkey->angle = 0.0f ;
1132       sgSetVec3 ( tkey->scale, 1, 1, 1 ) ;
1133     }
1134   }
1135 
1136   //compute frame number
1137   u32 frame = time / ticks_per_frame - first_frame;
1138   if ((time % ticks_per_frame) != 0 || frame >= num_frames)
1139     parser.error("bad time");
1140 
1141   if ( frame+1 > obj->num_tkeys )
1142     obj->num_tkeys = frame+1;
1143 
1144   return( &obj->tkeys[ frame ] );
1145 }
1146 
1147 #define MAX_TKEY_PER_MESH 256
1148 
parse_tkeys(aseObject * obj)1149 static int parse_tkeys( aseObject* obj )
1150 {
1151   bool match = false ;
1152   void *tkeys[MAX_TKEY_PER_MESH];
1153   int num_tkeys=0;
1154   char* token;
1155   int startLevel = parser.level;
1156   while ((token = parser.getLine( startLevel )) != NULL)
1157   {
1158     if (!strcmp(token,"*NODE_NAME"))
1159     {
1160       char* name;
1161       if (! parser.parseString(name, "obj name"))
1162         return FALSE;
1163       if ( obj->name && !strcmp(name,obj->name) )
1164         match = true ;
1165     }
1166     else if (match)
1167     {
1168       if (!strcmp(token,"*CONTROL_POS_SAMPLE"))
1169       {
1170         u32 time;
1171         if (! parser.parseUInt(time, "time"))
1172           return FALSE;
1173         aseTransform* tkey = get_tkey( obj, time );
1174 
1175         if (! parser.parseFloat(tkey->pos[0], "pos.x"))
1176           return FALSE;
1177         if (! parser.parseFloat(tkey->pos[1], "pos.y"))
1178           return FALSE;
1179         if (! parser.parseFloat(tkey->pos[2], "pos.z"))
1180           return FALSE;
1181 
1182         if ( obj->parent == NULL )
1183         {
1184           sgSubVec3 ( tkey->pos, obj->pos ) ;
1185         }
1186         else
1187         {
1188           for ( int i=0; i<3; i++ )
1189           {
1190             if ( obj->inherit_pos[i] )
1191               tkey->pos[i] -= obj->pos[i] ;
1192           }
1193         }
1194 
1195         //copy the position forward
1196         for ( u32 i=obj->num_tkeys; i<num_frames; i++ )
1197           sgCopyVec3 ( obj->tkeys[ i ].pos, tkey->pos ) ;
1198       }
1199       else if (!strcmp(token,"*CONTROL_ROT_SAMPLE"))
1200       {
1201         u32 time;
1202         if (!parser.parseUInt(time, "time"))
1203           return FALSE;
1204         aseTransform* tkey = get_tkey( obj, time );
1205 
1206         if (! parser.parseFloat(tkey->axis[0], "axis.x"))
1207           return FALSE;
1208         if (! parser.parseFloat(tkey->axis[1], "axis.y"))
1209           return FALSE;
1210         if (! parser.parseFloat(tkey->axis[2], "axis.z"))
1211           return FALSE;
1212         if (! parser.parseFloat(tkey->angle, "angle"))
1213           return FALSE;
1214       }
1215       else if (!strcmp(token,"*CONTROL_TCB_ROT_KEY"))
1216       {
1217         u32 time;
1218         if (!parser.parseUInt(time, "time"))
1219           return FALSE;
1220         aseTransform* tkey = new aseTransform;
1221         tkeys[num_tkeys++] = tkey;
1222         assert(num_tkeys < MAX_TKEY_PER_MESH);
1223         sgSetVec3 ( tkey->pos, 0, 0, 0 ) ; // "TCB": only rotation allowed :-/
1224         sgSetVec3 ( tkey->axis, 0, 0, 1 ) ;
1225         tkey->angle = 0.0f ;
1226         sgSetVec3 ( tkey->scale, 1, 1, 1 ) ;
1227 
1228 // *CONTROL_TCB_ROT_KEY 160	-0.9949	-0.0914	0.0434	3.1336	0.0000	0.0000	0.0000	0.0000	0.0000
1229         if (! parser.parseFloat(tkey->axis[0], "axis.x"))
1230           return FALSE;
1231         if (! parser.parseFloat(tkey->axis[1], "axis.y"))
1232           return FALSE;
1233         if (! parser.parseFloat(tkey->axis[2], "axis.z"))
1234           return FALSE;
1235         if (! parser.parseFloat(tkey->angle, "angle"))
1236           return FALSE;
1237         float dummy;
1238         if (! parser.parseFloat(dummy, "tens"))
1239           return FALSE;
1240         if (! parser.parseFloat(dummy, "cont"))
1241           return FALSE;
1242         if (! parser.parseFloat(dummy, "bias"))
1243           return FALSE;
1244         if (! parser.parseFloat(dummy, "easeIn"))
1245           return FALSE;
1246         if (! parser.parseFloat(dummy, "easeOut"))
1247           return FALSE;
1248       }
1249       else if (!strcmp(token,"*CONTROL_SCALE_SAMPLE"))
1250       {
1251         u32 time;
1252         if (! parser.parseUInt(time, "time"))
1253           return FALSE;
1254         aseTransform* tkey = get_tkey( obj, time );
1255 
1256         if (! parser.parseFloat(tkey->scale[0], "scale.x"))
1257           return FALSE;
1258         if (! parser.parseFloat(tkey->scale[1], "scale.y"))
1259           return FALSE;
1260         if (! parser.parseFloat(tkey->scale[2], "scale.z"))
1261           return FALSE;
1262       }
1263     }
1264   }
1265   if(num_tkeys)
1266   {
1267     obj->num_tkeys = num_tkeys;
1268     obj->tkeys = new aseTransform [ num_tkeys ] ;
1269     for(int i=0; i<num_tkeys; i++)
1270       obj->tkeys[i] = *((aseTransform *)tkeys[i]);
1271   }
1272 	return TRUE;
1273 }
1274 
1275 
parse_object(aseObject::Type type)1276 static int parse_object( aseObject::Type type )
1277 {
1278   aseObject* obj = new aseObject ( type ) ;
1279 
1280   char* token;
1281   int startLevel = parser.level;
1282   while ((token = parser.getLine( startLevel )) != NULL)
1283   {
1284     if (!strcmp(token,"*NODE_NAME"))
1285     {
1286       if ( !obj->name )
1287       {
1288         char* name;
1289 				if (! parser.parseString(name, "obj name"))
1290 					return FALSE;
1291 
1292 
1293         obj->name = ulStrDup ( name ) ;
1294       }
1295     }
1296     else if (!strcmp(token,"*NODE_PARENT"))
1297     {
1298       if ( !obj->parent )
1299       {
1300         char* name;
1301 				if (! parser.parseString(name, "parent name"))
1302 					return FALSE;
1303 
1304 
1305         obj->parent = ulStrDup ( name ) ;
1306       }
1307     }
1308     else if (!strcmp(token,"*NODE_TM"))
1309     {
1310       bool target = false ;
1311       bool match = false ;
1312       int startLevel = parser.level;
1313       while ((token = parser.getLine( startLevel )) != NULL)
1314       {
1315         if (!strcmp(token,"*NODE_NAME"))
1316         {
1317           char* name;
1318   				if (! parser.parseString(name, "obj name"))
1319   					return FALSE;
1320           if ( obj->name && !strcmp(name,obj->name) )
1321             match = true ;
1322           if ( strstr(name,".Target") != NULL )
1323             target = true ;
1324         }
1325         else if (match)
1326         {
1327           if (!strcmp(token,"*TM_POS"))
1328           {
1329             if (! parser.parseFloat(obj->pos[0], "pos.x"))
1330               return FALSE;
1331             if (! parser.parseFloat(obj->pos[1], "pos.y"))
1332               return FALSE;
1333             if (! parser.parseFloat(obj->pos[2], "pos.z"))
1334               return FALSE;
1335             sgCopyVec3 ( obj->target, obj->pos ) ;
1336           }
1337           else if (!strcmp(token,"*INHERIT_POS"))
1338           {
1339             int temp ;
1340             if (! parser.parseInt(temp, "inherit_pos.x"))
1341               return FALSE;
1342             obj->inherit_pos[0] = ( temp != 0 ) ;
1343             if (! parser.parseInt(temp, "inherit_pos.y"))
1344               return FALSE;
1345             obj->inherit_pos[1] = ( temp != 0 ) ;
1346             if (! parser.parseInt(temp, "inherit_pos.z"))
1347               return FALSE;
1348             obj->inherit_pos[2] = ( temp != 0 ) ;
1349           }
1350         }
1351         else if (target)
1352         {
1353           if (!strcmp(token,"*TM_POS"))
1354           {
1355             if (! parser.parseFloat(obj->target[0], "pos.x"))
1356               return FALSE;
1357             if (! parser.parseFloat(obj->target[1], "pos.y"))
1358               return FALSE;
1359             if (! parser.parseFloat(obj->target[2], "pos.z"))
1360               return FALSE;
1361           }
1362         }
1363       }
1364     }
1365     else if (!strcmp(token,"*MESH"))
1366     {
1367       if (! parse_mesh( obj ))
1368 				return FALSE;
1369     }
1370     else if (!strcmp(token,"*MESH_ANIMATION"))
1371     {
1372       int startLevel = parser.level;
1373       while ((token = parser.getLine( startLevel )) != NULL)
1374       {
1375         if (!strcmp(token,"*MESH"))
1376         {
1377           if (! parse_mesh( obj ))
1378 						return FALSE;
1379         }
1380       }
1381     }
1382     else if (!strcmp(token,"*TM_ANIMATION"))
1383     {
1384       if (! parse_tkeys( obj ))
1385 				return FALSE;
1386     }
1387     else if (!strcmp(token,"*MATERIAL_REF"))
1388     {
1389       if (! parser.parseUInt(obj->mat_index, "mat #"))
1390 				return FALSE;
1391     }
1392   }
1393 
1394   //if ( obj->parent != NULL )
1395   //  ulSetError( UL_DEBUG, "add_mesh: %s, parent=%s", obj->name, obj->parent ) ;
1396   //else
1397   //  ulSetError( UL_DEBUG, "add_mesh: %s", obj->name ) ;
1398 
1399   ssgEntity* mesh_entity = NULL ;
1400 
1401   if ( obj->mesh_count > 1 )
1402   {
1403     //how many frames?
1404     int num_frames = 0 ;
1405     int i ;
1406     for ( i=0; i<aseObject::MAX_FRAMES; i++ )
1407     {
1408       aseMesh* mesh = obj->mesh_list [ i ] ;
1409       if ( mesh != NULL )
1410         num_frames ++ ;
1411     }
1412 
1413     //allocate selector
1414     ssgSelector* selector = new ssgSelector ( num_frames ) ;
1415 
1416     //init
1417     for ( i=0; i<aseObject::MAX_FRAMES; i++ )
1418     {
1419       aseMesh* mesh = obj->mesh_list [ i ] ;
1420       if ( mesh == NULL )
1421         continue ;
1422 
1423       u32 num_subs = count_sub_materials ( obj->mat_index );
1424       if ( num_subs > 1 )
1425       {
1426         //break apart the mesh for each sub material
1427         ssgBranch* branch = new ssgBranch ;
1428         for ( u32 sub_index=0; sub_index<num_subs; sub_index++ )
1429         {
1430           ssgLeaf* leaf = add_mesh ( obj, mesh, sub_index );
1431           if ( leaf )
1432             branch -> addKid ( leaf ) ;
1433         }
1434         selector -> addKid ( branch ) ;
1435       }
1436       else
1437       {
1438         ssgLeaf* leaf = add_mesh ( obj, mesh, 0 ) ;
1439         if ( leaf )
1440           selector -> addKid ( leaf ) ;
1441       }
1442     }
1443 
1444     selector -> selectStep ( 0 ) ;
1445     mesh_entity = current_options -> createSelector ( selector ) ;
1446   }
1447   else if ( obj->mesh_list [ 0 ] != NULL )
1448   {
1449     aseMesh* mesh = obj->mesh_list [ 0 ] ;
1450     ssgBranch* branch = new ssgBranch ;
1451 
1452     u32 num_faces = mesh -> num_faces ;
1453     if ( num_faces == 0 )
1454     {
1455       ssgLeaf* leaf = add_points( obj, mesh ) ;
1456       if ( leaf )
1457         branch -> addKid ( leaf ) ;
1458     }
1459     else
1460     {
1461       u32 num_subs = count_sub_materials ( obj->mat_index );
1462       if ( num_subs > 1 )
1463       {
1464         //break apart the mesh for each sub material
1465         for ( u32 sub_index=0; sub_index<num_subs; sub_index++ )
1466         {
1467           ssgLeaf* leaf = add_mesh ( obj, mesh, sub_index );
1468           if ( leaf )
1469             branch -> addKid ( leaf ) ;
1470         }
1471       }
1472       else
1473       {
1474         ssgLeaf* leaf = add_mesh ( obj, mesh, 0 );
1475         if ( leaf )
1476           branch -> addKid ( leaf ) ;
1477       }
1478     }
1479 
1480     mesh_entity = branch ;
1481   }
1482   else
1483   {
1484     ssgBranch* branch = new ssgBranch ;
1485     ssgLeaf* leaf = add_points( obj, NULL ) ;
1486     if ( leaf )
1487       branch -> addKid ( leaf ) ;
1488     mesh_entity = branch ;
1489   }
1490 
1491   if ( mesh_entity != NULL )
1492   {
1493     //add to graph -- find parent branch
1494     ssgBranch* parent_branch ;
1495     if ( obj->parent )
1496     {
1497       ssgEntity* found = top_branch -> getByName ( obj->parent ) ;
1498       if ( found != NULL )
1499       {
1500         assert ( found -> isAKindOf ( ssgTypeBranch() ) ) ;
1501         parent_branch = (ssgBranch *) found ;
1502       }
1503       else
1504       {
1505         //parser.error("object %s: parent %s not seen",obj->name,obj->parent);
1506         parent_branch = top_branch ;
1507       }
1508     }
1509     else
1510     {
1511       parent_branch = top_branch ;
1512     }
1513 
1514     if ( obj->num_tkeys > 0 )
1515     {
1516       ssgAnimTransform * at = new ssgAnimTransform;
1517       at->setNum( obj->num_tkeys );
1518 
1519       /*
1520       Build the transforms
1521       */
1522       sgMat4 rmat;
1523       sgMakeIdentMat4 ( rmat ) ;
1524       at->setATransform ( rmat, 0);
1525 
1526       for ( u32 i = 1 ; i < obj->num_tkeys ; i++ )
1527       {
1528         aseTransform* tkey = obj->tkeys + i ;
1529 
1530         sgVec3 pos ;
1531         sgMat4 tmp ;
1532         sgMat4 mat ;
1533 
1534         /*
1535         *  compute rmat
1536         *  the key rotation is additive to the last rotation
1537         */
1538         sgMakeRotMat4 ( tmp, -tkey->angle * SG_RADIANS_TO_DEGREES, tkey->axis ) ;
1539         sgPostMultMat4 ( rmat, tmp ) ;
1540 
1541         /*
1542         *  rotation is around the mesh pivot point (obj->pos)
1543         *  translate -obj->pos
1544         */
1545         sgCopyVec3 ( pos, obj->pos ) ;
1546         sgNegateVec3 ( pos ) ;
1547         sgMakeTransMat4 ( mat, pos ) ;
1548 
1549         /*
1550         *  perform the rotation
1551         */
1552         sgPostMultMat4 ( mat, rmat ) ;
1553 
1554         /*
1555         *  translate obj->pos + tkey->pos
1556         */
1557         sgCopyVec3 ( pos, obj->pos ) ;
1558         sgAddVec3 ( pos, tkey->pos ) ;
1559         sgMakeTransMat4 ( tmp, pos ) ;
1560         sgPostMultMat4 ( mat, tmp ) ;
1561 
1562         at->setATransform ( mat, i);
1563       }
1564       // insert the ssgAnimTransform into the scene graph:
1565       at-> addKid ( mesh_entity ) ;
1566       mesh_entity = at;
1567     }
1568 
1569     parent_branch -> addKid ( mesh_entity ) ;
1570     mesh_entity -> setName ( obj->name ) ;
1571   }
1572 
1573   delete obj ;
1574 	return TRUE;
1575 }
1576 
1577 
parse()1578 static bool parse()
1579 {
1580   materials = new aseMaterial* [ MAX_MATERIALS ];
1581   if ( !materials )
1582   {
1583     parser.error("not enough memory");
1584     return false ;
1585   }
1586 
1587   num_materials = 0 ;
1588 
1589   first_frame = 0 ;
1590   last_frame = 0 ;
1591   frame_speed = 0 ;
1592   ticks_per_frame = 0 ;
1593   num_frames = 0 ;
1594 
1595   bool firsttime = true;
1596   char* token;
1597   int startLevel = parser.level;
1598   while ((token = parser.getLine( startLevel )) != NULL)
1599   {
1600     if (firsttime)
1601     {
1602       if (strcmp(token,"*3DSMAX_ASCIIEXPORT"))
1603       {
1604         parser.error("not ASE format");
1605         return false ;
1606       }
1607 			u32 version_number;
1608 			if (! parser.parseUInt(version_number, "version number") )
1609         return false ;
1610       if ( version_number != 200)
1611       {
1612         parser.error("invalid %s version",token);
1613         return false ;
1614       }
1615       firsttime = false;
1616     }
1617     else if (!strcmp(token,"*SCENE"))
1618     {
1619       int startLevel = parser.level;
1620       while ((token = parser.getLine( startLevel )) != NULL)
1621       {
1622         if (!strcmp(token,"*SCENE_FIRSTFRAME"))
1623         {
1624           if (! parser.parseUInt(first_frame, "FIRSTFRAME #"))
1625 						return FALSE;
1626         }
1627         else if (!strcmp(token,"*SCENE_LASTFRAME"))
1628         {
1629           if (! parser.parseUInt(last_frame, "LASTFRAME #"))
1630 						return FALSE;
1631           num_frames = last_frame - first_frame + 1;
1632         }
1633         else if (!strcmp(token,"*SCENE_FRAMESPEED"))
1634         {
1635           if (! parser.parseUInt(frame_speed, "FRAMESPEED #"))
1636 						return FALSE;
1637         }
1638         else if (!strcmp(token,"*SCENE_TICKSPERFRAME"))
1639         {
1640           if (! parser.parseUInt(ticks_per_frame, "TICKSPERFRAME #"))
1641 						return FALSE;
1642         }
1643       }
1644     }
1645     else if (!strcmp(token,"*MATERIAL_LIST"))
1646     {
1647       if (! parse_material_list())
1648 				return FALSE;
1649     }
1650     else if (!strcmp(token,"*GEOMOBJECT"))
1651     {
1652       if (! parse_object( aseObject::GEOM ))
1653 				return FALSE;
1654     }
1655     else if (!strcmp(token,"*HELPEROBJECT"))
1656     {
1657       if (! parse_object( aseObject::HELPER ))
1658 				return FALSE;
1659     }
1660     else if (!strcmp(token,"*CAMERAOBJECT"))
1661     {
1662       if (! parse_object( aseObject::CAMERA ))
1663 				return FALSE;
1664     }
1665   }
1666   return true ;
1667 }
1668 
1669 
parse_free()1670 static void parse_free()
1671 {
1672   u32 i ;
1673   for ( i = 0 ; i < num_materials ; i++ )
1674   {
1675     delete [] materials[ i ] -> name ;
1676     delete [] materials[ i ] -> tfname ;
1677     delete materials[ i ] ;
1678   }
1679   delete[] materials ;
1680   materials = 0 ;
1681 }
1682 
1683 
ssgLoadASE(const char * fname,const ssgLoaderOptions * options)1684 ssgEntity *ssgLoadASE ( const char *fname, const ssgLoaderOptions* options )
1685 {
1686   ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ;
1687   current_options = ssgGetCurrentOptions () ;
1688 
1689   top_branch = new ssgBranch ;
1690   if ( !parser.openFile( fname, &parser_spec ) )
1691   {
1692     delete top_branch ;
1693 		return 0;
1694   }
1695   if ( !parse() )
1696   {
1697     delete top_branch ;
1698     top_branch = 0 ;
1699   }
1700   parse_free();
1701   parser.closeFile();
1702 
1703   return top_branch ;
1704 }
1705