ivcon.c
Go to the documentation of this file.
00001 /* ivcon.c  24 May 2001 */
00002 
00003 /*
00004   Purpose:
00005 
00006    IVCON converts various 3D graphics files.
00007 
00008   Acknowledgements:
00009 
00010     Coding, comments, and advice were supplied by a number of collaborators.
00011 
00012     John F Flanagan made some corrections to the 3D Studio Max routines.
00013 
00014     Zik Saleeba (zik@zikzak.net) enhanced the DXF routines, and added the 
00015     Golgotha GMOD routines.
00016 
00017     Thanks to Susan M. Fisher, University of North Carolina,
00018     Department of Computer Science, for pointing out a coding error
00019     in FACE_NULL_DELETE that was overwriting all the data!
00020 
00021   Modified:
00022 
00023     04 July 2000
00024 
00025   Author:
00026 
00027     John Burkardt
00028 */
00029  
00030 #include <ctype.h>
00031 #include <math.h>
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 
00036 #define FALSE 0
00037 #define TRUE 1
00038 
00039 #define ERROR 1
00040 #define G1_SECTION_MODEL_QUADS 18
00041 #define G1_SECTION_MODEL_TEXTURE_NAMES 19
00042 #define G1_SECTION_MODEL_VERT_ANIMATION 20
00043 #define GMOD_MAX_SECTIONS 32
00044 #define GMOD_UNUSED_VERTEX 65535
00045 #define PI 3.141592653589793238462643
00046 #define SUCCESS 0
00047 
00048 #define DEG_TO_RAD   ( PI / 180.0 )
00049 #define RAD_TO_DEG   ( 180.0 / PI )
00050 
00051 /******************************************************************************/
00052 
00053 /* GLOBAL DATA */
00054 
00055 /******************************************************************************/
00056 
00057 /*
00058   BACKGROUND_RGB[3], the background color.
00059 
00060   BYTE_SWAP, byte swapping option.
00061 
00062   COR3[3][COR3_MAX], the coordinates of nodes.
00063 
00064   COR3_MATERIAL[COR3_MAX], the index of the material of each node.
00065 
00066   COR3_MAX, the maximum number of points.
00067 
00068   COR3_NORMAL[3][COR3_MAX], normal vectors associated with nodes.
00069 
00070   COR3_NUM, the number of points.
00071 
00072   COR3_RGB[3][COR3_MAX], RGB colors associated with nodes.
00073 
00074   COR3_TEX_UV[2][COR3_MAX], texture coordinates associated with nodes.
00075 
00076   FACE[ORDER_MAX][FACE_MAX] contains the index of the I-th node making up face J.
00077 
00078   FACE_AREA(FACE_MAX), the area of each face.
00079 
00080   FACE_MATERIAL[FACE_MAX]; the material of each face.
00081 
00082   FACE_MAX, the maximum number of faces.
00083 
00084   FACE_NORMAL[3][FACE_MAX], the face normal vectors.
00085 
00086   FACE_NUM, the number of faces.
00087 
00088   FACE_ORDER[FACE_MAX], the number of vertices per face.
00089 
00090   FACE_TEX_UV[2][FACE_MAX], texture coordinates associated with faces.
00091 
00092   LINE_DEX[LINES_MAX], node indices, denoting polylines, each terminated by -1.
00093 
00094   LINE_MATERIAL[LINES_MAX], index into RGBCOLOR for line color.
00095 
00096   LINES_MAX, the maximum number of line definition items.
00097 
00098   LINE_NUM, the number of line definition items.
00099 
00100   LINE_PRUNE, pruning option ( 0 = no pruning, nonzero = pruning).
00101 
00102   MATERIAL_MAX, the maximum number of materials.
00103 
00104   MATERIAL_NUM, the number of materials.
00105 
00106   ORDER_MAX, the maximum number of vertices per face.
00107 
00108   TEXTURE_MAX, the maximum number of textures.
00109 
00110   TEXTURE_NAME[TEXTURE_MAX][LINE_MAX_LEN], ...
00111 
00112   TEXTURE_NUM, the number of textures.
00113 
00114   TRANSFORM_MATRIX[4][4], the current transformation matrix.
00115 
00116   VERTEX_MATERIAL[ORDER_MAX][FACE_MAX]; the material of vertices of faces.
00117 
00118   VERTEX_NORMAL[3][ORDER_MAX][FACE_MAX], normals at vertices of faces. 
00119 
00120   VERTEX_RGB[3][ORDER_MAX][FACE_MAX], colors of vertices of faces. 
00121 
00122   VERTEX_TEX_UV[2][ORDER_MAX][FACE_MAX], texture coordinates of vertices of faces.
00123 */
00124 
00125 #define COLOR_MAX 1000
00126 #define COR3_MAX 200000
00127 #define FACE_MAX 200000
00128 #define LINE_MAX_LEN 256
00129 #define LEVEL_MAX 10
00130 #define LINES_MAX 100000
00131 #define MATERIAL_MAX 100
00132 #define ORDER_MAX 10
00133 #define TEXTURE_MAX 100
00134 
00135 char   anim_name[LINE_MAX_LEN];
00136 float  background_rgb[3];
00137 int    bad_num;
00138 int    byte_swap;
00139 int    bytes_num;
00140 int    color_num;
00141 int    comment_num;
00142 
00143 float  cor3[3][COR3_MAX];
00144 int    cor3_material[COR3_MAX];
00145 float  cor3_normal[3][COR3_MAX];
00146 int    cor3_num;
00147 float  cor3_tex_uv[3][COR3_MAX];
00148 
00149 int    debug;
00150 
00151 int    dup_num;
00152 
00153 int    face[ORDER_MAX][FACE_MAX];
00154 float  face_area[FACE_MAX];
00155 int    face_flags[FACE_MAX];
00156 int    face_material[FACE_MAX];
00157 float  face_normal[3][FACE_MAX];
00158 int    face_num;
00159 int    face_object[FACE_MAX];
00160 int    face_order[FACE_MAX];
00161 int    face_smooth[FACE_MAX];
00162 float  face_tex_uv[2][FACE_MAX];
00163 
00164 char   filein_name[1024];
00165 char   fileout_name[1024];
00166 
00167 int    group_num;
00168 
00169 int    i;
00170 char   input[LINE_MAX_LEN];
00171 int    k;
00172 char   level_name[LEVEL_MAX][LINE_MAX_LEN];
00173 
00174 int    line_dex[LINES_MAX];
00175 int    line_material[LINES_MAX];
00176 int    line_num;
00177 int    line_prune;
00178 
00179 int    list[COR3_MAX];
00180 
00181 char   material_binding[80];
00182 char   material_name[MATERIAL_MAX][LINE_MAX_LEN];
00183 int    material_num;
00184 float  material_rgba[4][MATERIAL_MAX];
00185 
00186 char   mat_name[81];
00187 int    max_order2;
00188 
00189 char   normal_binding[80];
00190 float  normal_temp[3][ORDER_MAX*FACE_MAX];
00191 
00192 char   object_name[81];
00193 int    object_num;
00194 
00195 float  origin[3];
00196 float  pivot[3];
00197 float  rgbcolor[3][COLOR_MAX];
00198 char   temp_name[81];
00199 
00200 int    text_num;
00201 
00202 char   texture_binding[80];
00203 char   texture_name[TEXTURE_MAX][LINE_MAX_LEN];
00204 int    texture_num;
00205 float  texture_temp[2][ORDER_MAX*FACE_MAX];
00206 
00207 float  transform_matrix[4][4];
00208 
00209 int    vertex_material[ORDER_MAX][FACE_MAX];
00210 float  vertex_normal[3][ORDER_MAX][FACE_MAX];
00211 float  vertex_rgb[3][ORDER_MAX][FACE_MAX];
00212 float  vertex_tex_uv[2][ORDER_MAX][FACE_MAX];
00213 
00214 /******************************************************************************/
00215 
00216 /* FUNCTION PROTOTYPES */
00217 
00218 /******************************************************************************/
00219 
00220 int                main ( int argc, char **argv );
00221 int                ase_read ( FILE *filein );
00222 int                ase_write ( FILE *fileout );
00223 int                byu_read ( FILE *filein );
00224 int                byu_write ( FILE *fileout );
00225 int                char_index_last ( char* string, char c );
00226 int                char_pad ( int *char_index, int *null_index, char *string, 
00227                      int STRING_MAX );
00228 char               char_read ( FILE *filein );
00229 int                char_write ( FILE *fileout, char c );
00230 int                command_line ( char **argv );
00231 void               cor3_normal_set ( void );
00232 void               cor3_range ( void );
00233 void               data_check ( void );
00234 void               data_init ( void );
00235 int                data_read ( void );
00236 void               data_report ( void );
00237 int                data_write ( void );
00238 int                dxf_read ( FILE *filein );
00239 int                dxf_write ( FILE *fileout );
00240 void               edge_null_delete ( void );
00241 void               face_area_set ( void );
00242 void               face_normal_ave ( void );
00243 void               face_null_delete ( void );
00244 int                face_print ( int iface );
00245 void               face_reverse_order ( void );
00246 int                face_subset ( void );
00247 void               face_to_line ( void );
00248 void               face_to_vertex_material ( void );
00249 char              *file_ext ( char *file_name );
00250 float              float_read ( FILE *filein );
00251 float              float_reverse_bytes ( float x );
00252 int                float_write ( FILE *fileout, float float_val );
00253 int                gmod_arch_check ( void );
00254 int                gmod_read ( FILE *filein );
00255 float              gmod_read_float ( FILE *filein );
00256 unsigned short     gmod_read_w16 ( FILE *filein );
00257 unsigned long      gmod_read_w32 ( FILE *filein );
00258 int                gmod_write ( FILE *fileout );
00259 void               gmod_write_float ( float Val, FILE *fileout );
00260 void               gmod_write_w16 ( unsigned short Val, FILE *fileout );
00261 void               gmod_write_w32 ( unsigned long Val, FILE *fileout );
00262 void               hello ( void );
00263 void               help ( void );
00264 int                hrc_read ( FILE *filein );
00265 int                hrc_write ( FILE *fileout );
00266 void               init_program_data ( void );
00267 int                interact ( void );
00268 int                iv_read ( FILE *filein );
00269 int                iv_write ( FILE *fileout );
00270 int                ivec_max ( int n, int *a );
00271 int                leqi ( char* string1, char* string2 );
00272 long int           long_int_read ( FILE *filein );
00273 int                long_int_write ( FILE *fileout, long int int_val );
00274 void               news ( void );
00275 void               node_to_vertex_material ( void );
00276 int                obj_read ( FILE *filein );
00277 int                obj_write ( FILE *fileout );
00278 int                pov_write ( FILE *fileout );
00279 int                rcol_find ( float a[][COR3_MAX], int m, int n, float r[] );
00280 float              rgb_to_hue ( float r, float g, float b );
00281 short int          short_int_read ( FILE *filein );
00282 int                short_int_write ( FILE *fileout, short int int_val );
00283 int                smf_read ( FILE *filein );
00284 int                smf_write ( FILE *fileout );
00285 int                stla_read ( FILE *filein );
00286 int                stla_write ( FILE *fileout );
00287 int                stlb_read ( FILE *filein );
00288 int                stlb_write ( FILE *fileout );
00289 void               tds_pre_process ( void );
00290 int                tds_read ( FILE *filein );
00291 unsigned long int  tds_read_ambient_section ( FILE *filein );
00292 unsigned long int  tds_read_background_section ( FILE *filein );
00293 unsigned long int  tds_read_boolean ( unsigned char *boolean, FILE *filein );
00294 unsigned long int  tds_read_camera_section ( FILE *filein );
00295 unsigned long int  tds_read_edit_section ( FILE *filein, int *views_read );
00296 unsigned long int  tds_read_keyframe_section ( FILE *filein, int *views_read );
00297 unsigned long int  tds_read_keyframe_objdes_section ( FILE *filein );
00298 unsigned long int  tds_read_light_section ( FILE *filein );
00299 unsigned long int  tds_read_u_long_int ( FILE *filein );
00300 int                tds_read_long_name ( FILE *filein );
00301 unsigned long int  tds_read_matdef_section ( FILE *filein );
00302 unsigned long int  tds_read_material_section ( FILE *filein );
00303 int                tds_read_name ( FILE *filein );
00304 unsigned long int  tds_read_obj_section ( FILE *filein );
00305 unsigned long int  tds_read_object_section ( FILE *filein );
00306 unsigned long int  tds_read_tex_verts_section ( FILE *filein );
00307 unsigned long int  tds_read_texmap_section ( FILE *filein );
00308 unsigned short int tds_read_u_short_int ( FILE *filein );
00309 unsigned long int  tds_read_spot_section ( FILE *filein );
00310 unsigned long int  tds_read_unknown_section ( FILE *filein );
00311 unsigned long int  tds_read_view_section ( FILE *filein, int *views_read );
00312 unsigned long int  tds_read_vp_section ( FILE *filein, int *views_read );
00313 int                tds_write ( FILE *fileout );
00314 int                tds_write_string ( FILE *fileout, char *string );
00315 int                tds_write_u_short_int ( FILE *fileout, 
00316                      unsigned short int int_val );
00317 int                tec_write ( FILE *fileout );
00318 void               tmat_init ( float a[4][4] );
00319 void               tmat_mxm ( float a[4][4], float b[4][4], float c[4][4] );
00320 void               tmat_mxp ( float a[4][4], float x[4], float y[4] );
00321 void               tmat_mxp2 ( float a[4][4], float x[][3], float y[][3], int n );
00322 void               tmat_mxv ( float a[4][4], float x[4], float y[4] );
00323 void               tmat_rot_axis ( float a[4][4], float b[4][4], float angle, 
00324                      char axis );
00325 void               tmat_rot_vector ( float a[4][4], float b[4][4], float angle, 
00326                      float v1, float v2, float v3 );
00327 void               tmat_scale ( float a[4][4], float b[4][4], float sx, float sy, 
00328                      float sz );
00329 void               tmat_shear ( float a[4][4], float b[4][4], char *axis, 
00330                      float s );
00331 void               tmat_trans ( float a[4][4], float b[4][4], float x, float y, 
00332                      float z );
00333 int                tria_read ( FILE *filein );
00334 int                tria_write ( FILE *fileout );
00335 int                trib_read ( FILE *filein );
00336 int                trib_write ( FILE *fileout );
00337 int                txt_write ( FILE *fileout );
00338 int                ucd_write ( FILE *fileout );
00339 void               vertex_normal_set ( void );
00340 void               vertex_to_face_material ( void );
00341 void               vertex_to_node_material ( void );
00342 int                vla_read ( FILE *filein );
00343 int                vla_write ( FILE *fileout );
00344 int                wrl_write ( FILE *filout );
00345 int                xgl_write ( FILE *fileout );
00346 
00347 /******************************************************************************/
00348 
00349 int main ( int argc, char **argv )
00350 
00351 /******************************************************************************/
00352 
00353 /*
00354   Purpose:
00355 
00356     MAIN is the main program for converting graphics files.
00357 
00358   Modified:
00359 
00360     26 May 1999
00361 
00362   Author:
00363  
00364     John Burkardt
00365 */
00366 {
00367   int result;
00368 /*
00369   Initialize the program data.
00370 */
00371   init_program_data ( );
00372 /*
00373   If there are at least two command line arguments, call COMMAND_LINE.
00374   Otherwise call INTERACT and get information from the user.
00375 */ 
00376   if ( argc >= 2 ) {
00377     result = command_line ( argv );
00378   }
00379   else {
00380     result = interact (  );
00381   }
00382 
00383   return result;
00384 }
00385 /******************************************************************************/
00386 
00387 int ase_read ( FILE *filein )
00388 
00389 /******************************************************************************/
00390 
00391 /*
00392   Purpose:
00393    
00394     ASE_READ reads an AutoCAD ASE file.
00395 
00396   Modified:
00397 
00398     22 May 1999
00399 
00400   Author:
00401 
00402     John Burkardt
00403 */
00404 {
00405   float bval;
00406   int   count;
00407   float gval;
00408   int   i;
00409   int   iface;
00410   int   ivert;
00411   int   iword;
00412   int   level;
00413   char *next;
00414   int   nlbrack;
00415   int   nrbrack;
00416   int   cor3_num_old;
00417   int   face_num_old;
00418   float rval;
00419   float temp;
00420   int   width;
00421   char  word[LINE_MAX_LEN];
00422   char  word1[LINE_MAX_LEN];
00423   char  word2[LINE_MAX_LEN];
00424   char  wordm1[LINE_MAX_LEN];
00425   float x;
00426   float y;
00427   float z;
00428 
00429   level = 0;
00430   strcpy ( level_name[0], "Top" );
00431   cor3_num_old = cor3_num;
00432   face_num_old = face_num;
00433   nlbrack = 0;
00434   nrbrack = 0;
00435 
00436   strcpy ( word, " " );
00437   strcpy ( wordm1, " " );
00438 /*
00439   Read a line of text from the file.
00440 */
00441 
00442   for ( ;; ) {
00443 
00444     if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
00445       break;
00446     }
00447 
00448     text_num = text_num + 1;
00449     next = input;
00450     iword = 0;
00451 /*
00452   Read the next word from the line.
00453 */
00454     for ( ;; ) {
00455 
00456       strcpy ( wordm1, word );
00457       strcpy ( word, " " );
00458 
00459       count = sscanf ( next, "%s%n", word, &width );
00460       next = next + width;
00461 
00462       if ( count <= 0 ) {
00463         break;
00464       }
00465 
00466       iword = iword + 1;
00467 
00468       if ( iword == 1 ) {
00469         strcpy ( word1, word );
00470       }
00471 /*
00472   In case the new word is a bracket, update the bracket count.
00473 */
00474       if ( strcmp ( word, "{" ) == 0 ) {
00475 
00476         nlbrack = nlbrack + 1;
00477         level = nlbrack - nrbrack;
00478         strcpy ( level_name[level], wordm1 );
00479       }
00480       else if ( strcmp ( word, "}" ) == 0 ) {
00481 
00482         nrbrack = nrbrack + 1;
00483 
00484         if ( nlbrack < nrbrack ) {
00485 
00486           printf ( "\n" );
00487           printf ( "ASE_READ - Fatal error!\n" );
00488           printf ( "  Extraneous right bracket on line %d\n", text_num );
00489           printf ( "  Currently processing field:\n" );
00490           printf ( "%s\n", level_name[level] );
00491           return ERROR;
00492         }
00493 
00494       }
00495 /*
00496   *3DSMAX_ASCIIEXPORT  200
00497 */
00498       if ( strcmp ( word1, "*3DSMAX_ASCIIEXPORT" ) == 0 ) {
00499         break;
00500       }
00501 /*
00502   *COMMENT
00503 */
00504       else if ( strcmp ( word1, "*COMMENT" ) == 0 ) {
00505         break;
00506       }
00507 /*
00508   *GEOMOBJECT
00509 */
00510       else if ( strcmp ( level_name[level], "*GEOMOBJECT" ) == 0 ) {
00511 
00512         if ( strcmp ( word, "{" ) == 0 ) {
00513           continue;
00514         }
00515         else if ( strcmp ( word, "}" ) == 0 ) {
00516           level = nlbrack - nrbrack;
00517           continue;
00518         }
00519 /*
00520   Why don't you read and save this name?
00521 */
00522         else if ( strcmp ( word, "*NODE_NAME" ) == 0 ) {
00523           break;
00524         }
00525         else if ( strcmp ( word, "*NODE_TM" ) == 0 ) {
00526           continue;
00527         }
00528         else if ( strcmp ( word, "*MESH" ) == 0 ) {
00529           continue;
00530         }
00531         else if ( strcmp ( word, "*PROP_CASTSHADOW" ) == 0 ) {
00532           break;
00533         }
00534         else if ( strcmp ( word, "*PROP_MOTIONBLUR" ) == 0 ) {
00535           break;
00536         }
00537         else if ( strcmp ( word, "*PROP_RECVSHADOW" ) == 0 ) {
00538           break;
00539         }
00540         else {
00541           bad_num = bad_num + 1;
00542           printf ( "Bad data in GEOMOBJECT, line %d\n", text_num );
00543           break;
00544         }
00545       }
00546 /*
00547   *MESH
00548 */
00549       else if ( strcmp ( level_name[level], "*MESH" ) == 0 ) {
00550 
00551         if ( strcmp ( word, "{" ) == 0 ) {
00552           continue;
00553         }
00554         else if ( strcmp ( word, "}" ) == 0 ) {
00555           level = nlbrack - nrbrack;
00556           continue;
00557         }
00558         else if ( strcmp ( word, "*MESH_CFACELIST" ) == 0 ) {
00559           continue;
00560         }
00561         else if ( strcmp ( word, "*MESH_CVERTLIST" ) == 0 ) {
00562           continue;
00563         }
00564         else if ( strcmp ( word, "*MESH_FACE_LIST" ) == 0 ) {
00565           continue;
00566         }
00567         else if ( strcmp ( word, "*MESH_NORMALS" ) == 0 ) {
00568           continue;
00569         }
00570         else if ( strcmp ( word, "*MESH_NUMCVERTEX" ) == 0 ) {
00571           break;
00572         }
00573         else if ( strcmp ( word, "*MESH_NUMCVFACES" ) == 0 ) {
00574           break;
00575         }
00576         else if ( strcmp ( word, "*MESH_NUMFACES" ) == 0 ) {
00577           break;
00578         }
00579         else if ( strcmp ( word, "*MESH_NUMTVERTEX" ) == 0 ) {
00580           break;
00581         }
00582         else if ( strcmp ( word, "*MESH_NUMTVFACES" ) == 0 ) {
00583           break;
00584         }
00585         else if ( strcmp ( word, "*MESH_NUMVERTEX" ) == 0 ) {
00586           break;
00587         }
00588         else if ( strcmp ( word, "*MESH_TFACELIST" ) == 0 ) {
00589           continue;
00590         }
00591         else if ( strcmp ( word, "*MESH_TVERTLIST" ) == 0 ) {
00592           continue;
00593         }
00594         else if ( strcmp ( word, "*MESH_VERTEX_LIST" ) == 0 ) {
00595           continue;
00596         }
00597         else if ( strcmp ( word, "*TIMEVALUE" ) == 0 ) {
00598           break;
00599         }
00600         else {
00601           bad_num = bad_num + 1;
00602           printf ( "Bad data in MESH, line %d\n", text_num );
00603           break;
00604         }
00605       }
00606 /*
00607   *MESH_CFACELIST
00608 */
00609       else if ( strcmp ( level_name[level], "*MESH_CFACELIST" ) == 0 ) {
00610 
00611         if ( strcmp ( word, "{" ) == 0 ) {
00612           continue;
00613         }
00614         else if ( strcmp ( word, "}" ) == 0 ) {
00615           level = nlbrack - nrbrack;
00616           continue;
00617         }
00618         else if ( strcmp ( word, "*MESH_CFACE" ) == 0 ) {
00619           break;
00620         }
00621         else {
00622           bad_num = bad_num + 1;
00623           printf ( "Bad data in MESH_CFACE, line %d\n", text_num );
00624           break;
00625         }
00626       }
00627 /*
00628   *MESH_CVERTLIST
00629 
00630   Mesh vertex indices must be incremented by COR3_NUM_OLD before being stored
00631   in the internal array.
00632 */
00633       else if ( strcmp ( level_name[level], "*MESH_CVERTLIST" ) == 0 ) {
00634 
00635         if ( strcmp ( word, "{" ) == 0 ) {
00636           continue;
00637         }
00638         else if ( strcmp ( word, "}" ) == 0 ) {
00639           level = nlbrack - nrbrack;
00640           continue;
00641         }
00642         else if ( strcmp ( word, "*MESH_VERTCOL" ) == 0 ) {
00643 
00644           count = sscanf ( next, "%d%n", &i, &width );
00645           next = next + width;
00646 
00647           i = i + cor3_num_old;
00648 
00649           count = sscanf ( next, "%f%n", &rval, &width );
00650           next = next + width;
00651 
00652           count = sscanf ( next, "%f%n", &gval, &width );
00653           next = next + width;
00654 
00655           count = sscanf ( next, "%f%n", &bval, &width );
00656           next = next + width;
00657 
00658           if ( material_num < MATERIAL_MAX ) {
00659             material_rgba[0][material_num] = rval;
00660             material_rgba[1][material_num] = gval;
00661             material_rgba[2][material_num] = bval;
00662             material_rgba[3][material_num] = 1.0;
00663           }
00664 
00665           material_num = material_num + 1;
00666           cor3_material[i] = material_num;
00667         }
00668         else {
00669           bad_num = bad_num + 1;
00670           printf ( "\n" );
00671           printf ( "ASE_READ - Warning!\n" );
00672           printf ( "  Bad data in MESH_CVERTLIST, line %d\n", text_num );
00673           break;
00674         }
00675 
00676       }
00677 /*
00678   *MESH_FACE_LIST
00679   This coding assumes a face is always triangular or quadrilateral.
00680 */
00681       else if ( strcmp ( level_name[level], "*MESH_FACE_LIST" ) == 0 ) {
00682 
00683         if ( strcmp ( word, "{" ) == 0 ) {
00684           continue;
00685         }
00686         else if ( strcmp ( word, "}" ) == 0 ) {
00687           level = nlbrack - nrbrack;
00688           continue;
00689         }
00690         else if ( strcmp ( word, "*MESH_FACE" ) == 0 ) {
00691 
00692           if ( face_num < FACE_MAX ) {
00693 
00694             face_material[face_num] = 0;
00695             face_order[face_num] = 0;
00696 
00697             count = sscanf ( next, "%d%n", &i, &width );
00698             next = next + width;
00699 
00700             count = sscanf ( next, "%s%n", word2, &width );
00701             next = next + width;
00702             count = sscanf ( next, "%s%n", word2, &width );
00703             next = next + width;
00704 
00705             count = sscanf ( next, "%d%n", &i, &width );
00706             next = next + width;
00707             face[0][face_num] = i + cor3_num_old;
00708             face_order[face_num] = face_order[face_num] + 1;
00709 
00710             count = sscanf ( next, "%s%n", word2, &width );
00711             next = next + width;
00712 
00713             count = sscanf ( next, "%d%n", &i, &width );
00714             next = next + width;
00715             face[1][face_num] = i + cor3_num_old;
00716             face_order[face_num] = face_order[face_num] + 1;
00717 
00718             count = sscanf ( next, "%s%n", word2, &width );
00719             next = next + width;
00720 
00721             count = sscanf ( next, "%d%n", &i, &width );
00722             next = next + width;
00723             face[2][face_num] = i + cor3_num_old;
00724             face_order[face_num] = face_order[face_num] + 1;
00725 
00726             count = sscanf ( next, "%s%n", word2, &width );
00727             next = next + width;
00728 
00729             if ( strcmp ( word2, "D:" ) == 0 ) {
00730               count = sscanf ( next, "%d%n", &i, &width );
00731               next = next + width;
00732               face[3][face_num] = i + cor3_num_old;
00733               face_order[face_num] = face_order[face_num] + 1;
00734             }
00735           }
00736 
00737           face_num = face_num + 1;
00738 
00739           break;
00740 
00741         }
00742         else {
00743           bad_num = bad_num + 1;
00744           printf ( "Bad data in MESH_FACE_LIST, line %d\n", text_num );
00745           break;
00746         }
00747       }
00748 /*
00749   *MESH_NORMALS
00750 */
00751       else if ( strcmp ( level_name[level], "*MESH_NORMALS" ) == 0 ) {
00752 
00753         if ( strcmp ( word, "{" ) == 0 ) {
00754           continue;
00755         }
00756         else if ( strcmp ( word, "}" ) == 0 ) {
00757           level = nlbrack - nrbrack;
00758           continue;
00759         }
00760         else if ( strcmp ( word, "*MESH_FACENORMAL" ) == 0 ) {
00761 
00762           count = sscanf ( next, "%d%n", &iface, &width );
00763           next = next + width;
00764 
00765           count = sscanf ( next, "%f%n", &x, &width );
00766           next = next + width;
00767 
00768           count = sscanf ( next, "%f%n", &y, &width );
00769           next = next + width;
00770 
00771           count = sscanf ( next, "%f%n", &z, &width );
00772           next = next + width;
00773 
00774           iface = iface + face_num_old;
00775           ivert = 0;
00776 
00777           face_normal[0][iface] = x;
00778           face_normal[1][iface] = y;
00779           face_normal[2][iface] = z;
00780 
00781           break;
00782 
00783         }
00784         else if ( strcmp ( word, "*MESH_VERTEXNORMAL" ) == 0 ) {
00785 
00786           count = sscanf ( next, "%d%n", &i, &width );
00787           next = next + width;
00788 
00789           count = sscanf ( next, "%f%n", &x, &width );
00790           next = next + width;
00791 
00792           count = sscanf ( next, "%f%n", &y, &width );
00793           next = next + width;
00794 
00795           count = sscanf ( next, "%f%n", &z, &width );
00796           next = next + width;
00797 
00798           vertex_normal[0][ivert][iface] = x;
00799           vertex_normal[1][ivert][iface] = y;
00800           vertex_normal[2][ivert][iface] = z;
00801           ivert = ivert + 1;
00802 
00803           break;
00804         }
00805         else {
00806           bad_num = bad_num + 1;
00807           printf ( "Bad data in MESH_NORMALS, line %d\n", text_num );
00808           break;
00809         }
00810       }
00811 /*
00812   *MESH_TFACELIST
00813 */
00814       else if ( strcmp ( level_name[level], "*MESH_TFACELIST" ) == 0 ) {
00815 
00816         if ( strcmp ( word, "{" ) == 0 ) {
00817           continue;
00818         }
00819         else if ( strcmp ( word, "}" ) == 0 ) {
00820           level = nlbrack - nrbrack;
00821           continue;
00822         }
00823         else if ( strcmp ( word1, "*MESH_TFACE" ) == 0 ) {
00824           break;
00825         }
00826         else {
00827           bad_num = bad_num + 1;
00828           printf ( "Bad data in MESH_TFACE_LIST, line %d\n", text_num );
00829           break;
00830         }
00831       }
00832 /*
00833   *MESH_TVERTLIST
00834 */
00835       else if ( strcmp ( level_name[level], "*MESH_TVERTLIST" ) == 0 ) {
00836 
00837         if ( strcmp ( word, "{" ) == 0 ) {
00838           continue;
00839         }
00840         else if ( strcmp ( word, "}" ) == 0 ) {
00841           level = nlbrack - nrbrack;
00842           continue;
00843         }
00844         else if ( strcmp ( word1, "*MESH_TVERT" ) == 0  ) {
00845           break;
00846         }
00847         else {
00848           bad_num = bad_num + 1;
00849           printf ( "Bad data in MESH_TVERTLIST, line %d\n", text_num );
00850           break;
00851         }
00852       }
00853 /*
00854   *MESH_VERTEX_LIST
00855 */
00856       else if ( strcmp ( level_name[level], "*MESH_VERTEX_LIST" ) == 0 ) {
00857 
00858         if ( strcmp ( word, "{" ) == 0 ) {
00859           cor3_num_old = cor3_num;
00860           continue;
00861         }
00862         else if ( strcmp ( word, "}" ) == 0 ) {
00863           level = nlbrack - nrbrack;
00864           continue;
00865         }
00866         else if ( strcmp ( word1, "*MESH_VERTEX" ) == 0 ) {
00867 
00868           count = sscanf ( next, "%d%n", &i, &width );
00869           next = next + width;
00870 
00871           count = sscanf ( next, "%f%n", &x, &width );
00872           next = next + width;
00873 
00874           count = sscanf ( next, "%f%n", &y, &width );
00875           next = next + width;
00876 
00877           count = sscanf ( next, "%f%n", &z, &width );
00878           next = next + width;
00879 
00880           i = i + cor3_num_old;
00881           if ( cor3_num < i + 1 ) {
00882             cor3_num = i + 1;
00883           }
00884 
00885           if ( i < COR3_MAX ) {
00886 
00887             cor3[0][i] =
00888               transform_matrix[0][0] * x 
00889             + transform_matrix[0][1] * y 
00890             + transform_matrix[0][2] * z 
00891             + transform_matrix[0][3];
00892 
00893             cor3[1][i] =
00894               transform_matrix[1][0] * x 
00895             + transform_matrix[1][1] * y 
00896             + transform_matrix[1][2] * z 
00897             + transform_matrix[1][3];
00898 
00899             cor3[2][i] =
00900               transform_matrix[2][0] * x 
00901             + transform_matrix[2][1] * y 
00902             + transform_matrix[2][2] * z 
00903             + transform_matrix[2][3];
00904           }
00905 
00906           break;
00907         }
00908         else {
00909           bad_num = bad_num + 1;
00910           printf ( "Bad data in MESH_VERTEX_LIST, line %d\n", text_num );
00911           break;
00912         }
00913       }
00914 /*
00915   *NODE_TM
00916 
00917   Each node should start out with a default transformation matrix.
00918 */
00919       else if ( strcmp ( level_name[level], "*NODE_TM" ) == 0 ) {
00920 
00921         if ( strcmp ( word, "{" ) == 0 ) {
00922 
00923           tmat_init ( transform_matrix );
00924 
00925           continue;
00926         }
00927         else if ( strcmp ( word, "}" ) == 0 ) {
00928           level = nlbrack - nrbrack;
00929           continue;
00930         }
00931         else if ( strcmp ( word, "*INHERIT_POS" ) == 0 ) {
00932           break;
00933         }
00934         else if ( strcmp ( word, "*INHERIT_ROT" ) == 0 ) {
00935           break;
00936         }
00937         else if ( strcmp ( word, "*INHERIT_SCL" ) == 0 ) {
00938           break;
00939         }
00940         else if ( strcmp ( word, "*NODE_NAME" ) == 0 ) {
00941           break;
00942         }
00943         else if ( strcmp ( word, "*TM_POS" ) == 0 ) {
00944           break;
00945         }
00946         else if ( strcmp ( word, "*TM_ROTANGLE" ) == 0 ) {
00947           break;
00948         }
00949         else if ( strcmp ( word, "*TM_ROTAXIS" ) == 0 ) {
00950           break;
00951         }
00952         else if ( strcmp ( word, "*TM_ROW0" ) == 0 ) {
00953 
00954           count = sscanf ( next, "%f%n", &temp, &width );
00955           next = next + width;
00956           transform_matrix[0][0] = temp;
00957 
00958           count = sscanf ( next, "%f%n", &temp, &width );
00959           next = next + width;
00960           transform_matrix[1][0] = temp;
00961 
00962           count = sscanf ( next, "%f%n", &temp, &width );
00963           next = next + width;
00964           transform_matrix[2][0] = temp;
00965 
00966           break;
00967         }
00968         else if ( strcmp ( word, "*TM_ROW1" ) == 0 ) {
00969 
00970           count = sscanf ( next, "%f%n", &temp, &width );
00971           next = next + width;
00972           transform_matrix[0][1] = temp;
00973 
00974           count = sscanf ( next, "%f%n", &temp, &width );
00975           next = next + width;
00976           transform_matrix[1][1] = temp;
00977 
00978           count = sscanf ( next, "%f%n", &temp, &width );
00979           next = next + width;
00980           transform_matrix[2][1] = temp;
00981 
00982           break;
00983         }
00984         else if ( strcmp ( word, "*TM_ROW2" ) == 0 ) {
00985 
00986           count = sscanf ( next, "%f%n", &temp, &width );
00987           next = next + width;
00988           transform_matrix[0][2] = temp;
00989 
00990           count = sscanf ( next, "%f%n", &temp, &width );
00991           next = next + width;
00992           transform_matrix[1][2] = temp;
00993 
00994           count = sscanf ( next, "%f%n", &temp, &width );
00995           next = next + width;
00996           transform_matrix[2][2] = temp;
00997 
00998           break;
00999         }
01000         else if ( strcmp ( word, "*TM_ROW3" ) == 0 ) {
01001 
01002           count = sscanf ( next, "%f%n", &temp, &width );
01003           next = next + width;
01004           transform_matrix[0][3] = temp;
01005 
01006           count = sscanf ( next, "%f%n", &temp, &width );
01007           next = next + width;
01008           transform_matrix[1][3] = temp;
01009 
01010           count = sscanf ( next, "%f%n", &temp, &width );
01011           next = next + width;
01012           transform_matrix[2][3] = temp;
01013 
01014           break;
01015         }
01016         else if ( strcmp ( word, "*TM_SCALE" ) == 0 ) {
01017           break;
01018         }
01019         else if ( strcmp ( word, "*TM_SCALEAXIS" ) == 0 ) {
01020           break;
01021         }
01022         else if ( strcmp ( word, "*TM_SCALEAXISANG" ) == 0 ) {
01023           break;
01024         }
01025         else {
01026           bad_num = bad_num + 1;
01027           printf ( "Bad data in NODE_TM, line %d\n", text_num );
01028           break;
01029         }
01030       }
01031 /*
01032   *SCENE
01033 */
01034       else if ( strcmp ( level_name[level], "*SCENE" ) == 0 ) {
01035 
01036         if ( strcmp ( word, "{" ) == 0 ) {
01037           continue;
01038         }
01039         else if ( strcmp ( word, "}" ) == 0 ) {
01040           level = nlbrack - nrbrack;
01041           continue;
01042         }
01043         else if ( strcmp ( word, "*SCENE_AMBIENT_STATIC" ) == 0 ) {
01044           break;
01045         }
01046         else if ( strcmp ( word, "*SCENE_BACKGROUND_STATIC" ) == 0 ) {
01047           break;
01048         }
01049         else if ( strcmp ( word, "*SCENE_FILENAME" ) == 0 ) {
01050           break;
01051         }
01052         else if ( strcmp ( word, "*SCENE_FIRSTFRAME" ) == 0 ) {
01053           break;
01054         }
01055         else if ( strcmp ( word, "*SCENE_FRAMESPEED" ) == 0 ) {
01056           break;
01057         }
01058         else if ( strcmp ( word, "*SCENE_LASTFRAME" ) == 0 ) {
01059           break;
01060         }
01061         else if ( strcmp ( word, "*SCENE_TICKSPERFRAME" ) == 0 ) {
01062           break;
01063         }
01064         else {
01065           bad_num = bad_num + 1;
01066           printf ( "Bad data in SCENE, line %d\n", text_num );
01067           break;
01068         }
01069 
01070       }
01071 
01072     }
01073 /*
01074   End of loop reading words from the line.
01075 */
01076   }
01077 /*
01078   End of loop reading lines from input file.
01079 */
01080 
01081   return SUCCESS;
01082 }
01083 /******************************************************************************/
01084 
01085 int ase_write ( FILE *fileout )
01086 
01087 /******************************************************************************/
01088 
01089 /*
01090   Purpose:
01091 
01092     ASE_WRITE writes graphics information to an AutoCAD ASE file.
01093 
01094   Modified:
01095 
01096     30 September 1998
01097 
01098   Author:
01099 
01100     John Burkardt
01101 
01102 */
01103 {
01104   int i1;
01105   int i2;
01106   int i3;
01107   int i4;
01108   int iface;
01109   int ivert;
01110   int j;
01111   int text_num;
01112 
01113   text_num = 0;
01114 /*
01115   Write the header.
01116 */
01117   fprintf ( fileout, "*3DSMAX_ASCIIEXPORT 200\n" );
01118   fprintf ( fileout, "*COMMENT \"%s, created by IVCON.\"\n", fileout_name );
01119   fprintf ( fileout, "*COMMENT \"Original data in %s\"\n", filein_name );
01120 
01121   text_num = text_num + 3;
01122 /*
01123   Write the scene block.
01124 */
01125   fprintf ( fileout, "*SCENE {\n" );
01126   fprintf ( fileout, "  *SCENE_FILENAME \"\"\n" );
01127   fprintf ( fileout, "  *SCENE_FIRSTFRAME 0\n" );
01128   fprintf ( fileout, "  *SCENE_LASTFRAME 100\n" );
01129   fprintf ( fileout, "  *SCENE_FRAMESPEED 30\n" );
01130   fprintf ( fileout, "  *SCENE_TICKSPERFRAME 160\n" );
01131   fprintf ( fileout, "  *SCENE_BACKGROUND_STATIC 0.0000 0.0000 0.0000\n" );
01132   fprintf ( fileout, "  *SCENE_AMBIENT_STATIC 0.0431 0.0431 0.0431\n" );
01133   fprintf ( fileout, "}\n" );
01134 
01135   text_num = text_num + 9;
01136 /*
01137   Begin the big geometry block.
01138 */
01139   fprintf ( fileout, "*GEOMOBJECT {\n" );
01140   fprintf ( fileout, "  *NODE_NAME \"%s\"\n", object_name );
01141 
01142   text_num = text_num + 2;
01143 /*
01144   Sub block NODE_TM:
01145 */
01146   fprintf ( fileout, "  *NODE_TM {\n" );
01147   fprintf ( fileout, "    *NODE_NAME \"Object01\"\n" );
01148   fprintf ( fileout, "    *INHERIT_POS 0 0 0\n" );
01149   fprintf ( fileout, "    *INHERIT_ROT 0 0 0\n" );
01150   fprintf ( fileout, "    *INHERIT_SCL 0 0 0\n" );
01151   fprintf ( fileout, "    *TM_ROW0 1.0000 0.0000 0.0000\n" );
01152   fprintf ( fileout, "    *TM_ROW1 0.0000 1.0000 0.0000\n" );
01153   fprintf ( fileout, "    *TM_ROW2 0.0000 0.0000 1.0000\n" );
01154   fprintf ( fileout, "    *TM_ROW3 0.0000 0.0000 0.0000\n" );
01155   fprintf ( fileout, "    *TM_POS 0.0000 0.0000 0.0000\n" );
01156   fprintf ( fileout, "    *TM_ROTAXIS 0.0000 0.0000 0.0000\n" );
01157   fprintf ( fileout, "    *TM_ROTANGLE 0.0000\n" );
01158   fprintf ( fileout, "    *TM_SCALE 1.0000 1.0000 1.0000\n" );
01159   fprintf ( fileout, "    *TM_SCALEAXIS 0.0000 0.0000 0.0000\n" );
01160   fprintf ( fileout, "    *TM_SCALEAXISANG 0.0000\n" );
01161   fprintf ( fileout, "  }\n" );
01162 
01163   text_num = text_num + 16;
01164 /*
01165   Sub block MESH:
01166     Items
01167 */
01168   fprintf ( fileout, "  *MESH {\n" );
01169   fprintf ( fileout, "    *TIMEVALUE 0\n" );
01170   fprintf ( fileout, "    *MESH_NUMVERTEX %d\n", cor3_num );
01171   fprintf ( fileout, "    *MESH_NUMFACES %d\n", face_num );
01172 
01173   text_num = text_num + 4;
01174 /*
01175   Sub sub block MESH_VERTEX_LIST
01176 */
01177   fprintf ( fileout, "    *MESH_VERTEX_LIST {\n" );
01178   text_num = text_num + 1;
01179 
01180   for ( j = 0; j < cor3_num; j++ ) {
01181     fprintf ( fileout, "      *MESH_VERTEX %d %f %f %f\n", j, cor3[0][j],
01182       cor3[1][j], cor3[2][j] );
01183     text_num = text_num + 1;
01184   }
01185 
01186   fprintf ( fileout, "    }\n" );
01187   text_num = text_num + 1;
01188 /*
01189   Sub sub block MESH_FACE_LIST
01190     Items MESH_FACE
01191 */
01192   fprintf ( fileout, "    *MESH_FACE_LIST {\n" );
01193   text_num = text_num + 1;
01194 
01195   for ( iface = 0; iface < face_num; iface++ ) {
01196 
01197     i1 = face[0][iface];
01198     i2 = face[1][iface];
01199     i3 = face[2][iface];
01200 
01201     if ( face_order[iface] == 3 ) {
01202       fprintf ( fileout, "      *MESH_FACE %d: A: %d B: %d C: %d", iface, i1, i2, i3 ); 
01203       fprintf ( fileout, " AB: 1 BC: 1 CA: 1 *MESH_SMOOTHING *MESH_MTLID 1\n" );
01204       text_num = text_num + 1;
01205     }
01206     else if ( face_order[iface] == 4 ) {
01207       i4 = face[3][iface];
01208       fprintf ( fileout, "      *MESH_FACE %d: A: %d B: %d C: %d D: %d", iface, i1, i2, i3, i4 ); 
01209       fprintf ( fileout, " AB: 1 BC: 1 CD: 1 DA: 1 *MESH_SMOOTHING *MESH_MTLID 1\n" );
01210       text_num = text_num + 1;
01211     }
01212   }
01213 
01214   fprintf ( fileout, "    }\n" );
01215   text_num = text_num + 1;
01216 /*
01217   Item MESH_NUMTVERTEX.
01218 */
01219   fprintf ( fileout, "    *MESH_NUMTVERTEX 0\n" );
01220   text_num = text_num + 1;
01221 /*
01222   Item NUMCVERTEX.
01223 */
01224   fprintf ( fileout, "    *MESH_NUMCVERTEX 0\n" );
01225   text_num = text_num + 1;
01226 /*
01227   Sub block MESH_NORMALS
01228     Items MESH_FACENORMAL, MESH_VERTEXNORMAL (repeated)
01229 */
01230   fprintf ( fileout, "    *MESH_NORMALS {\n" );
01231   text_num = text_num + 1;
01232 
01233   for ( iface = 0; iface < face_num; iface++ ) {
01234 
01235     fprintf ( fileout, "      *MESH_FACENORMAL %d %f %f %f\n", 
01236       iface, face_normal[0][iface], face_normal[1][iface], face_normal[2][iface] );
01237     text_num = text_num + 1;
01238 
01239     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
01240       fprintf ( fileout, "      *MESH_VERTEXNORMAL %d %f %f %f\n", 
01241         face[ivert][iface], vertex_normal[0][ivert][iface], 
01242         vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
01243       text_num = text_num + 1;
01244     }
01245   }
01246 
01247   fprintf ( fileout, "    }\n" );
01248   text_num = text_num + 1;
01249 /*
01250   Close the MESH object.
01251 */
01252   fprintf ( fileout, "  }\n" );
01253 /*
01254   A few closing parameters.
01255 */
01256   fprintf ( fileout, "  *PROP_MOTIONBLUR 0\n" );
01257   fprintf ( fileout, "  *PROP_CASTSHADOW 1\n" );
01258   fprintf ( fileout, "  *PROP_RECVSHADOW 1\n" );
01259 /*
01260   Close the GEOM object.
01261 */
01262   fprintf ( fileout, "}\n" );
01263 
01264   text_num = text_num + 5;
01265 /*
01266   Report.
01267 */
01268   printf ( "\n" );
01269   printf ( "ASE_WRITE - Wrote %d text lines;\n", text_num );
01270 
01271   return SUCCESS;
01272 }
01273 /**********************************************************************/
01274 
01275 int byu_read ( FILE *filein )
01276 
01277 /**********************************************************************/
01278 
01279 /*
01280   Purpose:
01281 
01282     BYU_READ reads graphics data from a Movie.BYU surface geometry file.
01283 
01284   Discussion:
01285 
01286     A Movie.BYU surface geometry file contains 4 groups of data.
01287 
01288     The first group of data is a single line, containing 4 integers,
01289     each one left justified in 8 columns.  The integers are:
01290 
01291       PART_NUM, VERTEX_NUM, POLY_NUM, EDGE_NUM,
01292  
01293     that is, the number of parts or objects, the number of vertices or nodes,
01294     the number of polygons or faces, and the number of edges.
01295 
01296     The second group of data is a single line, containing 2 integers,
01297     each one left justified in 8 columnes.  The integers are:
01298 
01299       POLY1, POLY2,
01300 
01301     the starting and ending polygon numbers.  Presumably, this means
01302     that the polygons are labeled POLY1, POLY1+1, ..., POLY2, comprising
01303     a total of POLY_NUM polygons.
01304 
01305     The third group is the X, Y and Z coordinates of all the vertices.
01306     These may be written using a FORTRAN format of 6E12.5, which
01307     crams two sets of (X,Y,Z) data onto each line, with each real value
01308     written in an exponential format with 5 places after the decimal.
01309     However, it is generally possible to write the XYZ coordinate data
01310     for each vertex on a separate line.
01311 
01312     The fourth group defines the polygons in terms of the vertex indices.
01313     For each polygon, the vertices that make up the polygon are listed in
01314     counterclockwise order.  The last vertex listed is given with a negative
01315     sign to indicate the end of the list.  All the vertices for all the
01316     polygons are listed one after the other, using a format that puts
01317     up to 10 left-justified integers on a line, with each integer occupying
01318     8 spaces.
01319 
01320     This code will certainly read a BYU file created by BYU_WRITE, but
01321     it will not handle more general files.  In particular, an object
01322     can have several parts, the coordinate data can be grouped so
01323     that there are 2 sets of (x,y,z) data per line, and so on.
01324 
01325   Example:
01326 
01327       1       8       6      24
01328       1       6
01329     0.00000E+00 0.00000E+00 0.00000E+00
01330     1.00000E+00 0.00000E+00 0.00000E+00
01331     1.00000E+00 2.00000E+00 0.00000E+00
01332     0.00000E+00 2.00000E+00 0.00000E+00
01333     0.00000E+00 0.00000E+00 1.00000E+00
01334     1.00000E+00 0.00000E+00 1.00000E+00
01335     1.00000E+00 2.00000E+00 1.00000E+00
01336     0.00000E+00 2.00000E+00 1.00000E+00
01337       4       3       2      -1
01338       5       6       7      -8
01339       1       5       8      -4
01340       4       8       7      -3
01341       3       7       6      -2
01342       2       6       5      -1
01343 
01344   Modified:
01345 
01346     24 May 2001
01347 
01348   Author:
01349 
01350     John Burkardt
01351 
01352 */
01353 {
01354   int cor3_num_new;
01355   int count;
01356   int edge_num;
01357   int face_num_new;
01358   int iface;
01359   int ival;
01360   int ivert;
01361   int j;
01362   char *next;
01363   int part_num;
01364   int poly1;
01365   int poly2;
01366   int text_num;
01367   int width;
01368   float x;
01369   float y;
01370   float z;
01371 
01372   text_num = 0;
01373 
01374   if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
01375     return ERROR;
01376   }
01377   text_num = text_num + 1;
01378 
01379   sscanf ( input, "%d %d %d %d", &part_num, &cor3_num_new, &face_num_new,
01380     &edge_num );
01381 
01382   if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
01383     return ERROR;
01384   }
01385   text_num = text_num + 1;
01386 
01387   sscanf ( input, "%d %d", &poly1, &poly2 );
01388 
01389   for ( j = cor3_num; j < cor3_num + cor3_num_new; j++ ) {
01390 
01391     if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
01392       return ERROR;
01393     }
01394     text_num = text_num + 1;
01395 
01396     sscanf ( input, "%f %f %f", &x, &y, &z );
01397     cor3[0][j] = x;
01398     cor3[1][j] = y;
01399     cor3[2][j] = z;
01400   }
01401 
01402   for ( iface = face_num; iface < face_num + face_num_new; iface++ ) {
01403 
01404     if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
01405       return ERROR;
01406     }
01407     text_num = text_num + 1;
01408 
01409     next = input;
01410     ivert = 0;
01411 
01412     for (;;) {
01413 
01414       count = sscanf ( next, "%d%n", &ival, &width );
01415       next = next + width;
01416 
01417       if ( count <= 0 ) {
01418         return ERROR;
01419       }
01420 
01421       if ( ival > 0 ) {
01422         face[ivert][iface] = ival - 1 + cor3_num;
01423       }
01424       else {
01425         face[ivert][iface] = - ival - 1 - cor3_num;
01426         break;
01427       }
01428 
01429       ivert = ivert + 1;
01430 
01431     }
01432     face_order[iface] = ivert + 1;
01433   }
01434 
01435   cor3_num = cor3_num + cor3_num_new;
01436   face_num = face_num + face_num_new;
01437 /*
01438   Report.
01439 */
01440   printf ( "\n" );
01441   printf ( "BYU_READ - Read %d text lines.\n", text_num );
01442 
01443   return SUCCESS;
01444 }
01445 /**********************************************************************/
01446 
01447 int byu_write ( FILE *fileout )
01448 
01449 /**********************************************************************/
01450 
01451 /*
01452   Purpose:
01453 
01454     BYU_WRITE writes out the graphics data as a Movie.BYU surface geometry file.
01455 
01456   Discussion:
01457 
01458     A Movie.BYU surface geometry file contains 4 groups of data.
01459 
01460     The first group of data is a single line, containing 4 integers,
01461     each one left justified in 8 columns.  The integers are:
01462 
01463       PART_NUM, VERTEX_NUM, POLY_NUM, EDGE_NUM,
01464  
01465     that is, the number of parts or objects, the number of vertices or nodes,
01466     the number of polygons or faces, and the number of edges.
01467 
01468     The second group of data is a single line, containing 2 integers,
01469     each one left justified in 8 columnes.  The integers are:
01470 
01471       POLY1, POLY2,
01472 
01473     the starting and ending polygon numbers.  Presumably, this means
01474     that the polygons are labeled POLY1, POLY1+1, ..., POLY2, comprising
01475     a total of POLY_NUM polygons.
01476 
01477     The third group is the X, Y and Z coordinates of all the vertices.
01478     These may be written using a FORTRAN format of 6E12.5, which
01479     crams two sets of (X,Y,Z) data onto each line, with each real value
01480     written in an exponential format with 5 places after the decimal.
01481     However, it is generally possible to write the XYZ coordinate data
01482     for each vertex on a separate line.
01483 
01484     The fourth group defines the polygons in terms of the vertex indices.
01485     For each polygon, the vertices that make up the polygon are listed in
01486     counterclockwise order.  The last vertex listed is given with a negative
01487     sign to indicate the end of the list.  All the vertices for all the
01488     polygons are listed one after the other, using a format that puts
01489     up to 10 left-justified integers on a line, with each integer occupying
01490     8 spaces.
01491 
01492   Example:
01493 
01494       1       8       6      24
01495       1       6
01496     0.00000E+00 0.00000E+00 0.00000E+00
01497     1.00000E+00 0.00000E+00 0.00000E+00
01498     1.00000E+00 2.00000E+00 0.00000E+00
01499     0.00000E+00 2.00000E+00 0.00000E+00
01500     0.00000E+00 0.00000E+00 1.00000E+00
01501     1.00000E+00 0.00000E+00 1.00000E+00
01502     1.00000E+00 2.00000E+00 1.00000E+00
01503     0.00000E+00 2.00000E+00 1.00000E+00
01504       4       3       2      -1
01505       5       6       7      -8
01506       1       5       8      -4
01507       4       8       7      -3
01508       3       7       6      -2
01509       2       6       5      -1
01510 
01511   Modified:
01512 
01513     24 May 2001
01514 
01515   Author:
01516 
01517     John Burkardt
01518 */
01519 {
01520   int edge_num;
01521   int iface;
01522   int ivert;
01523   int j;
01524   int jp;
01525   int part_num;
01526   int text_num;
01527 
01528   text_num = 0;
01529 
01530   edge_num = 0;
01531   for ( iface = 0; iface < face_num; iface++ ) {
01532     edge_num = edge_num + face_order[iface];
01533   }
01534 
01535   part_num = 1;
01536 
01537   fprintf ( fileout, "%d %d %d %d\n", part_num, cor3_num, face_num, edge_num );
01538   text_num = text_num + 1;
01539 
01540   fprintf ( fileout, "1 %d\n", face_num );
01541   text_num = text_num + 1;
01542 
01543   for ( j = 0; j < cor3_num; j++ ) {
01544     fprintf ( fileout, "%f %f %f\n", cor3[0][j], cor3[1][j], cor3[2][j] );
01545     text_num = text_num + 1;
01546   }
01547 
01548   for ( iface = 0; iface < face_num; iface++ ) {
01549 
01550     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
01551 
01552       jp = face[ivert][iface] + 1;
01553       if ( ivert == face_order[iface] - 1 ) {
01554         jp = - jp;
01555       }
01556      fprintf ( fileout, "%d ", jp );
01557     }
01558     fprintf ( fileout, "\n" );
01559     text_num = text_num + 1;
01560   }
01561 /*
01562   Report.
01563 */
01564   printf ( "\n" );
01565   printf ( "BYU_WRITE - Wrote %d text lines.\n", text_num );
01566 
01567   return SUCCESS;
01568 }
01569 /******************************************************************************/
01570 
01571 int char_index_last ( char* string, char c )
01572 
01573 /******************************************************************************/
01574 
01575 /*
01576   Purpose:
01577 
01578     CHAR_INDEX_LAST reports the last occurrence of a character in a string.
01579 
01580   Author:
01581  
01582     John Burkardt
01583 */
01584 {
01585   int i;
01586   int j;
01587   int nchar;
01588 
01589   j = -1;
01590 
01591   nchar = strlen ( string );
01592 
01593   for ( i = 0; i < nchar; i++ ) {
01594     if ( string[i] == c ) {
01595       j = i;
01596     }
01597   }
01598 
01599   return j;
01600 
01601 }
01602 /******************************************************************************/
01603 
01604 int char_pad ( int *char_index, int *null_index, char *string, 
01605   int STRING_MAX )
01606 
01607 /******************************************************************************/
01608 
01609 /*
01610   Purpose:
01611 
01612     CHAR_PAD "pads" a character in a string with a blank on either side.
01613 
01614   Modified:
01615 
01616     16 October 1998
01617 
01618   Author:
01619 
01620     John Burkardt
01621 
01622   Parameters:
01623 
01624     Input/output, int *CHAR_INDEX, the position of the character to be padded.
01625     On output, this is increased by 1.
01626 
01627     Input/output, int *NULL_INDEX, the position of the terminating NULL in 
01628     the string.  On output, this is increased by 2.
01629 
01630     Input/output, char STRING[STRING_MAX], the string to be manipulated.
01631 
01632     Input, int STRING_MAX, the maximum number of characters that can be stored
01633     in the string.
01634 
01635     Output, int CHAR_PAD, is SUCCESS if the operation worked, and ERROR otherwise.
01636 */
01637 {
01638   int i;
01639 
01640   if ( *char_index < 0 || 
01641        *char_index >= *null_index || 
01642        *char_index > STRING_MAX-1 ) {
01643     return ERROR;
01644   }
01645 
01646   if ( (*null_index) + 2 > STRING_MAX-1 ) {
01647     return ERROR;
01648   }
01649 
01650   for ( i = *null_index + 2; i > *char_index + 2; i-- ) {
01651     string[i] = string[i-2];
01652   }
01653   string[*char_index+2] = ' ';
01654   string[*char_index+1] = string[*char_index];
01655   string[*char_index] = ' ';
01656 
01657   *char_index = *char_index + 1;
01658   *null_index = *null_index + 2;
01659 
01660   return SUCCESS;
01661 }
01662 /******************************************************************************/
01663 
01664 char char_read ( FILE *filein )
01665 
01666 /******************************************************************************/
01667 
01668 /*
01669   Purpose:
01670 
01671     CHAR_READ reads one character from a binary file.
01672 
01673   Modified:
01674 
01675     24 May 1999
01676 
01677   Author:
01678 
01679     John Burkardt
01680 */
01681 {
01682   char c;
01683 
01684   c = ( char ) fgetc ( filein );
01685 
01686   return c;
01687 }
01688 /******************************************************************************/
01689 
01690 int char_write ( FILE *fileout, char c )
01691 
01692 /******************************************************************************/
01693 
01694 /*
01695   Purpose:
01696 
01697     CHAR_WRITE writes one character to a binary file.
01698 
01699   Modified:
01700 
01701     24 May 1999
01702 
01703   Author:
01704 
01705     John Burkardt
01706 */
01707 {
01708   fputc ( c, fileout );
01709 
01710   return 1;
01711 }
01712 /******************************************************************************/
01713 
01714 int command_line ( char **argv )
01715 
01716 /******************************************************************************/
01717 
01718 /*
01719 
01720   Purpose:
01721 
01722     COMMAND_LINE carries out a command-line session of file conversion.
01723 
01724   Discussion:
01725 
01726     This routine is invoked when the user command is something like
01727 
01728       ivcon filein_name fileout_name
01729 
01730     or
01731 
01732       ivcon -rn filein_name fileout_name
01733 
01734     where "-rn" signals the "reverse normals" option, or
01735 
01736       ivcon -rf filein_name fileout_name
01737 
01738     where "-rf" signals the "reverse faces" option.
01739 
01740   Modified:
01741 
01742     28 June 1999
01743 
01744   Author:
01745  
01746     John Burkardt
01747 */
01748 {
01749   int   i;
01750   int   iarg;
01751   int   icor3;
01752   int   ierror;
01753   int   iface;
01754   int   ivert;
01755   int   reverse_faces;
01756   int   reverse_normals;
01757 /* 
01758   Initialize local data. 
01759 */
01760   iarg = 0;
01761   ierror = 0;
01762   reverse_faces = FALSE;
01763   reverse_normals = FALSE;
01764 /*
01765   Initialize the graphics data.
01766 */
01767   data_init ( );
01768 /*
01769   Get the -RN option, -RF option, and the input file name. 
01770 */
01771   iarg = iarg + 1;
01772   strcpy ( filein_name, argv[iarg] );
01773 
01774   if ( leqi ( filein_name, "-RN" ) == TRUE ) {
01775     reverse_normals = TRUE;
01776     printf ( "\n" );
01777     printf ( "COMMAND_LINE: Reverse_Normals option requested.\n" );
01778     iarg = iarg + 1;
01779     strcpy ( filein_name, argv[iarg] );
01780   }
01781 
01782   if ( leqi ( filein_name, "-RF" ) == TRUE ) {
01783     reverse_faces = TRUE;
01784     printf ( "\n" );
01785     printf ( "COMMAND_LINE: Reverse_Faces option requested.\n" );
01786     iarg = iarg + 1;
01787     strcpy ( filein_name, argv[iarg] );
01788   }
01789 /*
01790   Read the input. 
01791 */
01792   ierror = data_read ( );
01793 
01794   if ( ierror == ERROR ) {
01795     printf ( "\n" );
01796     printf ( "COMMAND_LINE - Fatal error!\n" );
01797     printf ( "  Failure while reading input data.\n" );
01798     return ERROR;
01799   }
01800 /*
01801   Reverse the normal vectors if requested.
01802 */
01803   if ( reverse_normals == TRUE ) {
01804 
01805     for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
01806       for ( i = 0; i < 3; i++ ) {
01807         cor3_normal[i][icor3] = - cor3_normal[i][icor3];
01808       }
01809     }
01810 
01811     for ( iface = 0; iface < face_num; iface++ ) {
01812       for ( i = 0; i < 3; i++ ) {
01813         face_normal[i][iface] = - face_normal[i][iface];
01814       }
01815     }
01816 
01817     for ( iface = 0; iface < face_num; iface++ ) {
01818       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
01819         for ( i = 0; i < 3; i++ ) {
01820           vertex_normal[i][ivert][iface] = 
01821             - vertex_normal[i][ivert][iface];
01822         }
01823       }
01824     }
01825     printf ( "\n" );
01826     printf ( "COMMAND_LINE - Note:\n" );
01827     printf ( "  Reversed node, face, and vertex normals.\n" );
01828   }
01829 /*
01830   Reverse the faces if requested.
01831 */
01832   if ( reverse_faces == TRUE ) {
01833 
01834     face_reverse_order ( );
01835 
01836     printf ( "\n" );
01837     printf ( "COMMAND_LINE - Note:\n" );
01838     printf ( "  Reversed the face definitions.\n" );
01839   }
01840 /*
01841   Write the output file. 
01842 */
01843   iarg = iarg + 1;
01844   strcpy ( fileout_name, argv[iarg] );
01845 
01846   ierror = data_write ( );
01847 
01848   if ( ierror == ERROR ) {
01849     printf ( "\n" );
01850     printf ( "COMMAND_LINE - Fatal error!\n" );
01851     printf ( "  Failure while writing output data.\n" );
01852     return ERROR;
01853   }
01854   return SUCCESS;
01855 }
01856 /******************************************************************************/
01857 
01858 void cor3_normal_set ( void )
01859 
01860 /******************************************************************************/
01861 
01862 /*
01863   Purpose:
01864 
01865     COR3_NORMAL_SET computes node normal vectors.
01866 
01867   Modified:
01868 
01869     18 November 1998
01870 
01871   Author:
01872 
01873     John Burkardt
01874 */
01875 {
01876   int   icor3;
01877   int   iface;
01878   int   ivert;
01879   int   j;
01880   float norm;
01881   float temp;
01882 
01883   for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
01884     for ( j = 0; j < 3; j++ ) {
01885       cor3_normal[j][icor3] = 0.0;
01886     }
01887   }
01888 /*
01889   Add up the normals at all the faces to which the node belongs.
01890 */
01891   for ( iface = 0; iface < face_num; iface++ ) {
01892 
01893     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
01894 
01895       icor3 = face[ivert][iface];
01896 
01897       for ( j = 0; j < 3; j++ ) {
01898         cor3_normal[j][icor3] = cor3_normal[j][icor3]
01899           + vertex_normal[j][ivert][iface];
01900       }
01901     }
01902   }
01903 /*
01904   Renormalize.
01905 */
01906   for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
01907 
01908     norm = 0.0;
01909     for ( j = 0; j < 3; j++ ) {
01910       temp = cor3_normal[j][icor3];
01911       norm = norm + temp * temp;
01912     }
01913 
01914     if ( norm == 0.0 ) {
01915       norm = 3.0;
01916       for ( j = 0; j < 3; j++ ) {
01917         cor3_normal[j][icor3] = 1.0;
01918       }
01919     }
01920 
01921     norm = ( float ) sqrt ( norm );
01922 
01923     for ( j = 0; j < 3; j++ ) {
01924       cor3_normal[j][icor3] = cor3_normal[j][icor3] / norm;
01925     }
01926   }
01927 
01928   return;
01929 }
01930 /******************************************************************************/
01931 
01932 void cor3_range ( void )
01933 
01934 /******************************************************************************/
01935 
01936 /*
01937   Purpose:
01938 
01939     COR3_RANGE computes the coordinate minima and maxima.
01940 
01941   Modified:
01942 
01943     31 August 1998
01944 
01945   Author:
01946 
01947     John Burkardt
01948 */
01949 {
01950   int   i;
01951   float xave;
01952   float xmax;
01953   float xmin;
01954   float yave;
01955   float ymax;
01956   float ymin;
01957   float zave;
01958   float zmax;
01959   float zmin;
01960 
01961   xave = cor3[0][0];
01962   xmax = cor3[0][0];
01963   xmin = cor3[0][0];
01964 
01965   yave = cor3[1][0];
01966   ymax = cor3[1][0];
01967   ymin = cor3[1][0];
01968 
01969   zave = cor3[2][0];
01970   zmax = cor3[2][0];
01971   zmin = cor3[2][0];
01972 
01973   for ( i = 1; i < cor3_num; i++ ) {
01974 
01975     xave = xave + cor3[0][i];
01976     if ( cor3[0][i] < xmin ) {
01977       xmin = cor3[0][i];
01978     }
01979     if ( cor3[0][i] > xmax ) {
01980       xmax = cor3[0][i];
01981     }
01982 
01983     yave = yave + cor3[1][i];
01984     if ( cor3[1][i] < ymin ) {
01985       ymin = cor3[1][i];
01986     }
01987     if ( cor3[1][i] > ymax ) {
01988       ymax = cor3[1][i];
01989     }
01990 
01991     zave = zave + cor3[2][i];
01992     if ( cor3[2][i] < zmin ) {
01993       zmin = cor3[2][i];
01994     }
01995     if ( cor3[2][i] > zmax ) {
01996       zmax = cor3[2][i];
01997     }
01998   }
01999 
02000   xave = xave / cor3_num;
02001   yave = yave / cor3_num;
02002   zave = zave / cor3_num;
02003 
02004   printf ( "\n" );
02005   printf ( "COR3_RANGE - Data range:\n" );
02006   printf ( "\n" );
02007   printf ( "   Minimum   Average   Maximum  Range\n" );
02008   printf ( "\n" );
02009   printf ( "X  %f %f %f %f\n", xmin, xave, xmax, xmax-xmin );
02010   printf ( "Y  %f %f %f %f\n", ymin, yave, ymax, ymax-ymin );
02011   printf ( "Z  %f %f %f %f\n", zmin, zave, zmax, zmax-zmin );
02012 
02013 }
02014 /******************************************************************************/
02015 
02016 void data_check ( void )
02017 
02018 /******************************************************************************/
02019 
02020 /*
02021   Purpose:
02022    
02023     DATA_CHECK checks the input data.
02024 
02025   Modified:
02026 
02027     18 May 1999
02028 
02029   Author:
02030  
02031     John Burkardt
02032 */
02033 {
02034   int iface;
02035   int nfix;
02036 
02037   if ( color_num > COLOR_MAX ) {
02038     printf ( "\n" );
02039     printf ( "DATA_CHECK - Warning!\n" );
02040     printf ( "  The input data requires %d colors.\n", color_num );
02041     printf ( "  There was only room for %d\n", COLOR_MAX );
02042     color_num = COLOR_MAX;
02043   }
02044   
02045   if ( cor3_num > COR3_MAX ) {
02046     printf ( "\n" );
02047     printf ( "DATA_CHECK - Warning!\n" );
02048     printf ( "  The input data requires %d points.\n", cor3_num );
02049     printf ( "  There was only room for %d\n", COR3_MAX );
02050     cor3_num = COR3_MAX;
02051   }
02052 
02053   if ( face_num > FACE_MAX ) {
02054     printf ( "\n" );
02055     printf ( "DATA_CHECK - Warning!\n" );
02056     printf ( "  The input data requires %d faces.\n", face_num );
02057     printf ( "  There was only room for %d\n", FACE_MAX );
02058     face_num = FACE_MAX;
02059   }
02060 
02061   if ( line_num > LINES_MAX ) {
02062     printf ( "\n" );
02063     printf ( "DATA_CHECK - Warning!\n" );
02064     printf ( "  The input data requires %d line items.\n", line_num );
02065     printf ( "  There was only room for %d.\n", LINES_MAX );
02066     line_num = LINES_MAX;
02067   }
02068 
02069   nfix = 0;
02070 
02071   for ( iface = 0; iface < face_num; iface++ ) {
02072 
02073     if ( face_order[iface] > ORDER_MAX ) {
02074       face_order[iface] = ORDER_MAX;
02075       nfix = nfix + 1;
02076     }
02077 
02078   }
02079 
02080   if ( nfix > 0 ) {
02081     printf ( "\n" );
02082     printf ( "DATA_CHECK - Warning!\n" );
02083     printf ( "  Corrected %d faces using more than %d vertices per face.\n",
02084       nfix, ORDER_MAX );
02085   }
02086 
02087   for ( i = 0; i < material_num; i++ ) {
02088     if ( strcmp ( material_name[i], "" ) == 0 ) {
02089       strcpy ( material_name[i], "Material_0000" );
02090     }
02091   }
02092 
02093   for ( i = 0; i < texture_num; i++ ) {
02094     if ( strcmp ( texture_name[i], "" ) == 0 ) {
02095       strcpy ( texture_name[i], "Texture_0000" );
02096     }
02097   }
02098 
02099   printf ( "\n" );
02100   printf ( "DATA_CHECK - Data checked.\n" );
02101 
02102   return;
02103 }
02104 /******************************************************************************/
02105 
02106 void data_init ( void )
02107 
02108 /******************************************************************************/
02109 
02110 /*
02111   Purpose:
02112 
02113     DATA_INIT initializes the internal graphics data.
02114 
02115   Modified:
02116 
02117     04 July 2000
02118 
02119   Author:
02120 
02121     John Burkardt
02122 */
02123 {
02124   int i;
02125   int iface;
02126   int ivert;
02127   int j;
02128   int k;
02129 
02130   strcpy( anim_name, "" );
02131 
02132   for ( i = 0; i < 3; i++ ) {
02133     background_rgb[i] = 0.0;
02134   }
02135 
02136   for ( i = 0; i < 3; i++ ) {
02137     for ( j = 0; j < COR3_MAX; j++ ) {
02138       cor3[i][j] = 0.0;
02139     }
02140   }
02141 
02142   for ( i = 0; i < COR3_MAX; i++ ) {
02143     cor3_material[i] = 0;
02144   }
02145 
02146   for ( i = 0; i < 3; i++ ) {
02147     for ( j = 0; j < COR3_MAX; j++ ) {
02148       cor3_normal[i][j] = 0.0;
02149     }
02150   }
02151 
02152   for ( j = 0; j < COR3_MAX; j++ ) {
02153     cor3_tex_uv[0][j] = 0.0;
02154     cor3_tex_uv[1][j] = 0.0;
02155   }
02156 
02157   for ( iface = 0; iface < FACE_MAX; iface++ ) {
02158     for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
02159       face[ivert][iface] = 0;
02160     }
02161   }
02162 
02163   for ( iface = 0; iface < FACE_MAX; iface++ ) {
02164     face_flags[iface] = 6;
02165   }
02166 
02167   for ( iface = 0; iface < FACE_MAX; iface++ ) {
02168     face_material[iface] = 0;
02169   }
02170 
02171   for ( iface = 0; iface < FACE_MAX; iface++ ) {
02172     for ( i = 0; i < 3; i++ ) {
02173       face_normal[i][iface] = 0;
02174     }
02175   }
02176 
02177   for ( iface = 0; iface < FACE_MAX; iface++ ) {
02178     face_object[iface] = -1;
02179   }
02180 
02181   for ( iface = 0; iface < FACE_MAX; iface++ ) {
02182     face_order[iface] = 0;
02183   }
02184 
02185   for ( iface = 0; iface < FACE_MAX; iface++ ) {
02186     face_smooth[iface] = 1;
02187   }
02188 
02189   for ( i = 0; i < LINES_MAX; i++ ) {
02190     line_dex[i] = -1;
02191   }
02192 
02193   for ( i = 0; i < LINES_MAX; i++ ) {
02194     line_material[i] = 0;
02195   }
02196 
02197   strcpy ( material_binding, "DEFAULT" );
02198 
02199   for ( j = 0; j < MATERIAL_MAX; j++ ) {
02200     strcpy ( material_name[j], "Material_0000" );
02201   }
02202 
02203   for ( i = 0; i < 4; i++ ) {
02204     for ( j = 0; j < MATERIAL_MAX; j++ ) {
02205       material_rgba[i][j] = 0.0;
02206     }
02207   }
02208 
02209   strcpy ( normal_binding, "DEFAULT" );
02210 
02211   for ( j = 0; j < ORDER_MAX*FACE_MAX; j++ ) {
02212     for ( i = 0; i < 3; i++ ) {
02213       normal_temp[i][j] = 0;
02214     }
02215   }
02216 
02217   color_num = 0;
02218   cor3_num = 0;
02219   face_num = 0;
02220   group_num = 0;
02221   line_num = 0;
02222   material_num = 0;
02223   object_num = 0;
02224   texture_num = 0;
02225 
02226   strcpy ( object_name, "IVCON" );
02227 
02228   for ( i = 0; i < 3; i++ ) {
02229     origin[i] = 0.0;
02230   }
02231 
02232   for ( i = 0; i < 3; i++ ) {
02233     pivot[i] = 0.0;
02234   }
02235 
02236   for ( j = 0; j < COLOR_MAX; j++ ) {
02237     rgbcolor[0][j] = 0.299;
02238     rgbcolor[1][j] = 0.587;
02239     rgbcolor[2][j] = 0.114;
02240   }
02241 
02242   strcpy ( texture_binding, "DEFAULT" );
02243 
02244   for ( j = 0; j < TEXTURE_MAX; j++ ) {
02245     strcpy ( texture_name[j], "Texture_0000" );
02246   }
02247 
02248   tmat_init ( transform_matrix );
02249 
02250   for ( iface = 0; iface < FACE_MAX; iface++ ) {
02251     for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
02252       vertex_material[ivert][iface] = 0;
02253     }
02254   }
02255 
02256   for ( iface = 0; iface < FACE_MAX; iface++ ) {
02257     for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
02258       for ( i = 0; i < 3; i++ ) {
02259         vertex_normal[i][ivert][iface] = 0.0;
02260       }
02261     }
02262   }
02263 
02264   for ( j = 0; j < 3; j++ ) {
02265     for ( k = 0; k < FACE_MAX; k++ ) {
02266       vertex_rgb[0][j][k] = 0.299;
02267       vertex_rgb[1][j][k] = 0.587;
02268       vertex_rgb[2][j][k] = 0.114;
02269     }
02270   }
02271 
02272   for ( iface = 0; iface < FACE_MAX; iface++ ) {
02273     for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
02274       for ( i = 0; i < 2; i++ ) {
02275         vertex_tex_uv[i][ivert][iface] = 0.0;
02276       }
02277     }
02278   }
02279 
02280   if ( debug ) {
02281     printf ( "\n" );
02282     printf ( "DATA_INIT: Graphics data initialized.\n" );
02283   }
02284 
02285   return;
02286 }
02287 /******************************************************************************/
02288 
02289 int data_read ( void )
02290 
02291 /******************************************************************************/
02292 
02293 /*
02294   Purpose:
02295 
02296     DATA_READ reads a file into internal graphics data.
02297 
02298   Modified:
02299 
02300     26 September 1999
02301 
02302   Author:
02303  
02304     John Burkardt
02305 */
02306 {
02307   FILE *filein;
02308   char *filein_type;
02309   int   icor3;
02310   int   ierror;
02311   int   iface;
02312   int   iline;
02313   int   ivert;
02314   int   ntemp;
02315 /* 
02316   Retrieve the input file type. 
02317 */
02318    filein_type = file_ext ( filein_name );
02319 
02320   if ( filein_type == NULL ) {
02321     printf ( "\n" );
02322     printf ( "DATA_READ - Fatal error!\n" );
02323     printf ( "  Could not determine the type of '%s'.\n", filein_name );
02324     return ERROR;
02325   }
02326   else if ( debug ) {
02327     printf ( "\n" );
02328     printf ( "DATA_READ: Input file has type %s.\n", filein_type );  
02329   }
02330 /*
02331   Initialize some data.
02332 */
02333   max_order2 = 0;
02334   bad_num = 0;
02335   bytes_num = 0;
02336   comment_num = 0;
02337   dup_num = 0;
02338   text_num = 0;
02339 /* 
02340   Open the file. 
02341 */
02342   if ( leqi ( filein_type, "3DS" ) == TRUE ||
02343        leqi ( filein_type, "STLB" ) == TRUE ||
02344        leqi ( filein_type, "TRIB" ) == TRUE ) {
02345     filein = fopen ( filein_name, "rb" );
02346   }
02347   else {
02348     filein = fopen ( filein_name, "r" );
02349   }
02350 
02351   if ( filein == NULL ) {
02352     printf ( "\n" );
02353     printf ( "DATA_READ - Fatal error!\n" );
02354     printf ( "  Could not open the input file '%s'!\n", filein_name );
02355     return ERROR;
02356   }
02357 /*
02358   Read the information in the file. 
02359 */
02360   if ( leqi ( filein_type, "3DS" ) == TRUE ) {
02361 
02362     ierror = tds_read ( filein );
02363 /*
02364   Cleanup: distribute the node textures to the vertices.
02365 */
02366     if ( ierror == SUCCESS ) {
02367 
02368       for ( iface = 0; iface < face_num; iface++ ) {
02369         for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
02370           icor3 = face[ivert][iface];
02371           vertex_tex_uv[0][ivert][iface] = cor3_tex_uv[0][icor3];
02372           vertex_tex_uv[1][ivert][iface] = cor3_tex_uv[1][icor3];
02373         }
02374       }
02375 
02376     }
02377 
02378   }
02379   else if ( leqi ( filein_type, "ASE" ) == TRUE ) {
02380 
02381     ierror = ase_read ( filein );
02382 
02383     if ( ierror == SUCCESS ) {
02384 
02385       node_to_vertex_material ( );
02386 
02387       vertex_to_face_material ( );
02388 
02389     }
02390 
02391   }
02392   else if ( leqi ( filein_type, "BYU" ) == TRUE ) {
02393 
02394     ierror = byu_read ( filein );
02395 
02396   }
02397   else if ( leqi ( filein_type, "DXF" ) == TRUE ) {
02398 
02399     ierror = dxf_read ( filein );
02400 
02401   }
02402   else if ( leqi ( filein_type, "GMOD" ) == TRUE ) {
02403 
02404     ierror = gmod_read ( filein );
02405 
02406   }
02407   else if ( leqi ( filein_type, "HRC" ) == TRUE ) {
02408 
02409     ierror = hrc_read ( filein );
02410 
02411   }
02412   else if ( leqi ( filein_type, "IV" ) == TRUE ) {
02413 
02414     ierror = iv_read ( filein );
02415 
02416   }
02417   else if ( leqi ( filein_type, "OBJ" ) == TRUE ) {
02418 
02419     ierror = obj_read ( filein );
02420 
02421   }
02422   else if ( leqi ( filein_type, "SMF" ) == TRUE ) {
02423 
02424     ierror = smf_read ( filein );
02425 
02426   }
02427   else if ( 
02428     leqi ( filein_type, "STL" ) == TRUE ||
02429     leqi ( filein_type, "STLA") == TRUE ) {
02430 
02431     ierror = stla_read ( filein );
02432 
02433     if( ierror ) {
02434         // might be binary
02435         fclose(filein);
02436         filein = fopen ( filein_name, "rb" );
02437         ierror = stlb_read ( filein );
02438     }
02439   }
02440   else if ( leqi ( filein_type, "STLB") == TRUE ) {
02441 
02442       ierror = stlb_read ( filein );
02443 
02444   }
02445   else if ( 
02446     leqi ( filein_type, "TRI" ) == TRUE ||
02447     leqi ( filein_type, "TRIA") == TRUE ) {
02448 
02449     ierror = tria_read ( filein );
02450 
02451   }
02452   else if ( leqi ( filein_type, "TRIB") == TRUE ) {
02453 
02454     ierror = trib_read ( filein );
02455 
02456   }
02457   else if ( leqi ( filein_type, "VLA" ) == TRUE ) {
02458 
02459     ierror = vla_read ( filein );
02460 
02461   }
02462   else {
02463     printf ( "\n" );
02464     printf ( "DATA_READ - Fatal error!\n" );
02465     printf ( "  Unacceptable input file type.\n" );
02466     return ERROR;
02467   }
02468 
02469   fclose ( filein );
02470 
02471   if ( debug ) {
02472     printf ( "DATA_READ: Finished reading the data file.\n" );
02473   }
02474 /*
02475   Catch errors reported by the various reading routines.
02476 */
02477   if ( ierror == ERROR ) {
02478     return ierror;
02479   }
02480 /*
02481   Restore the transformation matrix.
02482 */
02483   tmat_init ( transform_matrix );
02484 /*
02485   Report on what we read.
02486 */
02487   if ( face_num < FACE_MAX ) {
02488     ntemp = face_num;
02489   }
02490   else {
02491     ntemp = FACE_MAX;
02492   }
02493 
02494   max_order2 = ivec_max ( ntemp, face_order );
02495 
02496   data_report ( );
02497 /*
02498   Warn about any errors that occurred during reading.
02499 */
02500   if ( ierror == ERROR ) {
02501     printf ( "\n" );
02502     printf ( "DATA_READ - Fatal error!\n" );
02503     printf ( "  An error occurred while reading the input file.\n" );
02504     return ERROR;
02505   }
02506 /*
02507   Check the data.
02508   You MUST wait until after this check before doing other computations,
02509   since COR3_NUM and other variables could be much larger than the legal
02510   maximums, until corrected by DATA_CHECK.
02511 */
02512   data_check ( );
02513 /*
02514   MATERIALS FIXUPS:
02515 
02516   If there are no materials at all, define one.
02517 */
02518   if ( material_num < 1 ) {
02519     material_num = 1;
02520     strcpy ( material_name[0], "Material_0000" );
02521     material_rgba[0][0] = 0.7;
02522     material_rgba[1][0] = 0.7;
02523     material_rgba[2][0] = 0.7;
02524     material_rgba[3][0] = 1.0;
02525   }
02526 /*
02527   If a node has not been assigned a material, set it to material 0.
02528 */
02529   for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
02530     if ( cor3_material[icor3] < 0 || cor3_material[icor3] > material_num - 1 ) {
02531       cor3_material[icor3] = 0;
02532     }
02533   }
02534 /*
02535   If a vertex has not been assigned a material, set it to material 0.
02536 */
02537   for ( iface = 0; iface < face_num; iface++ ) {
02538     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
02539       if ( vertex_material[ivert][iface] < 0 || vertex_material[ivert][iface] > material_num - 1 ) {
02540         vertex_material[ivert][iface] = 0;
02541       }
02542     }
02543   }
02544 /*
02545   If a face has not been assigned a material, set it to material 0.
02546 */
02547   for ( iface = 0; iface < face_num; iface++ ) {
02548     if ( face_material[iface] < 0 || face_material[iface] > material_num - 1 ) {
02549       face_material[iface] = 0;
02550     }
02551   }
02552 /*
02553   If a line item has not been assigned a material, set it to material 0.
02554 */
02555   for ( iline = 0; iline < line_num; iline++ ) {
02556     if ( line_dex[iline] == -1 ) {
02557       line_material[iline] = -1;
02558     }
02559     else if ( line_material[iline] < 0 || line_material[iline] > material_num - 1 ) {
02560       line_material[iline] = 0;
02561     }
02562   }
02563 /*
02564   Delete edges of zero length.
02565 */
02566   edge_null_delete ( );
02567 /*
02568   Compute the area of each face.
02569 */
02570   face_area_set ( );
02571 /*
02572   Delete faces with zero area.
02573 */
02574   face_null_delete ( );
02575 /*
02576   Recompute zero face-vertex normals from vertex positions.
02577 */
02578   vertex_normal_set ( );
02579 /*
02580   Compute the node normals from the vertex normals.
02581 */
02582   cor3_normal_set ( );
02583 /*
02584   Recompute zero face normals by averaging face-vertex normals.
02585 */
02586   face_normal_ave ( );
02587 /*
02588   Report on the nodal coordinate range.
02589 */
02590   cor3_range ( );
02591 
02592   return SUCCESS;
02593 }
02594 /**********************************************************************/
02595 
02596 void data_report ( void )
02597 
02598 /**********************************************************************/
02599 
02600 /*
02601   Purpose:
02602 
02603     DATA_REPORT gives a summary of the contents of the data file.
02604 
02605   Modified:
02606 
02607     24 May 1999
02608 
02609   Author:
02610 
02611     John Burkardt
02612 */
02613 {
02614   printf ( "\n" );
02615   printf ( "DATA_REPORT - The input file contains:\n" );
02616   printf ( "\n" );
02617   printf ( "  Bad data items             %d\n", bad_num );
02618   printf ( "  Text lines                 %d\n", text_num );
02619   printf ( "  Text bytes (binary data)   %d\n", bytes_num );
02620   printf ( "  Colors                     %d\n", color_num );
02621   printf ( "  Comments                   %d\n", comment_num );
02622   printf ( "  Duplicate points           %d\n", dup_num );
02623   printf ( "  Faces                      %d\n", face_num );
02624   printf ( "  Groups                     %d\n", group_num );
02625   printf ( "  Vertices per face, maximum %d\n", max_order2 );
02626   printf ( "  Line items                 %d\n", line_num );
02627   printf ( "  Points                     %d\n", cor3_num );
02628   printf ( "  Objects                    %d\n", object_num );
02629 
02630   return;
02631 }
02632 /******************************************************************************/
02633 
02634 int data_write ( void )
02635 
02636 /******************************************************************************/
02637 
02638 /*
02639   Purpose:
02640 
02641     DATA_WRITE writes the internal graphics data to a file.
02642 
02643   Modified:
02644 
02645     22 May 1999
02646 
02647   Author:
02648  
02649     John Burkardt
02650 */
02651 {
02652   FILE *fileout;
02653   char *fileout_type;
02654   int   line_num_save;
02655   int   result;
02656 
02657   result = SUCCESS;
02658 /* 
02659   Retrieve the output file type. 
02660 */
02661   fileout_type = file_ext ( fileout_name );
02662 
02663   if ( fileout_type == NULL ) {
02664     printf ( "\n" );
02665     printf ( "DATA_WRITE - Fatal error!\n" );
02666     printf ( "  Could not determine the output file type.\n" );
02667     return ERROR;
02668   }
02669 /* 
02670   Open the output file. 
02671 */
02672   if ( leqi ( fileout_type, "3DS" ) == TRUE ||
02673        leqi ( fileout_type, "STLB" ) == TRUE ||
02674        leqi ( fileout_type, "TRIB" ) ) {
02675     fileout = fopen ( fileout_name, "wb" );
02676   }
02677   else {
02678     fileout = fopen ( fileout_name, "w" );
02679   }
02680 
02681   if ( fileout == NULL ) {
02682     printf ( "\n" );
02683     printf ( "DATA_WRITE - Fatal error!\n" );
02684     printf ( "  Could not open the output file!\n" );
02685     return ERROR;
02686   }
02687 /* 
02688   Write the output file. 
02689 */
02690   if ( leqi ( fileout_type, "3DS" ) == TRUE ) {
02691 
02692     tds_pre_process();
02693     result = tds_write ( fileout );
02694 
02695   }
02696   else if ( leqi ( fileout_type, "ASE" ) == TRUE ) {
02697 
02698     result = ase_write ( fileout );
02699 
02700   }
02701   else if ( leqi ( fileout_type, "BYU" ) == TRUE ) {
02702 
02703     result = byu_write ( fileout );
02704 
02705   }
02706   else if ( leqi ( fileout_type, "DXF" ) == TRUE ) {
02707 
02708     result = dxf_write ( fileout );
02709 
02710   }
02711   else if ( leqi ( fileout_type, "GMOD" ) == TRUE ) {
02712 
02713     result = gmod_write ( fileout );
02714 
02715   }
02716   else if ( leqi ( fileout_type, "HRC" ) == TRUE ) {
02717 
02718     result = hrc_write ( fileout );
02719 
02720   }
02721   else if ( leqi ( fileout_type, "IV" ) == TRUE ) {
02722 
02723     result = iv_write ( fileout );
02724 
02725   }
02726   else if ( leqi ( fileout_type, "OBJ" ) == TRUE ) {
02727 
02728     result = obj_write ( fileout );
02729 
02730   }
02731   else if ( leqi ( fileout_type, "POV" ) == TRUE ) {
02732 
02733     result = pov_write ( fileout );
02734 
02735   }
02736   else if ( leqi ( fileout_type, "SMF" ) == TRUE ) {
02737 
02738     result = smf_write ( fileout );
02739 
02740   }
02741   else if ( 
02742     leqi ( fileout_type, "STL" ) == TRUE ||
02743     leqi ( fileout_type, "STLA" ) == TRUE ) {
02744 
02745     result = stla_write ( fileout );
02746 
02747   }
02748   else if ( leqi ( fileout_type, "STLB" ) == TRUE ) {
02749 
02750     result = stlb_write ( fileout );
02751 
02752   }
02753   else if ( leqi ( fileout_type, "TEC" ) == TRUE ) {
02754 
02755     result = tec_write ( fileout );
02756 
02757   }
02758   else if ( 
02759     leqi ( fileout_type, "TRI" ) == TRUE ||
02760     leqi ( fileout_type, "TRIA" ) == TRUE ) {
02761 
02762     result = tria_write ( fileout );
02763 
02764   }
02765   else if ( leqi ( fileout_type, "TRIB" ) == TRUE ) {
02766 
02767     result = trib_write ( fileout );
02768 
02769   }
02770   else if ( leqi ( fileout_type, "TXT" ) == TRUE ) {
02771 
02772     result = txt_write ( fileout );
02773 
02774   }
02775   else if ( leqi ( fileout_type, "UCD" ) == TRUE ) {
02776 
02777     result = ucd_write ( fileout );
02778 
02779   }
02780   else if ( leqi ( fileout_type, "VLA" ) == TRUE ) {
02781 
02782     line_num_save = line_num;
02783 
02784     if ( face_num > 0 ) {
02785 
02786       printf ( "\n" );
02787       printf ( "DATA_WRITE - Note:\n" );
02788       printf ( "  Face information will temporarily be converted to\n" );
02789       printf ( "  line information for output to a VLA file.\n" );
02790 
02791       face_to_line ( );
02792 
02793       if ( line_num > LINES_MAX ) {
02794         printf ( "\n" );
02795         printf ( "DATA_WRITE - Warning:\n" );
02796         printf ( "  Some face information was lost.\n" );
02797         printf ( "  The maximum number of lines is %d.\n", LINES_MAX );
02798         printf ( "  The number of lines needed is %d.\n", line_num );
02799         line_num = LINES_MAX;
02800       }
02801 
02802     }
02803 
02804     result = vla_write ( fileout );
02805 
02806     line_num = line_num_save;
02807 
02808   }
02809   else if ( leqi ( fileout_type, "WRL" ) == TRUE ) {
02810 
02811     result = wrl_write ( fileout );
02812 
02813   }
02814   else if ( leqi ( fileout_type, "XGL" ) == TRUE ) {
02815 
02816     result = xgl_write ( fileout );
02817 
02818   }
02819   else {
02820 
02821     result = ERROR;
02822     printf ( "\n" );
02823     printf ( "DATA_WRITE - Fatal error!\n" );
02824     printf ( "  Unacceptable output file type \"%s\".\n", fileout_type );
02825 
02826   }
02827 /*  
02828   Close the output file. 
02829 */
02830   fclose ( fileout );
02831 
02832   if ( result == ERROR ) {
02833     return ERROR;
02834   }
02835   else {
02836     return SUCCESS;
02837   }
02838 }
02839 /******************************************************************************/
02840 
02841 int dxf_read ( FILE *filein )
02842 
02843 /******************************************************************************/
02844 
02845 /*
02846   Purpose:
02847    
02848     DXF_READ reads an AutoCAD DXF file.
02849 
02850   Examples:
02851 
02852       0
02853     SECTION
02854       2
02855     HEADER
02856     999
02857     diamond.dxf created by IVREAD.
02858     999
02859     Original data in diamond.obj.
02860       0
02861     ENDSEC
02862       0
02863     SECTION
02864       2
02865     TABLES
02866       0
02867     ENDSEC
02868       0
02869     SECTION
02870       2
02871     BLOCKS
02872       0
02873     ENDSEC
02874       0
02875     SECTION
02876       2
02877     ENTITIES
02878       0
02879     LINE
02880       8
02881     0
02882      10
02883       0.00  (X coordinate of beginning of line.)
02884      20
02885       0.00  (Y coordinate of beginning of line.)
02886      30
02887       0.00  (Z coordinate of beginning of line.)
02888      11
02889       1.32  (X coordinate of end of line.)
02890      21
02891       1.73  (Y coordinate of end of line.)
02892      31
02893       2.25  (Z coordinate of end of line.)
02894       0
02895     3DFACE
02896       8
02897      Cube
02898     10
02899     -0.50  (X coordinate of vertex 1)
02900     20
02901      0.50  (Y coordinate of vertex 1)   
02902     30
02903       1.0  (Z coordinate of vertex 1)  
02904     11
02905      0.50  (X coordinate of vertex 2)  
02906     21
02907      0.50  (Y coordinate of vertex 2)
02908     31
02909       1.0  (Z coordinate of vertex 2)
02910     12
02911      0.50  (X coordinate of vertex 3) 
02912     22
02913      0.50  (Y coordinate of vertex 3)
02914     32
02915      0.00  (Z coordinate of vertex 3)
02916       0
02917     ENDSEC
02918       0
02919     EOF
02920 
02921   Modified:
02922 
02923     23 May 1999
02924 
02925   Author:
02926  
02927     John Burkardt
02928 */
02929 {
02930   int   code;
02931   int   count;
02932   float cvec[3];
02933   int   icor3;
02934   char  input1[LINE_MAX_LEN];
02935   char  input2[LINE_MAX_LEN];
02936   int   ivert;
02937   float rval;
02938   int   width;
02939   int   linemode;
02940   int   cpos;
02941 
02942   linemode = 0;
02943   ivert = 0;
02944 /* 
02945   Read the next two lines of the file into INPUT1 and INPUT2. 
02946 */
02947 
02948   for ( ;; ) {
02949 
02950 /* 
02951   INPUT1 should contain a single integer, which tells what INPUT2
02952   will contain.
02953 */
02954     if ( fgets ( input1, LINE_MAX_LEN, filein ) == NULL ) {
02955       break;
02956     }
02957 
02958     text_num = text_num + 1;
02959 
02960     count = sscanf ( input1, "%d%n", &code, &width );
02961     if ( count <= 0 ) {
02962       break;
02963     }
02964 /*
02965   Read the second line, and interpret it according to the code.
02966 */
02967     if ( fgets ( input2, LINE_MAX_LEN, filein ) == NULL ) {
02968       break;
02969     }
02970 
02971     text_num = text_num + 1;
02972 
02973     if ( code == 0 ) {
02974     
02975       if ( ivert > 0 ) {
02976         /* finish off the face */
02977         face_order[face_num] = ivert;
02978         face_num = face_num + 1;
02979         ivert = 0;
02980       }
02981       
02982       if ( strncmp( input2, "LINE", 4 ) == 0 ) {
02983         linemode = 1;
02984       }
02985       else if ( strncmp( input2, "3DFACE", 6 ) == 0 ) {
02986         linemode = 0;
02987         ivert = 0;
02988       }
02989     }
02990     else {
02991       
02992       for (cpos = 0; input1[cpos] == ' '; cpos++) 
02993       {};
02994       
02995       if ( input1[cpos] == '1' || input1[cpos] == '2' || input1[cpos] == '3' ) {
02996 
02997         count = sscanf ( input2, "%e%n", &rval, &width );
02998 
02999         switch ( input1[cpos] )
03000         {
03001           case '1':
03002             if ( line_num > 0 ) {
03003               if ( linemode ) {
03004                 line_dex[line_num] = - 1;
03005                 line_material[line_num] = - 1;
03006                 line_num = line_num + 1;
03007               }
03008             }
03009             cvec[0] = rval;
03010             break;
03011 
03012           case '2':
03013             cvec[1] = rval;
03014             break;
03015 
03016           case '3':
03017             cvec[2] = rval;
03018 
03019             if ( cor3_num < 1000 ) {
03020               icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
03021             } 
03022             else {
03023               icor3 = -1;
03024             }
03025 
03026             if ( icor3 == -1 ) {
03027               icor3 = cor3_num;
03028               if ( cor3_num < COR3_MAX ) {
03029                 cor3[0][cor3_num] = cvec[0];
03030                 cor3[1][cor3_num] = cvec[1];
03031                 cor3[2][cor3_num] = cvec[2];
03032               }
03033               cor3_num = cor3_num + 1;
03034             }
03035             else {
03036               dup_num = dup_num + 1;
03037             }
03038 
03039             if ( linemode ) {
03040               line_dex[line_num] = icor3;
03041               line_material[line_num] = 0;
03042               line_num = line_num + 1;
03043             }
03044             else {
03045               face[ivert][face_num] = icor3;
03046               ivert = ivert + 1;
03047             }
03048             break;
03049         
03050           default:
03051             break;
03052         }
03053       }
03054     }
03055   }
03056 
03057   if ( line_num > 0 ) {
03058     if ( linemode ) {
03059       line_dex[line_num] = - 1;
03060       line_material[line_num] = - 1;
03061       line_num = line_num + 1;
03062     }
03063   }
03064   return SUCCESS;
03065 }
03066 /******************************************************************************/
03067 
03068 int dxf_write ( FILE *fileout )
03069 
03070 /******************************************************************************/
03071 
03072 /*
03073   Purpose:
03074    
03075     DXF_WRITE writes graphics information to an AutoCAD DXF file.
03076 
03077   Examples:
03078 
03079       0
03080     SECTION
03081       2
03082     HEADER
03083     999
03084     diamond.dxf created by IVREAD.
03085     999
03086     Original data in diamond.obj.
03087       0
03088     ENDSEC
03089       0
03090     SECTION
03091       2
03092     TABLES
03093       0
03094     ENDSEC
03095       0
03096     SECTION
03097       2
03098     BLOCKS
03099       0
03100     ENDSEC
03101       0
03102     SECTION
03103       2
03104     ENTITIES
03105       0
03106     LINE
03107       8
03108     0
03109      10
03110       0.00  (X coordinate of beginning of line.)
03111      20
03112       0.00  (Y coordinate of beginning of line.)
03113      30
03114       0.00  (Z coordinate of beginning of line.)
03115      11
03116       1.32  (X coordinate of end of line.)
03117      21
03118       1.73  (Y coordinate of end of line.)
03119      31
03120       2.25  (Z coordinate of end of line.)
03121       0
03122     3DFACE
03123       8
03124      Cube
03125     10
03126     -0.50  (X coordinate of vertex 1)
03127     20
03128      0.50  (Y coordinate of vertex 1)   
03129     30
03130       1.0  (Z coordinate of vertex 1)  
03131     11
03132      0.50  (X coordinate of vertex 2)  
03133     21
03134      0.50  (Y coordinate of vertex 2)
03135     31
03136       1.0  (Z coordinate of vertex 2)
03137     12
03138      0.50  (X coordinate of vertex 3) 
03139     22
03140      0.50  (Y coordinate of vertex 3)
03141     32
03142      0.00  (Z coordinate of vertex 3)
03143       0
03144     ENDSEC
03145       0
03146     EOF
03147 
03148   Modified:
03149 
03150     16 May 1999
03151 
03152   Author:
03153  
03154     John Burkardt
03155 */
03156 {
03157   int   icor3;
03158   int   iline;
03159   int   iface;
03160   int   ivert;
03161   int   jcor3;
03162   int   newline;
03163   int   text_num;
03164 
03165 /* 
03166   Initialize. 
03167 */
03168   text_num = 0;
03169 
03170   fprintf ( fileout, "  0\n" );
03171   fprintf ( fileout, "SECTION\n" );
03172   fprintf ( fileout, "  2\n" );
03173   fprintf ( fileout, "HEADER\n" );
03174   fprintf ( fileout, "999\n" );
03175   fprintf ( fileout, "%s created by IVCON.\n", fileout_name );
03176   fprintf ( fileout, "999\n" );
03177   fprintf ( fileout, "Original data in %s.\n", filein_name );
03178   fprintf ( fileout, "  0\n" );
03179   fprintf ( fileout, "ENDSEC\n" );
03180   text_num = text_num + 10;
03181 
03182   fprintf ( fileout, "  0\n" );
03183   fprintf ( fileout, "SECTION\n" );
03184   fprintf ( fileout, "  2\n" );
03185   fprintf ( fileout, "TABLES\n" );
03186   fprintf ( fileout, "  0\n" );
03187   fprintf ( fileout, "ENDSEC\n" );
03188   text_num = text_num + 6;
03189 
03190   fprintf ( fileout, "  0\n" );
03191   fprintf ( fileout, "SECTION\n" );
03192   fprintf ( fileout, "  2\n" );
03193   fprintf ( fileout, "BLOCKS\n" );
03194   fprintf ( fileout, "  0\n" );
03195   fprintf ( fileout, "ENDSEC\n" );
03196   text_num = text_num + 6;
03197 
03198   fprintf ( fileout, "  0\n" );
03199   fprintf ( fileout, "SECTION\n" );
03200   fprintf ( fileout, "  2\n" );
03201   fprintf ( fileout, "ENTITIES\n" );
03202   text_num = text_num + 4;
03203 /*
03204   Handle lines.
03205 */
03206   jcor3 = 0;
03207   newline = TRUE;
03208 
03209   for ( iline = 0; iline < line_num; iline++ ) {
03210     
03211     icor3 = line_dex[iline];
03212 
03213     if ( icor3 == -1 ) {
03214 
03215       newline = TRUE;
03216     }
03217     else {
03218 
03219       if ( newline == FALSE ) {
03220 
03221         fprintf ( fileout, "  0\n" );
03222         fprintf ( fileout, "LINE\n" );
03223         fprintf ( fileout, "  8\n" );
03224         fprintf ( fileout, "  0\n" );
03225         fprintf ( fileout, " 10\n" );
03226         fprintf ( fileout, "%f\n", cor3[0][jcor3] );
03227         fprintf ( fileout, " 20\n" );
03228         fprintf ( fileout, "%f\n", cor3[1][jcor3] );
03229         fprintf ( fileout, " 30\n" );
03230         fprintf ( fileout, "%f\n", cor3[2][jcor3] );
03231         fprintf ( fileout, " 11\n" );
03232         fprintf ( fileout, "%f\n", cor3[0][icor3] );
03233         fprintf ( fileout, " 21\n" );
03234         fprintf ( fileout, "%f\n", cor3[1][icor3] );
03235         fprintf ( fileout, " 31\n" );
03236         fprintf ( fileout, "%f\n", cor3[2][icor3] );
03237 
03238         text_num = text_num + 16;
03239 
03240       }
03241 
03242       jcor3 = icor3;
03243       newline = FALSE;
03244 
03245     }
03246   }
03247 /*
03248   Handle faces.
03249   (If FACE_ORDER is greater than 10, you're sure to have problems here)
03250 */
03251   for ( iface = 0; iface < face_num; iface++ ) {
03252     
03253     fprintf ( fileout, "  0\n" );
03254     fprintf ( fileout, "3DFACE\n" );
03255     fprintf ( fileout, "  8\n" );
03256     fprintf ( fileout, "  Cube\n" );
03257     text_num = text_num + 4;
03258     
03259     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
03260 
03261       icor3 = face[ivert][iface];
03262       
03263       fprintf ( fileout, "1%d\n", ivert );
03264       fprintf ( fileout, "%f\n", cor3[0][icor3] );
03265       fprintf ( fileout, "2%d\n", ivert );
03266       fprintf ( fileout, "%f\n", cor3[1][icor3] );
03267       fprintf ( fileout, "3%d\n", ivert );
03268       fprintf ( fileout, "%f\n", cor3[2][icor3] );
03269 
03270       text_num = text_num + 6;
03271     }
03272   }
03273 
03274   fprintf ( fileout, "  0\n" );
03275   fprintf ( fileout, "ENDSEC\n" );
03276   fprintf ( fileout, "  0\n" );
03277   fprintf ( fileout, "EOF\n" );
03278   text_num = text_num + 4;
03279 /*
03280   Report.
03281 */
03282   printf ( "\n" );
03283   printf ( "DXF_WRITE - Wrote %d text lines.\n", text_num );
03284 
03285   return SUCCESS;
03286 }
03287 /**********************************************************************/
03288 
03289 void edge_null_delete ( void )
03290 
03291 /**********************************************************************/
03292 
03293 /*
03294   Purpose:
03295 
03296     EDGE_NULL_DELETE deletes face edges with zero length.
03297 
03298   Modified:
03299 
03300     16 July 1999
03301 
03302   Author:
03303 
03304     John Burkardt
03305 */
03306 {
03307   float distsq;
03308   int face2[ORDER_MAX];
03309   int face_order2;
03310   int iface;
03311   int inode;
03312   int ivert;
03313   int j;
03314   int jnode;
03315   int jvert;
03316   int edge_num;
03317   int edge_num_del;
03318   float vertex_normal2[3][ORDER_MAX];
03319   float x;
03320   float y;
03321   float z;
03322 
03323   edge_num = 0;
03324   edge_num_del = 0;
03325 /*
03326   Consider each face.
03327 */
03328   for ( iface = 0; iface < face_num; iface++ ) {
03329 /*
03330   Consider each pair of consecutive vertices.
03331 */
03332     face_order2 = 0;
03333 
03334     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
03335 
03336       edge_num = edge_num + 1;
03337 
03338       jvert = ivert + 1;
03339       if ( jvert >= face_order[iface] ) {
03340         jvert = 0;
03341       }
03342 
03343       inode = face[ivert][iface];
03344       jnode = face[jvert][iface];
03345 
03346 
03347       x = cor3[0][inode] - cor3[0][jnode];
03348       y = cor3[1][inode] - cor3[1][jnode];
03349       z = cor3[2][inode] - cor3[2][jnode];
03350 
03351       distsq = x * x + y * y + z * z;
03352 
03353       if ( distsq != 0.0 ) {
03354         face2[face_order2] = face[ivert][iface];
03355         vertex_normal2[0][face_order2] = vertex_normal[0][ivert][iface];
03356         vertex_normal2[1][face_order2] = vertex_normal[1][ivert][iface];
03357         vertex_normal2[2][face_order2] = vertex_normal[2][ivert][iface];
03358         face_order2 = face_order2 + 1;
03359       }
03360       else {
03361         edge_num_del = edge_num_del + 1;
03362       }
03363 
03364     }
03365 
03366     face_order[iface] = face_order2;
03367     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
03368       face[ivert][iface] = face2[ivert];
03369       for ( j = 0; j < 3; j++ ) {
03370         vertex_normal[j][ivert][iface] = vertex_normal2[j][ivert];
03371       }
03372     }
03373 
03374   }
03375 
03376   printf ( "\n" );
03377   printf ( "EDGE_NULL_DELETE:\n" );
03378   printf ( "  There are a total of %d edges.\n", edge_num );
03379   printf ( "  Of these, %d were of zero length, and deleted.\n", edge_num_del );
03380 
03381   return;
03382 }
03383 /**********************************************************************/
03384 
03385 void face_area_set ( void )
03386 
03387 /**********************************************************************/
03388 
03389 /*
03390   Purpose:
03391 
03392     FACE_AREA_SET computes the area of the faces.
03393 
03394   Formula:
03395 
03396     The area is the sum of the areas of the triangles formed by
03397     node N with consecutive pairs of nodes.
03398 
03399   Reference:
03400 
03401     Adrian Bowyer and John Woodwark,
03402     A Programmer's Geometry,
03403     Butterworths, 1983.
03404 
03405   Modified:
03406 
03407     17 July 1999
03408 
03409   Author:
03410 
03411     John Burkardt
03412 */
03413 {
03414   float alpha;
03415   float area_max;
03416   float area_min;
03417   float area_tri;
03418   float base;
03419   float dot;
03420   float height;
03421   int i;
03422   int i1;
03423   int i2;
03424   int i3;
03425   int iface;
03426   int face_num_del;
03427   float tol;
03428   float x;
03429   float x1;
03430   float x2;
03431   float x3;
03432   float y;
03433   float y1;
03434   float y2;
03435   float y3;
03436   float z;
03437   float z1;
03438   float z2;
03439   float z3;
03440 
03441   for ( iface = 0; iface < face_num; iface++ ) {
03442 
03443     face_area[iface] = 0.0;
03444 
03445     for ( i = 0; i < face_order[iface]-2; i++ ) {
03446 
03447       i1 = face[i][iface];
03448       i2 = face[i+1][iface];
03449       i3 = face[i+2][iface];
03450 
03451       x1 = cor3[0][i1];
03452       y1 = cor3[1][i1];
03453       z1 = cor3[2][i1];
03454 
03455       x2 = cor3[0][i2];
03456       y2 = cor3[1][i2];
03457       z2 = cor3[2][i2];
03458 
03459       x3 = cor3[0][i3];
03460       y3 = cor3[1][i3];
03461       z3 = cor3[2][i3];
03462 /*
03463   Find the projection of (P3-P1) onto (P2-P1).
03464 */
03465       dot =
03466         ( x2 - x1 ) * ( x3 - x1 ) +
03467         ( y2 - y1 ) * ( y3 - y1 ) +
03468         ( z2 - z1 ) * ( z3 - z1 );
03469 
03470       base = sqrt (
03471           ( x2 - x1 ) * ( x2 - x1 )
03472         + ( y2 - y1 ) * ( y2 - y1 )
03473         + ( z2 - z1 ) * ( z2 - z1 ) );
03474 /*
03475   The height of the triangle is the length of (P3-P1) after its
03476   projection onto (P2-P1) has been subtracted.
03477 */
03478       if ( base == 0.0 ) {
03479         height = 0.0;
03480       }
03481       else {
03482 
03483         alpha = dot / ( base * base );
03484 
03485         x = x3 - x1 - alpha * ( x2 - x1 );
03486         y = y3 - y1 - alpha * ( y2 - y1 );
03487         z = z3 - z1 - alpha * ( z2 - z1 );
03488 
03489         height = sqrt ( x * x + y * y + z * z );
03490 
03491       }
03492 
03493       area_tri = 0.5 * base * height;
03494 
03495       face_area[iface] = face_area[iface] + area_tri;
03496 
03497     }
03498 
03499   }
03500 
03501   area_min = face_area[0];
03502   area_max = face_area[0];
03503 
03504   for ( iface = 1; iface < face_num; iface++ ) {
03505     if ( area_min > face_area[iface] ) {
03506       area_min = face_area[iface];
03507     }
03508     if ( area_max < face_area[iface] ) {
03509       area_max = face_area[iface];
03510     }
03511   }
03512 
03513   printf ( "\n" );
03514   printf ( "FACE_AREA_SET:\n" );
03515   printf ( "  Minimum face area is %f\n", area_min );
03516   printf ( "  Maximum face area is %f\n", area_max );
03517 
03518   tol = area_max / 10000.0;
03519 
03520   if ( area_min < tol ) {
03521 
03522     face_num_del = 0;
03523 
03524     for ( iface = 0; iface < face_num; iface++ ) {
03525       if ( face_area[iface] < tol ) {
03526         face_order[iface] = 0;
03527         face_num_del = face_num_del + 1;
03528       }
03529     }
03530 
03531     printf ( "  Marked %d tiny faces for deletion.\n", face_num_del );
03532 
03533   }
03534 
03535   return;
03536 }
03537 /******************************************************************************/
03538 
03539 void face_normal_ave ( void )
03540 
03541 /******************************************************************************/
03542 
03543 /*
03544   Purpose:
03545 
03546     FACE_NORMAL_AVE sets face normals as average of face vertex normals.
03547 
03548   Modified:
03549 
03550     09 October 1998
03551 
03552   Author:
03553 
03554     John Burkardt
03555 */
03556 {
03557   int   i;
03558   int   iface;
03559   int   ivert;
03560   int   nfix;
03561   float norm;
03562   float x;
03563   float y;
03564   float z;
03565 
03566   if ( face_num <= 0 ) {
03567     return;
03568   }
03569   
03570   nfix = 0;
03571 
03572   for ( iface = 0; iface < face_num; iface++ ) {
03573 
03574 /*
03575   Check the norm of the current normal vector.
03576 */
03577     x = face_normal[0][iface];
03578     y = face_normal[1][iface];
03579     z = face_normal[2][iface];
03580     norm = ( float ) sqrt ( x * x + y * y + z * z );
03581 
03582     if ( norm == 0.0 ) {
03583 
03584       nfix = nfix + 1;
03585 
03586       for ( i = 0; i < 3; i++ ) {
03587         face_normal[i][iface] = 0.0;
03588       }
03589 
03590       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
03591         for ( i = 0; i < 3; i++ ) {
03592           face_normal[i][iface] = face_normal[i][iface] +
03593             vertex_normal[i][ivert][iface];
03594         }
03595       }
03596 
03597       x = face_normal[0][iface];
03598       y = face_normal[1][iface];
03599       z = face_normal[2][iface];
03600       norm = ( float ) sqrt ( x * x + y * y + z * z );
03601 
03602       if ( norm == 0.0 ) {
03603         for ( i = 0; i < 3; i++ ) {
03604           face_normal[i][iface] = ( float ) ( 1.0 / sqrt ( 3.0 ) );
03605         }
03606       }
03607       else {
03608         for ( i = 0; i < 3; i++ ) {
03609           face_normal[i][iface] = face_normal[i][iface] / norm;
03610         }
03611       }
03612     }
03613   }
03614 
03615   if ( nfix > 0 ) {
03616     printf ( "\n" );
03617     printf ( "FACE_NORMAL_AVE: Recomputed %d face normals\n", nfix );
03618     printf ( "  by averaging face vertex normals.\n" );
03619   }
03620   return;
03621 }
03622 /**********************************************************************/
03623 
03624 void face_null_delete ( void )
03625 
03626 /**********************************************************************/
03627 
03628 /*
03629   Purpose:
03630 
03631     FACE_NULL_DELETE deletes faces of order less than 3.
03632 
03633   Comments:
03634 
03635     Thanks to Susan M. Fisher, University of North Carolina,
03636     Department of Computer Science, for pointing out a coding error
03637     in FACE_NULL_DELETE that was overwriting all the data!
03638 
03639   Modified:
03640 
03641     30 November 1999
03642 
03643   Author:
03644 
03645     John Burkardt
03646 */
03647 {
03648   int iface;
03649   int ivert;
03650   int j;
03651   int face_num2;
03652 /*
03653   FACE_NUM2 is the number of faces we'll keep.
03654 */
03655   face_num2 = 0;
03656 /*
03657   Check every face.
03658 */
03659   for ( iface = 0; iface < face_num; iface++ ) {
03660 /*
03661   Keep it only if it has order 3 or more.
03662 */
03663     if ( face_order[iface] >= 3 ) {
03664 /*
03665   We don't have to slide data down in the array until
03666   NUMFACE2 and IFACE get out of synch, that is, after
03667   we've discarded at least one face.
03668 */
03669       if ( face_num2 != iface ) {
03670 
03671         face_area[face_num2] = face_area[iface];
03672         face_material[face_num2] = face_material[iface];
03673         face_order[face_num2] = face_order[iface];
03674         for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
03675           face[ivert][face_num2] = face[ivert][iface];
03676           vertex_material[ivert][face_num2] = vertex_material[ivert][iface];
03677           for ( j = 0; j < 3; j++ ) {
03678             vertex_normal[j][ivert][face_num2] = vertex_normal[j][ivert][iface];
03679           }
03680         }
03681 
03682       }
03683 /*
03684   Update the count only after we've used the un-incremented value
03685   as a pointer.
03686 */
03687       face_num2 = face_num2 + 1;
03688 
03689     }
03690 
03691   }
03692 
03693   printf ( "\n" );
03694   printf ( "FACE_NULL_DELETE\n" );
03695   printf ( "  There are a total of %d faces.\n", face_num );
03696   printf ( "  Of these, %d passed the order test.\n", face_num2 );
03697 
03698   face_num = face_num2;
03699 
03700   return;
03701 }
03702 /******************************************************************************/
03703 
03704 int face_print ( int iface )
03705 
03706 /******************************************************************************/
03707 
03708 /*
03709   Purpose:
03710 
03711     FACE_PRINT prints out information about a face.
03712 
03713   Modified:
03714 
03715     31 August 1998
03716 
03717   Author:
03718 
03719     John Burkardt
03720 */
03721 {
03722   int ivert;
03723   int j;
03724   int k;
03725 
03726   if ( iface < 0 || iface > face_num-1 ) {
03727     printf ( "\n" );
03728     printf ( "FACE_PRINT - Fatal error!\n" );
03729     printf ( "  Face indices must be between 1 and %d\n", face_num );
03730     printf ( "  But your requested value was %d\n", iface );
03731     return ERROR;
03732   }
03733 
03734   printf ( "\n" );
03735   printf ( "FACE_PRINT\n" );
03736   printf ( "  Information about face %d\n", iface );
03737   printf ( "\n" );
03738   printf ( "  Number of vertices is %d\n", face_order[iface] );
03739   printf ( "\n" );
03740   printf ( "  Vertex list:\n" );
03741   printf ( "    Vertex #, Node #, Material #, X, Y, Z:\n" );
03742   printf ( "\n" );
03743   for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
03744     j = face[ivert][iface];
03745     k = vertex_material[ivert][iface];
03746     printf ( " %d %d %d %f %f %f\n", ivert, j, k, cor3[0][j], cor3[1][j], 
03747      cor3[2][j] );
03748   }
03749 
03750   printf ( "\n" );
03751   printf ( "  Face normal vector:\n" );
03752   printf ( "\n" );
03753   printf ( " %f %f %f\n", face_normal[0][iface], face_normal[1][iface],
03754     face_normal[2][iface] );
03755 
03756   printf ( "\n" );
03757   printf ( "  Vertex face normals:\n" );
03758   printf ( "\n" );
03759   for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
03760     printf ( " %d %f %f %f\n", ivert, vertex_normal[0][ivert][iface],
03761       vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
03762   }
03763 
03764   return SUCCESS;
03765 
03766 }
03767 /**********************************************************************/
03768 
03769 void face_reverse_order ( void )
03770 
03771 /**********************************************************************/
03772 
03773 /*
03774   Purpose:
03775 
03776     FACE_REVERSE_ORDER reverses the order of the nodes in each face.
03777 
03778   Discussion:
03779 
03780     Reversing the order of the nodes requires that the normal vectors
03781     be reversed as well, so this routine will automatically reverse
03782     the normals associated with nodes, vertices and faces.
03783 
03784   Modified:
03785 
03786     28 June 1999
03787 
03788   Author:
03789 
03790     John Burkardt
03791 */
03792 {
03793   int i;
03794   int iface;
03795   int itemp;
03796   int ivert;
03797   int j;
03798   int m;
03799   float temp;
03800 
03801   for ( iface = 0; iface < face_num; iface++ ) {
03802 
03803     m = face_order[iface];
03804 
03805     for ( ivert = 0; ivert < ( m / 2 ); ivert++ ) {
03806 
03807       itemp = face[ivert][iface];
03808       face[ivert][iface] = face[m-1-ivert][iface];
03809       face[m-1-ivert][iface] = itemp;
03810 
03811       itemp = vertex_material[ivert][iface];
03812       vertex_material[ivert][iface] = vertex_material[m-1-ivert][iface];
03813       vertex_material[m-1-ivert][iface] = itemp;
03814 
03815       for ( j = 0; j < 3; j++ ) {
03816         temp = vertex_normal[j][ivert][iface];
03817         vertex_normal[j][ivert][iface] = vertex_normal[j][m-1-ivert][iface];
03818         vertex_normal[j][m-1-ivert][iface] = temp;
03819       }
03820 
03821       for ( j = 0; j < 2; j++ ) {
03822         temp = vertex_tex_uv[j][ivert][iface];
03823         vertex_tex_uv[j][ivert][iface] = vertex_tex_uv[j][m-1-ivert][iface];
03824         vertex_tex_uv[j][m-1-ivert][iface] = temp;
03825       }
03826 
03827     }
03828 
03829   }
03830 
03831   for ( i = 0; i < cor3_num; i++ ) {
03832     for ( j = 0; j < 3; j++ ) {
03833       cor3_normal[j][i] = - cor3_normal[j][i];
03834     }
03835   }
03836 
03837   for ( i = 0; i < face_num; i++ ) {
03838     for ( j = 0; j < 3; j++ ) {
03839       face_normal[j][i] = - face_normal[j][i];
03840     }
03841   }
03842 
03843   printf ( "\n" );
03844   printf ( "FACE_REVERSE_ORDER\n" );
03845   printf ( "  Each list of nodes defining a face\n" );
03846   printf ( "  has been reversed; related information,\n" );
03847   printf ( "  including normal vectors, was also updated.\n" );
03848 
03849   return;
03850 }
03851 
03852 /******************************************************************************/
03853 
03854 int face_subset ( void )
03855 
03856 /******************************************************************************/
03857 
03858 /*
03859   Purpose:
03860 
03861     FACE_SUBSET selects a subset of the current faces as the new object.
03862 
03863   Warning:
03864 
03865     The original graphic object is overwritten by the new one.
03866 
03867   Modified:
03868 
03869     12 October 1998
03870 
03871   Author:
03872 
03873     John Burkardt
03874 
03875 */
03876 {
03877   int i;
03878   int iface;
03879   int iface1;
03880   int iface2;
03881   int inc;
03882   int ivert;
03883   int j;
03884   int k;
03885   int cor3_num2;
03886 
03887   line_num = 0;
03888 /*
03889   Get the first and last faces to save, IFACE1 and IFACE2.
03890 */
03891   printf ( "\n" );
03892   printf ( "Enter lowest face number to save between 0 and %d:\n", face_num-1 );
03893   scanf ( "%d", &iface1 );
03894   if ( iface1 < 0 || iface1 > face_num - 1 ) {
03895     printf ( "Illegal choice!\n" );
03896     return ERROR;
03897   }
03898 
03899   printf ( "\n" );
03900   printf ( "Enter highest face number to save between %d and %d:\n", 
03901     iface1, face_num-1 );
03902   scanf ( "%d", &iface2 );
03903   if ( iface2 < iface1 || iface2 > face_num - 1 ) {
03904     printf ( "Illegal choice!\n" );
03905     return ERROR;
03906   }
03907 
03908   inc = iface1;
03909 /*
03910   "Slide" the data for the saved faces down the face arrays.
03911 */
03912   for ( iface = 0; iface < iface2 + 1 - iface1; iface++ ) {
03913     face_order[iface] = face_order[iface+inc];
03914     for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
03915       face[ivert][iface] = face[ivert][iface+inc];
03916       vertex_material[ivert][iface] = vertex_material[ivert][iface+inc];
03917       for ( i = 0; i < 3; i++ ) {
03918         vertex_normal[i][ivert][iface] =
03919           vertex_normal[i][ivert][iface+inc];
03920         vertex_rgb[i][ivert][iface] = vertex_rgb[i][ivert][iface+inc];
03921       }
03922     }
03923     for ( i = 0; i < 3; i++ ) {
03924       face_normal[i][iface] = face_normal[i][iface+inc];
03925     }
03926   }
03927 /*
03928   Now reset the number of faces.
03929 */
03930   face_num = iface2 + 1 - iface1;
03931 /*
03932   Now, for each point I, set LIST(I) = J if point I is the J-th
03933   point we are going to save, and 0 otherwise.  Then J will be
03934   the new label of point I.
03935 */
03936   for ( i = 0; i < cor3_num; i++ ) {
03937     list[i] = -1;
03938   }
03939 
03940   cor3_num2 = 0;
03941 
03942   for ( iface = 0; iface < face_num; iface++ ){
03943     for ( ivert = 0; ivert < face_order[iface]; ivert++ ){
03944       j = face[ivert][iface];
03945       if ( list[j] == -1 ) {
03946         cor3_num2 = cor3_num2 + 1;
03947         list[j] = cor3_num2;
03948       }
03949     }
03950   }
03951 /*
03952   Now make the nonzero list entries rise in order, so that
03953   we can compress the COR3 data in a minute.
03954 */
03955   cor3_num2 = 0;
03956 
03957   for ( i = 0; i < cor3_num; i++ ) {
03958     if ( list[i] != -1 ) {
03959       list[i] = cor3_num2;
03960       cor3_num2 = cor3_num2 + 1;
03961     }
03962   }
03963 /*
03964   Relabel the FACE array with the new node indices.
03965 */
03966   for ( iface = 0; iface < face_num; iface++ ){
03967     for ( ivert = 0; ivert < face_order[iface]; ivert++ ){
03968       j = face[ivert][iface];
03969       face[ivert][iface] = list[j];
03970     }
03971   }
03972 /*
03973   Rebuild the COR3 array by sliding data down.
03974 */
03975   for ( i = 0; i < cor3_num; i++ ){
03976     k = list[i];
03977     if ( k != -1 ) {
03978       for ( j = 0; j < 3; j++ ) {
03979         cor3[j][k] = cor3[j][i];
03980       }
03981     }
03982   }
03983 
03984   cor3_num = cor3_num2;
03985 
03986   return SUCCESS;
03987 }
03988 /**********************************************************************/
03989 
03990 void face_to_line ( void )
03991 
03992 /**********************************************************************/
03993 
03994 /*
03995   Purpose:
03996 
03997     FACE_TO_LINE converts face information to line information.
03998 
03999   Discussion:
04000 
04001     In some cases, the graphic information represented by polygonal faces
04002     must be converted to a representation based solely on line segments.
04003     This is particularly true if a VLA file is being written.
04004 
04005   Modified:
04006 
04007     26 May 1999
04008 
04009   Author:
04010 
04011     John Burkardt
04012 */
04013 {
04014   int icor3;
04015   int iface;
04016   int ivert;
04017   int jcor3;
04018   int jvert;
04019 /*
04020   Case 0:
04021   No line pruning.
04022 */
04023   if ( line_prune == 0 ) {
04024 
04025     for ( iface = 0; iface < face_num; iface++ ) {
04026 
04027       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
04028 
04029         icor3 = face[ivert][iface];
04030 
04031         line_num = line_num + 1;
04032         if ( line_num <= LINES_MAX ) {
04033           line_dex[line_num] = icor3;
04034           line_material[line_num] = vertex_material[ivert][iface];
04035         }
04036       }
04037 
04038       ivert = 0;
04039       icor3 = face[ivert][iface];
04040 
04041       line_num = line_num + 1;
04042       if ( line_num <= LINES_MAX ) {
04043         line_dex[line_num] = icor3;
04044         line_material[line_num] = vertex_material[ivert][iface];
04045       }
04046 
04047       line_num = line_num + 1;
04048       if ( line_num <= LINES_MAX ) {
04049         line_dex[line_num] = -1;
04050         line_material[line_num] = -1;
04051       }
04052     }
04053 
04054   }
04055 /*
04056   Case 2:
04057   Simple-minded line pruning.
04058   Only draw line (I,J) if I < J.
04059 */
04060   else {
04061 
04062     for ( iface = 0; iface < face_num; iface++ ) {
04063 
04064       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
04065 
04066         icor3 = face[ivert][iface];
04067 
04068         if ( ivert + 1 < face_order[iface] ) {
04069           jvert = ivert + 1;
04070         }
04071         else {
04072           jvert = 0;
04073         }
04074 
04075         jcor3 = face[jvert][iface];
04076         
04077         if ( icor3 < jcor3 ) {
04078 
04079           if ( line_num + 3 < LINES_MAX ) {
04080 
04081             line_num = line_num + 1;
04082             line_dex[line_num] = icor3;
04083             line_material[line_num] = vertex_material[ivert][iface];
04084 
04085             line_num = line_num + 1;
04086             line_dex[line_num] = jcor3;
04087             line_material[line_num] = vertex_material[jvert][iface];
04088 
04089             line_num = line_num + 1;
04090             line_dex[line_num] = -1;
04091             line_material[line_num] = -1;
04092 
04093           }
04094         }
04095       }
04096     }
04097 
04098   }
04099 
04100   return;
04101 }
04102 /**********************************************************************/
04103 
04104 void face_to_vertex_material ( void )
04105 
04106 /**********************************************************************/
04107 
04108 /*
04109   Purpose:
04110 
04111     FACE_TO_VERTEX_MAT extends face material definitions to vertices.
04112 
04113   Discussion:
04114 
04115     Assuming material indices are defined for all the faces, this
04116     routine assigns to each vertex of a face the material of that face.
04117 
04118   Modified:
04119 
04120     22 May 1999
04121 
04122   Author:
04123 
04124     John Burkardt
04125 */
04126 {
04127   int iface;
04128   int ivert;
04129 
04130   for ( iface = 0; iface < face_num; iface++ ) {
04131     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
04132       vertex_material[ivert][iface] = face_material[iface];
04133     }
04134   }
04135 
04136   return;
04137 }
04138 /******************************************************************************/
04139 
04140 char *file_ext ( char *file_name )
04141 
04142 /******************************************************************************/
04143 
04144 /*
04145   Purpose:
04146    
04147     FILE_EXT picks out the extension in a file name.
04148 
04149   Modified:
04150 
04151     21 July 1998
04152 
04153   Author:
04154  
04155     John Burkardt
04156 */
04157 {
04158   int i;
04159 
04160   i = char_index_last ( file_name, '.' );
04161 
04162   if ( i == -1 ) {
04163     return NULL;
04164   }
04165   else {
04166     return file_name + i + 1;
04167   }
04168 }
04169 /******************************************************************************/
04170 
04171 float float_read ( FILE *filein )
04172 
04173 /******************************************************************************/
04174 
04175 /*
04176   Purpose:
04177 
04178     FLOAT_READ reads 1 float from a binary file.
04179 
04180   Modified:
04181 
04182     24 May 1999
04183 */
04184 {
04185   float rval;
04186   float temp;
04187 
04188   fread ( &temp, sizeof ( float ), 1, filein );
04189 
04190   if ( byte_swap == TRUE ) {
04191     rval = float_reverse_bytes ( temp );
04192   }
04193   else {
04194     rval = temp;
04195   }
04196 
04197   return rval;
04198 }
04199 /******************************************************************************/
04200 
04201 float float_reverse_bytes ( float x )
04202 
04203 /******************************************************************************/
04204 
04205 /*
04206   Purpose:
04207 
04208     FLOAT_REVERSE_BYTES reverses the four bytes in a float.
04209 
04210   Modified:
04211 
04212     24 May 1999
04213 
04214   Author:
04215 
04216     John Burkardt
04217 
04218   Parameters:
04219 
04220     X, a float whose bytes are to be reversed.
04221 
04222     FLOAT_REVERSE_BYTES, a float with bytes in reverse order from those in X.
04223 */
04224 {
04225   char c;
04226   union {
04227     float yfloat;
04228     char ychar[4];
04229   } y;
04230 
04231   y.yfloat = x;
04232   
04233   c = y.ychar[0];
04234   y.ychar[0] = y.ychar[3];
04235   y.ychar[3] = c;
04236 
04237   c = y.ychar[1];
04238   y.ychar[1] = y.ychar[2];
04239   y.ychar[2] = c;
04240 
04241   return ( y.yfloat );
04242 }
04243 /******************************************************************************/
04244 
04245 int float_write ( FILE *fileout, float float_val )
04246 
04247 /******************************************************************************/
04248 
04249 /*
04250   Purpose:
04251 
04252     FLOAT_WRITE writes 1 float to a binary file.
04253 
04254   Modified:
04255 
04256     23 September 1998
04257 */
04258 {
04259   int nbyte = sizeof ( float );
04260   float temp;
04261 
04262   if ( byte_swap == TRUE ) {
04263     temp = float_reverse_bytes ( float_val );
04264   }
04265   else {
04266     temp = float_val;
04267   }
04268 
04269   fwrite ( &temp, nbyte, 1, fileout );
04270 
04271   return nbyte;
04272 }
04273 /******************************************************************************/
04274 
04275 int gmod_arch_check ( void )
04276 
04277 /******************************************************************************/
04278 
04279 /*
04280   Purpose:
04281    
04282     GMOD_ARCH_CHECK inquires into some features of the computer architecture.
04283 
04284   Modified:
04285 
04286     19 May 1999
04287 
04288   Author:
04289  
04290     Zik Saleeba (zik@zikzak.net)
04291 */
04292 {
04293   static unsigned char one[4];
04294   int temp;
04295   
04296   temp = sizeof ( float );
04297   if ( temp != 4 ) {
04298     return FALSE;
04299   }
04300 
04301   *(float *)one = 1.0;
04302   
04303   if (one[0] == 0 && one[1] == 0 && one[2] == 128 && one[3] == 63) {
04304     /* little endian IEEE floats */
04305     return TRUE;
04306   }
04307   
04308   if (one[0] == 63 && one[1] == 128 && one[2] == 0 && one[3] == 0) {
04309     /* big endian IEEE floats */
04310     return TRUE;
04311   }
04312   
04313   return FALSE;
04314 }
04315 /******************************************************************************/
04316 
04317 int gmod_read ( FILE *filein )
04318 
04319 /******************************************************************************/
04320 
04321 /*
04322   Purpose:
04323    
04324     GMOD_READ reads a golgotha GMOD file.
04325 
04326   Modified:
04327 
04328     19 May 1999
04329 
04330   Author:
04331  
04332     Zik Saleeba (zik@zikzak.net)
04333 */
04334 
04335 /*
04336 golgotha GMOD file format:
04337 
04338 
04339         FILE HEADER
04340 
04341 w32     magic number           f9 fa 63 1e
04342 w32     number of sections
04343 [ number of sections
04344     w32     section id
04345     w32     section offset
04346 ]
04347 
04348 
04349         TEXTURE NAME SECTION - section id = 0x13 (19)
04350 
04351 w16     number of faces
04352 [ number of faces
04353     w16     texture name length
04354     [ texture name length
04355         w8      texture name character
04356     ]
04357 ]
04358 
04359 
04360 
04361         MODEL QUADS SECTION - section id = 0x12 (18)
04362 
04363 w16     number of faces
04364 [ number of faces
04365     [ four vertices
04366         w16     vertex index
04367         float   xpos (0.0-1.0)
04368         float   ypos (0.0-1.0)
04369     ]
04370     float   scale
04371     w16     flags
04372     float   xnormal     (normal should be normalised)
04373     float   ynormal
04374     float   znormal
04375 ]
04376 
04377 
04378         VERTEX ARRAY SECTION - section id = 0x14 (20)
04379 
04380 w16     number of vertices
04381 w16     number of animations
04382 w16     length of animation name
04383 [ length of animation name
04384     w8      animation name character
04385 ]
04386 w16     number of frames in animation
04387 [ number of frames in animation
04388     [ number of vertices
04389         float   xpos
04390         float   ypos
04391         float   zpos
04392         float   xnormal
04393         float   ynormal
04394         float   znormal
04395     ]
04396 ]
04397 */
04398 {
04399   unsigned char MagicNumber[4];
04400   unsigned long int NumSections;
04401   int SectionCount;
04402   unsigned long int SectionID[GMOD_MAX_SECTIONS];
04403   unsigned long int SectionOffset[GMOD_MAX_SECTIONS];
04404   
04405   unsigned short NumAnimations;
04406   unsigned short NumFrames;
04407   unsigned short FaceCount;
04408   unsigned short TextureCount;
04409   int VertexCount;
04410   
04411   float Scale;
04412   unsigned short Flags;
04413   unsigned short TextureNameLen;
04414   unsigned short AnimationNameLen;
04415   int Order;
04416   int MaxCor = 0;
04417   
04418   /*
04419    * check if we can handle this architecture
04420    */
04421    
04422   if (!gmod_arch_check()) {
04423     printf("GMOD_READ - This architecture not supported.\n");
04424     return ERROR;
04425   }
04426   
04427   /* 
04428    * read the file header 
04429    */
04430    
04431   /* read the magic number */
04432   fread(MagicNumber, 1, 4, filein);
04433   if (MagicNumber[0] != 0xf9 || 
04434       MagicNumber[1] != 0xfa || 
04435       MagicNumber[2] != 0x63 || 
04436       MagicNumber[3] != 0x1e) {
04437     printf("GMOD_READ - Bad magic number on GMOD file.\n");
04438     return ERROR;
04439   }
04440   
04441   NumSections = gmod_read_w32(filein);
04442   if (NumSections >= GMOD_MAX_SECTIONS) {
04443     printf("GMOD_READ - Too many sections (%ld) in GMOD file - please increase static limit GMOD_MAX_SECTIONS\n", NumSections);
04444     return ERROR;
04445   }
04446   
04447 /* 
04448   Read the sections.
04449 */
04450 
04451   for ( SectionCount = 0; SectionCount < ( int ) NumSections; SectionCount++ ) {
04452     SectionID[SectionCount] = gmod_read_w32(filein);
04453     SectionOffset[SectionCount] = gmod_read_w32(filein);
04454   }
04455 /* 
04456   Read each successive section.
04457 */
04458   for ( SectionCount = 0; SectionCount < ( int ) NumSections; SectionCount++ ) {
04459 /* 
04460   Go to the start of the section.
04461 */
04462     fseek ( filein, ( long int ) SectionOffset[SectionCount], SEEK_SET );
04463 /* 
04464   What type of section is it?
04465 */
04466     switch (SectionID[SectionCount]) {
04467     
04468 /*
04469   Model section.
04470 */
04471       case G1_SECTION_MODEL_QUADS:
04472 /* 
04473   Get the number of faces.
04474 */
04475         face_num = gmod_read_w16 ( filein );
04476 
04477         if (face_num > FACE_MAX) {
04478           printf("GMOD_READ - Too many faces (%d) in GMOD file - please increase static limit FACE_MAX.\n", face_num);
04479           return ERROR;
04480         }
04481 /* 
04482   Get the information on each face.
04483 */
04484         for ( FaceCount = 0; FaceCount < ( unsigned short ) face_num; FaceCount++ ) {
04485         
04486           Order = 0;
04487           for ( VertexCount = 0; VertexCount < 4; VertexCount++ ) {
04488           
04489             /* read the vertex index */
04490 
04491             face[VertexCount][FaceCount] = gmod_read_w16(filein);
04492 
04493             if (face[VertexCount][FaceCount] != GMOD_UNUSED_VERTEX) {
04494               Order = VertexCount+1;
04495               if (MaxCor < face[VertexCount][FaceCount])
04496                 MaxCor = face[VertexCount][FaceCount];
04497             }
04498             
04499             /* read the texture position */
04500 
04501             vertex_tex_uv[0][VertexCount][FaceCount] = gmod_read_float(filein);
04502             vertex_tex_uv[1][VertexCount][FaceCount] = gmod_read_float(filein);
04503           }
04504           
04505           /* scale and flags */
04506 
04507           fread(&Scale, sizeof(Scale), 1, filein);
04508           Flags = gmod_read_w16(filein);
04509 
04510           if ( debug ) {
04511             printf ( "Flags = %d\n", Flags );
04512           }
04513           
04514           /* normal vector */
04515 
04516           face_normal[0][FaceCount] = gmod_read_float(filein);
04517           face_normal[1][FaceCount] = gmod_read_float(filein);
04518           face_normal[2][FaceCount] = gmod_read_float(filein);
04519           
04520           /* the order is the number of used vertices */
04521 
04522           face_order[FaceCount] = Order;
04523         }
04524         break;
04525       
04526       
04527 /*
04528   Texture name section.
04529 */
04530         
04531       case G1_SECTION_MODEL_TEXTURE_NAMES:
04532       
04533         /* get the number of textures */
04534 
04535         texture_num = gmod_read_w16(filein);
04536         if (texture_num > TEXTURE_MAX) {
04537           printf ( "GMOD_READ - Too many texture maps (%d) in GMOD file.\n", texture_num );
04538           printf ( "  Increase static limit TEXTURE_MAX.\n" );
04539           return ERROR;
04540         }
04541         face_num = texture_num;
04542         
04543         for (TextureCount = 0; TextureCount < ( unsigned short ) texture_num; 
04544           TextureCount++) {
04545           
04546           /* read the texture name */
04547 
04548           TextureNameLen = gmod_read_w16(filein);
04549           fread ( texture_name[TextureCount], sizeof(char), TextureNameLen, filein);
04550           texture_name[TextureCount][TextureNameLen] = '\0';
04551         }
04552         break;
04553        
04554     
04555       /*
04556        * vertex section
04557        */
04558         
04559       case G1_SECTION_MODEL_VERT_ANIMATION:
04560       
04561         /* get the number of vertices */
04562 
04563         cor3_num = gmod_read_w16(filein);
04564         if (cor3_num > COR3_MAX) {
04565           printf("GMOD_READ - Too many vertices (%d) in GMOD file - please increase static limit COR3_MAX.\n", cor3_num);
04566           return ERROR;
04567         }
04568       
04569 /* 
04570   Get the number of animations.
04571 */
04572 
04573         NumAnimations = gmod_read_w16(filein);
04574 
04575         if (NumAnimations > 1) {
04576           printf ( "GMOD_READ - Fatal error!\n" );
04577           printf ( "  GMOD files can only handle one animation.\n" );
04578           printf ( "  This file contains %d.\n", NumAnimations );
04579           return ERROR;
04580         }
04581         
04582         /* read the animation name */
04583         AnimationNameLen = gmod_read_w16(filein);
04584         fread ( anim_name, sizeof(char), AnimationNameLen, filein);
04585         anim_name[AnimationNameLen] = '\0';
04586         
04587         /* get the number of frames of animation */
04588         NumFrames = gmod_read_w16(filein);
04589         if (NumFrames > 1)
04590           printf("GMOD_READ - Too many frames of animation (%d) in GMOD file - will only use 1.\n", NumFrames);
04591         
04592         /* go through all the vertices, reading each one */
04593         for (VertexCount = 0; VertexCount < cor3_num; VertexCount++) {
04594           
04595           /* read the vertex */
04596           cor3[0][VertexCount] = gmod_read_float(filein);
04597           cor3[1][VertexCount] = gmod_read_float(filein);
04598           cor3[2][VertexCount] = gmod_read_float(filein);
04599           
04600           /* read the normal */
04601           cor3_normal[0][VertexCount] = gmod_read_float(filein);
04602           cor3_normal[1][VertexCount] = gmod_read_float(filein);
04603           cor3_normal[2][VertexCount] = gmod_read_float(filein);
04604         }
04605         break;
04606         
04607       default:
04608         continue;
04609     }
04610   }
04611   
04612 /* 
04613   Set some other stray info.
04614 */
04615   line_num = 0;
04616   
04617 /* 
04618   Check for sanity.
04619 */
04620   if ( MaxCor >= cor3_num ) {
04621     printf ( "GMOD_READ - Maximum coordinate index (%d)\n", MaxCor );
04622     printf ( "  exceeded number of coordinates (%d) in GMOD file.\n", cor3_num );
04623     return ERROR;
04624   }
04625 
04626   return SUCCESS;
04627 }
04628 /******************************************************************************/
04629 
04630 float gmod_read_float ( FILE *filein )
04631 
04632 /******************************************************************************/
04633 
04634 /*
04635   Purpose:
04636    
04637     GMOD_READ_FLOAT reads a float from a Golgotha GMOD file.
04638 
04639   Modified:
04640 
04641     19 May 1999
04642 
04643   Author:
04644  
04645     Zik Saleeba (zik@zikzak.net)
04646 */
04647 {
04648   int endian = 1;
04649   unsigned char *out_pos;
04650   int i;
04651   float Val;
04652 
04653   if (*(char *)&endian == 1) {
04654     /* we're little-endian, which is native for GMOD floats */
04655     fread(&Val, sizeof(Val), 1, filein);
04656   }
04657   else {
04658     /* we're big-endian, flip `em */
04659     out_pos = (unsigned char *)&Val;
04660     for ( i = sizeof(Val)-1; i >= 0; i-- ) {
04661       *(out_pos+i) = fgetc(filein);
04662     }
04663   }
04664   
04665   return Val;
04666 }
04667 /******************************************************************************/
04668 
04669 unsigned short gmod_read_w16 ( FILE *filein )
04670 
04671 /******************************************************************************/
04672 
04673 /*
04674   Purpose:
04675    
04676     GMOD_READ_W16 reads a 16 bit word from a Golgotha GMOD file.
04677 
04678   Modified:
04679 
04680     19 May 1999
04681 
04682   Author:
04683  
04684     Zik Saleeba (zik@zikzak.net)
04685 */
04686 {
04687   unsigned char Byte1;
04688   unsigned char Byte2;
04689   
04690   Byte1 = fgetc ( filein );
04691   Byte2 = fgetc ( filein );
04692   
04693   return Byte1 | (((unsigned short)Byte2) << 8);
04694 }
04695 /******************************************************************************/
04696 
04697 unsigned long gmod_read_w32 ( FILE *filein )
04698 
04699 /******************************************************************************/
04700 
04701 /*
04702   Purpose:
04703    
04704     GMOD_READ_W32 reads a 32 bit word from a Golgotha GMOD file.
04705 
04706   Modified:
04707 
04708     19 May 1999
04709 
04710   Author:
04711  
04712     Zik Saleeba (zik@zikzak.net)
04713 */
04714 {
04715   unsigned char Byte1, Byte2, Byte3, Byte4;
04716   
04717   Byte1 = fgetc(filein);
04718   Byte2 = fgetc(filein);
04719   Byte3 = fgetc(filein);
04720   Byte4 = fgetc(filein);
04721   
04722   return Byte1 | 
04723          (((unsigned long)Byte2) << 8) | 
04724          (((unsigned long)Byte3) << 16) | 
04725          (((unsigned long)Byte4) << 24);
04726 }
04727 
04728 /******************************************************************************/
04729 
04730 int gmod_write ( FILE *fileout ) {
04731 
04732 /******************************************************************************/
04733 
04734 /*
04735   Purpose:
04736    
04737     GMOD_WRITE writes a Golgotha GMOD file.
04738 
04739   Modified:
04740 
04741     19 May 1999
04742 
04743   Author:
04744  
04745     Zik Saleeba (zik@zikzak.net)
04746 */
04747   static unsigned char MagicNumber[4] = { 0xf9, 0xfa, 0x63, 0x1e };
04748   unsigned long NumSections;
04749   unsigned long SectionHeaderPos;
04750   unsigned long TextureNameSectionPos;
04751   unsigned long ModelSectionPos;
04752   unsigned long VertexSectionPos;
04753   
04754   int VertexCount;
04755   int FaceCount;
04756   int TextureCount;
04757   unsigned long SectionCount;
04758   float Scale;  
04759   float Min[3];
04760   float Max[3];
04761   int CorNumber;
04762   int DimensionCount;
04763   float MaxWidth;
04764 /*
04765   Check if we can handle this architecture.
04766 */
04767    
04768   if ( !gmod_arch_check() ) {
04769     printf("GMOD_WRITE - This architecture not supported.\n");
04770     return ERROR;
04771   }
04772   
04773 /* 
04774   Write the file header.
04775 */
04776    
04777 /* 
04778   Write the magic number.
04779 */
04780   fwrite ( MagicNumber, sizeof(char), 4, fileout );
04781 
04782 /* 
04783   Write the number of sections.
04784 */ 
04785   NumSections = 3;
04786   gmod_write_w32 ( NumSections, fileout ); 
04787   
04788 /* 
04789   Write a dummy section header which we'll overwrite later.
04790 */
04791   SectionHeaderPos = ftell ( fileout );
04792   for (SectionCount = 0; SectionCount < NumSections; SectionCount++) {
04793     gmod_write_w32 ( 0, fileout );
04794     gmod_write_w32 ( 0, fileout );
04795   }  
04796 /*
04797   Texture name section.
04798 */
04799   
04800 /* 
04801   Take note of where we are in the file.
04802 */
04803   TextureNameSectionPos = ftell ( fileout );
04804 
04805 /* 
04806   Write the number of textures.
04807 */
04808 
04809   gmod_write_w16 ( ( unsigned short ) face_num, fileout );
04810 /*
04811   Write the texture names.
04812 */
04813   for ( TextureCount = 0; TextureCount < face_num; TextureCount++ ) {
04814 
04815     gmod_write_w16 ( ( unsigned short ) strlen ( texture_name[TextureCount] ), 
04816       fileout );
04817 
04818     fwrite ( texture_name[TextureCount], strlen ( texture_name[TextureCount] ), 
04819       1, fileout );
04820   }
04821 
04822 /*
04823   Model section.
04824 */
04825 
04826 /* 
04827   Take note of where we are in the file.
04828 */
04829 
04830   ModelSectionPos = ftell(fileout);
04831 
04832 /* 
04833   Write the number of faces.
04834 */
04835 
04836   gmod_write_w16 ( ( unsigned short ) face_num, fileout );
04837 
04838 /* 
04839   Write the information on each face.
04840 */
04841 
04842   for ( FaceCount = 0; FaceCount < face_num; FaceCount++ ) {
04843 
04844     for (VertexCount = 0; VertexCount < ((face_order[FaceCount] < 4) ? face_order[FaceCount] : 4); VertexCount++) {
04845 
04846 /* 
04847   Write the vertex index.
04848 */
04849       gmod_write_w16 ( ( unsigned short ) face[VertexCount][FaceCount], fileout );
04850 
04851 /* 
04852   Write the texture position.
04853 */
04854 
04855       gmod_write_float ( vertex_tex_uv[0][VertexCount][FaceCount], fileout );
04856       gmod_write_float ( vertex_tex_uv[1][VertexCount][FaceCount], fileout );
04857     }
04858     
04859 /* 
04860   Write any extra vertices which are unused.
04861 */
04862 
04863     for ( ; VertexCount < 4; VertexCount++ ) {
04864     
04865 /* 
04866   Write the vertex index.
04867 */
04868       gmod_write_w16 ( GMOD_UNUSED_VERTEX, fileout );
04869 /* 
04870   Write the texture position.
04871 */
04872       gmod_write_float ( vertex_tex_uv[0][VertexCount][FaceCount], fileout );
04873 
04874       gmod_write_float ( vertex_tex_uv[1][VertexCount][FaceCount], fileout );
04875     }
04876 
04877 /*
04878   Scale and flags.
04879 */
04880     
04881 /* 
04882   Find the bounding box.
04883 */
04884 
04885     for ( DimensionCount = 0; DimensionCount < 3; DimensionCount++ ) {
04886       
04887       CorNumber = face[0][FaceCount];
04888       Min[DimensionCount] = cor3[DimensionCount][CorNumber];
04889       Max[DimensionCount] = cor3[DimensionCount][CorNumber];
04890       
04891       for (VertexCount = 1; VertexCount < ((face_order[FaceCount] < 4) ? face_order[FaceCount] : 4); VertexCount++) {
04892 
04893         CorNumber = face[VertexCount][FaceCount];
04894         
04895         if (Min[DimensionCount] > cor3[DimensionCount][CorNumber])
04896           Min[DimensionCount] = cor3[DimensionCount][CorNumber];
04897          
04898         if (Max[DimensionCount] < cor3[DimensionCount][CorNumber])
04899           Max[DimensionCount] = cor3[DimensionCount][CorNumber];
04900       }
04901     }
04902     
04903 /* 
04904   The scale is the "width" of the face for mipmapping - 
04905   I just take the maximum bounding box dimension.
04906 */
04907     MaxWidth = Max[0] - Min[0];
04908     for ( DimensionCount = 1; DimensionCount < 3; DimensionCount++ ) {
04909     
04910        if ( MaxWidth < Max[DimensionCount] - Min[DimensionCount] )
04911            MaxWidth = Max[DimensionCount] - Min[DimensionCount];
04912     }
04913 
04914     Scale = MaxWidth;
04915     fwrite ( &Scale, sizeof(Scale), 1, fileout );
04916     
04917 /* 
04918   Flags are just nothing.
04919 */
04920     gmod_write_w16 ( 0, fileout );
04921 /* 
04922   Normal vector.
04923 */
04924     gmod_write_float ( face_normal[0][FaceCount], fileout );
04925     gmod_write_float ( face_normal[1][FaceCount], fileout );
04926     gmod_write_float ( face_normal[2][FaceCount], fileout );
04927   }
04928 
04929 /*
04930   Vertex section.
04931 */
04932 
04933 /* 
04934   Take note of where we are in the file.
04935 */
04936 
04937   VertexSectionPos = ftell ( fileout );
04938 
04939 /* 
04940   Write the number of vertices.
04941 */
04942 
04943   gmod_write_w16 ( ( unsigned short ) cor3_num, fileout );
04944 
04945 /* 
04946   Write the number of animations.
04947 */
04948 
04949   gmod_write_w16 ( 1, fileout );
04950 
04951 /* 
04952   Write the animation name. 
04953 */
04954 
04955   gmod_write_w16 ( 0, fileout );
04956 
04957 /* 
04958   Write the number of frames of animation.
04959 */
04960 
04961   gmod_write_w16 ( 1, fileout );
04962 
04963 /* 
04964   Go through all the vertices, writing each one.
04965 */
04966 
04967   for ( VertexCount = 0; VertexCount < cor3_num; VertexCount++ ) {
04968 
04969 /* 
04970   Write the vertex.
04971 */
04972     gmod_write_float ( cor3[0][VertexCount], fileout );
04973     gmod_write_float ( cor3[1][VertexCount], fileout );
04974     gmod_write_float ( cor3[2][VertexCount], fileout );
04975 
04976 /* 
04977   Write the normal.
04978 */
04979     gmod_write_float ( cor3_normal[0][VertexCount], fileout );
04980     gmod_write_float ( cor3_normal[1][VertexCount], fileout );
04981     gmod_write_float ( cor3_normal[2][VertexCount], fileout );
04982   }
04983 /*
04984   Now rewrite the section header.
04985 */
04986    
04987 /* 
04988   Go back to the section header.
04989 */
04990   fseek ( fileout, ( long int ) SectionHeaderPos, SEEK_SET );
04991   
04992 /* 
04993   Write the texture name section header.
04994 */
04995   gmod_write_w32 ( G1_SECTION_MODEL_TEXTURE_NAMES, fileout );
04996   gmod_write_w32 ( TextureNameSectionPos, fileout );
04997 
04998 /* 
04999   Write the model section header.
05000 */
05001   gmod_write_w32 ( G1_SECTION_MODEL_QUADS, fileout );
05002   gmod_write_w32 ( ModelSectionPos, fileout );
05003 
05004 /* 
05005   Write the vertex section header.
05006 */
05007   gmod_write_w32 ( G1_SECTION_MODEL_VERT_ANIMATION, fileout );
05008   gmod_write_w32 ( VertexSectionPos, fileout );
05009 
05010   return SUCCESS;
05011 }
05012 
05013 /******************************************************************************/
05014 
05015 void gmod_write_float ( float Val, FILE *fileout )
05016 
05017 /******************************************************************************/
05018 
05019 /*
05020   Purpose:
05021    
05022     GMOD_WRITE_FLOAT writes a float to a Golgotha GMOD file.
05023 
05024   Modified:
05025 
05026     19 May 1999
05027 
05028   Author:
05029  
05030     Zik Saleeba (zik@zikzak.net)
05031 */
05032 {
05033   int endian = 1;
05034   unsigned char *out_pos;
05035   int i;
05036 
05037   if (*(char *)&endian == 1) {
05038     /* we're little-endian, which is native for GMOD floats */
05039     fwrite ( &Val, sizeof(Val), 1, fileout );
05040   }
05041   else {
05042     /* we're big-endian, flip `em */
05043     out_pos = (unsigned char *)&Val;
05044     for ( i = sizeof(Val)-1; i >= 0; i-- ) {
05045       fputc(*(out_pos+i), fileout);
05046     }
05047   }
05048 }
05049 /******************************************************************************/
05050 
05051 void gmod_write_w16 ( unsigned short Val, FILE *fileout )
05052 
05053 /******************************************************************************/
05054 
05055 /*
05056   Purpose:
05057    
05058     GMOD_WRITE_W16 writes a 16 bit word to a Golgotha GMOD file.
05059 
05060   Modified:
05061 
05062     13 September 2000
05063 
05064   Author:
05065  
05066     Zik Saleeba (zik@zikzak.net)
05067 */
05068 {
05069   unsigned char OutByte[2];
05070   
05071   OutByte[0] = (unsigned char)(Val & 0xff);
05072   OutByte[1] = (unsigned char)(Val >> 8);
05073   
05074   fwrite ( OutByte, sizeof(unsigned char), 2, fileout );
05075 }
05076 /******************************************************************************/
05077 
05078 void gmod_write_w32 ( unsigned long Val, FILE *fileout )
05079 
05080 /******************************************************************************/
05081 
05082 /*
05083   Purpose:
05084    
05085     GMOD_WRITE writes a 32 bit word to a Golgotha GMOD file.
05086 
05087   Modified:
05088 
05089     19 May 1999
05090 
05091   Author:
05092  
05093     Zik Saleeba (zik@zikzak.net)
05094 */
05095 {
05096   unsigned char OutByte[4];
05097   
05098   OutByte[0] = (unsigned char)(Val & 0xff);
05099   OutByte[1] = (unsigned char)((Val >> 8) & 0xff);
05100   OutByte[2] = (unsigned char)((Val >> 16) & 0xff);
05101   OutByte[3] = (unsigned char)((Val >> 24) & 0xff);
05102   
05103   fwrite ( OutByte, sizeof(unsigned char), 4, fileout );
05104 }
05105 
05106 /******************************************************************************/
05107 
05108 void hello ( void )
05109 
05110 /******************************************************************************/
05111 /*
05112   Purpose:
05113 
05114     HELLO prints an explanatory header message.
05115 
05116   Modified:
05117 
05118     04 July 2000
05119 
05120   Author:
05121  
05122     John Burkardt
05123 */
05124 {
05125   printf ( "\n" );
05126   printf ( "Hello:  This is IVCON,\n" );
05127   printf ( "  for 3D graphics file conversion.\n" );
05128   printf ( "\n" );
05129   printf ( "    \".3ds\"   3D Studio Max binary;\n" );
05130   printf ( "    \".ase\"   3D Studio Max ASCII export;\n" );
05131   printf ( "    \".byu\"   Movie.BYU surface geometry;\n" );
05132   printf ( "    \".dxf\"   DXF;\n" );
05133   printf ( "    \".gmod\"  Golgotha model;\n" );
05134   printf ( "    \".hrc\"   SoftImage hierarchy;\n" );
05135   printf ( "    \".iv\"    SGI Open Inventor;\n" );
05136   printf ( "    \".obj\"   WaveFront Advanced Visualizer;\n" );
05137   printf ( "    \".pov\"   Persistence of Vision (output only);\n" );
05138   printf ( "    \".smf\"   Michael Garland's format;\n" );
05139   printf ( "    \".stl\"   ASCII StereoLithography;\n" );
05140   printf ( "    \".stla\"  ASCII StereoLithography;\n" );
05141   printf ( "    \".stlb\"  Binary StereoLithography;\n" );
05142   printf ( "    \".tec\"   TECPLOT (output only);\n" );
05143   printf ( "    \".tri\"   [Greg Hood ASCII triangle format];\n" );
05144   printf ( "    \".tria\"  [Greg Hood ASCII triangle format];\n" );
05145   printf ( "    \".trib\"  [Greg Hood binary triangle format];\n" );
05146   printf ( "    \".txt\"   Text (output only);\n" );
05147   printf ( "    \".ucd\"   AVS UCD file(output only);\n" );
05148   printf ( "    \".vla\"   VLA;\n" );
05149   printf ( "    \".wrl\"   VRML (Virtual Reality Modeling Language) (output only).\n" );
05150   printf ( "    \".xgl\"   XML/OpenGL format (output only);\n" );
05151   printf ( "\n" );
05152   printf ( "  Current limits include:\n" );
05153   printf ( "    %d faces;\n", FACE_MAX );
05154   printf ( "    %d line items;\n", LINES_MAX );
05155   printf ( "    %d points;\n", COR3_MAX );
05156   printf ( "    %d face order;\n", ORDER_MAX );
05157   printf ( "    %d materials;\n", MATERIAL_MAX);
05158   printf ( "    %d textures.\n", TEXTURE_MAX );
05159   printf ( "\n" );
05160   printf ( "  Last modification: 04 July 2000.\n" );
05161   printf ( "\n" );
05162   printf ( "  Send problem reports to burkardt@psc.edu.\n" );
05163  
05164   return;
05165 }
05166 /******************************************************************************/
05167 
05168 void help ( void )
05169 
05170 /******************************************************************************/
05171 
05172 /*
05173   Purpose:
05174 
05175     HELP prints a list of the interactive commands.
05176 
05177   Modified:
05178 
05179     26 May 1999
05180 
05181   Author:
05182  
05183     John Burkardt
05184 */
05185 {
05186   printf ( "\n" );
05187   printf ( "Commands:\n" );
05188   printf ( "\n" );
05189   printf ( "< file   Read data from input file;\n" );
05190   printf ( "<< file  Append data in input file to current data;\n" );
05191   printf ( "> file   Write output file;\n" );
05192   printf ( "B        Switch the binary file byte-swapping mode;\n" );
05193   printf ( "D        Switch the debugging mode;\n" );
05194   printf ( "F        Print information about one face;\n" );
05195   printf ( "H        Print this help list;\n" );
05196   printf ( "I        Info, print out recent changes;\n" );
05197   printf ( "LINES    Convert face information to lines;\n" );
05198   printf ( "N        Recompute normal vectors;\n" );
05199   printf ( "P        Set LINE_PRUNE option.\n" );
05200   printf ( "Q        Quit;\n" );
05201   printf ( "R        Reverse the normal vectors.\n" );
05202   printf ( "S        Select face subset (NOT WORKING).\n" );
05203   printf ( "T        Transform the data.\n" );
05204   printf ( "W        Reverse the face node ordering.\n" );
05205 
05206   return;
05207 }
05208 /******************************************************************************/
05209 
05210 int hrc_read ( FILE *filein )
05211 
05212 /******************************************************************************/
05213 
05214 /*
05215   Purpose:
05216 
05217     HRC_READ reads graphics information from a SoftImage HRC file.
05218 
05219   Examples:
05220 
05221     HRCH: Softimage 4D Creative Environment v3.00
05222 
05223 
05224     model
05225     {
05226       name         "cube_10x10"
05227       scaling      1.000 1.000 1.000
05228       rotation     0.000 0.000 0.000
05229       translation  0.000 0.000 0.000
05230 
05231       mesh
05232       {
05233         flag    ( PROCESS )
05234         discontinuity  60.000
05235 
05236         vertices   8
05237         {
05238           [0] position  -5.000  -5.000  -5.000
05239           [1] position  -5.000  -5.000  5.000
05240           [2] position  -5.000  5.000  -5.000
05241           [3] position  -5.000  5.000  5.000
05242           [4] position  5.000  -5.000  -5.000
05243           [5] position  5.000  -5.000  5.000
05244           [6] position  5.000  5.000  -5.000
05245           [7] position  5.000  5.000  5.000
05246         }
05247 
05248         polygons   6
05249         {
05250           [0] nodes  4
05251               {
05252                 [0] vertex  0
05253                     normal  -1.000  0.000  0.000
05254                     uvTexture  0.000  0.000
05255                     vertexColor 255 178 178 178
05256                 [1] vertex  1
05257                     normal  -1.000  0.000  0.000
05258                     uvTexture  0.000  0.000
05259                     vertexColor 255 178 178 178
05260                 [2] vertex  3
05261                     normal  -1.000  0.000  0.000
05262                     uvTexture  0.000  0.000
05263                     vertexColor 255 178 178 178
05264                 [3] vertex  2
05265                     normal  -1.000  0.000  0.000
05266                     uvTexture  0.000  0.000
05267                     vertexColor 255 178 178 178
05268               }
05269               material  0
05270           [1] nodes  4
05271              {
05272                 [0] vertex  1
05273                     normal  0.000  0.000  1.000
05274                     uvTexture  0.000  0.000
05275                     vertexColor 255 178 178 178
05276                 [1] vertex  5
05277 
05278     ...etc.....
05279 
05280           [5] nodes  4
05281               {
05282                 [0] vertex  2
05283                     normal  0.000  1.000  0.000
05284                     uvTexture  0.000  0.000
05285                     vertexColor 255 178 178 178
05286                 [1] vertex  3
05287                     normal  0.000  1.000  0.000
05288                     uvTexture  0.000  0.000
05289                     vertexColor 255 178 178 178
05290                 [2] vertex  7
05291                     normal  0.000  1.000  0.000
05292                     uvTexture  0.000  0.000
05293                     vertexColor 255 178 178 178
05294                 [3] vertex  6
05295                     normal  0.000  1.000  0.000
05296                     uvTexture  0.000  0.000
05297                     vertexColor 255 178 178 178
05298               }
05299               material  0
05300         }
05301 
05302         edges   12
05303         {
05304           [1] vertices  3  2
05305           [2] vertices  2  0
05306           [3] vertices  0  1
05307           [4] vertices  1  3
05308           [5] vertices  7  3
05309           [6] vertices  1  5
05310           [7] vertices  5  7
05311           [8] vertices  6  7
05312           [9] vertices  5  4
05313           [10] vertices  4  6
05314           [11] vertices  2  6
05315           [12] vertices  4  0
05316         }
05317       }
05318 
05319       material [0]
05320       {
05321       name           "kazoo"
05322       type           PHONG
05323       ambient        0.0  1.0  0.0
05324       diffuse        1.0  0.0  0.0
05325       specular       0.0  0.0  1.0
05326       exponent      50.0
05327       reflectivity   0.0
05328       transparency   0.0
05329       refracIndex    1.0
05330       glow           0
05331       coc            0.0
05332       }
05333 
05334       texture [0]
05335       {
05336       name          "/usr/users/foss/HOUSE/PICTURES/mellon"
05337       glbname       "t2d1"
05338       anim          STATIC
05339       method        XY
05340       repeat        1  1
05341       scaling       1.000  1.000
05342       offset        0.000  0.000
05343       pixelInterp
05344       effect        INTENSITY
05345       blending      1.000
05346       ambient       0.977
05347       diffuse       1.000
05348       specular      0.966
05349       reflect       0.000
05350       transp        0.000
05351       roughness     0.000
05352       reflMap       1.000
05353       rotation      0.000
05354       txtsup_rot    0.000  0.000  0.000
05355       txtsup_trans  0.000  0.000  0.000
05356       txtsup_scal   1.000  1.000  1.000
05357       }
05358     }
05359 
05360   Modified:
05361 
05362     25 June 1999
05363 
05364   Author:
05365 
05366     John Burkardt
05367 */
05368 {
05369   float b;
05370   int   count;
05371   float g;
05372   int   i;
05373   int   icor3;
05374   int   ivert;
05375   int   iword;
05376   int   jval;
05377   int   level;
05378   char *next;
05379   int   nlbrack;
05380   int   nrbrack;
05381   int   cor3_num_old;
05382   float r;
05383   float t;
05384   float temp[3];
05385   int   width;
05386   char  word[LINE_MAX_LEN];
05387   char  word1[LINE_MAX_LEN];
05388   char  word2[LINE_MAX_LEN];
05389   char  wordm1[LINE_MAX_LEN];
05390   float x;
05391   float y;
05392   float z;
05393 
05394   level = 0;
05395   strcpy ( level_name[0], "Top" );
05396   nlbrack = 0;
05397   nrbrack = 0;
05398   cor3_num_old = cor3_num;
05399   strcpy ( word, " " );
05400   strcpy ( wordm1, " " );
05401 /*
05402   Read a line of text from the file.
05403 */
05404   for ( ;; ) {
05405 
05406     if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
05407       break;
05408     }
05409 
05410     text_num = text_num + 1;
05411     next = input;
05412     iword = 0;
05413 /*
05414   Read a word from the line.
05415 */
05416     for ( ;; ) {
05417 
05418       strcpy ( wordm1, word );
05419 
05420       count = sscanf ( next, "%s%n", word2, &width );
05421       next = next + width;
05422 
05423       if ( count <= 0 ) {
05424         break;
05425       }
05426 
05427       strcpy ( word, word2 );
05428 
05429       iword = iword + 1;
05430 
05431       if ( iword == 1 ) {
05432         strcpy ( word1, word );
05433       }
05434 /*
05435   The first line of the file must be the header.
05436 */
05437       if ( text_num == 1 ) {
05438 
05439         if ( strcmp ( word1, "HRCH:" ) != 0 ) {
05440           printf ( "\n" );
05441           printf ( "HRC_READ - Fatal error!\n" );
05442           printf ( "  The input file has a bad header.\n" );
05443           return ERROR;
05444         }
05445         else {
05446           comment_num = comment_num + 1;
05447         }
05448         break;
05449       }
05450 /*
05451   If the word is a curly bracket, count it.
05452 */
05453       if ( strcmp ( word, "{" ) == 0 ) {
05454         nlbrack = nlbrack + 1;
05455         level = nlbrack - nrbrack;
05456         strcpy ( level_name[level], wordm1 );
05457         if ( debug ) {
05458           printf ( "New level: %s\n", level_name[level] );
05459         }
05460       }
05461       else if ( strcmp ( word, "}" ) == 0 ) {
05462         nrbrack = nrbrack + 1;
05463 
05464         if ( nlbrack < nrbrack ) {
05465           printf ( "\n" );
05466           printf ( "HRC_READ - Fatal error!\n" );
05467           printf ( "  Extraneous right bracket on line %d.\n", text_num );
05468           printf ( "  Currently processing field %s\n.", level_name[level] );
05469           return ERROR;
05470         }
05471       }
05472 /*
05473   CONTROLPOINTS
05474 */
05475       if ( strcmp ( level_name[level], "controlpoints" ) == 0 ) {
05476 
05477         if ( strcmp ( word, "{" ) == 0 ) {
05478         }
05479         else if ( strcmp ( word, "}" ) == 0 ) {
05480 
05481           if ( line_num < LINES_MAX ) {
05482             line_dex[line_num] = -1;
05483             line_material[line_num] = 0;
05484           }
05485           line_num = line_num + 1;
05486           level = nlbrack - nrbrack;
05487         }
05488         else if ( word[0] == '[' ) {
05489         }
05490         else if ( strcmp ( word, "position" ) == 0 ) {
05491 
05492           count = sscanf ( next, "%f%n", &x, &width );
05493           next = next + width;
05494 
05495           count = sscanf ( next, "%f%n", &y, &width );
05496           next = next + width;
05497 
05498           count = sscanf ( next, "%f%n", &z, &width );
05499           next = next + width;
05500 
05501           temp[0] = x;
05502           temp[1] = y;
05503           temp[2] = z;
05504 
05505           if ( cor3_num < 1000 ) {
05506             icor3 = rcol_find ( cor3, 3, cor3_num, temp );
05507           }
05508           else {
05509             icor3 = -1;
05510           }
05511 
05512           if ( icor3 == -1 ) {
05513 
05514             icor3 = cor3_num;
05515             if ( cor3_num < COR3_MAX ) {
05516               cor3[0][cor3_num] = x;
05517               cor3[1][cor3_num] = y;
05518               cor3[2][cor3_num] = z;
05519             }
05520             cor3_num = cor3_num + 1;
05521 
05522           }
05523           else {
05524             dup_num = dup_num + 1;
05525           }
05526 
05527           if ( line_num < LINES_MAX ) {
05528             line_dex[line_num] = icor3;
05529             line_material[line_num] = 0;
05530           }
05531           line_num = line_num + 1;
05532         }
05533         else {
05534           bad_num = bad_num + 1;
05535           printf ( "CONTROLPOINTS: Bad data %s\n", word );
05536           return ERROR;
05537         }
05538 
05539       }
05540 /*
05541   EDGES
05542 */
05543       else if ( strcmp ( level_name[level], "edges" ) == 0 ) {
05544 
05545         if ( strcmp( word, "{" ) == 0 ) {
05546         }
05547         else if ( strcmp ( word, "}" ) == 0 ) {
05548           level = nlbrack - nrbrack;
05549         }
05550         else if ( word[0] == '[' ) {
05551         }
05552         else if ( strcmp ( word, "vertices" ) == 0 ) {
05553 
05554           count = sscanf ( next, "%d%n", &jval, &width );
05555           next = next + width;
05556 
05557           if ( line_num < LINES_MAX ) {
05558             line_dex[line_num] = jval + cor3_num_old;
05559             line_material[line_num] = 0;
05560           }
05561           line_num = line_num + 1;
05562 
05563           count = sscanf ( next, "%d%n", &jval, &width );
05564           next = next + width;
05565 
05566           if ( line_num < LINES_MAX ) {
05567             line_dex[line_num] = jval + cor3_num_old;
05568             line_material[line_num] = 0;
05569           }
05570           line_num = line_num + 1;
05571 
05572           if ( line_num < LINES_MAX ) {
05573             line_dex[line_num] = -1;
05574             line_material[line_num] = -1;
05575           }
05576           line_num = line_num + 1;
05577 
05578         }
05579         else {
05580           bad_num = bad_num + 1;
05581           printf ( "EDGES: Bad data %s\n", word );
05582           return ERROR;
05583         }
05584 
05585       }
05586 /*
05587   MATERIAL
05588 */
05589       else if ( strcmp ( level_name[level], "material" ) == 0 ) {
05590 
05591         if ( strcmp ( word, "{" ) == 0 ) {
05592           material_num = material_num + 1;
05593         }
05594         else if ( strcmp ( word, "}" ) == 0 ) {
05595           level = nlbrack - nrbrack;
05596         }
05597         else if ( word[0] == '[' ) {
05598         }
05599         else if ( strcmp ( word, "ambient" ) == 0 ) {
05600         }
05601         else if ( strcmp ( word, "coc" ) == 0 ) {
05602         }
05603         else if ( strcmp ( word, "diffuse" ) == 0 ) {
05604 
05605           count = sscanf ( next, "%f%n", &r, &width );
05606           next = next + width;
05607           material_rgba[0][material_num-1] = r;
05608 
05609           count = sscanf ( next, "%f%n", &g, &width );
05610           next = next + width;
05611           material_rgba[0][material_num-1] = g;
05612 
05613           count = sscanf ( next, "%f%n", &b, &width );
05614           next = next + width;
05615           material_rgba[0][material_num-1] = b;
05616 
05617         }
05618         else if ( strcmp ( word, "exponent" ) == 0 ) {
05619         }
05620         else if ( strcmp ( word, "glow" ) == 0 ) {
05621         }
05622         else if ( strcmp ( word, "name" ) == 0 ) {
05623           count = sscanf ( next, "%s%n", word, &width );
05624           next = next + width;
05625           strcpy ( material_name[material_num-1], word );
05626         }
05627         else if ( strcmp ( word, "reflectivity" ) == 0 ) {
05628         }
05629         else if ( strcmp ( word, "refracindex" ) == 0 ) {
05630         }
05631         else if ( strcmp ( word, "specular" ) == 0 ) {
05632         }
05633         else if ( strcmp ( word, "transparency" ) == 0 ) {
05634           count = sscanf ( next, "%f%n", &t, &width );
05635           next = next + width;
05636           material_rgba[3][material_num-1] = 1.0 - t;
05637         }
05638         else if ( strcmp ( word, "type" ) == 0 ) {
05639         }
05640         else {
05641           bad_num = bad_num + 1;
05642           printf ( "MATERIAL: Bad data %s\n", word );
05643           return ERROR;
05644         }
05645       }
05646 /*
05647   MESH
05648 */
05649       else if ( strcmp ( level_name[level], "mesh" ) == 0 ) {
05650 
05651         if ( strcmp ( word, "{" ) == 0 ) {
05652         }
05653         else if ( strcmp ( word, "}" ) == 0 ) {
05654           level = nlbrack - nrbrack;
05655         }
05656         else if ( strcmp ( word, "discontinuity" ) == 0 ) {
05657           break;
05658         }
05659         else if ( strcmp ( word, "edges" ) == 0 ) {
05660           break;
05661         }
05662         else if ( strcmp ( word, "flag" ) == 0 ) {
05663           break;
05664         }
05665         else if ( strcmp ( word, "polygons" ) == 0 ) {
05666           break;
05667         }
05668         else if ( strcmp ( word, "vertices" ) == 0 ) {
05669           break;
05670         }
05671         else {
05672           bad_num = bad_num + 1;
05673           printf ( "MESH: Bad data %s\n", word );
05674           return ERROR;
05675         }
05676 
05677       }
05678 /*
05679   MODEL
05680 */
05681       else if ( strcmp ( level_name[level], "model" ) == 0 ) {
05682 
05683         if ( strcmp ( word, "{" ) == 0 ) {
05684         }
05685         else if ( strcmp ( word, "}" ) == 0 ) {
05686           level = nlbrack - nrbrack;
05687         }
05688         else if ( strcmp ( word, "material" ) == 0 ) {
05689           break;
05690         }
05691         else if ( strcmp ( word, "mesh" ) == 0 ) {
05692           break;
05693         }
05694         else if ( strcmp ( word, "name" ) == 0 ) {
05695           break;
05696         }
05697         else if ( strcmp ( word, "patch" ) == 0 ) {
05698           break;
05699         }
05700         else if ( strcmp ( word, "rotation" ) == 0 ) {
05701           break;
05702         }
05703         else if ( strcmp ( word, "scaling" ) == 0 ) {
05704           break;
05705         }
05706         else if ( strcmp ( word, "spline" ) == 0 ) {
05707           break;
05708         }
05709         else if ( strcmp ( word, "translation" ) == 0 ) {
05710           break;
05711         }
05712         else {
05713           bad_num = bad_num + 1;
05714           printf ( "MODEL: Bad data %s\n", word );
05715           return ERROR;
05716         }
05717 
05718       }
05719 /*
05720   NODES
05721 */
05722       else if ( strcmp ( level_name[level], "nodes" ) == 0 ) {
05723 
05724         if ( strcmp ( word, "{" ) == 0 ) {
05725           ivert = 0;
05726           face_order[face_num] = 0;
05727           face_num = face_num + 1;
05728         }
05729         else if ( strcmp ( word, "}" ) == 0 ) {
05730           level = nlbrack - nrbrack;
05731         }
05732         else if ( word[0] == '[' ) {
05733         }
05734         else if ( strcmp ( word, "normal" ) == 0 ) {
05735 
05736           count = sscanf ( next, "%f%n", &x, &width );
05737           next = next + width;
05738 
05739           count = sscanf ( next, "%f%n", &y, &width );
05740           next = next + width;
05741 
05742           count = sscanf ( next, "%f%n", &z, &width );
05743           next = next + width;
05744 
05745           if ( ivert < ORDER_MAX && face_num < FACE_MAX ) {
05746             vertex_normal[0][ivert-1][face_num-1] = x;
05747             vertex_normal[1][ivert-1][face_num-1] = y;
05748             vertex_normal[2][ivert-1][face_num-1] = z;
05749           }
05750 
05751         }
05752         else if ( strcmp ( word, "uvTexture" ) == 0 ) {
05753 
05754           count = sscanf ( next, "%f%n", &x, &width );
05755           next = next + width;
05756 
05757           count = sscanf ( next, "%f%n", &y, &width );
05758           next = next + width;
05759 
05760           if ( ivert < ORDER_MAX && face_num < FACE_MAX ) {
05761             vertex_tex_uv[0][ivert-1][face_num-1] = x;
05762             vertex_tex_uv[1][ivert-1][face_num-1] = y;
05763           }
05764         }
05765         else if ( strcmp ( word, "vertex" ) == 0 ) {
05766 
05767           count = sscanf ( next, "%d%n", &jval, &width );
05768           next = next + width;
05769 
05770           if ( ivert < ORDER_MAX && face_num < FACE_MAX ) {
05771             face_order[face_num-1] = face_order[face_num-1] + 1;
05772             face[ivert][face_num-1] = jval;
05773           }
05774           ivert = ivert + 1;
05775 
05776         }
05777 /*
05778   Right now, we don't do anything with the vertexColor information.
05779 */
05780         else if ( strcmp ( word, "vertexColor" ) == 0 ) {
05781 
05782           count = sscanf ( next, "%d%n", &jval, &width );
05783           next = next + width;
05784 
05785           count = sscanf ( next, "%d%n", &jval, &width );
05786           next = next + width;
05787 
05788           count = sscanf ( next, "%d%n", &jval, &width );
05789           next = next + width;
05790 
05791           count = sscanf ( next, "%d%n", &jval, &width );
05792           next = next + width;
05793         }
05794         else {
05795           bad_num = bad_num + 1;
05796           printf ( "NODES: Bad data %s\n", word );
05797           return ERROR;
05798         }
05799 
05800       }
05801 /*
05802   PATCH
05803   I don't know what to do with this yet.
05804 */
05805       else if ( strcmp ( level_name[level], "patch" ) == 0 ) {
05806 
05807         if ( strcmp ( word, "{" ) == 0 ) {
05808         }
05809         else if ( strcmp ( word, "}" ) == 0 ) {
05810           level = nlbrack - nrbrack;
05811         }
05812         else if ( strcmp ( word, "approx_type" ) == 0 ) {
05813         }
05814         else if ( strcmp ( word, "controlpoints" ) == 0 ) {
05815         }
05816         else if ( strcmp ( word, "curv_u" ) == 0 ) {
05817         }
05818         else if ( strcmp ( word, "curv_v" ) == 0 ) {
05819         }
05820         else if ( strcmp ( word, "recmin" ) == 0 ) {
05821         }
05822         else if ( strcmp ( word, "recmax" ) == 0 ) {
05823         }
05824         else if ( strcmp ( word, "recursion" ) == 0 ) {
05825         }
05826         else if ( strcmp ( word, "spacial" ) == 0 ) {
05827         }
05828         else if ( strcmp ( word, "taggedpoints" ) == 0 ) {
05829         }
05830         else if ( strcmp ( word, "ucurve" ) == 0 ) {
05831         }
05832         else if ( strcmp ( word, "ustep" ) == 0 ) {
05833         }
05834         else if ( strcmp ( word, "utension" ) == 0 ) {
05835         }
05836         else if ( strcmp ( word, "utype" ) == 0 ) {
05837         }
05838         else if ( strcmp ( word, "vclose" ) == 0 ) {
05839         }
05840         else if ( strcmp ( word, "vcurve" ) == 0 ) {
05841         }
05842         else if ( strcmp ( word, "viewdep" ) == 0 ) {
05843         }
05844         else if ( strcmp ( word, "vpoint" ) == 0 ) {
05845         }
05846         else if ( strcmp ( word, "vstep" ) == 0 ) {
05847         }
05848         else if ( strcmp ( word, "vtension" ) == 0 ) {
05849         }
05850         else if ( strcmp ( word, "vtype" ) == 0 ) {
05851         }
05852         else {
05853           bad_num = bad_num + 1;
05854           printf ( "PATCH: Bad data %s\n", word );
05855           return ERROR;
05856         }
05857       }
05858 /*
05859   POLYGONS
05860 */
05861       else if ( strcmp ( level_name[level], "polygons" ) == 0 ) {
05862 
05863         if ( strcmp ( word, "{" ) == 0 ) {
05864         }
05865         else if ( strcmp ( word, "}" ) == 0 ) {
05866           level = nlbrack - nrbrack;
05867         }
05868         else if ( word[0] == '[' ) {
05869         }
05870         else if ( strcmp ( word, "material" ) == 0 ) {
05871 
05872           count = sscanf ( next, "%d%n", &jval, &width );
05873           next = next + width;
05874 
05875           for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
05876             vertex_material[ivert][face_num-1] = jval;
05877           }
05878 
05879         }
05880         else if ( strcmp ( word, "nodes" ) == 0 ) {
05881           count = sscanf ( next, "%s%n", word2, &width );
05882           next = next + width;
05883         }
05884         else {
05885           bad_num = bad_num + 1;
05886           printf ( "POLYGONS: Bad data %s\n", word );
05887           return ERROR;
05888         }
05889 
05890       }
05891 /*
05892   SPLINE
05893 */
05894       else if ( strcmp ( level_name[level], "spline" ) == 0 ) {
05895 
05896         if ( strcmp ( word, "{" ) == 0 ) {
05897         }
05898         else if ( strcmp ( word, "}" ) == 0 ) {
05899           level = nlbrack - nrbrack;
05900         }
05901         else if ( strcmp ( word, "controlpoints" ) == 0 ) {
05902           break;
05903         }
05904 /*
05905   WHY DON'T YOU READ IN THE OBJECT NAME HERE?
05906 */
05907         else if ( strcmp ( word, "name" ) == 0 ) {
05908           break;
05909         }
05910         else if ( strcmp ( word, "nbKeys" ) == 0 ) {
05911           break;
05912         }
05913         else if ( strcmp ( word, "step" ) == 0 ) {
05914           break;
05915         }
05916         else if ( strcmp ( word, "tension" ) == 0 ) {
05917           break;
05918         }
05919         else if ( strcmp ( word, "type" ) == 0 ) {
05920           break;
05921         }
05922         else {
05923           bad_num = bad_num + 1;
05924           printf ( "SPLINE: Bad data %s\n", word );
05925           return ERROR;
05926         }
05927 
05928       }
05929 /*
05930   TAGGEDPOINTS
05931 */
05932       else if ( strcmp ( level_name[level], "taggedpoints" ) == 0 ) {
05933 
05934         if ( strcmp ( word, "{" ) == 0 ) {
05935         }
05936         else if ( strcmp ( word, "}" ) == 0 ) {
05937           level = nlbrack - nrbrack;
05938         }
05939         else if ( word[0] == '[' ) {
05940         }
05941         else if ( strcmp ( word, "tagged" ) == 0 ) {
05942         }
05943         else {
05944           bad_num = bad_num + 1;
05945           printf ( "TAGGEDPOINTS: Bad data %s\n", word );
05946           return ERROR;
05947         }
05948 
05949       }
05950 /*
05951   TEXTURE
05952 */
05953       else if ( strcmp ( level_name[level], "texture" ) == 0 ) {
05954 
05955         if ( strcmp ( word, "{" ) == 0 ) {
05956           texture_num = texture_num + 1;
05957         }
05958         else if ( strcmp ( word, "}" ) == 0 ) {
05959           level = nlbrack - nrbrack;
05960         }
05961         else if ( word[0] == '[' ) {
05962         }
05963         else if ( strcmp ( word, "ambient" ) == 0 ) {
05964         }
05965         else if ( strcmp ( word, "anim" ) == 0 ) {
05966         }
05967         else if ( strcmp ( word, "blending" ) == 0 ) {
05968         }
05969         else if ( strcmp ( word, "diffuse" ) == 0 ) {
05970         }
05971         else if ( strcmp ( word, "effect" ) == 0 ) {
05972         }
05973         else if ( strcmp ( word, "glbname" ) == 0 ) {
05974         }
05975         else if ( strcmp ( word, "method" ) == 0 ) {
05976         }
05977         else if ( strcmp ( word, "name" ) == 0 ) {
05978           count = sscanf ( next, "%s%n", word, &width );
05979           next = next + width;
05980           strcpy ( texture_name[texture_num-1], word );
05981         }
05982         else if ( strcmp ( word, "offset" ) == 0 ) {
05983         }
05984         else if ( strcmp ( word, "pixelinterp" ) == 0 ) {
05985         }
05986         else if ( strcmp ( word, "reflect" ) == 0 ) {
05987         }
05988         else if ( strcmp ( word, "reflmap" ) == 0 ) {
05989         }
05990         else if ( strcmp ( word, "repeat" ) == 0 ) {
05991         }
05992         else if ( strcmp ( word, "rotation" ) == 0 ) {
05993         }
05994         else if ( strcmp ( word, "roughness" ) == 0 ) {
05995         }
05996         else if ( strcmp ( word, "scaling" ) == 0 ) {
05997         }
05998         else if ( strcmp ( word, "specular" ) == 0 ) {
05999         }
06000         else if ( strcmp ( word, "transp" ) == 0 ) {
06001         }
06002         else if ( strcmp ( word, "txtsup_rot" ) == 0 ) {
06003         }
06004         else if ( strcmp ( word, "txtsup_scal" ) == 0 ) {
06005         }
06006         else if ( strcmp ( word, "txtsup_trans" ) == 0 ) {
06007         }
06008         else {
06009           bad_num = bad_num + 1;
06010           printf ( "TEXTURE: Bad data %s\n", word );
06011           return ERROR;
06012         }
06013       }
06014 /*
06015   VERTICES
06016 */
06017       else if ( strcmp ( level_name[level], "vertices" ) == 0 ) {
06018 
06019         if ( strcmp ( word, "{" ) == 0 ) {
06020         }
06021         else if ( strcmp ( word, "}" ) == 0 ) {
06022           level = nlbrack - nrbrack;
06023         }
06024         else if ( word[0] == '[' ) {
06025         }
06026         else if ( strcmp ( word, "position" ) == 0 ) {
06027 
06028           count = sscanf ( next, "%f%n", &x, &width );
06029           next = next + width;
06030 
06031           count = sscanf ( next, "%f%n", &y, &width );
06032           next = next + width;
06033 
06034           count = sscanf ( next, "%f%n", &z, &width );
06035           next = next + width;
06036 
06037           if ( cor3_num < COR3_MAX ) {
06038             cor3[0][cor3_num] = x;
06039             cor3[1][cor3_num] = y;
06040             cor3[2][cor3_num] = z;
06041           }
06042           cor3_num = cor3_num + 1;
06043         }
06044         else {
06045           bad_num = bad_num + 1;
06046           printf ( "VERTICES: Bad data %s\n", word );
06047           return ERROR;
06048         }
06049       }
06050 /*
06051   Any other word:
06052 */
06053       else {
06054 
06055       }
06056     }
06057   }
06058 
06059 /*
06060   End of information in file.
06061 
06062   Check the "materials" defining a line.
06063 
06064   If COORDINDEX is -1, so should be the MATERIALINDEX.
06065   If COORDINDEX is not -1, then the MATERIALINDEX shouldn"t be either.
06066 */
06067   for ( i = 0; i < line_num; i++ ) {
06068 
06069     if ( line_dex[i] == -1 ) {
06070       line_material[i] = -1;
06071     }
06072     else if ( line_material[i] == -1 ) {
06073       line_material[i] = 0;
06074     }
06075 
06076   }
06077   return SUCCESS;
06078 }
06079 /******************************************************************************/
06080 
06081 int hrc_write ( FILE* fileout )
06082 
06083 /******************************************************************************/
06084 
06085 /*
06086   Purpose:
06087 
06088     HRC_WRITE writes graphics data to an HRC SoftImage file.
06089 
06090   Examples:
06091 
06092     HRCH: Softimage 4D Creative Environment v3.00
06093 
06094 
06095     model
06096     {
06097       name         "cube_10x10"
06098       scaling      1.000 1.000 1.000
06099       rotation     0.000 0.000 0.000
06100       translation  0.000 0.000 0.000
06101 
06102       mesh
06103       {
06104         flag    ( PROCESS )
06105         discontinuity  60.000
06106 
06107         vertices   8
06108         {
06109           [0] position  -5.000  -5.000  -5.000
06110           [1] position  -5.000  -5.000  5.000
06111           [2] position  -5.000  5.000  -5.000
06112           [3] position  -5.000  5.000  5.000
06113           [4] position  5.000  -5.000  -5.000
06114           [5] position  5.000  -5.000  5.000
06115           [6] position  5.000  5.000  -5.000
06116           [7] position  5.000  5.000  5.000
06117         }
06118 
06119         polygons   6
06120         {
06121           [0] nodes  4
06122               {
06123                 [0] vertex  0
06124                     normal  -1.000  0.000  0.000
06125                     uvTexture  0.000  0.000
06126                     vertexColor 255 178 178 178
06127                 [1] vertex  1
06128                     normal  -1.000  0.000  0.000
06129                     uvTexture  0.000  0.000
06130                     vertexColor 255 178 178 178
06131                 [2] vertex  3
06132                     normal  -1.000  0.000  0.000
06133                     uvTexture  0.000  0.000
06134                     vertexColor 255 178 178 178
06135                 [3] vertex  2
06136                     normal  -1.000  0.000  0.000
06137                     uvTexture  0.000  0.000
06138                     vertexColor 255 178 178 178
06139               }
06140               material  0
06141           [1] nodes  4
06142              {
06143                 [0] vertex  1
06144                     normal  0.000  0.000  1.000
06145                     uvTexture  0.000  0.000
06146                     vertexColor 255 178 178 178
06147                 [1] vertex  5
06148 
06149     ...etc.....
06150 
06151           [5] nodes  4
06152               {
06153                 [0] vertex  2
06154                     normal  0.000  1.000  0.000
06155                     uvTexture  0.000  0.000
06156                     vertexColor 255 178 178 178
06157                 [1] vertex  3
06158                     normal  0.000  1.000  0.000
06159                     uvTexture  0.000  0.000
06160                     vertexColor 255 178 178 178
06161                 [2] vertex  7
06162                     normal  0.000  1.000  0.000
06163                     uvTexture  0.000  0.000
06164                     vertexColor 255 178 178 178
06165                 [3] vertex  6
06166                     normal  0.000  1.000  0.000
06167                     uvTexture  0.000  0.000
06168                     vertexColor 255 178 178 178
06169               }
06170               material  0
06171         }
06172 
06173         edges   12
06174         {
06175           [1] vertices  3  2
06176           [2] vertices  2  0
06177           [3] vertices  0  1
06178           [4] vertices  1  3
06179           [5] vertices  7  3
06180           [6] vertices  1  5
06181           [7] vertices  5  7
06182           [8] vertices  6  7
06183           [9] vertices  5  4
06184           [10] vertices  4  6
06185           [11] vertices  2  6
06186           [12] vertices  4  0
06187         }
06188       }
06189 
06190       material [0]
06191       {
06192       name           "kazoo"
06193       type           PHONG
06194       ambient        0.0  1.0  0.0
06195       diffuse        1.0  0.0  0.0
06196       specular       0.0  0.0  1.0
06197       exponent      50.0
06198       reflectivity   0.0
06199       transparency   0.0
06200       refracIndex    1.0
06201       glow           0
06202       coc            0.0
06203       }
06204 
06205       texture [0]
06206       {
06207       name          "/usr/users/foss/HOUSE/PICTURES/mellon"
06208       glbname       "t2d1"
06209       anim          STATIC
06210       method        XY
06211       repeat        1  1
06212       scaling       1.000  1.000
06213       offset        0.000  0.000
06214       pixelInterp
06215       effect        INTENSITY
06216       blending      1.000
06217       ambient       0.977
06218       diffuse       1.000
06219       specular      0.966
06220       reflect       0.000
06221       transp        0.000
06222       roughness     0.000
06223       reflMap       1.000
06224       rotation      0.000
06225       txtsup_rot    0.000  0.000  0.000
06226       txtsup_trans  0.000  0.000  0.000
06227       txtsup_scal   1.000  1.000  1.000
06228       }
06229     }
06230 
06231   Modified:
06232 
06233     25 June 1998
06234 
06235   Author:
06236 
06237     John Burkardt
06238 
06239 */
06240 {
06241   int iface;
06242   int ivert;
06243   int j;
06244   int jhi;
06245   int jlo;
06246   int jrel;
06247   int k;
06248   int npts;
06249   int nseg;
06250   int text_num;
06251 
06252   nseg = 0;
06253   text_num = 0;
06254 
06255   fprintf ( fileout, "HRCH: Softimage 4D Creative Environment v3.00\n" );
06256   fprintf ( fileout, "\n" );
06257   fprintf ( fileout, "\n" );
06258   text_num = text_num + 3;
06259 
06260   fprintf ( fileout, "model\n" );
06261   fprintf ( fileout, "{\n" );
06262   fprintf ( fileout, "  name         \"%s\"\n", object_name );
06263   fprintf ( fileout, "  scaling      1.000 1.000 1.000\n" );
06264   fprintf ( fileout, "  rotation     0.000 0.000 0.000\n" );
06265   fprintf ( fileout, "  translation  0.000 0.000 0.000\n" );
06266   text_num = text_num + 6;
06267 
06268   if ( face_num > 0 ) {
06269 
06270     fprintf ( fileout, "\n" );
06271     fprintf ( fileout, "  mesh\n" );
06272     fprintf ( fileout, "  {\n" );
06273     fprintf ( fileout, "    flag    ( PROCESS )\n" );
06274     fprintf ( fileout, "    discontinuity  60.000\n" );
06275     text_num = text_num + 5;
06276 /*
06277   Point coordinates.
06278 */
06279     if ( cor3_num > 0 ) {
06280 
06281       fprintf ( fileout, "\n" );
06282       fprintf ( fileout, "    vertices %d\n", cor3_num );
06283       fprintf ( fileout, "    {\n" );
06284       text_num = text_num + 3;
06285 
06286       for ( j = 0; j < cor3_num; j++ ) {
06287 
06288         fprintf ( fileout, "      [%d] position %f %f %f\n", j, cor3[0][j], 
06289           cor3[1][j], cor3[2][j] );
06290         text_num = text_num + 1;
06291       }
06292       fprintf ( fileout, "    }\n" );
06293       text_num = text_num + 1;
06294     }
06295 /*
06296   Faces.
06297 */
06298     fprintf ( fileout, "\n" );
06299     fprintf ( fileout, "    polygons %d\n", face_num );
06300     fprintf ( fileout, "    {\n" );
06301     text_num = text_num + 3;
06302 
06303     for ( iface = 0; iface < face_num; iface++ ) {
06304 
06305       fprintf ( fileout, "      [%d] nodes %d\n", iface, face_order[iface] );
06306       fprintf ( fileout, "      {\n" );
06307       text_num = text_num + 2;
06308 
06309       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
06310 
06311         fprintf ( fileout, "        [%d] vertex %d\n", ivert, face[ivert][iface] );
06312         fprintf ( fileout, "            normal %f %f %f\n", 
06313           vertex_normal[0][ivert][iface], 
06314           vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
06315         fprintf ( fileout, "            uvTexture  %f %f\n", 
06316           vertex_tex_uv[0][ivert][iface], vertex_tex_uv[1][ivert][iface] );
06317         fprintf ( fileout, "            vertexColor  255 178 178 178\n" );
06318         text_num = text_num + 4;
06319       }
06320       fprintf ( fileout, "      }\n" );
06321       fprintf ( fileout, "      material %d\n", face_material[iface] );
06322       text_num = text_num + 2;
06323     }
06324     fprintf ( fileout, "    }\n" );
06325     fprintf ( fileout, "  }\n" );
06326     text_num = text_num + 2;
06327   }
06328 /*
06329   IndexedLineSet.
06330 */
06331   if ( line_num > 0 ) {
06332 
06333     nseg = 0;
06334 
06335     jhi = -1;
06336 
06337     for ( ;; ) {
06338 
06339       jlo = jhi + 1;
06340 /*
06341   Look for the next index JLO that is not -1.
06342 */
06343       while ( jlo < line_num ) {
06344         if ( line_dex[jlo] != -1 ) {
06345           break;
06346         }
06347         jlo = jlo + 1;
06348       }
06349 
06350       if ( jlo >= line_num ) {
06351         break;
06352       }
06353 /*
06354   Look for the highest following index JHI that is not -1.
06355 */
06356       jhi = jlo + 1;
06357 
06358       while ( jhi < line_num ) {
06359         if ( line_dex[jhi] == -1 ) {
06360           break;
06361         }
06362         jhi = jhi + 1;
06363       }
06364 
06365       jhi = jhi - 1;
06366 /*
06367   Our next line segment involves LINE_DEX indices JLO through JHI.
06368 */     
06369       nseg = nseg + 1;
06370       npts = jhi + 1 - jlo;
06371 
06372       fprintf ( fileout, "\n" );
06373       fprintf ( fileout, "  spline\n" );
06374       fprintf ( fileout, "  {\n" );
06375       fprintf ( fileout, "    name     \"spl%d\"\n", nseg );
06376       fprintf ( fileout, "    type     LINEAR\n" );
06377       fprintf ( fileout, "    nbKeys   %d\n", npts );
06378       fprintf ( fileout, "    tension  0.000\n" );
06379       fprintf ( fileout, "    step     1\n" );
06380       fprintf ( fileout, "\n" );
06381       text_num = text_num + 9;
06382 
06383       fprintf ( fileout, "    controlpoints\n" );
06384       fprintf ( fileout, "    {\n" );
06385       text_num = text_num + 2;
06386 
06387       for ( j = jlo; j <= jhi; j++ ) {
06388         jrel = j - jlo;
06389         k = line_dex[j];
06390         fprintf ( fileout, "      [%d] position %f %f %f\n", jrel,
06391           cor3[0][k], cor3[1][k], cor3[2][k] );
06392         text_num = text_num + 1;
06393       }
06394 
06395       fprintf ( fileout, "    }\n" );
06396       fprintf ( fileout, "  }\n" );
06397       text_num = text_num + 2;
06398     }
06399   }
06400 /*
06401   MATERIALS
06402 */
06403   for ( i = 0; i < material_num; i++ ) {
06404 
06405     fprintf ( fileout, "  material [%d]\n", i );
06406     fprintf ( fileout, "  {\n" );
06407     fprintf ( fileout, "    name           \"%s\"\n", material_name[i] );
06408     fprintf ( fileout, "    type           PHONG\n" );
06409     fprintf ( fileout, "    ambient        %f %f %f\n", material_rgba[0][i],
06410       material_rgba[1][i], material_rgba[2][i] );
06411     fprintf ( fileout, "    diffuse        %f %f %f\n", material_rgba[0][i],
06412       material_rgba[1][i], material_rgba[2][i] );
06413     fprintf ( fileout, "    specular       %f %f %f\n", material_rgba[0][i],
06414       material_rgba[1][i], material_rgba[2][i] );
06415     fprintf ( fileout, "    exponent      50.0\n" );
06416     fprintf ( fileout, "    reflectivity   0.0\n" );
06417     fprintf ( fileout, "    transparency   %f\n", 1.0 - material_rgba[3][i] );
06418     fprintf ( fileout, "    refracIndex    1.0\n" );
06419     fprintf ( fileout, "    glow           0\n" );
06420     fprintf ( fileout, "    coc            0.0\n" );
06421     fprintf ( fileout, "  }\n" );
06422 
06423     text_num = text_num + 14;
06424 
06425   }
06426 /*
06427   TEXTURES
06428 */
06429   for ( i = 0; i < texture_num; i++ ) {
06430 
06431     fprintf ( fileout, "  texture [%d]\n", i );
06432     fprintf ( fileout, "  {\n" );
06433     fprintf ( fileout, "    name           \"%s\"\n", texture_name[i] );
06434     fprintf ( fileout, "    glbname        \"t2d1\"\n" );
06435     fprintf ( fileout, "    anim           STATIC\n" );
06436     fprintf ( fileout, "    method         XY\n" );
06437     fprintf ( fileout, "    repeat         1 1\n" );
06438     fprintf ( fileout, "    scaling        1.000  1.000\n" );
06439     fprintf ( fileout, "    offset         0.000  0.000\n" );
06440     fprintf ( fileout, "    pixelInterp\n" );
06441     fprintf ( fileout, "    effect         INTENSITY\n" );
06442     fprintf ( fileout, "    blending       1.000\n" );
06443     fprintf ( fileout, "    ambient        0.977\n" );
06444     fprintf ( fileout, "    diffuse        1.000\n" );
06445     fprintf ( fileout, "    specular       0.966\n" );
06446     fprintf ( fileout, "    reflect        0.000\n" );
06447     fprintf ( fileout, "    transp         0.000\n" );
06448     fprintf ( fileout, "    roughness      0.000\n" );
06449     fprintf ( fileout, "    reflMap        1.000\n" );
06450     fprintf ( fileout, "    rotation       0.000\n" );
06451     fprintf ( fileout, "    txtsup_rot     0.000  0.000  0.000\n" );
06452     fprintf ( fileout, "    txtsup_trans   0.000  0.000  0.000\n" );
06453     fprintf ( fileout, "    txtsup_scal    1.000  1.000  1.000\n" );
06454     fprintf ( fileout, "  }\n" );
06455 
06456     text_num = text_num + 25;
06457 
06458   }
06459   fprintf ( fileout, "}\n" );
06460   text_num = text_num + 1;
06461 /*
06462   Report.
06463 */
06464   printf ( "\n" );
06465   printf ( "HRC_WRITE - Wrote %d text lines.\n", text_num );
06466 
06467   return SUCCESS;
06468 }
06469 /******************************************************************************/
06470 
06471 void init_program_data ( void )
06472 
06473 /******************************************************************************/
06474 
06475 /*
06476   Purpose:
06477 
06478     INIT_PROGRAM_DATA initializes the internal program data.
06479 
06480   Modified:
06481 
06482     26 May 1999
06483 
06484   Author:
06485 
06486     John Burkardt
06487 */
06488 {
06489   byte_swap = FALSE;
06490   debug = 0;
06491   line_prune = 1;
06492   color_num = 0;
06493   cor3_num = 0;
06494   face_num = 0;
06495   line_num = 0;
06496 
06497   if ( debug ) {
06498     printf ( "\n" );
06499     printf ( "INIT_PROGRAM_DATA: Program data initialized.\n" );
06500   }
06501 
06502   return;
06503 
06504 }
06505 /******************************************************************************/
06506 
06507 int interact ( void )
06508 
06509 /******************************************************************************/
06510 
06511 /*
06512   Purpose:
06513    
06514     INTERACT carries on an interactive session with the user.
06515 
06516   Modified:
06517 
06518     22 May 1999
06519 
06520   Author:
06521  
06522     John Burkardt
06523 */
06524 {
06525   int    i;
06526   int    icor3;
06527   int    ierror;
06528   int    iface;
06529   int    itemp;
06530   int    ivert;
06531   int    j;
06532   int    jvert;
06533   int    m;
06534   char  *next;
06535   float  temp;
06536   float  x;
06537   float  y;
06538   float  z;
06539 
06540   strcpy ( filein_name, "NO_IN_NAME" );
06541   strcpy ( fileout_name, "NO_OUT_NAME" );
06542 
06543 /*  
06544   Say hello. 
06545 */
06546   hello ( );
06547 /*  
06548   Get the next user command. 
06549 */
06550   printf ( "\n" );
06551   printf ( "Enter command (H for help)\n" );
06552 
06553   while ( fgets ( input, LINE_MAX_LEN, stdin ) != NULL ) {
06554 /*  
06555   Advance to the first nonspace character in INPUT. 
06556 */
06557     for ( next = input; *next != '\0' && isspace(*next); next++ ) {
06558     }
06559 /*  
06560   Skip blank lines and comments. 
06561 */
06562     if ( *next == '\0' ) {
06563       continue;
06564     }
06565 /*  
06566   Command: << FILENAME 
06567   Append new data to current graphics information.
06568 */
06569     if ( *next == '<' && *(next+1) == '<' ) {
06570 
06571       next = next + 2;
06572       sscanf ( next, "%s", filein_name );
06573 
06574       ierror = data_read ( );
06575 
06576       if ( ierror == ERROR ) {
06577         printf ( "\n" );
06578         printf ( "INTERACT - Fatal error!\n" );
06579         printf ( "  DATA_READ failed to read input data.\n" );
06580       }
06581     }
06582 /*  
06583   Command: < FILENAME 
06584 */
06585     else if ( *next == '<' ) {
06586 
06587       next = next + 1;
06588       sscanf ( next, "%s", filein_name );
06589 
06590       data_init ( );
06591 
06592       ierror = data_read ( );
06593 
06594       if ( ierror == ERROR ) {
06595         printf ( "\n" );
06596         printf ( "INTERACT - Fatal error!\n" );
06597         printf ( "  DATA_READ failed to read input data.\n" );
06598       }
06599     }
06600 /*  
06601   Command: > FILENAME 
06602 */
06603     else if ( *next == '>' ) {
06604 
06605       next = next + 1;
06606       sscanf ( next, "%s", fileout_name ); 
06607 
06608       ierror = data_write ( );
06609  
06610       if ( ierror == ERROR ) {
06611         printf ( "\n" );
06612         printf ( "INTERACT - Fatal error!\n" );
06613         printf ( "  OUTPUT_DATA failed to write output data.\n" );
06614       }
06615 
06616     }
06617 /*
06618   B: Switch byte swapping option.
06619 */
06620     else if ( *next == 'B' || *next == 'b' ) {
06621 
06622       if ( byte_swap == TRUE ) {
06623         byte_swap = FALSE;
06624         printf ( "Byte_swapping reset to FALSE.\n" );
06625       }
06626       else {
06627         byte_swap = TRUE;
06628         printf ( "Byte_swapping reset to TRUE.\n" );
06629       }
06630 
06631     }
06632 /*
06633   D: Switch debug option.
06634 */
06635     else if ( *next == 'D' || *next == 'd' ) {
06636       if ( debug ) {
06637         debug = 0;
06638         printf ( "Debug reset to FALSE.\n" );
06639       }
06640       else {
06641         debug = 1;
06642         printf ( "Debug reset to TRUE.\n" );
06643       }
06644     }
06645 /*  
06646   F: Check a face. 
06647 */
06648     else if ( *next == 'f' || *next == 'F' ) {
06649       printf ( "\n" );
06650       printf ( "  Enter a face index between 0 and %d:", face_num-1 );
06651       scanf ( "%d", &iface );
06652       face_print ( iface );
06653     }
06654 /*  
06655   H: Help
06656 */
06657     else if ( *next == 'h' || *next == 'H' ) {
06658       help ( );
06659     }
06660 /*
06661   I: Print change information. 
06662 */
06663     else if ( *next == 'i' || *next == 'I') {
06664       news ( );
06665     }
06666 /*
06667   LINES: 
06668   Convert face information to lines.
06669 */
06670     else if ( *next == 'l' || *next == 'L') {
06671 
06672       if ( face_num > 0 ) {
06673 
06674         printf ( "\n" );
06675         printf ( "INTERACT - Note:\n" );
06676         printf ( "  Face information will be converted\n" );
06677         printf ( "  to line information.\n" );
06678 
06679           face_to_line ( );
06680 
06681           if ( line_num > LINES_MAX ) {
06682 
06683             printf ( "\n" );
06684             printf ( "INTERACT - Note:\n" );
06685             printf ( "  Some face information was lost.\n" );
06686             printf ( "  The maximum number of lines is %d,\n", LINES_MAX );
06687             printf ( "  but we would need at least %d.\n", line_num );
06688 
06689             line_num = LINES_MAX;
06690 
06691           }
06692 
06693           face_num = 0;
06694       }
06695       else {
06696 
06697         printf ( "\n" );
06698         printf ( "INTERACT - Note:\n" );
06699         printf ( "  There were no faces to convert.\n" );
06700 
06701       }
06702 
06703     }
06704 /*
06705   N: Recompute normal vectors.
06706 */
06707     else if ( *next == 'n' || *next == 'N') {
06708 
06709       for ( iface = 0; iface < face_num; iface++ ) {
06710         for ( i = 0; i < 3; i++ ) {
06711           face_normal[i][iface] = 0.0;
06712         }
06713       }
06714 
06715       for ( iface = 0; iface < face_num; iface++ ) {
06716          for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
06717           for ( i = 0; i < 3; i++ ) {
06718             vertex_normal[i][ivert][iface] = 0.0;
06719           }
06720         }
06721       }
06722 
06723       vertex_normal_set ( );
06724 
06725       cor3_normal_set ( );
06726 
06727       face_normal_ave ( );
06728     }
06729 /*
06730   P: Line pruning optiont
06731 */
06732     else if ( *next == 'p' || *next == 'P' ) {
06733 
06734       printf ( "\n" );
06735       printf ( "INTERACT - SET LINE PRUNING OPTION.\n" );
06736       printf ( "\n" );
06737       printf ( "  LINE_PRUNE = 0 means no line pruning.\n" );
06738       printf ( "               nonzero means line pruning.\n" );
06739       printf ( "\n" );
06740       printf ( "  Current value is LINE_PRUNE = %d.\n", line_prune );
06741       printf ( "\n" );
06742       printf ( "  Enter new value for LINE_PRUNE.\n" );
06743 
06744       if ( fgets ( input, LINE_MAX_LEN, stdin ) == NULL ) {
06745         printf ( "  ??? Error trying to read input.\n" );
06746       }
06747       else {
06748         sscanf ( input, "%d", &line_prune );
06749         printf ( "  New value is LINE_PRUNE = %d.\n", line_prune );
06750       }
06751     }
06752 /*
06753   Q: Quit
06754 */
06755     else if ( *next == 'q' || *next == 'Q' ) {
06756       printf ( "\n" );
06757       printf ( "INTERACT - Normal end of execution.\n" );
06758       return SUCCESS;
06759     }
06760 /*
06761   R: Reverse normal vectors. 
06762 */
06763     else if ( *next == 'r' || *next == 'R' ) {
06764 
06765       for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
06766         for ( i = 0; i < 3; i++ ) {
06767           cor3_normal[i][icor3] = - cor3_normal[i][icor3];
06768         }
06769       }
06770 
06771       for ( iface = 0; iface < face_num; iface++ ) {
06772         for ( i = 0; i < 3; i++ ) {
06773           face_normal[i][iface] = - face_normal[i][iface];
06774         }
06775       }
06776 
06777       for ( iface = 0; iface < face_num; iface++ ) {
06778         for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
06779           for ( i = 0; i < 3; i++ ) {
06780             vertex_normal[i][ivert][iface] = 
06781               - vertex_normal[i][ivert][iface];
06782           }
06783         }
06784       }
06785       printf ( "\n" );
06786       printf ( "INTERACT - Note:\n" );
06787       printf ( "  Reversed node, face and vertex normals.\n" );
06788     }
06789 /*  
06790   S: Select a few faces, discard the rest.
06791 */
06792     else if ( *next == 's' || *next == 'S' ) {
06793       face_subset ( );
06794     }
06795 /*  
06796   T: Transform the data.
06797 */
06798     else if ( *next == 't' || *next == 'T' ) {
06799 
06800       printf ( "\n" );
06801       printf ( "For now, we only offer point scaling.\n" );
06802       printf ( "Enter X, Y, Z scale factors:\n" );
06803 
06804       scanf ( "%f %f %f", &x, &y, &z );
06805 
06806       for ( j = 0; j < cor3_num; j++ ) {
06807         cor3[0][j] = x * cor3[0][j];
06808         cor3[1][j] = y * cor3[1][j];
06809         cor3[2][j] = z * cor3[2][j];
06810       }
06811 
06812       for ( iface = 0; iface < face_num; iface++ ) {
06813         for ( i = 0; i < 3; i++ ) {
06814           face_normal[i][iface] = 0.0;
06815         }
06816       }
06817 
06818       for ( iface = 0; iface < face_num; iface++ ) {
06819          for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
06820           for ( i = 0; i < 3; i++ ) {
06821             vertex_normal[i][ivert][iface] = 0.0;
06822           }
06823         }
06824       }
06825 
06826       vertex_normal_set ( );
06827 
06828       cor3_normal_set ( );
06829 
06830       face_normal_ave ( );
06831     }
06832 /*
06833   U: Renumber faces, count objects:
06834 */
06835     else if ( *next == 'u' || *next == 'U' ) {
06836     }
06837 /*
06838   V: Convert polygons to triangles:
06839 */
06840     else if ( *next == 'v' || *next == 'V' ) {
06841     }
06842 /*
06843   W: Reverse the face node ordering. 
06844 */
06845     else if ( *next == 'w' || *next == 'W' ) {
06846 
06847       if ( face_num > 0 ) {
06848 
06849         for ( iface = 0; iface < face_num; iface++ ) {
06850 
06851           m = face_order[iface];
06852 
06853           for ( ivert = 0; ivert < m/2; ivert++ ) {
06854 
06855             jvert = m - ivert - 1;
06856 
06857             itemp = face[ivert][iface];
06858             face[ivert][iface] = face[jvert][iface];
06859             face[jvert][iface] = itemp;
06860 
06861             itemp = vertex_material[ivert][iface];
06862             vertex_material[ivert][iface] = vertex_material[jvert][iface];
06863             vertex_material[jvert][iface] = itemp;
06864 
06865             for ( i = 0; i < 3; i++ ) {
06866               temp = vertex_normal[i][ivert][iface];
06867               vertex_normal[i][ivert][iface] = 
06868                 vertex_normal[i][jvert][iface];
06869               vertex_normal[i][jvert][iface] = temp;
06870             }
06871           }
06872         }
06873         printf ( "\n" );
06874         printf ( "INTERACT - Note:\n" );
06875         printf ( "  Reversed face node ordering.\n" );
06876       }
06877     }
06878 /*
06879   Command: ???  
06880 */
06881     else {
06882       printf ( "\n" );
06883       printf ( "INTERACT: Warning!\n" );
06884       printf ( "  Your command was not recognized.\n" );
06885     }
06886 
06887     printf ( "\n" );
06888     printf ( "Enter command (H for help)\n" );
06889 
06890   }
06891   return SUCCESS;
06892 }
06893 /******************************************************************************/
06894 
06895 int iv_read ( FILE *filein )
06896 
06897 /******************************************************************************/
06898 
06899 /*
06900   Purpose:
06901 
06902     IV_READ reads graphics information from an Inventor file.
06903 
06904   Example:
06905 
06906      #Inventor V2.0 ascii
06907 
06908      Separator {
06909        Info {
06910          string "Inventor file generated by IVCON.
06911          Original data in file cube.iv."
06912        }
06913        Separator {
06914          LightModel {
06915            model PHONG
06916          }
06917          MatrixTransform { matrix
06918            0.9  0.0  0.0  0.0
06919            0.0 -0.9  0.0  0.0
06920            0.0  0.0 -1.5  0.0
06921            0.0  0.0  0.0  1.0
06922          }
06923          Material {
06924            ambientColor  0.2 0.2 0.2
06925            diffuseColor  [
06926              0.8 0.8 0.8,
06927              0.7 0.1 0.1,
06928              0.1 0.8 0.2,
06929            ]
06930            emissiveColor 0.0 0.0 0.0
06931            specularColor 0.0 0.0 0.0
06932            shininess     0.2
06933            transparency  [
06934              0.0, 0.5, 1.0,
06935            ]
06936          }
06937          Texture2 {
06938            filename      "fred.rgb"
06939            wrapS         REPEAT
06940            wrapT         REPEAT
06941            model         MODULATE
06942            blendColor    0.0 0.0 0.0
06943          }
06944 
06945          MaterialBinding {
06946            value PER_VERTEX_INDEXED
06947          }
06948          NormalBinding {
06949            value PER_VERTEX_INDEXED
06950          }
06951          TextureCoordinateBinding {
06952            value PER_VERTEX_INDEXED
06953          }
06954 
06955          ShapeHints {
06956            vertexOrdering COUNTERCLOCKWISE
06957            shapeType UNKNOWN_SHAPE_TYPE
06958            faceType CONVEX
06959            creaseAngle 6.28319
06960          }
06961 
06962          Coordinate3 {
06963            point [
06964                 8.59816       5.55317      -3.05561,
06965                 8.59816       2.49756      0.000000E+00,
06966                 ...etc...
06967                 2.48695       2.49756      -3.05561,
06968            ]
06969          }
06970 
06971          Normal {
06972            vector [
06973              0.71 0.71 0.0,
06974              ...etc...
06975              0.32 0.32 0.41,
06976            ]
06977          }
06978 
06979          TextureCoordinate2 {
06980            point [
06981                 0.0  1.0,
06982                 0.1, 0.8,
06983                 ...etc...
06984                 0.4  0.7,
06985            ]
06986          }
06987 
06988          IndexedLineSet {
06989            coordIndex [
06990               0,    1,    2,   -1,
06991               3,    4,    5,   -1,
06992               7,    8,    9,   -1,
06993             ...etc...
06994             189,  190,  191,   -1,
06995            ]
06996            materialIndex [
06997               0,    0,    0,   -1,
06998               1,    1,    1,   -1,
06999               2,    2,    2,   -1,
07000             ...etc...
07001              64,   64,   64,   -1,
07002            ]
07003          }
07004 
07005          IndexedFaceSet {
07006            coordIndex [
07007               0,    1,    2,   -1,
07008               3,    4,    5,   -1,
07009               7,    8,    9,   -1,
07010             ...etc...
07011             189,  190,  191,   -1,
07012            ]
07013            materialIndex [
07014               0,    0,    0,   -1,
07015               1,    1,    1,   -1,
07016               2,    2,    2,   -1,
07017             ...etc...
07018              64,   64,   64,   -1,
07019            ]
07020            normalIndex [
07021               0,    0,    0,   -1,
07022               1,    1,    1,   -1,
07023               2,    2,    2,   -1,
07024             ...etc...
07025              64,   64,   64,   -1,
07026            ]
07027            textureCoordIndex [
07028               0,    0,    0,   -1,
07029               1,    1,    1,   -1,
07030               2,    2,    2,   -1,
07031             ...etc...
07032              64,   64,   64,   -1,
07033            ]
07034          }
07035 
07036          IndexedTriangleStripSet {
07037            vertexProperty VertexProperty {
07038              vertex [ x y z,
07039                       ...
07040                       x y z ]
07041              normal [ x y z,
07042                       ...
07043                       x y z ]
07044              materialBinding OVERALL
07045              normalBinding PER_VERTEX_INDEXED
07046            }
07047            coordIndex [ 
07048              i, j, k, l, m, -1, 
07049              n, o, p, q, r, s, t, u, -1,
07050              v, w, x, -1 
07051                  ..., -1 ]
07052            normalIndex -1
07053          }
07054 
07055        }
07056      }
07057 
07058   Modified:
07059 
07060     01 July 1999
07061 
07062   Author:
07063 
07064     John Burkardt
07065 */
07066 {
07067   char  c;
07068   int   count;
07069   int   i;
07070   int   icol;
07071   int   icolor;
07072   int   icface;
07073   int   inormface;
07074   int   iface_num;
07075   int   irow;
07076   int   iuv;
07077   int   ivert;
07078   int   iword;
07079   int   ix;
07080   int   ixyz;
07081   int   iy;
07082   int   iz;
07083   int   j;
07084   int   jval;
07085   int   level;
07086   char *next;
07087   int   nlbrack;
07088   int   nrbrack;
07089   int   nu;
07090   int   null_index;
07091   int   cor3_num_old;
07092   int   line_num2;
07093   int   face_num2;
07094   int   normal_num_temp;
07095   int   text_numure_temp;
07096   int   nv;
07097   int   result;
07098   float rval;
07099   int   width;
07100   char  word[LINE_MAX_LEN];
07101   char  word1[LINE_MAX_LEN];
07102   char  wordm1[LINE_MAX_LEN];
07103   float xvec[3];
07104 
07105   icface = 0;
07106   icol = -1;
07107   inormface = 0;
07108   iface_num = face_num;
07109   irow = 0;
07110   ix = 0;
07111   ixyz = 0;
07112   iy = 0;
07113   iz = 0;
07114   jval = 0;
07115   level = 0;
07116   strcpy ( level_name[0], "Top" );
07117   nlbrack = 0;
07118   nrbrack = 0;
07119   nu = 0;
07120   cor3_num_old = cor3_num;
07121   face_num2 = face_num;
07122   line_num2 = line_num;
07123   normal_num_temp = 0;
07124   text_numure_temp = 0;
07125   nv = 0;
07126   rval = 0.0;
07127   strcpy ( word, " " );
07128   strcpy ( wordm1, " " );
07129 /*
07130   Read the next line of text from the input file.
07131 */
07132   for ( ;; ) {
07133 
07134     if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
07135       break;
07136     }
07137 
07138     text_num = text_num + 1;
07139     next = input;
07140     iword = 0;
07141 /*
07142   Remove all commas from the line, so we can use SSCANF to read
07143   numeric items.
07144 */
07145     i = 0;
07146     while ( input[i] != '\0' ) {
07147       if ( input[i] == ',' ) {
07148         input[i] = ' ';
07149       }
07150       i++;
07151     }
07152 /*
07153   Force brackets and braces to be buffered by spaces.
07154 */
07155     i = 0;
07156     while ( input[i] != '\0' ) {
07157       i++;
07158     }
07159     null_index = i;
07160 
07161     i = 0;
07162     while ( input[i] != '\0' && i < LINE_MAX_LEN ) {
07163 
07164       if ( input[i] == '[' || input[i] == ']' || 
07165            input[i] == '{' || input[i] == '}' ) {
07166 
07167         result = char_pad ( &i, &null_index, input, LINE_MAX_LEN );
07168         if ( result == ERROR ) {
07169           break;
07170         }
07171       } 
07172       else {
07173         i++;
07174       }
07175     }
07176 /*
07177   Read a word from the line.
07178 */
07179     for ( ;; ) {
07180 
07181       strcpy ( wordm1, word );
07182       strcpy ( word, " " );
07183 
07184       count = sscanf ( next, "%s%n", word, &width );
07185       next = next + width;
07186 
07187       if ( count <= 0 ) {
07188         break;
07189       }
07190 
07191       iword = iword + 1;
07192 
07193       if ( iword == 1 ) {
07194         strcpy ( word1, word );
07195       }
07196 /*
07197   The first line of the file must be the header.
07198 */
07199       if ( text_num == 1 ) {
07200 
07201         if ( leqi ( word1, "#Inventor" ) != TRUE ) { 
07202           printf ( "\n" );
07203           printf ( "IV_READ - Fatal error!\n" );
07204           printf ( "  The input file has a bad header.\n" );
07205           return ERROR;
07206         }
07207         else {
07208           comment_num = comment_num + 1;
07209         }
07210         break;
07211       }
07212 /*
07213   A comment begins anywhere with '#'.
07214   Skip the rest of the line.
07215 */
07216       if ( word[1] == '#' ) {
07217         comment_num = comment_num + 1;
07218         break;
07219       }
07220 /*
07221   If the word is a curly or square bracket, count it.
07222   If the word is a left bracket, the previous word is the name of a node.
07223 */
07224       if ( strcmp ( word, "{" ) == 0 || strcmp ( word, "[" ) == 0 ) {
07225         nlbrack = nlbrack + 1;
07226         level = nlbrack - nrbrack;
07227         strcpy ( level_name[level], wordm1 );
07228         if ( debug ) {
07229           printf ( "Begin level: %s\n", wordm1 );
07230         }
07231       }
07232       else if ( strcmp ( word, "}" ) == 0 || strcmp ( word, "]" ) == 0 ) {
07233         nrbrack = nrbrack + 1;
07234 
07235         if ( nlbrack < nrbrack ) {
07236           printf ( "\n" );
07237           printf ( "IV_READ - Fatal error!\n" );
07238           printf ( "  Extraneous right bracket on line %d.\n", text_num );
07239           printf ( "  Currently processing field %s\n.", level_name[level] );
07240           return ERROR;
07241         }
07242       }
07243 /*
07244   BASECOLOR
07245 */
07246       if ( leqi ( level_name[level], "BASECOLOR" ) == TRUE ) {
07247 
07248         if ( strcmp ( word, "{" ) == 0 ) {
07249         }
07250         else if ( strcmp ( word, "}" ) == 0 ) {
07251           level = nlbrack - nrbrack;
07252         }
07253         else if ( leqi ( word, "RGB" ) == TRUE ) {
07254         }
07255         else {
07256           bad_num = bad_num + 1;
07257           printf ( "Bad data %s\n", word );
07258         }
07259       }
07260 /*
07261   COORDINATE3
07262 */
07263       else if ( leqi ( level_name[level], "COORDINATE3" ) == TRUE ) {
07264 
07265         if ( strcmp ( word, "{" ) == 0 ) {
07266         }
07267         else if ( strcmp ( word, "}" ) == 0 ) {
07268           level = nlbrack - nrbrack;
07269         }
07270         else if ( leqi ( word, "POINT" ) == TRUE ) {
07271         }
07272         else {
07273           bad_num = bad_num + 1;
07274           printf ( "COORDINATE3: Bad data %s\n", word );
07275         }
07276       }
07277 /*
07278   COORDINATE4
07279 */
07280       else if ( leqi ( level_name[level], "COORDINATE4" ) == TRUE ) {
07281 
07282         if ( strcmp ( word, "{" ) == 0 ) {
07283         }
07284         else if ( strcmp ( word, "}" ) == 0 ) {
07285           level = nlbrack - nrbrack;
07286         }
07287         else if ( leqi ( word, "POINT" ) == TRUE ) {
07288         }
07289         else {
07290           bad_num = bad_num + 1;
07291           printf ( "COORDINATE4: Bad data %s\n", word );
07292         }
07293       }
07294 /*
07295   COORDINDEX
07296 */
07297       else if ( leqi ( level_name[level], "COORDINDEX" ) == TRUE ) {
07298 
07299         if ( strcmp ( word, "[" ) == 0 ) {
07300           ivert = 0;
07301         }
07302         else if ( strcmp ( word, "]" ) == 0 ) {
07303           level = nlbrack - nrbrack;
07304         }
07305 /*
07306   (indexedlineset) COORDINDEX
07307 */
07308         else if ( leqi ( level_name[level-1], "INDEXEDLINESET" ) == TRUE ) {
07309 
07310           count = sscanf ( word, "%d%n", &jval, &width );
07311 
07312           if ( count > 0 ) {
07313 
07314             if ( jval < -1 ) {
07315               bad_num = bad_num + 1;
07316             }
07317             else {
07318               if ( line_num < LINES_MAX ) {
07319                 if ( jval != -1 ) {
07320                   jval = jval + cor3_num_old;
07321                 }
07322                 line_dex[line_num] = jval;
07323               }
07324               line_num = line_num + 1;
07325             }
07326           }
07327           else {
07328             bad_num = bad_num + 1;
07329           }
07330         }
07331 /*
07332   (indexedfaceset) COORDINDEX
07333   Warning: If the list of indices is not terminated with a final -1, then
07334   the last face won't get counted.
07335 */
07336         else if ( leqi ( level_name[level-1], "INDEXEDFACESET" ) == TRUE ) {
07337 
07338           count = sscanf ( word, "%d%n", &jval, &width );
07339 
07340           if ( count > 0 ) {
07341             if ( jval == -1 ) {
07342               ivert = 0;
07343               face_num = face_num + 1;
07344             }
07345             else {
07346               if ( ivert == 0 ) {
07347                 if ( face_num < FACE_MAX ) {
07348                   face_order[face_num] = 0;
07349                 }
07350               }
07351               if ( face_num < FACE_MAX ) {
07352                 face_order[face_num] = face_order[face_num] + 1;
07353                 face[ivert][face_num] = jval + cor3_num_old;
07354                 ivert = ivert + 1;
07355               }
07356             }
07357           }
07358         }
07359 /*
07360   (indexednurbssurface) COORDINDEX
07361 */
07362         else if ( leqi ( level_name[level-1], "INDEXEDNURBSSURFACE" ) == TRUE ) {
07363         }
07364 /*
07365   (indexedtrianglestripset) COORDINDEX
07366 
07367   First three coordinate indices I1, I2, I3 define a triangle.
07368   Next triangle is defined by I2, I3, I4 (actually, I4, I3, I2
07369   to stay with same counterclockwise sense).
07370   Next triangle is defined by I3, I4, I5 ( do not need to reverse
07371   odd numbered triangles) and so on.
07372   List is terminated with -1.
07373 */
07374         else if ( leqi ( level_name[level-1], "INDEXEDTRIANGLESTRIPSET" ) == TRUE ) {
07375 
07376           count = sscanf ( word, "%d%n", &jval, &width );
07377 
07378           if ( count > 0 ) {
07379 
07380             if ( jval == -1 ) {
07381               ivert = 0;
07382             }
07383             else {
07384 
07385               ix = iy;
07386               iy = iz;
07387               iz = jval + cor3_num_old;
07388 
07389               if ( ivert == 0 ) {
07390                 if ( face_num < FACE_MAX ) {
07391                   face[ivert][face_num] = jval + cor3_num_old;
07392                   face_order[face_num] = 3;
07393                 }
07394               }
07395               else if ( ivert == 1 ) {
07396                 if ( face_num < FACE_MAX ) {
07397                   face[ivert][face_num] = jval + cor3_num_old;
07398                 }
07399               }
07400               else if ( ivert == 2 ) {
07401                 if ( face_num < FACE_MAX ) {
07402                   face[ivert][face_num] = jval + cor3_num_old;
07403                 }
07404                 face_num = face_num + 1;
07405               }
07406               else {
07407 
07408                 if ( face_num < FACE_MAX ) {
07409                   face_order[face_num] = 3;
07410                   if ( ( ivert % 2 ) == 0 ) {
07411                     face[0][face_num] = ix;
07412                     face[1][face_num] = iy;
07413                     face[2][face_num] = iz;
07414                   }
07415                   else {
07416                     face[0][face_num] = iz;
07417                     face[1][face_num] = iy;
07418                     face[2][face_num] = ix;
07419                   }
07420                 }
07421                 face_num = face_num + 1;
07422               }
07423               ivert = ivert + 1;
07424 /*
07425   Very very tentative guess as to how indices into the normal
07426   vector array are set up...
07427 */
07428               if ( face_num < FACE_MAX && ivert > 2 ) {
07429                 for ( i = 0; i < 3; i++ ) {
07430                   face_normal[i][face_num] = normal_temp[i][ix];
07431                 }
07432               }
07433             }
07434           }
07435         }
07436       }
07437 /*
07438   INDEXEDFACESET
07439 */
07440       else if ( leqi ( level_name[level], "INDEXEDFACESET" ) == TRUE ) {
07441 
07442         if ( strcmp ( word, "{" ) == 0 ) {
07443         }
07444         else if ( strcmp ( word, "}" ) == 0 ) {
07445           level = nlbrack - nrbrack;
07446         }
07447         else if ( leqi ( word, "COORDINDEX" ) == TRUE ) {
07448           ivert = 0;
07449         }
07450         else if ( leqi ( word, "MATERIALINDEX" ) == TRUE ) {
07451         }
07452         else if ( leqi ( word, "NORMALINDEX" ) == TRUE ) {
07453         }
07454         else if ( leqi ( word, "TEXTURECOORDINDEX" ) == TRUE ) {
07455           if ( texture_num <= 0 ) {
07456             texture_num = 1;
07457             strcpy ( texture_name[0], "Texture_0000" );
07458           }
07459         }
07460         else {
07461           bad_num = bad_num + 1;
07462           printf ( "Bad data %s\n", word );
07463         }
07464       }
07465 /*
07466   INDEXEDLINESET
07467 */
07468       else if ( leqi ( level_name[level], "INDEXEDLINESET" ) == TRUE ) {
07469 
07470         if ( strcmp ( word, "{" ) == 0 ) {
07471         }
07472         else if ( strcmp ( word, "}" ) == 0 ) {
07473           level = nlbrack - nrbrack;
07474         }
07475         else if ( leqi ( word, "COORDINDEX" ) == TRUE ) {
07476         }
07477         else if ( leqi ( word, "MATERIALINDEX" ) == TRUE ) {
07478         }
07479         else {
07480           bad_num = bad_num + 1;
07481           printf ( "Bad data %s\n", word );
07482         }
07483       }
07484 /*
07485   INDEXEDNURBSSURFACE
07486 */
07487       else if ( leqi ( level_name[level], "INDEXEDNURBSSURFACE" ) == TRUE ) {
07488 
07489         if ( strcmp ( word, "{" ) == 0 ) {
07490         }
07491         else if ( strcmp ( word, "}" ) == 0 ) {
07492           level = nlbrack - nrbrack;
07493         }
07494         else if ( leqi ( word, "NUMUCONTROLPOINTS") == TRUE ) {
07495 
07496           count = sscanf ( word, "%d%n", &jval, &width );
07497 
07498           if ( count > 0 ) {
07499             nu = jval;
07500             if ( debug ) {
07501               printf ( "NU = %d\n", nu );
07502             }
07503           }
07504           else {
07505             nu = 0;
07506             bad_num = bad_num + 1;
07507             printf ( "Bad data %s\n", word );
07508           }
07509         }
07510         else if ( leqi ( word, "NUMVCONTROLPOINTS" ) == TRUE ) {
07511 
07512           count = sscanf ( word, "%d%n", &jval, &width );
07513 
07514           if ( count > 0 ) {
07515             nv = jval;
07516             if ( debug ) {
07517               printf ( "NV = %d\n", nv );
07518             }
07519           }
07520           else {
07521             nv = 0;
07522             bad_num = bad_num + 1;
07523           }
07524         }
07525         else if ( leqi ( word, "COORDINDEX" ) == TRUE ) {
07526         }
07527         else if ( leqi ( word, "UKNOTVECTOR" ) == TRUE ) {
07528         }
07529         else if ( leqi ( word, "VKNOTVECTOR" ) == TRUE ) {
07530         }
07531         else {
07532           bad_num = bad_num + 1;
07533           printf ( "Bad data %s\n", word );
07534         }
07535       }
07536 /*
07537   INDEXEDTRIANGLESTRIPSET
07538 */
07539       else if ( leqi ( level_name[level], "INDEXEDTRIANGLESTRIPSET" ) == TRUE ) {
07540 
07541         if ( strcmp ( word, "{" ) == 0 ) {
07542         }
07543         else if ( strcmp ( word, "}" ) == 0 ) {
07544           level = nlbrack - nrbrack;
07545         }
07546         else if ( leqi ( word, "VERTEXPROPERTY" ) == TRUE ) {
07547           count = sscanf ( next, "%s%n", word, &width );
07548           next = next + width;
07549         }
07550         else if ( leqi ( word, "COORDINDEX" ) == TRUE ) {
07551           ivert = 0;
07552         }
07553         else if ( leqi ( word, "NORMALINDEX" ) == TRUE ) {
07554           count = sscanf ( next, "%s%n", word, &width );
07555           next = next + width;
07556         }
07557         else {
07558           bad_num = bad_num + 1;
07559           printf ( "Bad data %s\n", word );
07560         }
07561       }
07562 /*
07563   INFO
07564 */
07565       else if ( leqi ( level_name[level], "INFO" ) == TRUE ) {
07566 
07567         if ( strcmp ( word, "{" ) == 0 ) {
07568         }
07569         else if ( strcmp ( word, "}" ) == 0 ) {
07570           level = nlbrack - nrbrack;
07571         }
07572         else if ( leqi ( word, "STRING" ) == TRUE ) {
07573         }
07574         else if ( strcmp ( word, "\"" ) == 0 ) {
07575         }
07576         else {
07577         }
07578       }
07579 /*
07580   LIGHTMODEL
07581   Read, but ignore.
07582 */
07583       else if ( leqi ( level_name[level], "LIGHTMODEL" ) == TRUE ) {
07584 
07585         if ( strcmp ( word, "{" ) == 0 ) {
07586         }
07587         else if ( strcmp ( word, "}" ) == 0 ) {
07588           level = nlbrack - nrbrack;
07589         }
07590         else if ( leqi ( word, "model" ) == TRUE ) {
07591         }
07592         else {
07593         }
07594       }
07595 /*
07596   MATERIAL
07597   Read, but ignore.
07598 */
07599       else if ( leqi ( level_name[level],"MATERIAL" ) == TRUE ) {
07600 
07601         if ( strcmp ( word, "{" ) == 0 ) {
07602         }
07603         else if ( strcmp ( word, "}" ) == 0 ) {
07604           level = nlbrack - nrbrack;
07605         }
07606         else if ( leqi ( word, "AMBIENTCOLOR" ) == TRUE ) {
07607         }
07608         else if ( leqi ( word, "EMISSIVECOLOR" ) == TRUE ) {
07609         }
07610         else if ( leqi ( word, "DIFFUSECOLOR" ) == TRUE ) {
07611         }
07612         else if ( leqi ( word, "SHININESS" ) == TRUE ) {
07613         }
07614         else if ( leqi ( word, "SPECULARCOLOR" ) == TRUE ) {
07615         }
07616         else if ( leqi ( word, "TRANSPARENCY" ) == TRUE ) {
07617         }
07618         else {
07619         }
07620       }
07621 /*
07622   MATERIALBINDING
07623   Read, but ignore
07624 */
07625       else if ( leqi ( level_name[level], "MATERIALBINDING" ) == TRUE ) {
07626 
07627         if ( strcmp ( word, "{" ) == 0 ) {
07628         }
07629         else if ( strcmp ( word, "}" ) == 0 ) {
07630           level = nlbrack - nrbrack;
07631         }
07632         else if ( leqi ( word, "VALUE" ) == TRUE ) {
07633           count = sscanf ( next, "%s%n", material_binding, &width );
07634           next = next + width;
07635         }
07636         else {
07637           count = sscanf ( next, "%f%n", &rval, &width );
07638           next = next + width;
07639 
07640           if ( count > 0 ) {
07641           }
07642           else {
07643             bad_num = bad_num + 1;
07644             printf ( "Bad data %s\n", word );
07645           }
07646         }
07647       }
07648 /*
07649   MATERIALINDEX
07650 */
07651       else if ( leqi ( level_name[level], "MATERIALINDEX" ) == TRUE ) {
07652 
07653         if ( strcmp ( word, "[" ) == 0 ) {
07654           ivert = 0;
07655         }
07656         else if ( strcmp ( word, "]" ) == 0 ) {
07657           level = nlbrack - nrbrack;
07658         }
07659 /*
07660   (indexedfaceset) MATERIALINDEX
07661 */
07662         else if ( leqi ( level_name[level-1], "INDEXEDFACESET" ) == TRUE ) {
07663 
07664           count = sscanf ( word, "%d%n", &jval, &width );
07665 
07666           if ( count > 0 ) {
07667 
07668             if ( jval == -1 ) {
07669               ivert = 0;
07670               face_num2 = face_num2 + 1;
07671             }
07672             else {
07673 
07674               if ( face_num2 < FACE_MAX ) {
07675                 if ( jval != -1 ) {
07676                   jval = jval + cor3_num_old;
07677                 }
07678                 vertex_material[ivert][face_num2] = jval;
07679                 ivert = ivert + 1;
07680               }
07681             }
07682           }
07683           else {
07684             bad_num = bad_num + 1;
07685             printf ( "Bad data %s\n", word );
07686           }
07687         } 
07688 /*
07689   (indexedlineset) MATERIALINDEX
07690 */
07691         else if ( leqi ( level_name[level-1], "INDEXEDLINESET" ) == TRUE ) {
07692 
07693           count = sscanf ( word, "%d%n", &jval, &width );
07694 
07695           if ( count > 0 ) {
07696 
07697             if ( line_num2 < LINES_MAX ) {
07698               if ( jval != -1 ) {
07699                 jval = jval + cor3_num_old;
07700               }
07701               line_material[line_num2] = jval;
07702               line_num2 = line_num2 + 1;
07703             }
07704           }
07705           else {
07706             bad_num = bad_num + 1;
07707             printf ( "Bad data %s\n", word );
07708           }
07709         }
07710         else {
07711           count = sscanf ( word, "%d%n", &jval, &width );
07712 
07713           if ( count > 0 ) {
07714           }
07715           else {
07716             bad_num = bad_num + 1;
07717             printf ( "Bad data %s\n", word );
07718           }
07719         }
07720       }
07721 /*
07722   MATRIXTRANSFORM.
07723 */
07724       else if ( leqi ( level_name[level], "MATRIXTRANSFORM" ) == TRUE ) {
07725 
07726         if ( strcmp ( word, "{" ) == 0 ) {
07727         }
07728         else if ( strcmp ( word, "}" ) == 0 ) {
07729           level = nlbrack - nrbrack;
07730         }
07731         else if ( leqi ( word, "MATRIX" ) == TRUE ) {
07732           icol = -1;
07733           irow = 0;
07734         }
07735         else {
07736 
07737           count = sscanf ( word, "%f%n", &rval, &width );
07738 
07739           if ( count > 0 ) {
07740 
07741             icol = icol + 1;
07742             if ( icol > 3 ) {
07743               icol = 0;
07744               irow = irow + 1;
07745               if ( irow > 3 ) {
07746                 irow = 0;
07747               }
07748             }
07749 
07750             transform_matrix[irow][icol] = rval;
07751           }
07752 
07753         }
07754       }
07755 /*
07756   NORMAL
07757   The field "VECTOR" may be followed by three numbers,
07758   (handled here),  or by a square bracket, and sets of three numbers.
07759 */
07760       else if ( leqi ( level_name[level], "NORMAL" ) == TRUE ) {
07761 /*
07762   (vertexproperty) NORMAL
07763 */
07764         if ( leqi ( level_name[level-1], "VERTEXPROPERTY" ) == TRUE ) {
07765 
07766           if ( strcmp ( word, "[" ) == 0 ) {
07767             ixyz = 0;
07768           }
07769           else if ( strcmp ( word, "]" ) == 0 ) {
07770             level = nlbrack - nrbrack;
07771           }
07772           else {
07773   
07774             count = sscanf ( word, "%f%n", &rval, &width );
07775 
07776             if ( count > 0 ) {
07777 
07778               if ( inormface < FACE_MAX ) {
07779                 face_normal[ixyz][inormface] = rval;
07780               }
07781 
07782               ixyz = ixyz + 1;
07783               if ( ixyz > 2 ) {
07784                 ixyz = 0;
07785                 inormface = inormface + 1;
07786               }
07787             }
07788           }
07789         }
07790 /*
07791   (anythingelse) NORMAL
07792 */
07793         else {
07794 
07795           if ( strcmp ( word, "{" ) == 0 ) {
07796             ixyz = 0;
07797           }
07798           else if ( strcmp ( word, "}" ) == 0 ) {
07799             level = nlbrack - nrbrack;
07800           }
07801           else if ( leqi ( word, "VECTOR" ) == TRUE ) {
07802           }
07803           else {
07804 
07805             count = sscanf ( word, "%f%n", &rval, &width );
07806 
07807             if ( count > 0 ) {
07808 
07809 /*  COMMENTED OUT
07810 
07811               if ( nfnorm < FACE_MAX ) {
07812                 normal[ixyz][nfnorm] = rval;
07813               }
07814 
07815 */
07816               ixyz = ixyz + 1;
07817               if ( ixyz > 2 ) {
07818                 ixyz = 0;
07819               }
07820             }
07821             else {
07822               bad_num = bad_num + 1;
07823               printf ( "Bad data %s\n", word );
07824             }
07825           }
07826         }
07827       }
07828 /*
07829   NORMALBINDING
07830   Read, but ignore
07831 */
07832       else if ( leqi ( level_name[level], "NORMALBINDING" ) == TRUE ) {
07833 
07834         if ( strcmp ( word, "{" ) == 0 ) {
07835         }
07836         else if ( strcmp ( word, "}" ) == 0 ) {
07837           level = nlbrack - nrbrack;
07838         }
07839         else if ( leqi ( word, "VALUE" ) == TRUE ) {
07840           count = sscanf ( next, "%s%n", normal_binding, &width );
07841           next = next + width;
07842         }
07843         else {
07844           count = sscanf ( word, "%f%n", &rval, &width );
07845 
07846           if ( count > 0 ) {
07847           }
07848           else {
07849             bad_num = bad_num + 1;
07850             printf ( "Bad data %s\n", word );
07851           }
07852         }
07853       }
07854 /*
07855   NORMALINDEX
07856 */
07857       else if ( leqi ( level_name[level], "NORMALINDEX" ) == TRUE ) {
07858 /*
07859   (indexedtrianglestripset) NORMALINDEX
07860 */
07861         if ( leqi ( level_name[level-1], "INDEXEDTRIANGLESTRIPSET" ) == TRUE ) {
07862           count = sscanf ( word, "%d%n", &jval, &width );
07863 
07864           if ( count > 0 ) {
07865           }
07866           else if ( strcmp ( word, "[" ) == 0 ) {
07867           }
07868           else if ( strcmp ( word, "]" ) == 0 ) {
07869           }
07870         }
07871 /*
07872   (anythingelse) NORMALINDEX
07873 */
07874         else {
07875 
07876           if ( strcmp ( word, "[" ) == 0 ) {
07877             ivert = 0;
07878           }
07879           else if ( strcmp ( word, "]" ) == 0 ) {
07880             level = nlbrack - nrbrack;
07881           }
07882           else {
07883 
07884             count = sscanf ( word, "%d%n", &jval, &width );
07885 
07886             if ( count > 0 ) {
07887               if ( jval == -1 ) {
07888                 ivert = 0;
07889                 iface_num = iface_num + 1;
07890               }
07891               else {
07892                 if ( iface_num < FACE_MAX ) {
07893                   for ( i = 0; i < 3; i++ ){
07894                     vertex_normal[i][ivert][iface_num] = normal_temp[i][jval];
07895                   }
07896                   ivert = ivert + 1;
07897                 }
07898               }
07899             }
07900             else {
07901               bad_num = bad_num + 1;
07902               printf ( "Bad data %s\n", word );
07903             }
07904           }
07905         }
07906       }
07907 /*
07908   (coordinate3) POINT
07909 */
07910       else if ( leqi ( level_name[level], "POINT" ) == TRUE ) {
07911 
07912         if ( leqi ( level_name[level-1], "COORDINATE3" ) == TRUE ) {
07913 
07914           if ( strcmp ( word, "[" ) == 0 ) {
07915             ixyz = 0;
07916             cor3_num_old = cor3_num;
07917           }
07918           else if ( strcmp ( word, "]" ) == 0 ) {
07919             level = nlbrack - nrbrack;
07920           }
07921           else {
07922 
07923             count = sscanf ( word, "%f%n", &rval, &width );
07924 
07925             if ( count > 0 ) {
07926 
07927               if ( cor3_num < COR3_MAX ) {
07928                 xvec[ixyz] = rval;
07929               }
07930 
07931               ixyz = ixyz + 1;
07932 
07933               if ( ixyz == 3 ) {
07934 
07935                 ixyz = 0;
07936  
07937                 tmat_mxp ( transform_matrix, xvec, xvec );
07938 
07939                 cor3[0][cor3_num] = xvec[0];
07940                 cor3[1][cor3_num] = xvec[1];
07941                 cor3[2][cor3_num] = xvec[2];
07942 
07943                 cor3_num = cor3_num + 1;
07944 
07945                 continue;
07946               }
07947             }
07948             else {
07949               bad_num = bad_num + 1;
07950               break;
07951             }
07952           }
07953         }
07954 /*
07955   (texturecoodinate2) POINT
07956 */
07957         else if ( leqi ( level_name[level-1], "TEXTURECOORDINATE2" ) == TRUE ) { 
07958 
07959           if ( strcmp ( word, "[" ) == 0 ) {
07960             iuv = 0;
07961             text_numure_temp = 0;
07962           }
07963           else if ( strcmp ( word, "]" ) == 0 ) {
07964             level = nlbrack - nrbrack;
07965           }
07966           else {
07967 
07968             count = sscanf ( word, "%f%n", &rval, &width );
07969 
07970             if ( count > 0 ) {
07971 
07972               texture_temp[iuv][text_numure_temp] = rval;
07973 
07974               iuv = iuv + 1;
07975               if ( iuv == 2 ) {
07976                 iuv = 0;
07977                 text_numure_temp = text_numure_temp + 1;
07978               }
07979             }
07980             else {
07981               printf ( "TextureCoordinate2 { Point [: Bad data\n" );
07982               bad_num = bad_num + 1;
07983               break;
07984             }
07985           }
07986         }
07987       }
07988 /*
07989   RGB
07990 */
07991       else if ( leqi ( level_name[level],"RGB" ) == TRUE ) {
07992 /*
07993   (basecolor) RGB
07994 */
07995         if ( leqi ( level_name[level-1], "BASECOLOR" ) == TRUE ) {
07996 
07997           if ( strcmp ( word, "[" ) == 0 ) {
07998             icolor = 0;
07999           }
08000           else if ( strcmp ( word, "]" ) == 0 ) {
08001             level = nlbrack - nrbrack;
08002           }
08003           else {
08004 
08005             count = sscanf ( word, "%f%n", &rval, &width );
08006   
08007             if ( count > 0 ) {
08008 
08009               rgbcolor[icolor][color_num] = rval;
08010               icolor = icolor + 1;
08011 
08012               if ( icolor == 3 ) {
08013                 icolor = 0;
08014                 color_num = color_num + 1;
08015               }
08016             }
08017             else {
08018               bad_num = bad_num + 1;
08019               printf ( "Bad data %s\n", word );
08020             }
08021           }
08022         }
08023 /*
08024   (anythingelse RGB)
08025 */
08026         else {
08027 
08028           printf ( "HALSBAND DES TODES!\n" );
08029 
08030           if ( strcmp ( word, "[" ) == 0 ) {
08031             icolor = 0;
08032             ivert = 0;
08033           }
08034           else if ( strcmp ( word, "]" ) == 0 ) {
08035             level = nlbrack - nrbrack;
08036           }
08037           else {
08038 
08039             count = sscanf ( word, "%f%n", &rval, &width );
08040   
08041             if ( count > 0 ) {
08042  
08043               if ( icface < FACE_MAX ) {
08044 
08045                 vertex_rgb[icolor][ivert][icface] = rval;
08046 
08047                 icolor = icolor + 1;
08048                 if ( icolor == 3 ) {
08049                   icolor = 0;
08050                   color_num = color_num + 1;
08051                   ivert = ivert + 1;
08052                   if ( ivert == face_order[icface] ) {
08053                     ivert = 0;
08054                     icface = icface + 1;
08055                   }
08056                 }
08057               }
08058             }
08059             else {
08060               bad_num = bad_num + 1;
08061               printf ( "Bad data %s\n", word );
08062             }
08063           }
08064         }
08065 
08066       }
08067 /*
08068   SEPARATOR
08069 */
08070       else if ( leqi ( level_name[level], "SEPARATOR" ) == TRUE ) {
08071 
08072         if ( strcmp ( word, "{" ) == 0 ) {
08073         }
08074         else if ( strcmp ( word, "}" ) == 0 ) {
08075           level = nlbrack - nrbrack;
08076         }
08077         else {
08078         }
08079       }
08080 /*
08081   SHAPEHINTS
08082   Read, but ignore.
08083 */
08084       else if ( leqi ( level_name[level], "SHAPEHINTS" ) == TRUE ) {
08085 
08086         if ( strcmp ( word, "{" ) == 0 ) {
08087         }
08088         else if ( strcmp ( word, "}" ) == 0 ) {
08089           level = nlbrack - nrbrack;
08090         }
08091         else if ( leqi ( word, "CREASEANGLE" ) == TRUE ) {
08092 
08093           count = sscanf ( next, "%f%n", &rval, &width );
08094           next = next + width;
08095 
08096           if ( count <= 0 ) {
08097             bad_num = bad_num + 1;
08098             printf ( "Bad data %s\n", word );
08099           }
08100         }
08101         else if ( leqi ( word, "FACETYPE" ) == TRUE ) {
08102           count = sscanf ( next, "%s%n", word, &width );
08103           next = next + width;
08104         }
08105         else if ( leqi ( word, "SHAPETYPE" ) == TRUE ) {
08106           count = sscanf ( next, "%s%n", word, &width );
08107           next = next + width;
08108         }
08109         else if ( leqi ( word, "VERTEXORDERING" ) == TRUE ) {
08110           count = sscanf ( next, "%s%n", word, &width );
08111           next = next + width;
08112         }
08113         else {
08114           bad_num = bad_num + 1;
08115           printf ( "Bad data %s\n", word );
08116         }
08117       }
08118 /*
08119   TEXTURE2
08120 */
08121       else if ( leqi ( level_name[level], "TEXTURE2" ) == TRUE ) {
08122 
08123         if ( strcmp ( word, "{" ) == 0 ) {
08124         }
08125         else if ( strcmp ( word, "}" ) == 0 ) {
08126           level = nlbrack - nrbrack;
08127           texture_num = texture_num + 1;
08128         }
08129         else if ( leqi ( word, "BLENDCOLOR" ) == TRUE ) {
08130         }
08131 /*
08132   NEED TO REMOVE QUOTES SURROUNDING TEXTURE NAME.
08133 */
08134         else if ( leqi ( word, "FILENAME" ) == TRUE ) {
08135 
08136           count = sscanf ( next, "%s%n", word, &width );
08137           next = next + width;
08138 
08139           strcpy ( texture_name[texture_num], word );
08140 
08141           i = 0;
08142           j = 0;
08143           do {
08144             c = texture_name[texture_num][i];
08145             i = i + 1;
08146             if ( c != '"' ) {
08147               texture_name[texture_num][j] = c;
08148               j = j + 1;
08149             }
08150           } while ( c != '\0' );
08151 
08152         }
08153         else if ( leqi ( word, "IMAGE" ) == TRUE ) {
08154         }
08155         else if ( leqi ( word, "MODEL" ) == TRUE ) {
08156           count = sscanf ( next, "%s%n", word, &width );
08157           next = next + width;
08158         }
08159         else if ( leqi ( word, "WRAPS" ) == TRUE ) {
08160           count = sscanf ( next, "%s%n", word, &width );
08161           next = next + width;
08162         }
08163         else if ( leqi ( word, "WRAPT" ) == TRUE ) {
08164           count = sscanf ( next, "%s%n", word, &width );
08165           next = next + width;
08166         }
08167         else {
08168         }
08169       }
08170 /*
08171   TEXTURECOORDINATE2
08172 */
08173       else if ( leqi ( level_name[level], "TEXTURECOORDINATE2" ) == TRUE ) {
08174 
08175         if ( strcmp ( word, "{" ) == 0 ) {
08176         }
08177         else if ( strcmp ( word, "}" ) == 0 ) {
08178           level = nlbrack - nrbrack;
08179         }
08180         else if ( leqi ( word, "POINT" ) == TRUE ) {
08181         }
08182         else {
08183           bad_num = bad_num + 1;
08184           printf ( "TEXTURECOORDINATE2: Bad data %s\n", word );
08185         }
08186       }
08187 /*
08188   TEXTURECOORDINATEBINDING
08189 */
08190       else if ( leqi ( level_name[level], "TEXTURECOORDINATEBINDING" ) == TRUE ) {
08191 
08192         if ( strcmp ( word, "{" ) == 0 ) {
08193         }
08194         else if ( strcmp ( word, "}" ) == 0 ) {
08195           level = nlbrack - nrbrack;
08196         }
08197         else if ( leqi ( word, "VALUE" ) == TRUE ) {
08198           count = sscanf ( next, "%s%n", texture_binding, &width );
08199           next = next + width;
08200         }
08201         else {
08202           bad_num = bad_num + 1;
08203           printf ( "Bad data %s\n", word );
08204         }
08205       }
08206 /*
08207   TEXTURECOORDINDEX
08208 */
08209       else if ( leqi ( level_name[level], "TEXTURECOORDINDEX" ) == TRUE ) {
08210 
08211         if ( strcmp ( word, "[" ) == 0 ) {
08212           ivert = 0;
08213           iface_num = 0;
08214         }
08215         else if ( strcmp ( word, "]" ) == 0 ) {
08216           level = nlbrack - nrbrack;
08217         }
08218         else {
08219 
08220           count = sscanf ( word, "%d%n", &jval, &width );
08221 
08222           if ( count > 0 ) {
08223 
08224             if ( jval == - 1 ) {
08225               ivert = 0;
08226             }
08227             else {
08228 
08229               if ( iface_num < FACE_MAX ) {
08230                 vertex_tex_uv[0][ivert][iface_num] = texture_temp[0][jval];
08231                 vertex_tex_uv[1][ivert][iface_num] = texture_temp[1][jval];
08232               }
08233   
08234               ivert = ivert + 1;
08235 
08236               if ( ivert == face_order[iface_num] ) {
08237                 ivert = 0;
08238                 iface_num = iface_num + 1;
08239               }
08240             }
08241 
08242           }
08243           else {
08244             bad_num = bad_num + 1;
08245             printf ( "Bad data %s\n", word );
08246           }
08247 
08248         }
08249       }
08250 /*
08251   UKNOTVECTOR
08252 */
08253       else if ( leqi ( level_name[level], "UKNOTVECTOR" ) == TRUE ) {
08254 
08255         if ( strcmp ( word, "[" ) == 0 ) {
08256           continue;
08257         }
08258         else if ( strcmp ( word, "]" ) == 0 ) {
08259           level = nlbrack - nrbrack;
08260           continue;
08261         }
08262         else {
08263           count = sscanf ( word, "%d%n", &jval, &width );
08264         }
08265       }
08266 /*
08267   VECTOR
08268 */
08269       else if ( leqi ( level_name[level], "VECTOR" ) == TRUE ) {
08270         if ( strcmp ( word, "[" ) == 0 ) {
08271         }
08272         else if ( strcmp ( word, "]" ) == 0 ) {
08273           level = nlbrack - nrbrack;
08274         }
08275 /*
08276   (normal) VECTOR
08277 */
08278         else if ( leqi ( level_name[level-1], "NORMAL" ) == TRUE ) {
08279 
08280           count = sscanf ( word, "%f%n", &rval, &width );
08281 
08282           if ( count > 0 ) {
08283 
08284             if ( normal_num_temp < ORDER_MAX * FACE_MAX ) {
08285               normal_temp[ixyz][normal_num_temp] = rval;
08286               ixyz = ixyz + 1;
08287               if ( ixyz == 3 ) {
08288                 ixyz = 0;
08289                 normal_num_temp = normal_num_temp + 1;
08290               }
08291             }
08292           }
08293           else {
08294             bad_num = bad_num + 1;
08295             printf ( "NORMAL VECTOR: bad data %s\n", word );
08296           }
08297         }
08298       }
08299 /*
08300   (vertexproperty) VERTEX
08301 */
08302       else if ( leqi ( level_name[level], "VERTEX" ) == TRUE ) {
08303 
08304         if ( leqi ( level_name[level-1], "VERTEXPROPERTY" ) == TRUE ) {
08305 
08306           if ( strcmp ( word, "[" ) == 0 ) {
08307             ixyz = 0;
08308             cor3_num_old = cor3_num;
08309           }
08310           else if ( strcmp ( word, "]" ) == 0 ) {
08311             level = nlbrack - nrbrack;
08312           }
08313           else {
08314             count = sscanf ( word, "%f%n", &rval, &width );
08315 
08316             if ( count > 0 ) {
08317  
08318               if ( cor3_num < COR3_MAX ) {
08319                 cor3[ixyz][cor3_num] = rval;
08320               }
08321               ixyz = ixyz + 1;
08322               if ( ixyz == 3 ) {
08323                 ixyz = 0;
08324                 cor3_num = cor3_num + 1;
08325               }
08326 
08327             }
08328             else {
08329               bad_num = bad_num + 1;
08330               printf ( "Bad data %s\n", word );
08331             }
08332           }
08333         }
08334       }
08335 /*
08336   (indexedtrianglestripset) VERTEXPROPERTY
08337 */
08338       else if ( leqi ( level_name[level], "VERTEXPROPERTY" ) == TRUE ) {
08339 
08340         if ( strcmp ( word, "{" ) == 0 ) {
08341         }
08342         else if ( strcmp ( word, "}" ) == 0 ) {
08343           level = nlbrack - nrbrack;
08344         }
08345         else if ( leqi ( word, "VERTEX" ) == TRUE ) {
08346         }
08347         else if ( leqi ( word, "NORMAL" ) == TRUE ) {
08348           ixyz = 0;
08349         }
08350         else if ( leqi ( word, "MATERIALBINDING" ) == TRUE ) {
08351           count = sscanf ( next, "%s%n", word, &width );
08352           next = next + width;
08353         }
08354         else if ( leqi ( word, "NORMALBINDING" ) == TRUE ) {
08355           count = sscanf ( next, "%s%n", word, &width );
08356           next = next + width;
08357         }
08358         else {
08359           bad_num = bad_num + 1;
08360           printf ( "Bad data %s\n", word );
08361         }
08362       }
08363 /*
08364   VKNOTVECTOR
08365 */
08366       else if ( leqi ( level_name[level], "VKNOTVECTOR" ) == TRUE ) {
08367 
08368         if ( strcmp ( word, "[" ) == 0 ) {
08369           continue;
08370         }
08371         else if ( strcmp ( word, "]" ) == 0 ) {
08372           level = nlbrack - nrbrack;
08373           continue;
08374         }
08375         else {
08376           count = sscanf ( word, "%d%n", &jval, &width );
08377         }
08378       }
08379 /*
08380   Any other word:
08381 */
08382       else {
08383       }
08384     }
08385   }
08386 /*
08387   Reset the transformation matrix to the identity,
08388   because, presumably, we've applied it by now.
08389 */
08390   tmat_init ( transform_matrix );
08391 
08392   return SUCCESS;
08393 }
08394 /******************************************************************************/
08395 
08396 int iv_write ( FILE *fileout )
08397 
08398 /******************************************************************************/
08399 
08400 /*
08401   Purpose:
08402    
08403     IV_WRITE writes graphics information to an Inventor file.
08404 
08405   Modified:
08406 
08407     29 June 1999
08408 
08409   Author:
08410  
08411     John Burkardt
08412 */
08413 {
08414   int icor3;
08415   int iface;
08416   int itemp;
08417   int ivert;
08418   int j;
08419   int length;
08420   int text_num;
08421 
08422   text_num = 0;
08423 
08424   fprintf ( fileout, "#Inventor V2.0 ascii\n" );
08425   fprintf ( fileout, "\n" );
08426   fprintf ( fileout, "Separator {\n" );
08427   fprintf ( fileout, "  Info {\n" );
08428   fprintf ( fileout, "    string \"%s generated by IVCON.\"\n", fileout_name );
08429   fprintf ( fileout, "    string \"Original data in file %s.\"\n", filein_name );
08430   fprintf ( fileout, "  }\n" );
08431   fprintf ( fileout, "  Separator {\n" );
08432   text_num = text_num + 8;
08433 /*
08434   LightModel:
08435 
08436     BASE_COLOR ignores light sources, and uses only diffuse color
08437       and transparency.  Even without normal vector information,
08438       the object will show up.  However, you won't get shadow
08439       and lighting effects.
08440 
08441     PHONG uses the Phong lighting model, accounting for light sources
08442       and surface orientation.  This is the default.  I believe
08443       you need accurate normal vector information in order for this
08444       option to produce nice pictures.
08445 
08446     DEPTH ignores light sources, and calculates lighting based on
08447       the location of the object within the near and far planes
08448       of the current camera's view volume.
08449 */
08450   fprintf ( fileout, "    LightModel {\n" );
08451   fprintf ( fileout, "      model PHONG\n" );
08452   fprintf ( fileout, "    }\n" );
08453   text_num = text_num + 3;
08454 /*
08455   Transformation matrix.
08456 */
08457   fprintf ( fileout, "    MatrixTransform { matrix\n" );
08458   fprintf ( fileout, "      %f %f %f %f\n", transform_matrix[0][0],
08459     transform_matrix[0][1], transform_matrix[0][2], transform_matrix[0][3] );
08460   fprintf ( fileout, "      %f %f %f %f\n", transform_matrix[1][0],
08461     transform_matrix[1][1], transform_matrix[1][2], transform_matrix[1][3] );
08462   fprintf ( fileout, "      %f %f %f %f\n", transform_matrix[2][0],
08463     transform_matrix[2][1], transform_matrix[2][2], transform_matrix[2][3] );
08464   fprintf ( fileout, "      %f %f %f %f\n", transform_matrix[3][0],
08465     transform_matrix[3][1], transform_matrix[3][2], transform_matrix[3][3] );
08466   fprintf ( fileout, "    }\n" );
08467   text_num = text_num + 6;
08468 /*
08469   Material.
08470 */
08471   fprintf ( fileout, "    Material {\n" );
08472   fprintf ( fileout, "      ambientColor  0.2 0.2 0.2\n" );
08473   fprintf ( fileout, "      diffuseColor  0.8 0.8 0.8\n" );
08474   fprintf ( fileout, "      emissiveColor 0.0 0.0 0.0\n" );
08475   fprintf ( fileout, "      specularColor 0.0 0.0 0.0\n" );
08476   fprintf ( fileout, "      shininess     0.2\n" );
08477   fprintf ( fileout, "      transparency  0.0\n" );
08478   fprintf ( fileout, "    }\n" );
08479   text_num = text_num + 8;
08480 /*
08481   MaterialBinding
08482 */
08483   fprintf ( fileout, "    MaterialBinding {\n" );
08484   fprintf ( fileout, "      value PER_VERTEX_INDEXED\n" );
08485   fprintf ( fileout, "    }\n" );
08486   text_num = text_num + 3;
08487 /*
08488   NormalBinding
08489 
08490     PER_VERTEX promises that we will write a list of normal vectors
08491     in a particular order, namely, the normal vectors for the vertices
08492     of the first face, then the second face, and so on.
08493 
08494     PER_VERTEX_INDEXED promises that we will write a list of normal vectors,
08495     and then, as part of the IndexedFaceSet, we will give a list of
08496     indices referencing this normal vector list.
08497 */
08498   fprintf ( fileout, "    NormalBinding {\n" );
08499   fprintf ( fileout, "      value PER_VERTEX_INDEXED\n" );
08500   fprintf ( fileout, "    }\n" );
08501   text_num = text_num + 3;
08502 /*
08503   Texture2.
08504 
08505   FLAW: We can only handle on texture right now.
08506 */
08507   if ( texture_num > 0 ) {
08508     fprintf ( fileout, "    Texture2 {\n" );
08509     fprintf ( fileout, "      filename \"%s\"\n", texture_name[0] );
08510     fprintf ( fileout, "      wrapS       REPEAT\n" );
08511     fprintf ( fileout, "      wrapT       REPEAT\n" );
08512     fprintf ( fileout, "      model       MODULATE\n" );
08513     fprintf ( fileout, "      blendColor  0.0 0.0 0.0\n" );
08514     fprintf ( fileout, "    }\n" );
08515     text_num = text_num + 7;
08516   }
08517 /*
08518   TextureCoordinateBinding
08519 */
08520   fprintf ( fileout, "    TextureCoordinateBinding {\n" );
08521   fprintf ( fileout, "      value PER_VERTEX_INDEXED\n" );
08522   fprintf ( fileout, "    }\n" );
08523   text_num = text_num + 3;
08524 /*
08525   ShapeHints
08526 */
08527   fprintf ( fileout, "    ShapeHints {\n" );
08528   fprintf ( fileout, "      vertexOrdering COUNTERCLOCKWISE\n" );
08529   fprintf ( fileout, "      shapeType UNKNOWN_SHAPE_TYPE\n" );
08530   fprintf ( fileout, "      faceType CONVEX\n" );
08531   fprintf ( fileout, "      creaseAngle 6.28319\n" );
08532   fprintf ( fileout, "    }\n" );
08533   text_num = text_num + 6;
08534 /*
08535   Point coordinates.
08536 */
08537   fprintf ( fileout, "    Coordinate3 {\n" );
08538   fprintf ( fileout, "      point [\n" );
08539   text_num = text_num + 2;
08540 
08541   for ( j = 0; j < cor3_num; j++ ) {
08542     fprintf ( fileout, "        %f %f %f,\n", cor3[0][j], cor3[1][j], cor3[2][j] );
08543     text_num = text_num + 1;
08544   }
08545   fprintf ( fileout, "      ]\n" );
08546   fprintf ( fileout, "    }\n" );
08547   text_num = text_num + 2;
08548 /*
08549   Texture coordinates.
08550 */
08551   fprintf ( fileout, "    TextureCoordinate2 {\n" );
08552   fprintf ( fileout, "      point [\n" );
08553   text_num = text_num + 2;
08554 
08555   for ( iface = 0; iface < face_num; iface++ ) {
08556     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
08557       fprintf ( fileout, "        %f %f,\n", vertex_tex_uv[0][ivert][iface], 
08558         vertex_tex_uv[1][ivert][iface] );
08559       text_num = text_num + 1;
08560     }
08561   }
08562   fprintf ( fileout, "      ]\n" );
08563   fprintf ( fileout, "    }\n" );
08564   text_num = text_num + 2;
08565 /*
08566   BaseColor.
08567 */
08568   if ( color_num > 0 ) {
08569 
08570     fprintf ( fileout, "    BaseColor {\n" );
08571     fprintf ( fileout, "      rgb [\n" );
08572     text_num = text_num + 2;
08573 
08574     for ( j = 0; j < color_num; j++ ) {
08575       fprintf ( fileout, "        %f %f %f,\n", rgbcolor[0][j], rgbcolor[1][j], 
08576         rgbcolor[2][j] );
08577       text_num = text_num + 1;
08578     }
08579 
08580     fprintf ( fileout, "      ]\n" );
08581     fprintf ( fileout, "    }\n" );
08582     text_num = text_num + 2;
08583   }
08584 /*
08585   Normal vectors.
08586     Use the normal vectors associated with nodes.
08587 */
08588   if ( face_num > 0 ) {
08589 
08590     fprintf ( fileout, "    Normal { \n" );
08591     fprintf ( fileout, "      vector [\n" );
08592     text_num = text_num + 2;
08593 
08594     for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
08595       fprintf ( fileout, "        %f %f %f,\n", 
08596         cor3_normal[0][icor3], 
08597         cor3_normal[1][icor3], 
08598         cor3_normal[2][icor3] );
08599       text_num = text_num + 1;
08600     }
08601 
08602     fprintf ( fileout, "      ]\n" );
08603     fprintf ( fileout, "    }\n" );
08604     text_num = text_num + 2;
08605   }
08606 /*
08607   IndexedLineSet
08608 */
08609   if ( line_num > 0 ) {
08610 
08611     fprintf ( fileout, "    IndexedLineSet {\n" );
08612 /*
08613   IndexedLineSet coordIndex
08614 */
08615     fprintf ( fileout, "      coordIndex [\n" );
08616     text_num = text_num + 2;
08617 
08618     length = 0;
08619 
08620     for ( j = 0; j < line_num; j++ ) {
08621 
08622       if ( length == 0 ) {
08623         fprintf ( fileout, "       " );
08624       }
08625 
08626       fprintf ( fileout, " %d,", line_dex[j] );
08627       length = length + 1;
08628 
08629       if ( line_dex[j] == -1 || length >= 10 || j == line_num-1 ) {
08630         fprintf ( fileout, "\n" );
08631         text_num = text_num + 1;
08632         length = 0;
08633       }
08634     }
08635 
08636     fprintf ( fileout, "      ]\n" );
08637     text_num = text_num + 1;
08638 /*
08639   IndexedLineSet materialIndex.
08640 */
08641     fprintf ( fileout, "      materialIndex [\n" );
08642     text_num = text_num + 1;
08643 
08644     length = 0;
08645 
08646     for ( j = 0; j < line_num; j++ ) {
08647 
08648       if ( length == 0 ) {
08649         fprintf ( fileout, "       " );
08650       }
08651 
08652       fprintf ( fileout, " %d,", line_material[j] );
08653       length = length + 1;
08654 
08655       if ( line_material[j] == -1 || length >= 10 || j == line_num-1 ) {
08656         fprintf ( fileout, "\n" );
08657         text_num = text_num + 1;
08658         length = 0;
08659       }
08660     }
08661 
08662     fprintf ( fileout, "      ]\n" );
08663     fprintf ( fileout, "    }\n" );
08664     text_num = text_num + 2;
08665   }
08666 /*
08667   IndexedFaceSet.
08668 */
08669   if ( face_num > 0 ) {
08670 
08671     fprintf ( fileout, "    IndexedFaceSet {\n" );
08672     fprintf ( fileout, "      coordIndex [\n" );
08673     text_num = text_num + 2;
08674 
08675     for ( iface = 0; iface < face_num; iface++ ) {
08676 
08677       fprintf ( fileout, "       " );
08678 
08679       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
08680         fprintf ( fileout, " %d,", face[ivert][iface] );
08681       }
08682       fprintf ( fileout, " -1,\n" );
08683       text_num = text_num + 1;
08684     }
08685 
08686     fprintf ( fileout, "      ]\n" );
08687     text_num = text_num + 1;
08688 /*
08689   IndexedFaceSet normalIndex
08690 */
08691     fprintf ( fileout, "      normalIndex [\n" );
08692     text_num = text_num + 1;
08693 
08694     for ( iface = 0; iface < face_num; iface++ ) {
08695 
08696       fprintf ( fileout, "       " );
08697 
08698       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
08699         fprintf ( fileout, " %d,", face[ivert][iface] );
08700       }
08701       fprintf ( fileout, " -1,\n" );
08702       text_num = text_num + 1;
08703     }
08704     fprintf ( fileout, "      ]\n" );
08705     text_num = text_num + 1;
08706 /*
08707   IndexedFaceSet materialIndex
08708 */
08709     fprintf ( fileout, "      materialIndex [\n" );
08710     text_num = text_num + 1;
08711 
08712     for ( iface = 0; iface < face_num; iface++ ) {
08713 
08714       fprintf ( fileout, "       " );
08715 
08716       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
08717         fprintf ( fileout, " %d,", vertex_material[ivert][iface] );
08718       }
08719       fprintf ( fileout, " -1,\n" );
08720       text_num = text_num + 1;
08721     }
08722 
08723     fprintf ( fileout, "      ]\n" );
08724     text_num = text_num + 1;
08725 /*
08726   IndexedFaceSet textureCoordIndex
08727 */
08728     fprintf ( fileout, "      textureCoordIndex [\n" );
08729     text_num = text_num + 1;
08730 
08731     itemp = 0;
08732 
08733     for ( iface = 0; iface < face_num; iface++ ) {
08734 
08735       fprintf ( fileout, "       " );
08736 
08737       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
08738         fprintf ( fileout, " %d,", itemp );
08739         itemp = itemp + 1;
08740       }
08741       fprintf ( fileout, " -1,\n" );
08742       text_num = text_num + 1;
08743     }
08744 
08745     fprintf ( fileout, "      ]\n" );
08746 
08747     fprintf ( fileout, "    }\n" );
08748     text_num = text_num + 2;
08749   }
08750 /*
08751   Close up the Separator nodes.
08752 */
08753   fprintf ( fileout, "  }\n" );
08754   fprintf ( fileout, "}\n" );
08755   text_num = text_num + 2;
08756 /*
08757   Report.
08758 */
08759   printf ( "\n" );
08760   printf ( "IV_WRITE - Wrote %d text lines;\n", text_num );
08761 
08762   return SUCCESS;
08763 }
08764 /******************************************************************************/
08765 
08766 int ivec_max ( int n, int *a )
08767 
08768 /******************************************************************************/
08769 
08770 /*
08771   Purpose:
08772 
08773     IVEC_MAX returns the maximum element in an integer array.
08774 
08775   Modified:
08776 
08777     09 October 1998
08778 
08779   Author:
08780 
08781     John Burkardt
08782 */
08783 {
08784   int  i;
08785   int *ia;
08786   int  imax;
08787 
08788   if ( n <= 0 ) {
08789     imax = 0;
08790   }
08791   else {
08792     ia = a;
08793     imax = *ia;
08794     for ( i = 1; i < n; i++ ) {
08795       ia = ia + 1;
08796       if ( imax < *ia ) {
08797         imax = *ia;
08798       }
08799     }
08800   }
08801   return imax;
08802 }
08803 /******************************************************************************/
08804 
08805 int leqi ( char* string1, char* string2 )
08806 
08807 /******************************************************************************/
08808 
08809 /*
08810   Purpose:
08811 
08812     LEQI compares two strings for equality, disregarding case.
08813 
08814   Modified:
08815 
08816     15 September 1998
08817 
08818   Author:
08819  
08820     John Burkardt
08821 */
08822 {
08823   int i;
08824   int nchar;
08825   int nchar1;
08826   int nchar2;
08827 
08828   nchar1 = strlen ( string1 );
08829   nchar2 = strlen ( string2 );
08830 
08831   if ( nchar1 < nchar2 ) {
08832     nchar = nchar1;
08833   }
08834   else {
08835     nchar = nchar2;
08836   }
08837 /*
08838   The strings are not equal if they differ over their common length.
08839 */
08840   for ( i = 0; i < nchar; i++ ) {
08841 
08842     if ( toupper ( string1[i] ) != toupper ( string2[i] ) ) {
08843       return FALSE;
08844     }
08845   }
08846 /*
08847   The strings are not equal if the longer one includes nonblanks
08848   in the tail.
08849 */
08850   if ( nchar1 > nchar ) {
08851     for ( i = nchar; i < nchar1; i++ ) {
08852       if ( string1[i] != ' ' ) {
08853         return FALSE;
08854       }
08855     } 
08856   }
08857   else if ( nchar2 > nchar ) {
08858     for ( i = nchar; i < nchar2; i++ ) {
08859       if ( string2[i] != ' ' ) {
08860         return FALSE;
08861       }
08862     } 
08863   }
08864   return TRUE;
08865 }
08866 /******************************************************************************/
08867 
08868 long int long_int_read ( FILE *filein )
08869 
08870 /******************************************************************************/
08871 
08872 /*
08873   Purpose:
08874 
08875     LONG_INT_READ reads a long int from a binary file.
08876 
08877   Modified:
08878  
08879     24 May 1999
08880 
08881   Author:
08882 
08883     John Burkardt
08884 */
08885 {
08886   union {
08887     long int yint;
08888     char ychar[4];
08889   } y;
08890 
08891   if ( byte_swap == TRUE ) {
08892     y.ychar[3] = fgetc ( filein );
08893     y.ychar[2] = fgetc ( filein );
08894     y.ychar[1] = fgetc ( filein );
08895     y.ychar[0] = fgetc ( filein );
08896   }
08897   else {
08898     y.ychar[0] = fgetc ( filein );
08899     y.ychar[1] = fgetc ( filein );
08900     y.ychar[2] = fgetc ( filein );
08901     y.ychar[3] = fgetc ( filein );
08902   }
08903 
08904   return y.yint;
08905 }
08906 /******************************************************************************/
08907 
08908 int long_int_write ( FILE *fileout, long int int_val )
08909 
08910 /******************************************************************************/
08911 
08912 /*
08913   Purpose:
08914 
08915     LONG_INT_WRITE writes a long int to a binary file.
08916 
08917   Modified:
08918  
08919     14 October 1998
08920 
08921   Author:
08922 
08923     John Burkardt
08924 */
08925 {
08926   union {
08927     long int yint;
08928     char ychar[4];
08929   } y;
08930 
08931   y.yint = int_val;
08932 
08933   if ( byte_swap == TRUE ) {
08934     fputc ( y.ychar[3], fileout );
08935     fputc ( y.ychar[2], fileout );
08936     fputc ( y.ychar[1], fileout );
08937     fputc ( y.ychar[0], fileout );
08938   }
08939   else {
08940     fputc ( y.ychar[0], fileout );
08941     fputc ( y.ychar[1], fileout );
08942     fputc ( y.ychar[2], fileout );
08943     fputc ( y.ychar[3], fileout );
08944   }
08945 
08946   return 4;
08947 }
08948 /******************************************************************************/
08949 
08950 void news ( void )
08951 
08952 /******************************************************************************/
08953 
08954 /*
08955   Purpose:
08956 
08957     NEWS reports the program change history.
08958 
08959   Modified:
08960  
08961     26 September 1999
08962 
08963   Author:
08964  
08965     John Burkardt
08966 */
08967 {
08968   printf ( "\n" );
08969   printf ( "Recent changes:\n" );
08970   printf ( "\n" );
08971   printf ( "  04 July 2000\n" );
08972   printf ( "    Added preliminary XGL_WRITE.\n" );
08973   printf ( "  26 September 1999\n" );
08974   printf ( "    After ASE_READ, call NODE_TO_VERTEX_MAT and VERTEX_TO_FACE_MATERIAL.\n" );
08975   printf ( "  27 July 1999\n" );
08976   printf ( "    Corrected TMAT_ROT_VECTOR.\n" );
08977   printf ( "  17 July 1999\n" );
08978   printf ( "    Added null edge and face deletion.\n" );
08979   printf ( "    Corrected a string problem in SMF_READ.\n" );
08980   printf ( "  03 July 1999\n" );
08981   printf ( "    Fixed a problem with BINDING variables in SMF_READ.\n" );
08982   printf ( "  02 July 1999\n" );
08983   printf ( "    Added limited texture support in 3DS/IV.\n" );
08984   printf ( "  26 June 1999\n" );
08985   printf ( "    BYU_READ added.\n" );
08986   printf ( "  25 June 1999\n" );
08987   printf ( "    BYU_WRITE added.\n" );
08988   printf ( "  22 June 1999\n" );
08989   printf ( "    TRIB_READ added.\n" );
08990   printf ( "  16 June 1999\n" );
08991   printf ( "    TRIB_WRITE Greg Hood binary triangle output routine added.\n" );
08992   printf ( "  10 June 1999\n" );
08993   printf ( "    TRIA_WRITE Greg Hood ASCII triangle output routine added.\n" );
08994   printf ( "  09 June 1999\n" );
08995   printf ( "    TEC_WRITE TECPLOT output routine added.\n" );
08996   printf ( "    IV_READ and IV_WRITE use TRANSFORM_MATRIX now.\n" );
08997   printf ( "  26 May 1999\n" );
08998   printf ( "    LINE_PRUNE option added for VLA_WRITE.\n" );
08999   printf ( "  24 May 1999\n" );
09000   printf ( "    Added << command to append new graphics data to old.\n" );
09001   printf ( "    Stuck in first draft STLB_READ/STLB_WRITE routines.\n" );
09002   printf ( "    STLA_WRITE and STLB_WRITE automatically decompose \n" );
09003   printf ( "      non-triangular faces before writing.\n" );
09004   printf ( "  23 May 1999\n" );
09005   printf ( "    Stuck in first draft WRL_WRITE routine.\n" );
09006   printf ( "  22 May 1999\n" );
09007   printf ( "    Faces converted to lines before calling VLA_WRITE.\n" );
09008   printf ( "    Added UCD_WRITE.\n" );
09009   printf ( "    Added MATERIAL/PATCH/TAGGEDPOINTS fields in HRC_READ.\n" );
09010   printf ( "  17 May 1999\n" );
09011   printf ( "    Updated SMF_WRITE, SMF_READ to match code in IVREAD.\n" );
09012   printf ( "    Added transformation matrix routines.\n" );
09013   printf ( "  16 May 1999\n" );
09014   printf ( "    Zik Saleeba improved DXF support to handle polygons.\n" );
09015   printf ( "  15 April 1999\n" );
09016   printf ( "    Zik Saleeba added Golgotha GMOD file format support.\n" );
09017   printf ( "  03 December 1998\n" );
09018   printf ( "    Set up simple hooks in TDS_READ_MATERIAL_SECTION.\n" );
09019   printf ( "  02 December 1998\n" );
09020   printf ( "    Set up simple hooks for texture map names.\n" );
09021   printf ( "  19 November 1998\n" );
09022   printf ( "    IV_WRITE uses PER_VERTEX normal binding.\n" );
09023   printf ( "  18 November 1998\n" );
09024   printf ( "    Added node normals.\n" );
09025   printf ( "    Finally added the -RN option.\n" );
09026   printf ( "  17 November 1998\n" );
09027   printf ( "    Added face node ordering reversal option.\n" );
09028   printf ( "  20 October 1998\n" );
09029   printf ( "    Added DATA_REPORT.\n" );
09030   printf ( "  19 October 1998\n" );
09031   printf ( "    SMF_READ and SMF_WRITE added.\n" );
09032   printf ( "  16 October 1998\n" );
09033   printf ( "    Fixing a bug in IV_READ that chokes on ]} and other\n" );
09034   printf ( "    cases where brackets aren't properly spaced.\n" );
09035   printf ( "  11 October 1998\n" );
09036   printf ( "    Added face subset selection option S.\n" );
09037   printf ( "  09 October 1998\n" );
09038   printf ( "    Reworking normal vector treatments.\n" );
09039   printf ( "    Synchronizing IVREAD and IVCON.\n" );
09040   printf ( "    POV_WRITE added.\n" );
09041   printf ( "  02 October 1998\n" );
09042   printf ( "    IVCON reproduces BOX.3DS and CONE.3DS exactly.\n" );
09043   printf ( "  30 September 1998\n" );
09044   printf ( "    IVCON compiled on the PC.\n" );
09045   printf ( "    Interactive BYTE_SWAP option added for binary files.\n" );
09046   printf ( "  25 September 1998\n" );
09047   printf ( "    OBJECT_NAME made available to store object name.\n" );
09048   printf ( "  23 September 1998\n" );
09049   printf ( "    3DS binary files can be written.\n" );
09050   printf ( "  15 September 1998\n" );
09051   printf ( "    3DS binary files can be read.\n" );
09052   printf ( "  01 September 1998\n" );
09053   printf ( "    COR3_RANGE, FACE_NORMAL_AVE added.\n" );
09054   printf ( "    Major modifications to normal vectors.\n" );
09055   printf ( "  24 August 1998\n" );
09056   printf ( "    HRC_READ added.\n" );
09057   printf ( "  21 August 1998\n" );
09058   printf ( "    TXT_WRITE improved.\n" );
09059   printf ( "  20 August 1998\n" );
09060   printf ( "    HRC_WRITE can output lines as linear splines.\n" );
09061   printf ( "  19 August 1998\n" );
09062   printf ( "    Automatic normal computation for OBJ files.\n" );
09063   printf ( "    Added normal vector computation.\n" );
09064   printf ( "    HRC_WRITE is working.\n" );
09065   printf ( "  18 August 1998\n" );
09066   printf ( "    IV_READ/IV_WRITE handle BASECOLOR RGB properly now.\n" );
09067   printf ( "    Improved treatment of face materials and normals.\n" );
09068   printf ( "  17 August 1998\n" );
09069   printf ( "    ORDER_MAX increased to 35.\n" );
09070   printf ( "    FACE_PRINT routine added.\n" );
09071   printf ( "    INIT_DATA routine added.\n" );
09072   printf ( "  14 August 1998\n" );
09073   printf ( "    IV_READ is working.\n" );
09074   printf ( "  13 August 1998\n" );
09075   printf ( "    ASE_WRITE is working.\n" );
09076   printf ( "    IV_WRITE is working.\n" );
09077   printf ( "  12 August 1998\n" );
09078   printf ( "    ASE_READ is working.\n" );
09079   printf ( "  10 August 1998\n" );
09080   printf ( "    DXF_WRITE is working.\n" );
09081   printf ( "    DXF_READ is working.\n" );
09082   printf ( "  27 July 1998\n" );
09083   printf ( "    Interactive mode is working.\n" );
09084   printf ( "    OBJ_READ is working.\n" );
09085   printf ( "  25 July 1998\n" );
09086   printf ( "    OBJ_WRITE is working.\n" );
09087   printf ( "  24 July 1998\n" );
09088   printf ( "    DATA_CHECK checks the input data.\n" );
09089   printf ( "    VLA_READ is working.\n" );
09090   printf ( "    VLA_WRITE is working.\n" );
09091   printf ( "  23 July 1998\n" );
09092   printf ( "    STL_WRITE is working.\n" );
09093   printf ( "  22 July 1998\n" );
09094   printf ( "    STL_READ is working.\n" );
09095   printf ( "    TXT_WRITE is working.\n" );
09096 }
09097 /**********************************************************************/
09098 
09099 void node_to_vertex_material ( void )
09100 
09101 /**********************************************************************/
09102 
09103 /*
09104   Purpose:
09105 
09106     NODE_TO_VERTEX_MAT extends node material definitions to vertices.
09107 
09108   Discussion:
09109 
09110     A NODE is a point in space.
09111     A VERTEX is a node as used in a particular face.
09112     One node may be used as a vertex in several faces, or none.
09113 
09114   Modified:
09115 
09116     22 May 1999
09117 
09118   Author:
09119 
09120     John Burkardt
09121 */
09122 {
09123   int iface;
09124   int ivert;
09125   int node;
09126 
09127   for ( iface = 0; iface < face_num; iface++ ) {
09128     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
09129       node = face[ivert][iface];
09130       vertex_material[ivert][iface] = cor3_material[node];
09131     }
09132   }
09133 
09134   return;
09135 }
09136 /******************************************************************************/
09137 
09138 int obj_read ( FILE *filein )
09139 
09140 /******************************************************************************/
09141 
09142 /*
09143   Purpose:
09144    
09145     OBJ_READ reads a Wavefront OBJ file.
09146 
09147   Example:
09148 
09149     #  magnolia.obj
09150 
09151     mtllib ./vp.mtl
09152 
09153     g
09154     v -3.269770 -39.572201 0.876128
09155     v -3.263720 -39.507999 2.160890
09156     ...
09157     v 0.000000 -9.988540 0.000000
09158     g stem
09159     s 1
09160     usemtl brownskn
09161     f 8 9 11 10
09162     f 12 13 15 14
09163     ...
09164     f 788 806 774
09165 
09166   Modified:
09167 
09168     20 October 1998
09169 
09170   Author:
09171  
09172     John Burkardt
09173 */
09174 {
09175   int   count;
09176   int   i;
09177   int   ivert;
09178   char *next;
09179   char *next2;
09180   char *next3;
09181   int   node;
09182   int   vertex_normal_num;
09183   float r1;
09184   float r2;
09185   float r3;
09186   char  token[LINE_MAX_LEN];
09187   char  token2[LINE_MAX_LEN];
09188   int   width;
09189 /* 
09190   Initialize. 
09191 */
09192   vertex_normal_num = 0;
09193 /* 
09194   Read the next line of the file into INPUT. 
09195 */
09196   while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL ) {
09197 
09198     text_num = text_num + 1;
09199 /* 
09200   Advance to the first nonspace character in INPUT. 
09201 */
09202     for ( next = input; *next != '\0' && isspace(*next); next++ ) {
09203     }
09204 /* 
09205   Skip blank lines and comments. 
09206 */
09207 
09208     if ( *next == '\0' ) {
09209       continue;
09210     }
09211 
09212     if ( *next == '#' || *next == '$' ) {
09213       comment_num = comment_num + 1;
09214       continue;
09215     }
09216 /* 
09217   Extract the first word in this line. 
09218 */
09219     sscanf ( next, "%s%n", token, &width );
09220 /* 
09221   Set NEXT to point to just after this token. 
09222 */
09223 
09224     next = next + width;
09225 /*
09226   BEVEL
09227   Bevel interpolation.
09228 */
09229     if ( leqi ( token, "BEVEL" ) == TRUE ) {
09230       continue;
09231     }
09232 /*
09233   BMAT
09234   Basis matrix.
09235 */
09236     else if ( leqi ( token, "BMAT" ) == TRUE ) {
09237       continue;
09238     }
09239 /*
09240   C_INTERP
09241   Color interpolation.
09242 */
09243     else if ( leqi ( token, "C_INTERP" ) == TRUE ) {
09244       continue;
09245     }
09246 /*
09247   CON
09248   Connectivity between free form surfaces.
09249 */
09250     else if ( leqi ( token, "CON" ) == TRUE ) {
09251       continue;
09252     }
09253 /*
09254   CSTYPE
09255   Curve or surface type.
09256 */
09257     else if ( leqi ( token, "CSTYPE" ) == TRUE ) {
09258       continue;
09259     }
09260 /*
09261   CTECH
09262   Curve approximation technique.
09263 */
09264     else if ( leqi ( token, "CTECH" ) == TRUE ) {
09265       continue;
09266     }
09267 /*
09268   CURV
09269   Curve.
09270 */
09271     else if ( leqi ( token, "CURV" ) == TRUE ) {
09272       continue;
09273     }
09274 /*
09275   CURV2
09276   2D curve.
09277 */
09278     else if ( leqi ( token, "CURV2" ) == TRUE ) {
09279       continue;
09280     }
09281 /*
09282   D_INTERP
09283   Dissolve interpolation.
09284 */
09285     else if ( leqi ( token, "D_INTERP" ) == TRUE ) {
09286       continue;
09287     }
09288 /*
09289   DEG
09290   Degree.
09291 */
09292     else if ( leqi ( token, "DEG" ) == TRUE ) {
09293       continue;
09294     }
09295 /*
09296   END
09297   End statement.
09298 */
09299     else if ( leqi ( token, "END" ) == TRUE ) {
09300       continue;
09301     }
09302 /*  
09303   F V1 V2 V3
09304     or
09305   F V1/VT1/VN1 V2/VT2/VN2 ...
09306     or
09307   F V1//VN1 V2//VN2 ...
09308 
09309   Face.
09310   A face is defined by the vertices.
09311   Optionally, slashes may be used to include the texture vertex
09312   and vertex normal indices.
09313 
09314   OBJ line node indices are 1 based rather than 0 based.
09315   So we have to decrement them before loading them into FACE.
09316 */
09317 
09318     else if ( leqi ( token, "F" ) == TRUE ) {
09319 
09320       ivert = 0;
09321       face_order[face_num] = 0;
09322 /*
09323   Read each item in the F definition as a token, and then
09324   take it apart.
09325 */
09326       for ( ;; ) {
09327 
09328         count = sscanf ( next, "%s%n", token2, &width );
09329         next = next + width;
09330  
09331         if ( count != 1 ) {
09332           break;
09333         }
09334  
09335         count = sscanf ( token2, "%d%n", &node, &width );
09336         next2 = token2 + width;
09337 
09338         if ( count != 1 ) {
09339           break;
09340         }
09341 
09342         if ( ivert < ORDER_MAX && face_num < FACE_MAX ) {
09343           face[ivert][face_num] = node-1;
09344           vertex_material[ivert][face_num] = 0;
09345           face_order[face_num] = face_order[face_num] + 1;
09346         } 
09347 /*
09348   If there's a slash, skip to the next slash, and extract the
09349   index of the normal vector.
09350 */
09351         if ( *next2 == '/' ) {
09352 
09353           for ( next3 = next2 + 1; next3 < token2 + LINE_MAX_LEN; next3++ ) {
09354 
09355             if ( *next3 == '/' ) {
09356               next3 = next3 + 1;
09357               count = sscanf ( next3, "%d%n", &node, &width );
09358 
09359               node = node - 1;
09360               if ( 0 <= node && node < vertex_normal_num ) {
09361                 for ( i = 0; i < 3; i++ ) {
09362                   vertex_normal[i][ivert][face_num] = normal_temp[i][node];
09363                 }
09364               }
09365               break;
09366             }
09367           }
09368         }
09369         ivert = ivert + 1;
09370       } 
09371       face_num = face_num + 1;
09372     }
09373 
09374 /*  
09375   G  
09376   Group name.
09377 */
09378 
09379     else if ( leqi ( token, "G" ) == TRUE ) {
09380       continue;
09381     }
09382 /*
09383   HOLE
09384   Inner trimming hole.
09385 */
09386     else if ( leqi ( token, "HOLE" ) == TRUE ) {
09387       continue;
09388     }
09389 /*  
09390   L  
09391   I believe OBJ line node indices are 1 based rather than 0 based.
09392   So we have to decrement them before loading them into LINE_DEX.
09393 */
09394 
09395     else if ( leqi ( token, "L" ) == TRUE ) {
09396 
09397       for ( ;; ) {
09398 
09399         count = sscanf ( next, "%d%n", &node, &width );
09400         next = next + width;
09401 
09402         if ( count != 1 ) {
09403           break;
09404         }
09405 
09406         if ( line_num < LINES_MAX  ) {
09407           line_dex[line_num] = node-1;
09408           line_material[line_num] = 0;
09409         } 
09410         line_num = line_num + 1;
09411 
09412       } 
09413 
09414       if ( line_num < LINES_MAX ) {
09415         line_dex[line_num] = -1;
09416         line_material[line_num] = -1;
09417       }
09418       line_num = line_num + 1;
09419 
09420     }
09421 
09422 /*
09423   LOD
09424   Level of detail.
09425 */
09426     else if ( leqi ( token, "LOD" ) == TRUE ) {
09427       continue;
09428     }
09429 /*
09430   MG
09431   Merging group.
09432 */
09433     else if ( leqi ( token, "MG" ) == TRUE ) {
09434       continue;
09435     }
09436 /*
09437   MTLLIB
09438   Material library.
09439 */
09440 
09441     else if ( leqi ( token, "MTLLIB" ) == TRUE ) {
09442       continue;
09443     }
09444 /*
09445   O
09446   Object name.
09447 */
09448     else if ( leqi ( token, "O" ) == TRUE ) {
09449       continue;
09450     }
09451 /*
09452   P
09453   Point.
09454 */
09455     else if ( leqi ( token, "P" ) == TRUE ) {
09456       continue;
09457     }
09458 /*
09459   PARM
09460   Parameter values.
09461 */
09462     else if ( leqi ( token, "PARM" ) == TRUE ) {
09463       continue;
09464     }
09465 /*
09466   S  
09467   Smoothing group
09468 */
09469     else if ( leqi ( token, "S" ) == TRUE ) {
09470       continue;
09471     }
09472 /*
09473   SCRV
09474   Special curve.
09475 */
09476     else if ( leqi ( token, "SCRV" ) == TRUE ) {
09477       continue;
09478     }
09479 /*
09480   SHADOW_OBJ
09481   Shadow casting.
09482 */
09483     else if ( leqi ( token, "SHADOW_OBJ" ) == TRUE ) {
09484       continue;
09485     }
09486 /*
09487   SP
09488   Special point.
09489 */
09490     else if ( leqi ( token, "SP" ) == TRUE ) {
09491       continue;
09492     }
09493 /*
09494   STECH
09495   Surface approximation technique.
09496 */
09497     else if ( leqi ( token, "STECH" ) == TRUE ) {
09498       continue;
09499     }
09500 /*
09501   STEP
09502   Stepsize.
09503 */
09504     else if ( leqi ( token, "CURV" ) == TRUE ) {
09505       continue;
09506     }
09507 /*
09508   SURF
09509   Surface.
09510 */
09511     else if ( leqi ( token, "SURF" ) == TRUE ) {
09512       continue;
09513     }
09514 /*
09515   TRACE_OBJ
09516   Ray tracing.
09517 */
09518     else if ( leqi ( token, "TRACE_OBJ" ) == TRUE ) {
09519       continue;
09520     }
09521 /*
09522   TRIM
09523   Outer trimming loop.
09524 */
09525     else if ( leqi ( token, "TRIM" ) == TRUE ) {
09526       continue;
09527     }
09528 /*
09529   USEMTL  
09530   Material name.
09531 */
09532     else if ( leqi ( token, "USEMTL" ) == TRUE ) {
09533       continue;
09534     }
09535 
09536 /*
09537   V X Y Z W
09538   Geometric vertex.
09539   W is optional, a weight for rational curves and surfaces.
09540   The default for W is 1.
09541 */
09542 
09543     else if ( leqi ( token, "V" ) == TRUE ) {
09544 
09545       sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
09546 
09547       if ( cor3_num < COR3_MAX ) {
09548         cor3[0][cor3_num] = r1;
09549         cor3[1][cor3_num] = r2;
09550         cor3[2][cor3_num] = r3;
09551       }
09552 
09553       cor3_num = cor3_num + 1;
09554 
09555     }
09556 /*
09557   VN
09558   Vertex normals.
09559 */
09560 
09561     else if ( leqi ( token, "VN" ) == TRUE ) {
09562 
09563       sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
09564 
09565       if ( vertex_normal_num < ORDER_MAX * FACE_MAX ) {
09566         normal_temp[0][vertex_normal_num] = r1;
09567         normal_temp[1][vertex_normal_num] = r2;
09568         normal_temp[2][vertex_normal_num] = r3;
09569       }
09570 
09571       vertex_normal_num = vertex_normal_num + 1;
09572 
09573     }
09574 /*
09575   VT
09576   Vertex texture.
09577 */
09578     else if ( leqi ( token, "VT" ) == TRUE ) {
09579       continue;
09580     }
09581 /*
09582   VP
09583   Parameter space vertices.
09584 */
09585     else if ( leqi ( token, "VP" ) == TRUE ) {
09586       continue;
09587     }
09588 /*
09589   Unrecognized  
09590 */
09591     else {
09592       bad_num = bad_num + 1;
09593     }
09594 
09595   }
09596   return SUCCESS;
09597 }
09598 /******************************************************************************/
09599 
09600 int obj_write ( FILE *fileout )
09601 
09602 /******************************************************************************/
09603 
09604 /*
09605   Purpose:
09606    
09607     OBJ_WRITE writes a Wavefront OBJ file.
09608 
09609   Example:
09610 
09611     #  magnolia.obj
09612 
09613     mtllib ./vp.mtl
09614 
09615     g
09616     v -3.269770 -39.572201 0.876128
09617     v -3.263720 -39.507999 2.160890
09618     ...
09619     v 0.000000 -9.988540 0.000000
09620     g stem
09621     s 1
09622     usemtl brownskn
09623     f 8 9 11 10
09624     f 12 13 15 14
09625     ...
09626     f 788 806 774
09627 
09628   Modified:
09629 
09630     01 September 1998
09631 
09632   Author:
09633  
09634     John Burkardt
09635 */
09636 {
09637   int   i;
09638   int   iface;
09639   int   indexvn;
09640   int   ivert;
09641   int   k;
09642   int   new;
09643   int   text_num;
09644   float w;
09645 /* 
09646   Initialize. 
09647 */
09648   text_num = 0;
09649   w = 1.0;
09650 
09651   fprintf ( fileout, "# %s created by IVCON.\n", fileout_name );
09652   fprintf ( fileout, "# Original data in %s.\n", filein_name );
09653   fprintf ( fileout, "\n" );
09654   fprintf ( fileout, "g %s\n", object_name );
09655   fprintf ( fileout, "\n" );
09656 
09657   text_num = text_num + 5;
09658 /* 
09659   V: vertex coordinates. 
09660 */
09661   for ( i = 0; i < cor3_num; i++ ) {
09662     fprintf ( fileout, "v %f %f %f\n", 
09663       cor3[0][i], cor3[1][i], cor3[2][i]);
09664     text_num = text_num + 1;
09665   }
09666 
09667 /* 
09668   VN: Vertex face normal vectors. 
09669 */
09670   if ( face_num > 0 ) {
09671     fprintf ( fileout, "\n" );
09672     text_num = text_num + 1;
09673   }
09674 
09675   for ( iface = 0; iface < face_num; iface++ ) {
09676 
09677     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
09678 
09679       fprintf ( fileout, "vn %f %f %f\n", vertex_normal[0][ivert][iface],
09680         vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
09681       text_num = text_num + 1;
09682     }
09683   }
09684 /* 
09685   F: faces. 
09686 */
09687   if ( face_num > 0 ) {
09688     fprintf ( fileout, "\n" );
09689     text_num = text_num + 1;
09690   }
09691 
09692   indexvn = 0;
09693 
09694   for ( iface = 0; iface < face_num; iface++ ) {
09695 
09696     fprintf ( fileout, "f" );
09697     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
09698       indexvn = indexvn + 1;
09699       fprintf ( fileout, " %d//%d", face[ivert][iface]+1, indexvn );
09700     }
09701     fprintf ( fileout, "\n" );
09702     text_num = text_num + 1;
09703   }
09704 /* 
09705   L: lines. 
09706 */
09707   if ( line_num > 0 ) {
09708     fprintf ( fileout, "\n" );
09709     text_num = text_num + 1;
09710   }
09711 
09712   new = TRUE;
09713 
09714   for ( i = 0; i < line_num; i++ ) {
09715 
09716     k = line_dex[i];
09717 
09718     if ( k == -1 ) {
09719       fprintf ( fileout, "\n" );
09720       text_num = text_num + 1;
09721       new = TRUE;
09722     }
09723     else {
09724       if ( new == TRUE ) {
09725         fprintf ( fileout, "l" );
09726         new = FALSE;
09727       }
09728       fprintf ( fileout, " %d", k+1 );
09729     }
09730     
09731   }
09732 
09733   fprintf ( fileout, "\n" );
09734   text_num = text_num + 1;
09735 /*
09736   Report.
09737 */
09738   printf ( "\n" );
09739   printf ( "OBJ_WRITE - Wrote %d text lines.\n", text_num );
09740 
09741   return SUCCESS;
09742 }
09743 /******************************************************************************/
09744 
09745 int pov_write ( FILE *fileout )
09746 
09747 /******************************************************************************/
09748 
09749 /*
09750   Purpose:
09751 
09752     POV_WRITE writes graphics information to a POV file.
09753 
09754   Example:
09755 
09756     // cone.pov created by IVCON.
09757     // Original data in cone.iv
09758 
09759     #version 3.0
09760     #include "colors.inc"
09761     #include "shapes.inc"
09762     global_settings { assumed_gamma 2.2 }
09763 
09764     camera {
09765      right < 4/3, 0, 0>
09766      up < 0, 1, 0 >
09767      sky < 0, 1, 0 >
09768      angle 20
09769      location < 0, 0, -300 >
09770      look_at < 0, 0, 0>
09771     }
09772 
09773     light_source { < 20, 50, -100 > color White }
09774 
09775     background { color SkyBlue }
09776 
09777     #declare RedText = texture {
09778       pigment { color rgb < 0.8, 0.2, 0.2> }
09779       finish { ambient 0.2 diffuse 0.5 }
09780     }
09781 
09782     #declare BlueText = texture {
09783       pigment { color rgb < 0.2, 0.2, 0.8> }
09784       finish { ambient 0.2 diffuse 0.5 }
09785     }
09786     mesh {
09787       smooth_triangle {
09788         < 0.29, -0.29, 0.0>, < 0.0, 0.0, -1.0 >,
09789         < 38.85, 10.03, 0.0>, < 0.0, 0.0, -1.0 >,
09790         < 40.21, -0.29, 0.0>, <  0.0, 0.0, -1.0 >
09791         texture { RedText } }
09792         ...
09793       smooth_triangle {
09794         <  0.29, -0.29, 70.4142 >, < 0.0,  0.0, 1.0 >,
09795         <  8.56,  -2.51, 70.4142 >, < 0.0,  0.0, 1.0 >,
09796         <  8.85, -0.29, 70.4142 >, < 0.0,  0.0, 1.0 >
09797         texture { BlueText } }
09798     }
09799 
09800   Modified:
09801 
09802     08 October 1998
09803 
09804   Author:
09805 
09806     John Burkardt
09807 */
09808 {
09809   int i;
09810   int j;
09811   int jj;
09812   int jlo;
09813   int k;
09814   int text_num;
09815 
09816   text_num = 0;
09817   fprintf ( fileout,  "// %s created by IVCON.\n", fileout_name );
09818   fprintf ( fileout,  "// Original data in %s.\n", filein_name );
09819   text_num = text_num + 2;
09820 /*
09821   Initial declarations.
09822 */
09823   fprintf ( fileout, "\n" );
09824   fprintf ( fileout, "#version 3.0\n" );
09825   fprintf ( fileout, "#include \"colors.inc\"\n" );
09826   fprintf ( fileout, "#include \"shapes.inc\"\n" );
09827   fprintf ( fileout, "global_settings { assumed_gamma 2.2 }\n" );
09828   fprintf ( fileout, "\n" );
09829   fprintf ( fileout, "camera {\n" );
09830   fprintf ( fileout, " right < 4/3, 0, 0>\n" );
09831   fprintf ( fileout, " up < 0, 1, 0 >\n" );
09832   fprintf ( fileout, " sky < 0, 1, 0 >\n" );
09833   fprintf ( fileout, " angle 20\n" );
09834   fprintf ( fileout, " location < 0, 0, -300 >\n" );
09835   fprintf ( fileout, " look_at < 0, 0, 0>\n" );
09836   fprintf ( fileout, "}\n" );
09837   fprintf ( fileout, "\n" );
09838   fprintf ( fileout, "light_source { < 20, 50, -100 > color White }\n" );
09839   fprintf ( fileout, "\n" );
09840   fprintf ( fileout, "background { color SkyBlue }\n" );
09841 
09842   text_num = text_num + 15;
09843 /*
09844   Declare RGB textures.
09845 */
09846   fprintf ( fileout, "\n" );
09847   fprintf ( fileout, "#declare RedText = texture {\n" );
09848   fprintf ( fileout, "  pigment { color rgb < 0.8, 0.2, 0.2> }\n" );
09849   fprintf ( fileout, "  finish { ambient 0.2 diffuse 0.5 }\n" );
09850   fprintf ( fileout, "}\n" );
09851   fprintf ( fileout, "\n" );
09852   fprintf ( fileout, "#declare GreenText = texture {\n" );
09853   fprintf ( fileout, "  pigment { color rgb < 0.2, 0.8, 0.2> }\n" );
09854   fprintf ( fileout, "  finish { ambient 0.2 diffuse 0.5 }\n" );
09855   fprintf ( fileout, "}\n" );
09856   fprintf ( fileout, "\n" );
09857   fprintf ( fileout, "#declare BlueText = texture {\n" );
09858   fprintf ( fileout, "  pigment { color rgb < 0.2, 0.2, 0.8> }\n" );
09859   fprintf ( fileout, "  finish { ambient 0.2 diffuse 0.5 }\n" );
09860   fprintf ( fileout, "}\n" );
09861 /*
09862   Write one big object.
09863 */
09864   fprintf ( fileout,  "mesh {\n" );
09865   text_num = text_num + 1;
09866 /*
09867   Do the next face.
09868 */
09869   for ( i = 0; i < face_num; i++ ) {
09870 /*
09871   Break the face up into triangles, anchored at node 1.
09872 */
09873     for ( jlo = 0; jlo < face_order[i] - 2; jlo++ ) {
09874       fprintf ( fileout, "  smooth_triangle {\n" );
09875       text_num = text_num + 1;
09876 
09877       for ( j = jlo; j < jlo + 3; j++ ) {
09878 
09879         if ( j == jlo ) {
09880           jj = 0;
09881         }
09882         else {
09883           jj = j;
09884         }
09885 
09886         k = face[jj][i];
09887 
09888         fprintf ( fileout, "<%f, %f, %f>, <%f, %f, %f>",
09889           cor3[0][k], cor3[1][k], cor3[2][k], 
09890           vertex_normal[0][jj][i], 
09891           vertex_normal[1][jj][i],
09892           vertex_normal[2][jj][i] );
09893 
09894         if ( j < jlo + 2 ) {
09895           fprintf ( fileout, ",\n" );
09896         }
09897         else {
09898           fprintf ( fileout, "\n" );
09899         }
09900         text_num = text_num + 1;
09901 
09902       }
09903 
09904       if (i%6 == 1 ) {
09905         fprintf ( fileout,  "texture { RedText } }\n" );
09906       }
09907       else if ( i%2 == 0 ) {
09908         fprintf ( fileout,  "texture { BlueText } }\n" );
09909       }
09910       else {
09911         fprintf ( fileout,  "texture { GreenText } }\n" );
09912       }
09913       text_num = text_num + 1;
09914 
09915     }
09916 
09917   }
09918 
09919   fprintf ( fileout,  "}\n" );
09920   text_num = text_num + 1;
09921 /*
09922   Report.
09923 */
09924   printf ( "\n" );
09925   printf ( "POV_WRITE - Wrote %d text lines.\n", text_num );
09926 
09927   return SUCCESS;
09928 }
09929 /******************************************************************************/
09930 
09931 int rcol_find ( float a[][COR3_MAX], int m, int n, float r[] ) 
09932 
09933 /******************************************************************************/
09934 
09935 /*
09936   Purpose:
09937    
09938     RCOL_FIND finds if a vector occurs in a table.
09939 
09940   Comment:
09941 
09942     Explicitly forcing the second dimension to be COR3_MAX is a kludge.
09943     I have to figure out how to do this as pointer references.
09944 
09945     Also, since the array is not sorted, this routine should not be carelessly
09946     called repeatedly for really big values of N, because you'll waste a
09947     lot of time.
09948 
09949   Modified:
09950 
09951     27 April 1999
09952 
09953   Author:
09954  
09955     John Burkardt
09956 */
09957 {
09958   int i;
09959   int icol;
09960   int j;
09961 
09962   icol = -1;
09963 
09964   for ( j = 0; j < n; j++ ) {
09965     for ( i = 0; i < m; i++ ) {
09966       if ( a[i][j] != r[i] ) {
09967         break;
09968       }
09969       if ( i == m-1 ) {
09970         return j;
09971       }
09972     }
09973   }
09974 
09975   return icol;
09976 }
09977 /**********************************************************************/
09978 
09979 float rgb_to_hue ( float r, float g, float b )
09980 
09981 /**********************************************************************/
09982 
09983 /*
09984   Purpose:
09985 
09986     RGB_TO_HUE converts (R,G,B) colors to a hue value between 0 and 1.
09987 
09988   Discussion:
09989 
09990     The hue computed here should be the same as the H value computed
09991     for HLS and HSV, except that it ranges from 0 to 1 instead of
09992     0 to 360.
09993 
09994     A monochromatic color ( white, black, or a shade of gray) does not
09995     have a hue.  This routine will return a special value of H = -1
09996     for such cases.
09997 
09998   Examples:
09999 
10000     Color    R    G    B     H
10001 
10002     red  1.0  0.0  0.0   0.00
10003     yellow   1.0  1.0  0.0   0.16
10004     green    0.0  1.0  0.0   0.33
10005     cyan     0.0  1.0  1.0   0.50
10006     blue     0.0  0.0  1.0   0.67
10007     magenta  1.0  0.0  1.0   0.83
10008 
10009     black    0.0  0.0  0.0  -1.00
10010     gray     0.5  0.5  0.5  -1.00
10011     white    1.0  1.0  1.0  -1.00
10012 
10013   Modified:
10014 
10015     22 May 1999
10016 
10017   Author:
10018 
10019     John Burkardt
10020 
10021   Parameters:
10022 
10023     Input, float R, G, B, the red, green and blue values of the color.
10024     These values should be between 0 and 1.
10025 
10026     Output, float RGB_TO_HUE, the corresponding hue of the color, or -1.0 if
10027     the color is monochromatic.
10028 */
10029 {
10030   float h;
10031   float rgbmax;
10032   float rgbmin;
10033 /*
10034   Make sure the colors are between 0 and 1.
10035 */
10036   if ( r < 0.0 ) {
10037     r = 0.0;
10038   }
10039   else if ( r > 1.0 ) {
10040     r = 1.0;
10041   }
10042 
10043   if ( g < 0.0 ) {
10044     g = 0.0;
10045   }
10046   else if ( g > 1.0 ) {
10047     g = 1.0;
10048   }
10049 
10050   if ( b < 0.0 ) {
10051     b = 0.0;
10052   }
10053   else if ( b > 1.0 ) {
10054     b = 1.0;
10055   }
10056 /*
10057   Compute the minimum and maximum of R, G and B.
10058 */
10059   rgbmax = r;
10060   if ( g > rgbmax ) {
10061     rgbmax = g;
10062   }
10063   if ( b > rgbmax ) {
10064     rgbmax = b;
10065   }
10066 
10067   rgbmin = r;
10068   if ( g < rgbmin ) {
10069     rgbmin = g;
10070   }
10071   if ( b < rgbmin ) {
10072     rgbmin = b;
10073   }
10074 /*
10075   If RGBMAX = RGBMIN, { the color has no hue.
10076 */
10077   if ( rgbmax == rgbmin ) {
10078     h = - 1.0;
10079   }
10080 /*
10081   Otherwise, we need to determine the dominant color.
10082 */
10083   else {
10084 
10085     if ( r == rgbmax ) {
10086       h = ( g - b ) / ( rgbmax - rgbmin );
10087     }
10088     else if ( g == rgbmax ) {
10089       h = 2.0 + ( b - r ) / ( rgbmax - rgbmin );
10090     }
10091     else if ( b == rgbmax ) {
10092       h = 4.0 + ( r - g ) / ( rgbmax - rgbmin );
10093     }
10094 
10095     h = h / 6.0;
10096 /*
10097   Make sure H lies between 0 and 1.0.
10098 */
10099     if ( h < 0.0 ) {
10100       h = h + 1.0;
10101     }
10102     else if ( h > 1.0 ) {
10103       h = h - 1.0;
10104     }
10105 
10106   }
10107 
10108   return h;
10109 }
10110 /******************************************************************************/
10111 
10112 short int short_int_read ( FILE *filein )
10113 
10114 /******************************************************************************/
10115 /*
10116   Purpose:
10117 
10118     SHORT_INT_READ reads a short int from a binary file.
10119 
10120   Modified:
10121 
10122     14 October 1998
10123 
10124   Author:
10125 
10126     John Burkardt
10127 */
10128 {
10129   unsigned char  c1;
10130   unsigned char  c2;
10131   short int      ival;
10132 
10133   c1 = fgetc ( filein );
10134   c2 = fgetc ( filein );
10135 
10136   ival = c1 | ( c2 << 8 );
10137 
10138   return ival;
10139 }
10140 /******************************************************************************/
10141 
10142 int short_int_write ( FILE *fileout, short int short_int_val )
10143 
10144 /******************************************************************************/
10145 
10146 /*
10147   Purpose:
10148 
10149     SHORT_INT_WRITE writes a short int to a binary file.
10150 
10151   Modified:
10152 
10153     14 October 1998
10154 
10155   Author:
10156 
10157     John Burkardt
10158 */
10159 {
10160   union {
10161     short int yint;
10162     char ychar[2];
10163   } y;
10164 
10165   y.yint = short_int_val;
10166 
10167   if ( byte_swap == TRUE ) {
10168     fputc ( y.ychar[1], fileout );
10169     fputc ( y.ychar[0], fileout );
10170   }
10171   else {
10172     fputc ( y.ychar[0], fileout );
10173     fputc ( y.ychar[1], fileout );
10174   }
10175 
10176   return 2;
10177 }
10178 /******************************************************************************/
10179 
10180 int smf_read ( FILE *filein )
10181 
10182 /******************************************************************************/
10183 
10184 /*
10185   Purpose:
10186    
10187     SMF_READ reads an SMF file.
10188 
10189   Example:
10190 
10191     #SMF2.0
10192     #  cube_face.smf
10193     #  This example demonstrates how an RGB color can be assigned to
10194     #  each face of an object.
10195     #    
10196     # First, define the geometry of the cube.
10197     #
10198     v 0.0  0.0  0.0
10199     v 1.0  0.0  0.0
10200     v 0.0  1.0  0.0
10201     v 1.0  1.0  0.0
10202     v 0.0  0.0  1.0
10203     v 1.0  0.0  1.0
10204     v 0.0  1.0  1.0
10205     v 1.0  1.0  1.0
10206     f 1 4 2
10207     f 1 3 4
10208     f 5 6 8
10209     f 5 8 7
10210     f 1 2 6
10211     f 1 6 5
10212     f 2 4 8
10213     f 2 8 6
10214     f 4 3 7
10215     f 4 7 8
10216     f 3 1 5
10217     f 3 5 7
10218     #
10219     #  Colors will be bound 1 per face.
10220     #
10221     bind c face
10222     c 1.0  0.0  0.0
10223     c 1.0  0.0  0.0
10224     c 0.0  1.0  0.0
10225     c 0.0  1.0  0.0
10226     c 0.0  0.0  1.0
10227     c 0.0  0.0  1.0
10228     c 1.0  1.0  0.0
10229     c 1.0  1.0  0.0
10230     c 0.0  1.0  1.0
10231     c 0.0  1.0  1.0
10232     c 1.0  0.0  1.0
10233     c 1.0  0.0  1.0
10234     #
10235     #  Normal vectors will be bound 1 per face.
10236     #
10237     bind n face
10238     n  0.0   0.0  -1.0
10239     n  0.0   0.0  -1.0
10240     n  0.0   0.0   1.0
10241     n  0.0   0.0   1.0
10242     n  0.0  -1.0   0.0
10243     n  0.0  -1.0   0.0
10244     n  1.0   0.0   0.0
10245     n  1.0   0.0   0.0
10246     n  0.0   1.0   0.0
10247     n  0.0   1.0   0.0
10248     n -1.0   0.0   0.0
10249     n -1.0   0.0   0.0
10250     #
10251     #  Texture coordinate pairs will be bound 1 per face.
10252     #
10253     bind r face
10254     r  0.0   0.0
10255     r  0.0   0.1
10256     r  0.0   0.2
10257     r  0.0   0.3
10258     r  0.1   0.0
10259     r  0.1   0.1
10260     r  0.1   0.2
10261     r  0.1   0.3
10262     r  0.2   0.0
10263     r  0.2   0.1
10264     r  0.2   0.2
10265     r  0.2   0.3
10266 
10267   Modified:
10268 
10269     03 July 1999
10270 
10271   Author:
10272  
10273     John Burkardt
10274 */
10275 {
10276   float angle;
10277   char  axis;
10278   float b;
10279   char  cnr[LINE_MAX_LEN];
10280   int   count;
10281   float dx;
10282   float dy;
10283   int   face_count;
10284   float g;
10285   int   icor3_normal;
10286   int   icor3_tex_uv;
10287   int   iface_normal;
10288   int   iface_tex_uv;
10289   int   imat;
10290   int   ivert;
10291   int   level;
10292   char *next;
10293   int   node;
10294   int   node_count;
10295   float r;
10296   float r1;
10297   float r2;
10298   float r3;
10299   float rgba[4];
10300   char *string;
10301   float sx;
10302   float sy;
10303   float sz;
10304   char  token[LINE_MAX_LEN];
10305   char  token2[LINE_MAX_LEN];
10306   char  type[LINE_MAX_LEN];
10307   float u;
10308   float v;
10309   int   vertex_base;
10310   int   vertex_correction;
10311   int   width;
10312   float x;
10313   float xvec[3];
10314   float y;
10315   float z;
10316 
10317   face_count = 0;
10318   icor3_normal = 0;
10319   icor3_tex_uv = 0;
10320   iface_normal = 0;
10321   iface_tex_uv = 0;
10322   level = 0;
10323   node_count = 0;
10324   vertex_base = 0;
10325   vertex_correction = 0;
10326 /* 
10327   Read the next line of the file into INPUT. 
10328 */
10329   while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL ) {
10330 
10331     text_num = text_num + 1;
10332 
10333     if ( debug ) {
10334       printf ( "SMF_READ: DEBUG: Reading line #%d\n", text_num );
10335     }
10336 /* 
10337   Advance to the first nonspace character in INPUT. 
10338 */
10339     for ( next = input; *next != '\0' && isspace(*next); next++ ) {
10340     }
10341 /* 
10342   Skip blank lines. 
10343 */
10344 
10345     if ( *next == '\0' ) {
10346       continue;
10347     }
10348 /*
10349   Skip comment lines.
10350 */
10351     if ( *next == '#' || *next == '$' ) {
10352       comment_num = comment_num + 1;
10353       continue;
10354     }
10355 /* 
10356   Extract the first word in this line. 
10357 */
10358     sscanf ( next, "%s%n", token, &width );
10359 /* 
10360   Set NEXT to point to just after this token. 
10361 */
10362     next = next + width;
10363 /*
10364   BEGIN
10365   Reset the transformation matrix to identity.
10366   Node numbering starts at zero again.  (Really, this is level based)
10367   (Really should define a new transformation matrix, and concatenate.)
10368   (Also, might need to keep track of level.)
10369 */
10370     if ( leqi ( token, "BEGIN" ) == TRUE ) {
10371 
10372       level = level + 1;
10373 
10374       vertex_base = cor3_num;
10375       group_num = group_num + 1;
10376       tmat_init ( transform_matrix );
10377 
10378     }
10379 /*
10380   BIND [c|n|r] [vertex|face]
10381   Specify the binding for RGB color, Normal, or Texture.
10382   Options are "vertex" or "face"
10383 */
10384     else if ( leqi ( token, "BIND" ) == TRUE ) {
10385 
10386       sscanf ( next, "%s%n", cnr, &width );
10387       next = next + width;
10388 
10389       if ( debug ) {
10390         printf ( "CNR = %s\n", cnr );
10391       }
10392 
10393       sscanf ( next, "%s%n", type, &width );
10394       next = next + width;
10395 
10396       if ( debug ) {
10397         printf ( "TYPE = %s\n", type );
10398       }
10399 
10400       if ( leqi ( cnr, "C" ) == TRUE ) {
10401 
10402         if ( leqi ( type, "VERTEX" ) == TRUE ) {
10403           strcpy ( material_binding, "PER_VERTEX" );
10404         }
10405         else if ( leqi ( type, "FACE" ) == TRUE ) {
10406           strcpy ( material_binding, "PER_FACE" );
10407         }
10408 
10409       }
10410       else if ( leqi ( cnr, "N" ) == TRUE ) {
10411 
10412         if ( leqi ( type, "VERTEX" ) == TRUE ) {
10413           strcpy ( normal_binding, "PER_VERTEX" );
10414         }
10415         else if ( leqi ( type, "FACE" ) == TRUE ) {
10416           strcpy ( normal_binding, "PER_FACE" );
10417         }
10418 
10419       }
10420       else if ( leqi ( cnr, "R" ) == TRUE ) {
10421 
10422         if ( leqi ( type, "VERTEX" ) == TRUE ) {
10423           strcpy ( texture_binding, "PER_VERTEX" );
10424         }
10425         else if ( leqi ( type, "FACE" ) == TRUE ) {
10426           strcpy ( texture_binding, "PER_FACE" );
10427         }
10428 
10429       }
10430 
10431     }
10432 /*
10433   C <r> <g> <b>
10434   Specify an RGB color, with R, G, B between 0.0 and 1.0.
10435 */
10436     else if ( leqi ( token, "C" ) == TRUE ) {
10437 
10438       sscanf ( next, "%f%n", &r, &width );
10439       next = next + width;
10440 
10441       sscanf ( next, "%f%n", &g, &width );
10442       next = next + width;
10443 
10444       sscanf ( next, "%f%n", &b, &width );
10445       next = next + width;
10446 /*
10447     Set up a temporary material (R,G,B,1.0).
10448     Add the material to the material database, or find the index of
10449       a matching material already in.
10450     Assign the material of the node or face to this index.
10451 */
10452       rgba[0] = r;
10453       rgba[1] = g;
10454       rgba[2] = b;
10455       rgba[3] = 1.0;
10456 
10457       if ( material_num < MATERIAL_MAX ) {
10458 
10459         for ( k = 0; k < 4; k++ ) {
10460           material_rgba[k][material_num] = rgba[k];
10461         }
10462 
10463         imat = material_num;
10464         material_num = material_num + 1;
10465 
10466       }
10467       else {
10468 
10469         imat = 0;
10470 
10471       }
10472 
10473       if ( leqi ( material_binding, "PER_FACE" ) == TRUE ) {
10474 
10475         face_count = face_count + 1;
10476         face_material[face_count] = imat;
10477 
10478       }
10479       else if ( leqi ( material_binding, "PER_VERTEX" ) == TRUE ) {
10480 
10481         node_count = node_count + 1;
10482         cor3_material[node_count] = imat;
10483 
10484       }
10485       else {
10486 
10487         printf ( "\n" );
10488         printf ( "SMF_READ - Fatal error!\n" );
10489         printf ( "  Material binding undefined!\n" );
10490         return ERROR;
10491 
10492       }
10493 
10494     }
10495 /*
10496   END
10497   Drop down a level. 
10498 */
10499     else if ( leqi ( token, "END" ) == TRUE ) {
10500 
10501       level = level - 1;
10502 
10503       if ( level < 0 ) {
10504         printf ( "\n" );
10505         printf ( "SMF_READ - Fatal error!\n" );
10506         printf ( "  More END statements than BEGINs!\n" );
10507         return ERROR;
10508       }
10509     }
10510 /*  
10511   F V1 V2 V3
10512 
10513   Face.
10514   A face is defined by the vertices.
10515   Node indices are 1 based rather than 0 based.
10516   So we have to decrement them before loading them into FACE.
10517   Note that vertex indices start back at 0 each time a BEGIN is entered.
10518   The strategy here won't handle nested BEGIN's, just one at a time.
10519 */
10520 
10521     else if ( leqi ( token, "F" ) == TRUE ) {
10522 
10523       ivert = 0;
10524       face_order[face_num] = 0;
10525 /*
10526   Read each item in the F definition as a token, and then
10527   take it apart.
10528 */
10529       for ( ;; ) {
10530 
10531         count = sscanf ( next, "%s%n", token2, &width );
10532         next = next + width;
10533  
10534         if ( count != 1 ) {
10535           break;
10536         }
10537  
10538         count = sscanf ( token2, "%d%n", &node, &width );
10539 
10540         if ( count != 1 ) {
10541           break;
10542         }
10543 
10544         if ( ivert < ORDER_MAX && face_num < FACE_MAX ) {
10545           face[ivert][face_num] = node - 1 + vertex_base;
10546           vertex_material[ivert][face_num] = 0;
10547           face_order[face_num] = face_order[face_num] + 1;
10548         } 
10549         ivert = ivert + 1;
10550       } 
10551       face_num = face_num + 1;
10552     }
10553 /*
10554   N <x> <y> <z>
10555   Specify a normal vector.
10556 */
10557     else if ( leqi ( token, "N" ) == TRUE ) {
10558 
10559       sscanf ( next, "%f%n", &x, &width );
10560       next = next + width;
10561 
10562       sscanf ( next, "%f%n", &y, &width );
10563       next = next + width;
10564 
10565       sscanf ( next, "%f%n", &z, &width );
10566       next = next + width;
10567 
10568       if ( leqi ( normal_binding, "PER_FACE" ) == TRUE ) {
10569 
10570         face_normal[0][iface_normal] = x;
10571         face_normal[1][iface_normal] = y;
10572         face_normal[2][iface_normal] = z;
10573 
10574         iface_normal = iface_normal + 1;
10575 
10576       }
10577       else if ( leqi ( normal_binding, "PER_VERTEX" ) == TRUE ) {
10578 
10579         cor3_normal[0][icor3_normal] = x;
10580         cor3_normal[1][icor3_normal] = y;
10581         cor3_normal[2][icor3_normal] = z;
10582 
10583         icor3_normal = icor3_normal + 1;
10584 
10585       }
10586       else {
10587 
10588         printf ( "\n" );
10589         printf ( "SMF_READ - Fatal error!\n" );
10590         printf ( "  Normal binding undefined!\n" );
10591         return ERROR;
10592                     
10593       }
10594     }
10595 /*
10596   R <u> <v>
10597   Specify a texture coordinate.
10598 */
10599     else if ( leqi ( token, "R" ) == TRUE ) {
10600 
10601       sscanf ( next, "%f%n", &u, &width );
10602       next = next + width;
10603 
10604       sscanf ( next, "%f%n", &v, &width );
10605       next = next + width;
10606 
10607       if ( leqi ( texture_binding, "PER_FACE" ) == TRUE ) {
10608 
10609         face_tex_uv[0][iface_tex_uv] = u;
10610         face_tex_uv[1][iface_tex_uv] = v;
10611 
10612         icor3_tex_uv = icor3_tex_uv + 1;
10613 
10614       }
10615       else if ( leqi ( texture_binding, "PER_VERTEX" ) == TRUE ) {
10616 
10617         cor3_tex_uv[0][icor3_tex_uv] = u;
10618         cor3_tex_uv[1][icor3_tex_uv] = v;
10619 
10620         icor3_tex_uv = icor3_tex_uv + 1;
10621       }
10622       else {
10623         printf ( "\n" );
10624         printf ( "SMF_READ - Fatal error!\n" );
10625         printf ( "  Texture binding undefined!\n" );
10626         return ERROR;
10627       }
10628 
10629     }
10630 /*
10631   ROT [x|y|z] <theta>
10632 */
10633     else if ( leqi ( token, "ROT" ) == TRUE ) {
10634 
10635       sscanf ( next, "%c%n", &axis, &width );
10636       next = next + width;
10637 
10638       sscanf ( next, "%f%n", &angle, &width );
10639       next = next + width;
10640 
10641       tmat_rot_axis ( transform_matrix, transform_matrix, angle, axis );
10642 
10643     }
10644 /*
10645   SCALE <sx> <sy> <sz>
10646 */
10647     else if ( leqi ( token, "SCALE" ) == TRUE ) {
10648 
10649       sscanf ( next, "%f%n", &sx, &width );
10650       next = next + width;
10651 
10652       sscanf ( next, "%f%n", &sy, &width );
10653       next = next + width;
10654 
10655       sscanf ( next, "%f%n", &sz, &width );
10656       next = next + width;
10657 
10658       tmat_scale ( transform_matrix, transform_matrix, sx, sy, sz );
10659     }
10660 /*
10661   SET VERTEX_CORRECTION <i>
10662   Specify increment to add to vertex indices in file.
10663 */
10664     else if ( leqi ( token, "SET" ) == TRUE ) {
10665 
10666       sscanf ( next, "%s%n", cnr, &width );
10667       next = next + width;
10668 
10669       sscanf ( next, "%d%n", &vertex_correction, &width );
10670       next = next + width;
10671 
10672     }
10673 /*
10674   T_SCALE <dx> <dy>
10675   Specify a scaling to texture coordinates.
10676 */
10677     else if ( leqi ( token, "T_SCALE" ) == TRUE ) {
10678 
10679       sscanf ( next, "%f%n", &dx, &width );
10680       next = next + width;
10681 
10682       sscanf ( next, "%f%n", &dy, &width );
10683       next = next + width;
10684 
10685     }
10686 /*
10687   T_TRANS <dx> <dy>
10688   Specify a translation to texture coordinates.
10689 */
10690     else if ( leqi ( token, "T_TRANS" ) == TRUE ) {
10691 
10692       sscanf ( next, "%f%n", &dx, &width );
10693       next = next + width;
10694 
10695       sscanf ( next, "%f%n", &dy, &width );
10696       next = next + width;
10697 
10698     }
10699 /*
10700   TEX <filename>
10701   Specify a filename containing the texture.
10702   (ANY CHANCE THIS IS RIGHT?)
10703 */
10704     else if ( leqi ( token, "TEX" ) == TRUE ) {
10705 
10706       sscanf ( next, "%s%n", string, &width );
10707 
10708       for ( i = 0; i < LINE_MAX_LEN; i++ ) {
10709         texture_name[texture_num][i] = string[i];
10710         if ( string[i] == '\0' ) {
10711           break;
10712         }
10713       }
10714 
10715       texture_num = texture_num + 1;
10716 
10717     }
10718 /*
10719   TRANS <dx> <dy> <dz>
10720 */
10721     else if ( leqi ( token, "TRANS" ) == TRUE ) {
10722 
10723       sscanf ( next, "%f%n", &x, &width );
10724       next = next + width;
10725 
10726       sscanf ( next, "%f%n", &y, &width );
10727       next = next + width;
10728 
10729       sscanf ( next, "%f%n", &z, &width );
10730       next = next + width;
10731 
10732       tmat_trans ( transform_matrix, transform_matrix, x, y, z );
10733     }
10734 /*
10735   V X Y Z
10736   Geometric vertex.
10737 */
10738     else if ( leqi ( token, "V" ) == TRUE ) {
10739 
10740       sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
10741 
10742       xvec[0] = r1;
10743       xvec[1] = r2;
10744       xvec[2] = r3;
10745 /*
10746   Apply current transformation matrix.
10747   Right now, we can only handle one matrix, not a stack of
10748   matrices representing nested BEGIN/END's.
10749 */
10750       tmat_mxp ( transform_matrix, xvec, xvec );
10751 
10752       if ( cor3_num < COR3_MAX ) {
10753         for ( i = 0; i < 3; i++ ) {
10754           cor3[i][cor3_num] = xvec[i];
10755         }
10756       }
10757 
10758       cor3_num = cor3_num + 1;
10759 
10760     }
10761 /*
10762   Unrecognized keyword.
10763 */
10764     else {
10765 
10766       bad_num = bad_num + 1;
10767 
10768       if ( bad_num <= 10 ) {
10769         printf ( "\n" );
10770         printf ( "SMF_READ: Bad data on line %d.\n", text_num );
10771       }
10772     }
10773 
10774   }
10775 /*
10776   Extend the material definition 
10777   * from the face to the vertices and nodes, or
10778   * from the vertices to the faces and nodes.
10779 */
10780   if ( strcmp ( material_binding, "PER_FACE" ) == 0 ) {
10781 
10782     face_to_vertex_material ( );
10783 
10784     vertex_to_node_material ( );
10785 
10786   }
10787   else if ( strcmp ( material_binding, "PER_VERTEX" ) == 0 ) {
10788 
10789     node_to_vertex_material ( );
10790 
10791     vertex_to_face_material ( );
10792 
10793   }
10794 
10795   return SUCCESS;
10796 }
10797 /******************************************************************************/
10798 
10799 int smf_write ( FILE *fileout )
10800 
10801 /******************************************************************************/
10802 
10803 /*
10804   Purpose:
10805    
10806     SMF_WRITE writes graphics information to an SMF file.
10807 
10808   Example:
10809 
10810     #SMF2.0
10811     #  cube_face.smf
10812     #  This example demonstrates how an RGB color can be assigned to
10813     #  each face of an object.
10814     #    
10815     # First, define the geometry of the cube.
10816     #
10817     v 0.0  0.0  0.0
10818     v 1.0  0.0  0.0
10819     v 0.0  1.0  0.0
10820     v 1.0  1.0  0.0
10821     v 0.0  0.0  1.0
10822     v 1.0  0.0  1.0
10823     v 0.0  1.0  1.0
10824     v 1.0  1.0  1.0
10825     f 1 4 2
10826     f 1 3 4
10827     f 5 6 8
10828     f 5 8 7
10829     f 1 2 6
10830     f 1 6 5
10831     f 2 4 8
10832     f 2 8 6
10833     f 4 3 7
10834     f 4 7 8
10835     f 3 1 5
10836     f 3 5 7
10837     #
10838     #  Colors will be bound 1 per face.
10839     #
10840     bind c face
10841     c 1.0  0.0  0.0
10842     c 1.0  0.0  0.0
10843     c 0.0  1.0  0.0
10844     c 0.0  1.0  0.0
10845     c 0.0  0.0  1.0
10846     c 0.0  0.0  1.0
10847     c 1.0  1.0  0.0
10848     c 1.0  1.0  0.0
10849     c 0.0  1.0  1.0
10850     c 0.0  1.0  1.0
10851     c 1.0  0.0  1.0
10852     c 1.0  0.0  1.0
10853     #
10854     #  Normal vectors will be bound 1 per face.
10855     #
10856     bind n face
10857     n  0.0   0.0  -1.0
10858     n  0.0   0.0  -1.0
10859     n  0.0   0.0   1.0
10860     n  0.0   0.0   1.0
10861     n  0.0  -1.0   0.0
10862     n  0.0  -1.0   0.0
10863     n  1.0   0.0   0.0
10864     n  1.0   0.0   0.0
10865     n  0.0   1.0   0.0
10866     n  0.0   1.0   0.0
10867     n -1.0   0.0   0.0
10868     n -1.0   0.0   0.0
10869     #
10870     #  Texture coordinate pairs will be bound 1 per face.
10871     #
10872     bind r face
10873     r  0.0   0.0
10874     r  0.0   0.1
10875     r  0.0   0.2
10876     r  0.0   0.3
10877     r  0.1   0.0
10878     r  0.1   0.1
10879     r  0.1   0.2
10880     r  0.1   0.3
10881     r  0.2   0.0
10882     r  0.2   0.1
10883     r  0.2   0.2
10884     r  0.2   0.3
10885 
10886   Modified:
10887 
10888     05 July 1999
10889 
10890   Author:
10891  
10892     John Burkardt
10893 */
10894 {
10895   int   i;
10896   int   icor3;
10897   int   iface;
10898   int   imat;
10899   int   ivert;
10900   int   text_num;
10901 /* 
10902   Initialize. 
10903 */
10904   text_num = 0;
10905 
10906   fprintf ( fileout, "#$SMF 2.0\n" );
10907   fprintf ( fileout, "#$vertices %d\n", cor3_num );
10908   fprintf ( fileout, "#$faces %d\n", face_num );
10909   fprintf ( fileout, "#\n" );
10910   fprintf ( fileout, "# %s created by IVCON.\n", fileout_name );
10911   fprintf ( fileout, "# Original data in %s.\n", filein_name );
10912   fprintf ( fileout, "#\n" );
10913 
10914   text_num = text_num + 7;
10915 /* 
10916   V: vertex coordinates. 
10917 */
10918   for ( i = 0; i < cor3_num; i++ ) {
10919     fprintf ( fileout, "v %f %f %f\n", 
10920       cor3[0][i], cor3[1][i], cor3[2][i] );
10921     text_num = text_num + 1;
10922   }
10923 /* 
10924   F: faces. 
10925 */
10926   if ( face_num > 0 ) {
10927     fprintf ( fileout, "\n" );
10928     text_num = text_num + 1;
10929   }
10930 
10931   for ( iface = 0; iface < face_num; iface++ ) {
10932 
10933     fprintf ( fileout, "f" );
10934     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
10935       fprintf ( fileout, " %d", face[ivert][iface]+1 );
10936     }
10937     fprintf ( fileout, "\n" );
10938     text_num = text_num + 1;
10939   }
10940 /*
10941   Material binding.
10942 */
10943   fprintf ( fileout, "bind c vertex\n" );
10944   text_num = text_num + 1;
10945 /*
10946   Material RGB values at each node.
10947 */
10948   for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
10949 
10950     imat = cor3_material[icor3];
10951 
10952     fprintf ( fileout, "c %f %f %f\n", material_rgba[0][imat], 
10953       material_rgba[1][imat], material_rgba[2][imat] );
10954 
10955     text_num = text_num + 1;
10956   }
10957 /*
10958   Normal binding.
10959 */
10960   fprintf ( fileout, "bind n vertex\n" );
10961   text_num = text_num + 1;
10962 /*
10963   Normal vector at each node.
10964 */
10965   for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
10966 
10967     fprintf ( fileout, "n %f %f %f\n", cor3_normal[0][icor3],
10968       cor3_normal[1][icor3], cor3_normal[2][icor3] );
10969 
10970     text_num = text_num + 1;
10971   }
10972 
10973   if ( texture_num > 0 ) {
10974 /*
10975   Texture filename.
10976 */
10977     fprintf ( fileout, "tex %s\n", texture_name[0] );
10978     text_num = text_num + 1;
10979 /*
10980   Texture binding.
10981 */
10982     fprintf ( fileout, "bind r vertex\n" );
10983     text_num = text_num + 1;
10984 /*
10985   Texture coordinates at each node.
10986 */
10987     for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
10988       fprintf ( fileout, "r %f %f\n", cor3_tex_uv[0][icor3], 
10989         cor3_tex_uv[1][icor3] );
10990       text_num = text_num + 1;
10991     }
10992 
10993   }
10994 /*
10995   Report.
10996 */
10997   printf ( "\n" );
10998   printf ( "SMF_WRITE - Wrote %d text lines.\n", text_num );
10999 
11000   return SUCCESS;
11001 }
11002 /******************************************************************************/
11003 
11004 int stla_read ( FILE *filein )
11005 
11006 /******************************************************************************/
11007 
11008 /*
11009   Purpose:
11010    
11011     STLA_READ reads an ASCII STL (stereolithography) file.
11012 
11013   Examples:
11014 
11015     solid MYSOLID
11016       facet normal 0.4 0.4 0.2
11017         outerloop
11018           vertex  1.0 2.1 3.2
11019           vertex  2.1 3.7 4.5
11020           vertex  3.1 4.5 6.7
11021         endloop
11022       endfacet
11023       ...
11024       facet normal 0.2 0.2 0.4
11025         outerloop
11026           vertex  2.0 2.3 3.4
11027           vertex  3.1 3.2 6.5
11028           vertex  4.1 5.5 9.0
11029         endloop
11030       endfacet
11031     endsolid MYSOLID
11032 
11033   Modified:
11034 
11035     20 October 1998
11036 
11037   Author:
11038  
11039     John Burkardt
11040 */
11041 {
11042   int   count;
11043   int   i;
11044   int   icor3;
11045   int   ivert;
11046   char *next;
11047   float r1;
11048   float r2;
11049   float r3;
11050   float r4;
11051   float temp[3];
11052   char  token[LINE_MAX_LEN];
11053   int   width;
11054 /*
11055   Read the next line of the file into INPUT. 
11056 */
11057   while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL ) {
11058 
11059     text_num = text_num + 1;
11060 /*
11061   Advance to the first nonspace character in INPUT. 
11062 */
11063     for ( next = input; *next != '\0' && isspace(*next); next++ ) {
11064     }
11065 /*
11066   Skip blank lines and comments. 
11067 */
11068     if ( *next == '\0' || *next == '#' || *next == '!' || *next == '$' ) {
11069       continue;
11070     }
11071 /*
11072   Extract the first word in this line. 
11073 */
11074     sscanf ( next, "%s%n", token, &width );
11075 /*
11076   Set NEXT to point to just after this token. 
11077 */
11078     next = next + width;
11079 /*
11080   FACET
11081 */
11082     if ( leqi ( token, "facet" ) == TRUE ) {
11083 /* 
11084   Get the XYZ coordinates of the normal vector to the face. 
11085 */
11086       sscanf ( next, "%*s %e %e %e", &r1, &r2, &r3 );  
11087 
11088       if ( face_num < FACE_MAX ) {
11089         face_normal[0][face_num] = r1;
11090         face_normal[1][face_num] = r2;
11091         face_normal[2][face_num] = r3;
11092       }
11093 
11094       fgets ( input, LINE_MAX_LEN, filein );
11095       text_num = text_num + 1;
11096 
11097       ivert = 0;
11098 
11099       for ( ;; ) {
11100 
11101         fgets ( input, LINE_MAX_LEN, filein );
11102         text_num = text_num + 1;
11103 
11104         count = sscanf ( input, "%*s %e %e %e", &r1, &r2, &r3 );
11105 
11106         if ( count != 3 ) {
11107           break;
11108         }
11109 
11110         temp[0] = r1;
11111         temp[1] = r2;
11112         temp[2] = r3;
11113 
11114         if ( cor3_num < 1000 ) {
11115           icor3 = rcol_find ( cor3, 3, cor3_num, temp );
11116         }
11117         else {
11118           icor3 = -1;
11119         }
11120 
11121         if ( icor3 == -1 ) {
11122 
11123           icor3 = cor3_num;
11124 
11125           if ( cor3_num < COR3_MAX ) {
11126             for ( i = 0; i < 3; i++ ) {
11127               cor3[i][cor3_num] = temp[i];
11128             }
11129           }
11130           cor3_num = cor3_num + 1;
11131         }
11132         else {
11133           dup_num = dup_num + 1;
11134         }
11135 
11136         if ( ivert < ORDER_MAX && face_num < FACE_MAX ) {
11137           face[ivert][face_num] = icor3;
11138           vertex_material[ivert][face_num] = 0;
11139           for ( i = 0; i < 3; i++ ) {
11140             vertex_normal[i][ivert][face_num] = face_normal[i][face_num];
11141           }
11142         }
11143 
11144         ivert = ivert + 1;
11145       } 
11146 
11147       fgets ( input, LINE_MAX_LEN, filein );
11148       text_num = text_num + 1;
11149 
11150       if ( face_num < FACE_MAX ) {
11151         face_order[face_num] = ivert;
11152       } 
11153 
11154       face_num = face_num + 1;
11155 
11156     }
11157 /*
11158   COLOR 
11159 */
11160 
11161     else if ( leqi ( token, "color" ) == TRUE ) {
11162       sscanf ( next, "%*s %f %f %f %f", &r1, &r2, &r3, &r4 );
11163     }
11164 /* 
11165  SOLID 
11166 */
11167     else if ( leqi ( token, "solid" ) == TRUE ) {
11168       object_num = object_num + 1;
11169     }
11170 /* 
11171  ENDSOLID 
11172 */
11173     else if ( leqi ( token, "endsolid" ) == TRUE ) {
11174     }
11175 /* 
11176   Unexpected or unrecognized. 
11177 */
11178     else {
11179       printf ( "\n" );
11180       printf ( "STLA_READ - Fatal error!\n" );
11181       printf ( "  Unrecognized first word on line.\n" );
11182       return ERROR;
11183     }
11184 
11185   }
11186   return SUCCESS;
11187 }
11188 /******************************************************************************/
11189 
11190 int stla_write ( FILE *fileout )
11191 
11192 /******************************************************************************/
11193 
11194 /*
11195   Purpose:
11196    
11197     STLA_WRITE writes an ASCII STL (stereolithography) file.
11198 
11199   Examples:
11200 
11201     solid MYSOLID
11202       facet normal 0.4 0.4 0.2
11203         outerloop
11204           vertex  1.0 2.1 3.2
11205           vertex  2.1 3.7 4.5
11206           vertex  3.1 4.5 6.7
11207         endloop
11208       endfacet
11209       ...
11210       facet normal 0.2 0.2 0.4
11211         outerloop
11212           vertex  2.0 2.3 3.4
11213           vertex  3.1 3.2 6.5
11214           vertex  4.1 5.5 9.0
11215         endloop
11216       endfacet
11217     endsolid
11218 
11219   Discussion:
11220 
11221     The polygons in an STL file should only be triangular.  This routine 
11222     will try to automatically decompose higher-order polygonal faces into 
11223     suitable triangles, without actually modifying the internal graphics 
11224     data.
11225 
11226   Modified:
11227 
11228     01 September 1998
11229 
11230   Author:
11231  
11232     John Burkardt
11233 */
11234 {
11235   int icor3;
11236   int iface;
11237   int jvert;
11238   int face_num2;
11239   int text_num;
11240 /*
11241   Initialize.
11242 */
11243   text_num = 0;
11244   face_num2 = 0;
11245 
11246   fprintf ( fileout, "solid MYSOLID created by IVCON, original data in %s\n", 
11247     filein_name );
11248 
11249   text_num = text_num + 1;
11250 
11251   for ( iface = 0; iface < face_num; iface++ ) {
11252 
11253     for ( jvert = 2; jvert < face_order[iface]; jvert++ ) {
11254 
11255       face_num2 = face_num2 + 1;
11256 
11257       fprintf ( fileout, "  facet normal %f %f %f\n", 
11258         face_normal[0][iface], face_normal[1][iface], face_normal[2][iface] );
11259 
11260       fprintf ( fileout, "    outer loop\n" );
11261 
11262       icor3 = face[0][iface];
11263       fprintf ( fileout, "      vertex %f %f %f\n", 
11264         cor3[0][icor3], cor3[1][icor3], cor3[2][icor3] );
11265 
11266       icor3 = face[jvert-1][iface];
11267       fprintf ( fileout, "      vertex %f %f %f\n", 
11268         cor3[0][icor3], cor3[1][icor3], cor3[2][icor3] );
11269 
11270       icor3 = face[jvert][iface];
11271       fprintf ( fileout, "      vertex %f %f %f\n", 
11272         cor3[0][icor3], cor3[1][icor3], cor3[2][icor3] );
11273 
11274       fprintf ( fileout, "    endloop\n" );
11275       fprintf ( fileout, "  endfacet\n" );
11276       text_num = text_num + 7;
11277     }
11278   }
11279 
11280   fprintf ( fileout, "endsolid MYSOLID\n" );
11281   text_num = text_num + 1;
11282 /*
11283   Report.
11284 */
11285   printf ( "\n" );
11286   printf ( "STLA_WRITE - Wrote %d text lines.\n", text_num );
11287 
11288   if ( face_num != face_num2 ) {
11289     printf ( "  Number of faces in original data was %d.\n", face_num );
11290     printf ( "  Number of triangular faces in decomposed data is %d.\n",
11291       face_num2 );
11292   }
11293 
11294   return SUCCESS;
11295 }
11296 /******************************************************************************/
11297 
11298 int stlb_read ( FILE *filein )
11299 
11300 /******************************************************************************/
11301 
11302 /*
11303   Purpose:
11304    
11305     STLB_READ reads a binary STL (stereolithography) file.
11306 
11307   Example:
11308 
11309     80 byte string = header containing nothing in particular
11310 
11311     4 byte int = number of faces
11312 
11313     For each face:
11314 
11315       3 4-byte floats = components of normal vector to face;
11316       3 4-byte floats = coordinates of first node;
11317       3 4-byte floats = coordinates of second node;
11318       3 4-byte floats = coordinates of third and final node;
11319         2-byte int = attribute, whose value is 0.
11320 
11321   Modified:
11322 
11323     24 May 1999
11324 
11325   Author:
11326  
11327     John Burkardt
11328 */
11329 {
11330   short int attribute = 0;
11331   char c;
11332   float cvec[3];
11333   int icor3;
11334   int i;
11335   int iface;
11336   int ivert;
11337 /* 
11338   80 byte Header.
11339 */
11340   for ( i = 0; i < 80; i++ ) {
11341     c = char_read ( filein );
11342     if ( debug ) {
11343       printf ( "%d\n", c );
11344     }
11345     bytes_num = bytes_num + 1;
11346  }
11347 /*
11348   Number of faces.
11349 */
11350   face_num = long_int_read ( filein );
11351   bytes_num = bytes_num + 4;
11352 /*
11353   For each (triangular) face,
11354     components of normal vector,
11355     coordinates of three vertices,
11356     2 byte "attribute".
11357 */
11358   for ( iface = 0; iface < face_num; iface++ ) {
11359 
11360     face_order[iface] = 3;
11361     face_material[iface] = 0;
11362 
11363     for ( i = 0; i < 3; i++ ) {
11364       face_normal[i][iface] = float_read ( filein );
11365       bytes_num = bytes_num + 4;
11366     }
11367 
11368     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
11369 
11370       for ( i = 0; i < 3; i++ ) {
11371         cvec[i] = float_read ( filein );
11372         bytes_num = bytes_num + 4;
11373       }
11374 
11375       if ( cor3_num < 1000 ) {
11376         icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
11377       }
11378       else {
11379         icor3 = -1;
11380       }
11381 
11382       if ( icor3 == -1 ) {
11383         icor3 = cor3_num;
11384         if ( cor3_num < COR3_MAX ) {
11385           cor3[0][cor3_num] = cvec[0];
11386           cor3[1][cor3_num] = cvec[1];
11387           cor3[2][cor3_num] = cvec[2];
11388         }
11389         cor3_num = cor3_num + 1;
11390       }
11391       else {
11392         dup_num = dup_num + 1;
11393       }
11394 
11395       face[ivert][iface] = icor3;
11396 
11397     }
11398     attribute = short_int_read ( filein );
11399     if ( debug ) {
11400       printf ( "ATTRIBUTE = %d\n", attribute );
11401     }
11402     bytes_num = bytes_num + 2;
11403   }
11404 
11405   return SUCCESS;
11406 }
11407 /******************************************************************************/
11408 
11409 int stlb_write ( FILE *fileout )
11410 
11411 /******************************************************************************/
11412 
11413 /*
11414   Purpose:
11415    
11416     STLB_WRITE writes a binary STL (stereolithography) file.
11417 
11418   Example:
11419 
11420     80 byte string = header containing nothing in particular
11421 
11422     4 byte int = number of faces
11423 
11424     For each face:
11425 
11426       3 4-byte floats = components of normal vector to face;
11427       3 4-byte floats = coordinates of first node;
11428       3 4-byte floats = coordinates of second node;
11429       3 4-byte floats = coordinates of third and final node;
11430         2-byte int = attribute, whose value is 0.
11431 
11432   Discussion:
11433 
11434     The polygons in an STL file should only be triangular.  This routine 
11435     will try to automatically decompose higher-order polygonal faces into 
11436     suitable triangles, without actually modifying the internal graphics 
11437     data.
11438 
11439   Modified:
11440 
11441     24 May 1999
11442 
11443   Author:
11444  
11445     John Burkardt
11446 */
11447 {
11448   short int attribute = 0;
11449   char c;
11450   int i;
11451   int icor3;
11452   int iface;
11453   int jvert;
11454   int face_num2;
11455 /* 
11456   80 byte Header.
11457 */
11458   for ( i = 0; i < 80; i++ ) {
11459     c = ' ';
11460     bytes_num = bytes_num + char_write ( fileout, c );
11461   }
11462 /*
11463   Number of faces.
11464 */
11465   face_num2 = 0;
11466   for ( iface = 0; iface < face_num; iface++ ) {
11467     face_num2 = face_num2 + face_order[iface] - 2;
11468   }
11469 
11470   bytes_num = bytes_num + long_int_write ( fileout, face_num2 );
11471 /*
11472   For each (triangular) face,
11473     components of normal vector,
11474     coordinates of three vertices,
11475     2 byte "attribute".
11476 */
11477   for ( iface = 0; iface < face_num; iface++ ) {
11478 
11479     for ( jvert = 2; jvert < face_order[iface]; jvert++ ) {
11480 
11481       for ( i = 0; i < 3; i++ ) {
11482         bytes_num = bytes_num + float_write ( fileout, face_normal[i][iface] );
11483       }
11484 
11485       icor3 = face[0][iface];
11486       for ( i = 0; i < 3; i++ ) {
11487         bytes_num = bytes_num + float_write ( fileout, cor3[i][icor3] );
11488       }
11489 
11490       icor3 = face[jvert-1][iface];
11491       for ( i = 0; i < 3; i++ ) {
11492         bytes_num = bytes_num + float_write ( fileout, cor3[i][icor3] );
11493       }
11494 
11495       icor3 = face[jvert][iface];
11496       for ( i = 0; i < 3; i++ ) {
11497         bytes_num = bytes_num + float_write ( fileout, cor3[i][icor3] );
11498       }
11499 
11500       bytes_num = bytes_num + short_int_write ( fileout, attribute );
11501 
11502     }
11503 
11504   }
11505 /*
11506   Report.
11507 */
11508   printf ( "\n" );
11509   printf ( "STLB_WRITE - Wrote %d bytes.\n", bytes_num );
11510 
11511   if ( face_num != face_num2 ) {
11512     printf ( "  Number of faces in original data was %d.\n", face_num );
11513     printf ( "  Number of triangular faces in decomposed data is %d.\n",
11514       face_num2 );
11515   }
11516 
11517   return SUCCESS;
11518 }
11519 /******************************************************************************/
11520 
11521 void tds_pre_process ( void )
11522 
11523 /******************************************************************************/
11524 
11525 /*
11526   Purpose:
11527 
11528     TDS_PRE_PROCESS divides the monolithic object into acceptably small pieces.
11529 
11530   Note:
11531 
11532     The 3DS binary format allows an unsigned short int for the number of
11533     points, and number of faces in an object.  This limits such quantities
11534     to 65535.  We have at least one interesting object with more faces
11535     than that.  So we need to tag faces and nodes somehow.
11536 
11537   Modified:
11538 
11539     14 October 1998
11540 
11541   Author:
11542 
11543     John Burkardt
11544 */
11545 {
11546 /*  static unsigned short int BIG = 60000; */
11547 
11548   return;
11549 }
11550 /******************************************************************************/
11551 
11552 int tds_read ( FILE *filein )
11553 
11554 /******************************************************************************/
11555 
11556 /*
11557   Purpose:
11558    
11559     TDS_READ reads a 3D Studio MAX binary 3DS file.
11560 
11561   Modified:
11562 
11563     20 October 1998
11564 
11565   Author:
11566  
11567     John Burkardt
11568 */
11569 {
11570   unsigned long int   chunk_begin;
11571   unsigned long int   chunk_end;
11572   unsigned long int   chunk_length;
11573   unsigned long int   chunk_length2;
11574   unsigned long int   position;
11575   unsigned short int  temp_int;
11576   int                 version;
11577   int                 views_read;
11578 /* 
11579   Initialize.
11580 */
11581   views_read = 0;
11582 
11583   temp_int = tds_read_u_short_int ( filein );
11584 
11585   if ( temp_int == 0x4d4d ) {
11586 
11587     if ( debug ) {
11588       printf ( "TDS_READ: DEBUG: Read magic number %0X.\n", temp_int );
11589     }
11590 /* 
11591   Move to 28 bytes from the beginning of the file. 
11592 */
11593     position = 28;
11594     fseek ( filein, ( long ) position, SEEK_SET );
11595     version = fgetc ( filein );
11596 
11597     if ( version < 3 ) {
11598       printf ( "\n" );
11599       printf ( "TDS_READ - Fatal error!\n" );
11600       printf ( "  This routine can only read 3DS version 3 or later.\n" );
11601       printf ( "  The input file is version %d.\n" ,version );
11602       return ERROR;
11603     }
11604 
11605     if ( debug ) {
11606       printf ( "TDS_READ: DEBUG: Version number is %d.\n", version );
11607     }
11608 /* 
11609   Move to 2 bytes from the beginning of the file. 
11610   Set CURRENT_POINTER to the first byte of the chunk.
11611   Set CHUNK_LENGTH to the number of bytes in the chunk.
11612 */
11613     chunk_begin = 0;
11614     position = 2;
11615     fseek ( filein, ( long ) position, SEEK_SET );
11616 
11617     chunk_length = tds_read_u_long_int ( filein );
11618     position = 6;
11619 
11620     chunk_end = chunk_begin + chunk_length;
11621 
11622     if ( debug ) {
11623       printf ( "TDS_READ:\n" );
11624       printf ( "  Chunk begin  = %lu.\n", chunk_begin );
11625       printf ( "  Chunk length = %lu.\n", chunk_length );
11626       printf ( "  Chunk end    = %lu.\n", chunk_end );
11627     }
11628 
11629     while ( position + 2 < chunk_end ) {
11630 
11631       temp_int = tds_read_u_short_int ( filein );
11632       position = position + 2;
11633 
11634       if ( debug ) {
11635         printf ( "TDS_READ: Short int = %0X, position = %lu.\n", temp_int, position );
11636       }
11637 
11638       if ( temp_int == 0x0002 ) {
11639         if ( debug ) {
11640           printf ( "TDS_READ: Read_Initial_Section:\n" );
11641         }
11642         chunk_length2 = tds_read_u_long_int ( filein );
11643         position = position + 4;
11644         position = position - 6 + chunk_length2;
11645         fseek ( filein, ( long ) position, SEEK_SET );
11646       }
11647       else if ( temp_int == 0x3d3d ) {
11648         if ( debug ) {
11649           printf ( "TDS_READ: Read_Edit_Section:\n" );
11650         }
11651         position = position - 2;
11652         position = position + tds_read_edit_section ( filein, &views_read );
11653       }
11654       else if ( temp_int == 0xb000 ) {
11655         if ( debug ) {
11656           printf ( "TDS_READ: Read_Keyframe_Section:\n" );
11657         }
11658 
11659         position = position - 2;
11660         position = position + tds_read_keyframe_section ( filein, &views_read );
11661       }
11662       else {
11663         printf ( "\n" );
11664         printf ( "TDS_READ - Fatal error!\n" );
11665         printf ( "  Unexpected input, position = %lu.\n", position );
11666         printf ( "  TEMP_INT = %hux\n", temp_int );
11667         return ERROR;
11668       }
11669     }
11670     position = chunk_begin + chunk_length;
11671     fseek ( filein, ( long ) position, SEEK_SET );
11672   }
11673   else {
11674     printf ( "\n" );
11675     printf ( "TDS_READ - Fatal error!\n" );
11676     printf ( "  Could not find the main section tag.\n" );
11677     return ERROR;
11678   }
11679 
11680   return SUCCESS;
11681 }
11682 /******************************************************************************/
11683 
11684 unsigned long tds_read_ambient_section ( FILE *filein )
11685 
11686 /******************************************************************************/
11687 
11688 {
11689   unsigned long int   current_pointer;
11690   unsigned char       end_found = FALSE;
11691   int                 i;
11692   long int            pointer;
11693   float               rgb_val[3];
11694   unsigned short int  temp_int;
11695   unsigned long int   temp_pointer;
11696   unsigned long int   teller; 
11697   unsigned char       true_c_val[3];
11698  
11699   current_pointer = ftell ( filein ) - 2;
11700   temp_pointer = tds_read_u_long_int ( filein );
11701   teller = 6;
11702  
11703   while ( end_found == FALSE ) {
11704 
11705     temp_int = tds_read_u_short_int ( filein );
11706     teller = teller + 2;
11707  
11708     switch ( temp_int ) {
11709       case 0x0010:
11710         if ( debug ) {
11711           printf ( "     COLOR_F color definition section tag of %0X\n", 
11712             temp_int );
11713         }
11714         for ( i = 0; i < 3; i++ ) {
11715           rgb_val[i] = float_read ( filein );
11716         }
11717         if ( debug ) {
11718           printf ( "RGB_VAL = %f %f %f\n", rgb_val[0], rgb_val[1], rgb_val[2] );
11719         }
11720         teller = teller + 3 * sizeof ( float );
11721         break;
11722       case 0x0011:
11723         if ( debug ) {
11724           printf ( "     COLOR_24 24 bit color definition section tag of %0X\n",
11725             temp_int );
11726         }
11727 
11728         for ( i = 0; i < 3; i++ ) {
11729           true_c_val[i] = fgetc ( filein );
11730         }
11731         if ( debug ) {
11732           printf ( "TRUE_C_VAL = %d %d %d\n", true_c_val[0], true_c_val[1], 
11733             true_c_val[2] );
11734         }
11735         teller = teller + 3;
11736         break;
11737       default:
11738         break;
11739     }
11740  
11741     if ( teller >= temp_pointer ) {
11742       end_found = TRUE;
11743     }
11744 
11745   }
11746  
11747   pointer = ( long ) ( current_pointer + temp_pointer );
11748   fseek ( filein, pointer, SEEK_SET );
11749 
11750   return ( temp_pointer );
11751 }
11752 /******************************************************************************/
11753 
11754 unsigned long tds_read_background_section ( FILE *filein )
11755 
11756 /******************************************************************************/
11757 
11758 {
11759   unsigned long int   current_pointer;
11760   unsigned char       end_found = FALSE;
11761   int                 i;
11762   long int            pointer;
11763   float               rgb_val[3];
11764   unsigned short int  temp_int;
11765   unsigned long int   temp_pointer;
11766   unsigned long int   teller; 
11767   unsigned char       true_c_val[3];
11768  
11769   current_pointer = ftell ( filein ) - 2;
11770   temp_pointer = tds_read_u_long_int ( filein );
11771   teller = 6;
11772 
11773   while ( end_found == FALSE ) {
11774 
11775     temp_int = tds_read_u_short_int ( filein );
11776     teller = teller + 2;
11777  
11778     switch ( temp_int ) {
11779       case 0x0010:
11780         if ( debug ) {
11781           printf ( "   COLOR_F RGB color definition section tag of %0X\n", 
11782             temp_int );
11783         }
11784         for ( i = 0; i < 3; i++ ) {
11785           rgb_val[i] = float_read ( filein );
11786         }
11787         if ( debug ) {
11788           printf ( "RGB_VAL = %f %f %f\n", rgb_val[0], rgb_val[1], rgb_val[2] );
11789         }
11790         teller = teller + 3 * sizeof ( float );
11791         break;
11792       case 0x0011:
11793         if ( debug ) {
11794           printf ( "   COLOR_24 24 bit color definition section tag of %0X\n", 
11795             temp_int );
11796         }
11797  
11798         for ( i = 0; i < 3; i++ ) {
11799           true_c_val[i] = fgetc ( filein );
11800         }
11801         if ( debug ) {
11802           printf ( "TRUE_C_VAL = %d %d %d\n", true_c_val[0], true_c_val[1], 
11803             true_c_val[2] );
11804         }
11805         teller = teller + 3;
11806         break;
11807       default:
11808         break;
11809     }
11810 
11811     if ( teller >= temp_pointer ) {
11812       end_found = TRUE;
11813     }
11814 
11815   }
11816  
11817   pointer = ( long ) ( current_pointer + temp_pointer );
11818   fseek ( filein, pointer, SEEK_SET );
11819 
11820   return ( temp_pointer );
11821 }
11822 /******************************************************************************/
11823 
11824 unsigned long tds_read_boolean ( unsigned char *boolean, FILE *filein )
11825 
11826 /******************************************************************************/
11827 
11828 {
11829   unsigned long current_pointer;
11830   long int      pointer;
11831   unsigned long temp_pointer;
11832  
11833   current_pointer = ftell ( filein ) - 2;
11834   temp_pointer = tds_read_u_long_int ( filein );
11835  
11836   *boolean = fgetc ( filein );
11837  
11838   pointer = ( long ) ( current_pointer + temp_pointer );
11839   fseek ( filein, pointer, SEEK_SET );
11840 
11841   return ( temp_pointer );
11842 }
11843 /******************************************************************************/
11844 
11845 unsigned long tds_read_camera_section ( FILE *filein )
11846 
11847 /******************************************************************************/
11848 {
11849   float               camera_eye[3];
11850   float               camera_focus[3];
11851   unsigned long int   current_pointer;
11852   float               lens;
11853   long int            pointer;
11854   float               rotation;
11855   unsigned long int   temp_pointer;
11856   unsigned short int  u_short_int_val;
11857  
11858   current_pointer = ftell ( filein ) - 2;
11859   temp_pointer = tds_read_u_long_int ( filein );
11860  
11861   camera_eye[0] = float_read ( filein );
11862   camera_eye[1] = float_read ( filein );
11863   camera_eye[2] = float_read ( filein );
11864  
11865   camera_focus[0] = float_read ( filein );
11866   camera_focus[1] = float_read ( filein );
11867   camera_focus[2] = float_read ( filein );
11868 
11869   rotation = float_read ( filein );
11870   lens = float_read ( filein );
11871 
11872   if ( debug ) {
11873     printf ( " Found camera viewpoint at XYZ = %f %f %f.\n",
11874       camera_eye[0], camera_eye[1], camera_eye[2] );
11875     printf ( "     Found camera focus coordinates at XYZ = %f %f %f.\n",
11876       camera_focus[0], camera_focus[1], camera_focus[2] );
11877     printf ( "     Rotation of camera is:  %f.\n", rotation );
11878     printf ( "     Lens in used camera is: %f mm.\n", lens );
11879   }
11880  
11881   if ( ( temp_pointer-38 ) > 0 ) {
11882 
11883     if ( debug ) {
11884       printf ( "          Found extra camera sections.\n" );
11885     }
11886 
11887     u_short_int_val = tds_read_u_short_int ( filein );
11888 
11889     if ( u_short_int_val == 0x4710 ) {
11890       if ( debug ) {
11891         printf ( "          CAM_SEE_CONE.\n" );
11892       }
11893       tds_read_unknown_section ( filein );
11894     }
11895 
11896     u_short_int_val = tds_read_u_short_int ( filein );
11897 
11898     if ( u_short_int_val == 0x4720 ) {
11899       if ( debug ) {
11900         printf ( "          CAM_RANGES.\n" );
11901       }
11902       tds_read_unknown_section ( filein );
11903     }
11904 
11905   }
11906  
11907   pointer = ( long ) ( current_pointer + temp_pointer );
11908   fseek ( filein, pointer, SEEK_SET );
11909 
11910   return ( temp_pointer );
11911 }
11912 /******************************************************************************/
11913 
11914 unsigned long tds_read_edit_section ( FILE *filein, int *views_read )
11915 
11916 /******************************************************************************/
11917 
11918 /*
11919   Modified:
11920 
11921     18 September 1998
11922 */
11923 {
11924   unsigned long int   chunk_length;
11925   unsigned long int   current_pointer;
11926   unsigned char       end_found = FALSE;
11927   long int            pointer;
11928   unsigned long int   teller;
11929   unsigned short int  temp_int;
11930 
11931   current_pointer = ftell ( filein ) - 2;
11932   chunk_length = tds_read_u_long_int ( filein );
11933   teller = 6;
11934  
11935   while ( end_found == FALSE ) {
11936 
11937     temp_int = tds_read_u_short_int ( filein );
11938     teller = teller + 2;
11939  
11940     if ( debug ) {
11941       printf ( "    TDS_READ_EDIT_SECTION processing tag %0X\n", temp_int );
11942     }
11943 
11944     switch ( temp_int ) {
11945       case 0x1100:
11946         if ( debug ) {
11947           printf ( "    BIT_MAP section tag of %0X\n", temp_int );
11948         }
11949         teller = teller + tds_read_unknown_section ( filein );
11950         break;
11951       case 0x1201:
11952         if ( debug ) {
11953           printf ( "    USE_SOLID_BGND section tag of %0X\n", temp_int );
11954         }
11955         teller = teller + tds_read_unknown_section ( filein );
11956         break;
11957       case 0x1300:
11958         if ( debug ) {
11959           printf ( "    V_GRADIENT section tag of %0X\n", temp_int );
11960         }
11961         teller = teller + tds_read_unknown_section ( filein );
11962         break;
11963       case 0x1400:
11964         teller = teller + tds_read_unknown_section ( filein );
11965         break;
11966       case 0x1420:
11967         teller = teller + tds_read_unknown_section ( filein );
11968         break;
11969       case 0x1450:
11970         teller = teller + tds_read_unknown_section ( filein );
11971         break;
11972       case 0x1500:
11973         teller = teller + tds_read_unknown_section ( filein );
11974         break;
11975       case 0x2200:
11976         teller = teller + tds_read_unknown_section ( filein );
11977         break;
11978       case 0x2201:
11979         teller = teller + tds_read_unknown_section ( filein );
11980         break;
11981       case 0x2210:
11982         teller = teller + tds_read_unknown_section ( filein );
11983         break;
11984       case 0x2300:
11985         teller = teller + tds_read_unknown_section ( filein );
11986         break;
11987       case 0x2302:
11988         teller = teller + tds_read_unknown_section ( filein );
11989         break;
11990       case 0x3000:
11991         teller = teller + tds_read_unknown_section ( filein );
11992         break;
11993       case 0x2100:
11994         if ( debug ) {
11995           printf ( "    AMBIENT_LIGHT section tag of %0X\n", temp_int );
11996         }
11997         teller = teller + tds_read_ambient_section ( filein );
11998         break;
11999       case 0x1200:
12000         if ( debug ) {
12001           printf ( "    SOLID_BGND section tag of %0X\n", temp_int );
12002         }
12003         teller = teller + tds_read_background_section ( filein );
12004         break;
12005       case 0x0100:
12006         if ( debug ) {
12007           printf ( "    MASTER_SCALE section tag of %0X\n", temp_int );
12008         }
12009         teller = teller + tds_read_unknown_section ( filein );
12010         break;
12011       case 0x3d3e:
12012         if ( debug ) {
12013           printf ( "    MESH_VERSION section tag of %0X\n", temp_int );
12014         }
12015         teller = teller + tds_read_unknown_section ( filein );
12016         break;
12017       case 0xafff:
12018         if ( debug ) {
12019           printf ( "    MAT_ENTRY section tag of %0X\n", temp_int );
12020         }
12021         teller = teller + tds_read_material_section ( filein );
12022         break;
12023       case 0x4000:
12024         if ( debug ) {
12025           printf ( "    NAMED_OBJECT section tag of %0X\n", temp_int );
12026         }
12027         teller = teller + tds_read_object_section ( filein );
12028         break;
12029       case 0x7001:
12030         if ( debug ) {
12031           printf ( "    VIEWPORT_LAYOUT section tag of %0X\n", 
12032             temp_int );
12033         }
12034         teller = teller + tds_read_view_section ( filein, views_read );
12035         break;
12036       case 0x7012:
12037         if ( debug ) {
12038           printf ( "    VIEWPORT_DATA_3 section tag of %0X\n", temp_int );
12039         }
12040         teller = teller + tds_read_unknown_section ( filein );
12041         break;
12042       case 0x7011:
12043         if ( debug ) {
12044           printf ( "    VIEWPORT_DATA section tag of %0X\n", temp_int );
12045         }
12046         teller = teller + tds_read_unknown_section ( filein );
12047         break;
12048       case 0x7020:
12049         if ( debug ) {
12050           printf ( "    VIEWPORT_SIZE section tag of %0X\n", temp_int );
12051         }
12052         teller = teller + tds_read_unknown_section ( filein );
12053         break;
12054       default:
12055         if ( debug ) {
12056           printf ( "    Junk.\n" );
12057         }
12058         break;
12059     }
12060  
12061     if ( teller >= chunk_length ) {
12062       end_found = TRUE;
12063     }
12064 
12065   }
12066  
12067   pointer = ( long ) ( current_pointer + chunk_length );
12068 
12069   fseek ( filein, pointer, SEEK_SET );
12070 
12071   return ( chunk_length );
12072 }
12073 /******************************************************************************/
12074 
12075 unsigned long tds_read_keyframe_section ( FILE *filein, int *views_read )
12076 
12077 /******************************************************************************/
12078 {
12079   unsigned long int   current_pointer;
12080   unsigned char       end_found = FALSE;
12081   long int            pointer;
12082   unsigned short int  temp_int;
12083   unsigned long int   temp_pointer;
12084   unsigned long int   teller;
12085  
12086   current_pointer = ftell ( filein ) - 2;
12087   temp_pointer = tds_read_u_long_int ( filein );
12088   teller = 6;
12089  
12090   while ( end_found == FALSE ) {
12091 
12092     temp_int = tds_read_u_short_int ( filein );
12093     teller = teller + 2;
12094 
12095     switch ( temp_int ) {
12096       case 0x7001:
12097         if ( debug ) {
12098           printf ( "    VIEWPORT_LAYOUT main definition section tag of %0X\n",
12099             temp_int );
12100         }
12101         teller = teller + tds_read_view_section ( filein, views_read );
12102         break;
12103       case 0xb008:
12104         if ( debug ) {
12105           printf ( "    KFSEG frames section tag of %0X\n", temp_int );
12106         }
12107         teller = teller + tds_read_unknown_section ( filein );
12108         break;
12109       case 0xb002:
12110         if ( debug ) {
12111           printf ( "    OBJECT_NODE_TAG object description section tag of %0X\n",
12112             temp_int);
12113         }
12114         teller = teller + tds_read_keyframe_objdes_section ( filein );
12115         break;
12116       case 0xb009:
12117         if ( debug ) {
12118           printf ( "    KFCURTIME section tag of %0X\n", temp_int );
12119         }
12120         teller = teller + tds_read_unknown_section ( filein );
12121         break;
12122       case 0xb00a:
12123         if ( debug ) {
12124           printf ( "    KFHDR section tag of %0X\n", temp_int );
12125         }
12126         teller = teller + tds_read_unknown_section ( filein );
12127         break;
12128       default: 
12129         break;
12130     }
12131  
12132     if ( teller >= temp_pointer ) {
12133       end_found = TRUE;
12134     }
12135 
12136   }
12137  
12138   pointer = ( long ) ( current_pointer + temp_pointer );
12139   fseek ( filein, pointer, SEEK_SET );
12140 
12141   return ( temp_pointer );
12142 }
12143 /******************************************************************************/
12144 
12145 unsigned long tds_read_keyframe_objdes_section ( FILE *filein )
12146 
12147 /******************************************************************************/
12148 
12149 /*
12150   Modified:
12151 
12152     21 September 1998
12153 */
12154 {
12155   unsigned long int   chunk_size;
12156   unsigned long int   current_pointer;
12157   unsigned char       end_found = FALSE;
12158   long int            pointer;
12159   unsigned short int  temp_int;
12160   unsigned long int   temp_pointer;
12161   unsigned long int   teller;
12162   unsigned long int   u_long_int_val;
12163   unsigned short int  u_short_int_val;
12164  
12165   current_pointer = ftell ( filein ) - 2;
12166   temp_pointer = tds_read_u_long_int ( filein );
12167   teller = 6;
12168  
12169   while ( end_found == FALSE ) {
12170 
12171     temp_int = tds_read_u_short_int ( filein );
12172     teller = teller + 2;
12173 
12174     switch ( temp_int ) {
12175       case 0xb011:
12176         if ( debug ) {
12177           printf ( "      INSTANCE_NAME section tag of %0X\n", temp_int );
12178         }
12179         teller = teller + tds_read_unknown_section ( filein );
12180         break;
12181       case 0xb010:
12182         if ( debug ) {
12183           printf ( "      NODE_HDR section tag of %0X\n", temp_int );
12184         }
12185         teller = teller + tds_read_unknown_section ( filein );
12186         break;
12187       case 0xb020:
12188         if ( debug ) {
12189           printf ( "      POS_TRACK_TAG section tag of %0X\n", temp_int );
12190         }
12191         chunk_size = tds_read_u_long_int ( filein );
12192         if ( debug ) {
12193           printf ( "      chunk_size = %d\n", chunk_size );
12194         }
12195         u_short_int_val = tds_read_u_short_int ( filein );
12196         u_short_int_val = tds_read_u_short_int ( filein );
12197         u_short_int_val = tds_read_u_short_int ( filein );
12198         u_short_int_val = tds_read_u_short_int ( filein );
12199         u_short_int_val = tds_read_u_short_int ( filein );
12200         u_short_int_val = tds_read_u_short_int ( filein );
12201         u_short_int_val = tds_read_u_short_int ( filein );
12202         u_short_int_val = tds_read_u_short_int ( filein );
12203         u_long_int_val = tds_read_u_long_int ( filein );
12204         if ( debug ) {
12205           printf ( "u_short_int_val = %d\n", u_short_int_val );
12206           printf ( "u_long_int_val = %d\n", u_long_int_val );
12207         }
12208         origin[0] = float_read ( filein );
12209         origin[1] = float_read ( filein );
12210         origin[2] = float_read ( filein );
12211         teller = teller + 32;
12212         break;
12213       case 0xb013:
12214         if ( debug ) {
12215           printf ( "      PIVOT section tag of %0X\n", temp_int );
12216         }
12217         chunk_size = tds_read_u_long_int ( filein );
12218         pivot[0] = float_read ( filein );
12219         pivot[1] = float_read ( filein );
12220         pivot[2] = float_read ( filein );
12221         teller = teller + 12;
12222         break;
12223       case 0xb014:
12224         if ( debug ) {
12225           printf ( "      BOUNDBOX section tag of %0X\n", temp_int );
12226         }
12227         teller = teller + tds_read_unknown_section ( filein );
12228         break;
12229       case 0xb015:
12230         if ( debug ) {
12231           printf ( "      MORPH_SMOOTH section tag of %0X\n", temp_int );
12232         }
12233         teller = teller + tds_read_unknown_section ( filein );
12234         break;
12235       case 0xb021:
12236         if ( debug ) {
12237           printf ( "      ROT_TRACK_TAG section tag of %0X\n", temp_int );
12238         }
12239         teller = teller + tds_read_unknown_section ( filein );
12240         break;
12241       case 0xb022:
12242         if ( debug ) {
12243           printf ( "      SCL_TRACK_TAG section tag of %0X\n", temp_int );
12244         }
12245         teller = teller + tds_read_unknown_section ( filein );
12246         break;
12247       case 0xb030:
12248         if ( debug ) {
12249           printf ( "      NODE_ID section tag of %0X\n", temp_int );
12250         }
12251         teller = teller + tds_read_unknown_section ( filein );
12252         break;
12253       default: 
12254         break;
12255     }
12256  
12257     if ( teller >= temp_pointer ) {
12258       end_found = TRUE;
12259     }
12260 
12261   }
12262  
12263   pointer = ( long ) ( current_pointer+temp_pointer );
12264   fseek ( filein, pointer, SEEK_SET );
12265 
12266   return ( temp_pointer );
12267 }
12268 /******************************************************************************/
12269 
12270 unsigned long tds_read_light_section ( FILE *filein )
12271 
12272 /******************************************************************************/
12273 {
12274   unsigned char       boolean;
12275   unsigned long int   current_pointer;
12276   unsigned char       end_found = FALSE;
12277   int                 i;
12278   float               light_coors[3];
12279   long int            pointer;
12280   float               rgb_val[3];
12281   unsigned long int   teller;
12282   unsigned short int  temp_int;
12283   unsigned long int   temp_pointer;
12284   unsigned char       true_c_val[3];
12285  
12286   current_pointer = ftell ( filein ) - 2;
12287   temp_pointer = tds_read_u_long_int ( filein );
12288   teller = 6;
12289 
12290   light_coors[0] = float_read ( filein );
12291   light_coors[1] = float_read ( filein );
12292   light_coors[2] = float_read ( filein );
12293 
12294   teller = teller + 3 * 4;
12295  
12296   if ( debug ) {
12297     printf ( "     Found light at coordinates XYZ = %f %f %f.\n",
12298       light_coors[0], light_coors[1], light_coors[2] );
12299   }
12300  
12301   while ( end_found == FALSE ) {
12302 
12303     temp_int = tds_read_u_short_int ( filein );
12304     teller = teller + 2;
12305  
12306     switch ( temp_int ) {
12307       case 0x0010:
12308         if ( debug ) {
12309           printf ( "      COLOR_F RGB color definition section tag of %0X\n", 
12310             temp_int );
12311         }
12312         for ( i = 0; i < 3; i++ ) {
12313           rgb_val[i] = float_read ( filein );
12314         }
12315         if ( debug ) {
12316           printf ( "      RGB_VAL value set to %f %f %f\n", rgb_val[0],
12317             rgb_val[1], rgb_val[2] );
12318         }
12319         teller = teller + 3 * sizeof ( float );
12320         break;
12321       case 0x0011:
12322         if ( debug ) {
12323           printf ( "      COLOR_24 24 bit color definition section tag of %0X\n",
12324             temp_int );
12325         }
12326 
12327         for ( i = 0; i < 3; i++ ) {
12328           true_c_val[i] = fgetc ( filein );
12329         }
12330         if ( debug ) {
12331           printf ( "      TRUE_C_VAL value set to %d %d %d\n", true_c_val[0],
12332             true_c_val[1], true_c_val[2] );
12333         }
12334         teller = teller + 3;
12335         break;
12336       case 0x4620:
12337         if ( debug ) {
12338           printf ( "      DL_OFF section: %0X\n", temp_int );
12339         }
12340         teller = teller + tds_read_boolean ( &boolean, filein );
12341         if ( debug ) {
12342           if ( boolean == TRUE ) {
12343             printf ( "      Light is on\n" );
12344           }
12345           else {
12346             printf ( "      Light is off\n" );
12347           }
12348         }
12349         break;
12350       case 0x4610:
12351         if ( debug  ) {
12352           printf ( "      DL_SPOTLIGHT section tag of %0X\n", temp_int );
12353         }
12354         teller = teller + tds_read_spot_section ( filein );
12355         break;
12356       case 0x465a:
12357         if ( debug  ) {
12358           printf ( "      DL_OUTER_RANGE section tag of %0X\n", temp_int );
12359         }
12360         teller = teller + tds_read_unknown_section ( filein );
12361         break;
12362       default:
12363         break;
12364     }
12365  
12366     if ( teller >= temp_pointer ) {
12367       end_found = TRUE;
12368     }
12369 
12370   }
12371  
12372   pointer = ( long ) ( current_pointer + temp_pointer );
12373   fseek ( filein, pointer, SEEK_SET );
12374  
12375   return ( temp_pointer );
12376 }
12377 /******************************************************************************/
12378 
12379 unsigned long int tds_read_u_long_int ( FILE *filein )
12380 
12381 /******************************************************************************/
12382 
12383 /*
12384   Modified:
12385  
12386     01 October 1998
12387 
12388   Author:
12389 
12390     John Burkardt
12391 */
12392 {
12393   union {
12394     unsigned long int yint;
12395     char ychar[4];
12396   } y;
12397 
12398   if ( byte_swap == TRUE ) {
12399     y.ychar[3] = fgetc ( filein );
12400     y.ychar[2] = fgetc ( filein );
12401     y.ychar[1] = fgetc ( filein );
12402     y.ychar[0] = fgetc ( filein );
12403   }
12404   else {
12405     y.ychar[0] = fgetc ( filein );
12406     y.ychar[1] = fgetc ( filein );
12407     y.ychar[2] = fgetc ( filein );
12408     y.ychar[3] = fgetc ( filein );
12409   }
12410 
12411   return y.yint;
12412 }
12413 /******************************************************************************/
12414 
12415 int tds_read_long_name ( FILE *filein )
12416 
12417 /******************************************************************************/
12418 {
12419   unsigned char  letter;
12420   unsigned int   teller;
12421 
12422   teller = 0;
12423   letter = fgetc ( filein );
12424 /*
12425   Could be a dummy object. 
12426 */
12427   if ( letter == 0 ) {
12428     strcpy ( temp_name, "Default_name" );
12429     return -1; 
12430   }
12431 
12432   temp_name[teller] = letter;
12433   teller = teller + 1;
12434  
12435   do {
12436     letter = fgetc ( filein );
12437     temp_name[teller] = letter;
12438     teller = teller + 1;
12439   } while ( letter != 0 );
12440  
12441   temp_name[teller-1] = 0;
12442  
12443   if ( debug ) {
12444     printf ( "      tds_read_long_name found name: %s.\n", temp_name );
12445   }
12446 
12447   return teller;
12448 }
12449 /******************************************************************************/
12450 
12451 unsigned long tds_read_matdef_section ( FILE *filein )
12452 
12453 /******************************************************************************/
12454 {
12455   unsigned long int  current_pointer;
12456   long int           pointer;
12457   int                teller;
12458   unsigned long int  temp_pointer;
12459  
12460   current_pointer = ftell ( filein ) - 2;
12461   temp_pointer = tds_read_u_long_int ( filein );
12462  
12463   teller = tds_read_long_name ( filein );
12464 
12465   if ( teller == -1 ) {
12466     if ( debug ) {
12467       printf ( "      No material name found.\n" );
12468     }
12469   }
12470   else {
12471     strcpy ( mat_name, temp_name );
12472     if ( debug ) {
12473       printf ( "      Material name %s.\n", mat_name );
12474     }
12475   }
12476  
12477   pointer = ( long ) ( current_pointer + temp_pointer );
12478   fseek ( filein, pointer, SEEK_SET );
12479 
12480   return ( temp_pointer );
12481 }
12482 /******************************************************************************/
12483 
12484 unsigned long tds_read_material_section ( FILE *filein )
12485 
12486 /******************************************************************************/
12487 {
12488   unsigned long int   current_pointer;
12489   unsigned char       end_found = FALSE;
12490   long int            pointer;
12491   unsigned short int  temp_int;
12492   unsigned long int   temp_pointer;
12493   unsigned long int   teller;
12494  
12495   current_pointer = ftell ( filein ) - 2;
12496 
12497   temp_pointer = tds_read_u_long_int ( filein );
12498   teller = 6;
12499  
12500   while ( end_found == FALSE ) {
12501 
12502     temp_int = tds_read_u_short_int ( filein );
12503     teller = teller + 2;
12504  
12505     switch ( temp_int ) {
12506 
12507       case 0xa000:
12508         if ( debug ) {
12509           printf ( "     MAT_NAME definition section tag of %0X\n", 
12510             temp_int );
12511         }
12512         teller = teller + tds_read_matdef_section ( filein );
12513         break;
12514       case 0xa010:
12515         if ( debug ) {
12516           printf ( "     MAT_AMBIENT definition section tag of %0X\n", 
12517             temp_int );
12518         }
12519         teller = teller + tds_read_unknown_section ( filein );
12520         break;
12521       case 0xa020:
12522         if ( debug ) {
12523           printf ( "     MAT_DIFFUSE definition section tag of %0X\n", 
12524             temp_int );
12525         }
12526         teller = teller + tds_read_unknown_section ( filein );
12527         break;
12528       case 0xa030:
12529         if ( debug ) {
12530           printf ( "     MAT_SPECULAR definition section tag of %0X\n", 
12531             temp_int );
12532         }
12533         teller = teller + tds_read_unknown_section ( filein );
12534         break;
12535       case 0xa040:
12536         if ( debug ) {
12537           printf ( "     MAT_SHININESS definition section tag of %0X\n", 
12538             temp_int );
12539         }
12540         teller = teller + tds_read_unknown_section ( filein );
12541         break;
12542       case 0xa041:
12543         if ( debug ) {
12544           printf ( "     MAT_SHIN2PCT definition section tag of %0X\n", 
12545             temp_int );
12546         }
12547         teller = teller + tds_read_unknown_section ( filein );
12548         break;
12549       case 0xa042:
12550         if ( debug ) {
12551           printf ( "     MAT_SHIN3PCT definition section tag of %0X\n", 
12552             temp_int );
12553         }
12554         teller = teller + tds_read_unknown_section ( filein );
12555         break;
12556       case 0xa050:
12557         if ( debug ) {
12558           printf ( "     MAT_TRANSPARENCY definition section tag of %0X\n", 
12559             temp_int );
12560         }
12561         teller = teller + tds_read_unknown_section ( filein );
12562         break;
12563       case 0xa052:
12564         if ( debug ) {
12565           printf ( "     MAT_XPFALL definition section tag of %0X\n", 
12566             temp_int );
12567         }
12568         teller = teller + tds_read_unknown_section ( filein );
12569         break;
12570       case 0xa053:
12571         if ( debug ) {
12572           printf ( "     MAT_REFBLUR definition section tag of %0X\n", 
12573             temp_int );
12574         }
12575         teller = teller + tds_read_unknown_section ( filein );
12576         break;
12577       case 0xa080:
12578         if ( debug ) {
12579           printf ( "     MAT_SELF_ILLUM definition section tag of %0X\n", 
12580             temp_int );
12581         }
12582         teller = teller + tds_read_unknown_section ( filein );
12583         break;
12584       case 0xa081:
12585         if ( debug ) {
12586           printf ( "     MAT_TWO_SIDE definition section tag of %0X\n", 
12587             temp_int );
12588         }
12589         teller = teller + tds_read_unknown_section ( filein );
12590         break;
12591       case 0xa082:
12592         if ( debug ) {
12593           printf ( "     MAT_DECAL definition section tag of %0X\n", 
12594             temp_int );
12595         }
12596         teller = teller + tds_read_unknown_section ( filein );
12597         break;
12598       case 0xa083:
12599         if ( debug ) {
12600           printf ( "     MAT_ADDITIVE definition section tag of %0X\n", 
12601             temp_int );
12602         }
12603         teller = teller + tds_read_unknown_section ( filein );
12604         break;
12605       case 0xa084:
12606         if ( debug ) {
12607           printf ( "     MAT_SELF_ILPCT definition section tag of %0X\n", 
12608             temp_int );
12609         }
12610         teller = teller + tds_read_unknown_section ( filein );
12611         break;
12612       case 0xa085:
12613         if ( debug ) {
12614           printf ( "     MAT_WIRE definition section tag of %0X\n", 
12615             temp_int );
12616         }
12617         teller = teller + tds_read_unknown_section ( filein );
12618         break;
12619       case 0xa086:
12620         if ( debug ) {
12621           printf ( "     MAT_SUPERSMP definition section tag of %0X\n", 
12622             temp_int );
12623         }
12624         teller = teller + tds_read_unknown_section ( filein );
12625         break;
12626       case 0xa087:
12627         if ( debug ) {
12628           printf ( "     MAT_WIRESIZE definition section tag of %0X\n", 
12629             temp_int );
12630         }
12631         teller = teller + tds_read_unknown_section ( filein );
12632         break;
12633       case 0xa088:
12634         if ( debug ) {
12635           printf ( "     MAT_FACEMAP definition section tag of %0X\n", 
12636             temp_int );
12637         }
12638         teller = teller + tds_read_unknown_section ( filein );
12639         break;
12640       case 0xa08a:
12641         if ( debug ) {
12642           printf ( "     MAT_XPFALLIN definition section tag of %0X\n", 
12643             temp_int );
12644         }
12645         teller = teller + tds_read_unknown_section ( filein );
12646         break;
12647       case 0xa08c:
12648         if ( debug ) {
12649           printf ( "     MAT_PHONGSOFT definition section tag of %0X\n", 
12650             temp_int );
12651         }
12652         teller = teller + tds_read_unknown_section ( filein );
12653         break;
12654       case 0xa08e:
12655         if ( debug ) {
12656           printf ( "     MAT_WIREABS definition section tag of %0X\n", 
12657             temp_int );
12658         }
12659         teller = teller + tds_read_unknown_section ( filein );
12660         break;
12661       case 0xa100:
12662         if ( debug ) {
12663           printf ( "     MAT_SHADING definition section tag of %0X\n", 
12664             temp_int );
12665         }
12666         teller = teller + tds_read_unknown_section ( filein );
12667         break;
12668       case 0xa200:
12669         if ( debug ) {
12670           printf ( "     MAT_TEXMAP definition section tag of %0X\n", 
12671             temp_int );
12672         }
12673         teller = teller + tds_read_texmap_section ( filein );
12674 /*
12675         teller = teller + tds_read_unknown_section ( filein );
12676 */
12677         break;
12678       case 0xa204:
12679         if ( debug ) {
12680           printf ( "     MAT_SPECMAP definition section tag of %0X\n", 
12681             temp_int );
12682         }
12683         teller = teller + tds_read_unknown_section ( filein );
12684         break;
12685       case 0xa210:
12686         if ( debug ) {
12687           printf ( "     MAT_OPACMAP definition section tag of %0X\n", 
12688             temp_int );
12689         }
12690         teller = teller + tds_read_unknown_section ( filein );
12691         break;
12692       case 0xa220:
12693         if ( debug ) {
12694           printf ( "     MAT_REFLMAP definition section tag of %0X\n", 
12695             temp_int );
12696         }
12697         teller = teller + tds_read_unknown_section ( filein );
12698         break;
12699       case 0xa230:
12700         if ( debug ) {
12701           printf ( "     MAT_BUMPMAP definition section tag of %0X\n", 
12702             temp_int );
12703         }
12704         teller = teller + tds_read_unknown_section ( filein );
12705         break;
12706       case 0xa353:
12707         if ( debug ) {
12708           printf ( "     MAT_MAP_TEXBLUR definition section tag of %0X\n", 
12709             temp_int );
12710         }
12711         teller = teller + tds_read_unknown_section ( filein );
12712         break;
12713       default:
12714         if ( debug ) {
12715           printf ( "  Junk section tag of %0X\n", temp_int );
12716         }
12717         break;
12718     }
12719  
12720     if ( teller >= temp_pointer ) {
12721       end_found = TRUE;
12722     }
12723 
12724   }
12725   pointer = ( long ) ( current_pointer + temp_pointer );
12726 
12727   fseek ( filein, pointer, SEEK_SET );
12728 
12729   return ( temp_pointer );
12730 }
12731 /******************************************************************************/
12732 
12733 int tds_read_name ( FILE *filein )
12734 
12735 /******************************************************************************/
12736 {
12737   unsigned char  letter;
12738   unsigned int   teller;
12739 
12740   teller = 0;
12741   letter = fgetc ( filein );
12742 /*
12743   Could be a dummy object.  
12744 */
12745 
12746   if ( letter == 0 ) {
12747     strcpy ( temp_name, "Default name" );
12748     return (-1); 
12749   }
12750 
12751   temp_name[teller] = letter;
12752   teller = teller + 1;
12753  
12754   do {
12755     letter = fgetc ( filein );
12756     temp_name[teller] = letter;
12757     teller = teller + 1;
12758   } while ( ( letter != 0 ) && ( teller < 12 ) );
12759  
12760   temp_name[teller-1] = 0;
12761  
12762   if ( debug ) {
12763     printf ( "      tds_read_name found name: %s.\n", temp_name );
12764   }
12765 
12766   return 0;
12767 }
12768 /******************************************************************************/
12769 
12770 unsigned long tds_read_obj_section ( FILE *filein )
12771 
12772 /******************************************************************************/
12773 
12774 /*
12775   Comments:
12776 
12777     Thanks to John F Flanagan for some suggested corrections.
12778 
12779   Modified:
12780 
12781     30 June 2001
12782 */
12783 {
12784   unsigned short int  b;
12785   unsigned long int   chunk_size;
12786   unsigned short int  color_index;
12787   unsigned long int   current_pointer;
12788   unsigned char       end_found = FALSE;
12789   unsigned short int  g;
12790   int                 i;
12791   int                 j;
12792   int                 cor3_num_base;
12793   int                 cor3_num_inc;
12794   int                 face_num_inc;
12795   long int            pointer;
12796   unsigned short int  r;
12797   unsigned short int  temp_int;
12798   unsigned long int   temp_pointer;
12799   unsigned long int   temp_pointer2;
12800   unsigned long int   teller; 
12801  
12802   current_pointer = ftell ( filein ) - 2;
12803   temp_pointer = tds_read_u_long_int ( filein );
12804   teller = 6;
12805   cor3_num_base = cor3_num;
12806 
12807   while ( end_found == FALSE ) {
12808 
12809     temp_int = tds_read_u_short_int ( filein );
12810     teller = teller + 2;
12811 
12812     switch ( temp_int ) {
12813 
12814       case 0x4000:
12815         if ( debug ) {
12816           printf ( "        NAMED_OBJECT section tag of %0X\n", 
12817             temp_int );
12818         }
12819         teller = teller + tds_read_unknown_section ( filein );
12820         break;
12821 
12822       case 0x4100:
12823         if ( debug ) {
12824           printf ( "        N_TRI_OBJECT section tag of %0X\n", 
12825             temp_int );
12826         }
12827         teller = teller + tds_read_unknown_section ( filein );
12828         break;
12829 
12830       case 0x4110:
12831 
12832         if ( debug ) {
12833           printf ( "        POINT_ARRAY section tag of %0X\n", temp_int );
12834         }
12835 
12836         current_pointer = ftell ( filein ) - 2;
12837         temp_pointer2 = tds_read_u_long_int ( filein );
12838         cor3_num_inc =  ( int ) tds_read_u_short_int ( filein );
12839  
12840         for ( i = cor3_num; i < cor3_num + cor3_num_inc; i++ ) {
12841           cor3[0][i] = float_read ( filein );
12842           cor3[1][i] = float_read ( filein );
12843           cor3[2][i] = float_read ( filein );
12844         }
12845  
12846         cor3_num = cor3_num + cor3_num_inc;
12847         teller = teller + temp_pointer2;
12848         break;
12849 
12850       case 0x4111:
12851         if ( debug ) {
12852           printf ( "        POINT_FLAG_ARRAY faces (2) section tag of %0X\n", 
12853             temp_int );
12854         }
12855         teller = teller + tds_read_unknown_section ( filein );
12856         break;
12857 
12858       case 0x4120:
12859 
12860         if ( debug ) {
12861           printf ( "        FACE_ARRAY section tag of %0X\n", 
12862             temp_int );
12863         }
12864 
12865         temp_pointer2 = tds_read_u_long_int ( filein );
12866         face_num_inc = ( int ) tds_read_u_short_int ( filein );
12867  
12868         for ( i = face_num; i < face_num + face_num_inc; i++ ) {
12869           face[0][i] = tds_read_u_short_int ( filein ) + cor3_num_base;
12870           face[1][i] = tds_read_u_short_int ( filein ) + cor3_num_base;
12871           face[2][i] = tds_read_u_short_int ( filein ) + cor3_num_base;
12872           face_order[i] = 3;
12873           face_flags[i] = tds_read_u_short_int ( filein );
12874 /*
12875   Color is given per face, and as 24 bit RGB data packed in one word.
12876   Extract RGB from the word, and assign R / 255 to each vertex.
12877 
12878   Just a guess, JVB, 30 June 2001.
12879 */
12880           temp_int = face_flags[i] & 0x000F;
12881           r = ( temp_int & 0x0004 ) >> 2;
12882           g = ( temp_int & 0x0002 ) >> 1;
12883           b = ( temp_int & 0x0001 );
12884 
12885           for ( j = 0; j < 3; j++ ) {
12886             vertex_rgb[0][j][i] = ( float ) r / 255.0;
12887             vertex_rgb[1][j][i] = ( float ) g / 255.0;
12888             vertex_rgb[2][j][i] = ( float ) b / 255.0;
12889           }
12890 
12891         }
12892 
12893         temp_int = tds_read_u_short_int ( filein );
12894         if ( temp_int == 0x4150 ) {
12895           for ( i = face_num; i < face_num + face_num_inc; i++ ) {
12896             face_smooth[i] = ( int ) tds_read_u_long_int ( filein ) 
12897               + cor3_num_base;
12898           }
12899         }
12900         face_num = face_num + face_num_inc;
12901         teller = ftell ( filein );
12902         break;
12903 
12904       case 0x4130:
12905         if ( debug ) {
12906           printf ( "        MSH_MAT_GROUP section tag of %0X\n", 
12907             temp_int );
12908         }
12909         teller = teller + tds_read_unknown_section ( filein );
12910         break;
12911 
12912       case 0x4140:
12913         if ( debug ) {
12914           printf ( "        TEX_VERTS section tag of %0X\n", 
12915             temp_int );
12916         }
12917         teller = teller + tds_read_tex_verts_section ( filein );
12918         break;
12919 
12920       case 0x4150:
12921         if ( debug ) {
12922           printf ( "        SMOOTH_GROUP section tag of %0X\n", 
12923             temp_int );
12924         }
12925         teller = teller + tds_read_unknown_section ( filein );
12926         break;
12927 
12928       case 0x4160:
12929 
12930         if ( debug ) {
12931           printf ( "        MESH_MATRIX section tag of %0X\n", 
12932             temp_int );
12933         }
12934 
12935         tds_read_u_long_int ( filein );
12936 
12937         for ( j = 0; j < 4; j++ ) {
12938           for ( i = 0; i < 3; i++ ) {
12939             transform_matrix[j][i] = float_read ( filein );
12940           }
12941         }
12942         transform_matrix[0][3] = 0.0;
12943         transform_matrix[1][3] = 0.0;
12944         transform_matrix[2][3] = 0.0;
12945         transform_matrix[3][3] = 0.0;
12946 
12947         teller = teller + 12 * sizeof ( float );
12948         break;
12949 
12950       case 0x4165:
12951 
12952         if ( debug ) {
12953           printf ( "        MESH_COLOR section tag of %0X\n", temp_int );
12954         }
12955 
12956         chunk_size = tds_read_u_long_int ( filein );
12957 
12958         if ( chunk_size == 7 ) {
12959           color_index = fgetc ( filein );
12960           teller = teller + 5;
12961         }
12962         else {
12963           color_index = tds_read_u_short_int ( filein );
12964           teller = teller + 6;
12965         } 
12966         if ( debug ) {
12967           printf ( "        Color index set to %d\n", color_index );
12968         }
12969         break;
12970 
12971       case 0x4170:
12972         if ( debug ) {
12973           printf ( "        MESH_TEXTURE_INFO section tag of %0X\n", 
12974             temp_int );
12975         }
12976         teller = teller + tds_read_unknown_section ( filein );
12977         break;
12978 
12979       default:
12980         if ( debug ) {
12981           printf ( "        JUNK section tag of %0X\n", temp_int );
12982         }
12983         break;
12984     }
12985  
12986     if (  teller >= temp_pointer ) {
12987       end_found = TRUE;
12988     }
12989 
12990   }
12991  
12992   pointer = ( long int ) ( current_pointer + temp_pointer );
12993   fseek ( filein, pointer, SEEK_SET );
12994 
12995   return ( temp_pointer );
12996 }
12997 /******************************************************************************/
12998 
12999 unsigned long tds_read_object_section ( FILE *filein )
13000 
13001 /******************************************************************************/
13002 {
13003   unsigned char       end_found = FALSE;
13004   unsigned long int   current_pointer;
13005   int                 int_val;
13006   long int            pointer;
13007   unsigned short int  temp_int;
13008   unsigned long int   temp_pointer;
13009   unsigned long int   teller;
13010  
13011   current_pointer = ftell ( filein ) - 2;
13012   temp_pointer = tds_read_u_long_int ( filein );
13013   teller = 6;
13014 /*
13015   Why don't you read and save the name here?
13016 */
13017   int_val = tds_read_name ( filein );
13018 
13019   if ( int_val == -1 ) {
13020     if ( debug ) {
13021       printf ( "      Dummy Object found\n" );
13022     }
13023   }
13024   else {
13025     strcpy ( object_name, temp_name );
13026   }
13027  
13028   while ( end_found == FALSE ) {
13029 
13030     temp_int = tds_read_u_short_int ( filein );
13031     teller = teller + 2;
13032 
13033     switch ( temp_int ) {
13034       case 0x4700:
13035         if ( debug ) {
13036           printf ( "      N_CAMERA section tag of %0X\n", temp_int );
13037         }
13038         teller = teller + tds_read_camera_section ( filein );
13039         break;
13040       case 0x4600:
13041         if ( debug ) {
13042           printf ( "      N_DIRECT_LIGHT section tag of %0X\n", temp_int );
13043         }
13044         teller = teller + tds_read_light_section ( filein );
13045         break;
13046       case 0x4100:
13047         if ( debug ) {
13048           printf ( "      OBJ_TRIMESH section tag of %0X\n", temp_int );
13049         }
13050         teller = teller + tds_read_obj_section ( filein );
13051         break;
13052       case 0x4010: 
13053         if ( debug ) {
13054           printf ( "      OBJ_HIDDEN section tag of %0X\n", temp_int );
13055         }
13056         teller = teller + tds_read_unknown_section ( filein );
13057         break;
13058       case 0x4012: 
13059         if ( debug ) {
13060           printf ( "      OBJ_DOESNT_CAST section tag of %0X\n", temp_int );
13061         }
13062         teller = teller + tds_read_unknown_section ( filein );
13063         break;
13064       default:
13065         break;
13066     }
13067  
13068     if ( teller >= temp_pointer ) {
13069       end_found = TRUE;
13070     }
13071 
13072   }
13073  
13074   pointer = ( long ) ( current_pointer + temp_pointer );
13075 
13076   fseek ( filein, pointer, SEEK_SET );
13077 
13078   return ( temp_pointer );
13079 }
13080 /******************************************************************************/
13081 
13082 unsigned long int tds_read_tex_verts_section ( FILE *filein )
13083 
13084 /******************************************************************************/
13085  
13086 /*
13087   Purpose:
13088  
13089     TDS_READ_TEX_VERTS_SECTION reads the texture vertex data.
13090  
13091   Discussion:
13092  
13093     The texture vertex data seems to be associated with nodes.  This routine
13094     distributes that data to vertices (nodes as they make up a particular
13095     face).
13096  
13097   Modified:
13098  
13099     02 July 1999
13100  
13101   Author:
13102  
13103     John Burkardt
13104 */
13105 {
13106   unsigned long int  current_pointer;
13107   int                icor3;
13108   long int           pointer;
13109   unsigned long int  temp_pointer;
13110   unsigned short int n2;
13111  
13112   current_pointer = ftell ( filein ) - 2;
13113   temp_pointer = tds_read_u_long_int ( filein );
13114  
13115   pointer = ( long int ) ( current_pointer + temp_pointer );
13116 
13117   n2 = tds_read_u_short_int ( filein );
13118  
13119   for ( icor3 = 0; icor3 < n2; icor3++ ) {
13120     cor3_tex_uv[0][icor3] = float_read ( filein );
13121     cor3_tex_uv[1][icor3] = float_read ( filein );
13122   }
13123  
13124   fseek ( filein, pointer, SEEK_SET );
13125 
13126   return ( temp_pointer );
13127 }
13128 /******************************************************************************/
13129 
13130 unsigned long tds_read_texmap_section ( FILE *filein )
13131 
13132 /******************************************************************************/
13133  
13134 /*
13135   Purpose:
13136 
13137     TDS_READ_TEXMAP_SECTION tries to get the TEXMAP name from the TEXMAP section.
13138  
13139   Warning:
13140 
13141     The code has room for lots of textures.  In this routine, we behave as
13142     though there were only one, and we stick its name in the first name slot.
13143  
13144   Modified:
13145  
13146     30 June 1999
13147 
13148   Author:
13149  
13150     John Burkardt
13151 */
13152 {
13153   unsigned long int  current_pointer;
13154   long int           pointer;
13155   int                teller;
13156   unsigned long int  temp_pointer;
13157  
13158   texture_num = texture_num + 1;
13159  
13160   current_pointer = ftell ( filein ) - 2;
13161   temp_pointer = tds_read_u_long_int ( filein );
13162  
13163   tds_read_u_short_int ( filein );
13164   tds_read_u_short_int ( filein );
13165   tds_read_u_short_int ( filein );
13166   tds_read_u_short_int ( filein );
13167  
13168 /*
13169   This next short int should equal A300.
13170 */
13171   tds_read_u_short_int ( filein );
13172   tds_read_u_long_int ( filein );
13173 /*
13174   Now read the TEXMAP file name.
13175 */
13176   teller = tds_read_long_name ( filein );
13177 
13178   if ( teller == -1 ) {
13179     if ( debug ) {
13180       printf ( "      No TEXMAP name found.\n" );
13181     }
13182   }
13183   else {
13184     strcpy ( texture_name[0], temp_name );
13185     if ( debug ) {
13186       printf ( "      TEXMAP name %s.\n", texture_name[0] );
13187     }
13188   }
13189  
13190   pointer = ( long ) ( current_pointer + temp_pointer );
13191   fseek ( filein, pointer, SEEK_SET );
13192 
13193   return ( temp_pointer );
13194 }
13195 /******************************************************************************/
13196 
13197 unsigned short int tds_read_u_short_int ( FILE *filein )
13198 
13199 /******************************************************************************/
13200 {
13201   unsigned char  c1;
13202   unsigned char  c2;
13203   short int      ival;
13204 
13205   c1 = fgetc ( filein );
13206   c2 = fgetc ( filein );
13207 
13208   ival = c1 | ( c2 << 8 );
13209 
13210   return ival;
13211 }
13212 /******************************************************************************/
13213 
13214 unsigned long tds_read_spot_section ( FILE *filein )
13215 
13216 /******************************************************************************/
13217 {
13218   unsigned long int  current_pointer;
13219   float              falloff;
13220   float              hotspot;
13221   long int           pointer;
13222   float              target[4];
13223   unsigned long int  temp_pointer;
13224 
13225   current_pointer = ftell ( filein ) - 2;
13226   temp_pointer = tds_read_u_long_int ( filein );
13227  
13228   target[0] = float_read ( filein );
13229   target[1] = float_read ( filein );
13230   target[2] = float_read ( filein );
13231   hotspot = float_read ( filein );
13232   falloff = float_read ( filein );
13233  
13234   if ( debug ) {
13235     printf ( "      The target of the spot is XYZ = %f %f %f.\n",
13236       target[0], target[1], target[2] );
13237     printf ( "      The hotspot of this light is %f.\n", hotspot );
13238     printf ( "      The falloff of this light is %f.\n", falloff );
13239   }
13240  
13241   pointer = ( long ) ( current_pointer + temp_pointer );
13242 
13243   fseek ( filein, pointer, SEEK_SET );
13244 
13245   return ( temp_pointer );
13246 }
13247 /******************************************************************************/
13248 
13249 unsigned long int tds_read_unknown_section ( FILE *filein )
13250 
13251 /******************************************************************************/
13252 {
13253   unsigned long int  current_pointer;
13254   long int           pointer;
13255   unsigned long int  temp_pointer;
13256  
13257   current_pointer = ftell ( filein ) - 2;
13258   temp_pointer = tds_read_u_long_int ( filein );
13259  
13260   pointer = ( long int ) ( current_pointer + temp_pointer );
13261 
13262   fseek ( filein, pointer, SEEK_SET );
13263 
13264   return ( temp_pointer );
13265 }
13266 /******************************************************************************/
13267 
13268 unsigned long tds_read_view_section ( FILE *filein, int *views_read )
13269 
13270 /******************************************************************************/
13271 {
13272   unsigned long int   current_pointer;
13273   unsigned char       end_found = FALSE;
13274   long int            pointer;
13275   unsigned short int  temp_int;
13276   unsigned long int   temp_pointer;
13277   unsigned long int   teller;
13278  
13279   current_pointer = ftell ( filein ) - 2;
13280   temp_pointer = tds_read_u_long_int ( filein );
13281   teller = 6;
13282  
13283   while ( end_found == FALSE ) {
13284 
13285     temp_int = tds_read_u_short_int ( filein );
13286     teller = teller + 2;
13287 
13288     switch ( temp_int ) {
13289       case 0x7012:
13290         if ( debug ) {
13291           printf ( "     VIEWPORT_DATA_3 section tag of %0X\n", temp_int );
13292         }
13293         teller = teller + tds_read_vp_section ( filein, views_read );
13294         break;
13295       case 0x7011:
13296         if ( debug ) {
13297           printf ( "     VIEWPORT_DATA section tag of %0X\n", temp_int );
13298         }
13299         teller = teller + tds_read_unknown_section ( filein );
13300         break;
13301       case 0x7020:
13302         if ( debug ) {
13303           printf ( "     VIEWPORT_SIZE section tag of %0X\n", temp_int );
13304         }
13305         teller = teller + tds_read_vp_section ( filein, views_read );
13306         break;
13307       default:
13308         break;
13309     }
13310  
13311     if ( teller >= temp_pointer ) {
13312       end_found = TRUE;
13313     }
13314  
13315     if ( *views_read > 3 ) {
13316       end_found = TRUE;
13317     }
13318   }
13319  
13320   pointer = ( long int ) ( current_pointer + temp_pointer );
13321 
13322   fseek ( filein, pointer, SEEK_SET );
13323 
13324   return ( temp_pointer );
13325 }
13326 /******************************************************************************/
13327 
13328 unsigned long tds_read_vp_section ( FILE *filein, int *views_read )
13329 
13330 /******************************************************************************/
13331 {
13332   unsigned int       attribs;
13333   unsigned long int  current_pointer;
13334   int                i;
13335   int                int_val;
13336   long int           pointer;
13337   unsigned int       port;
13338   unsigned long int  temp_pointer;
13339   char              *viewports[11] = {
13340                       "Bogus",
13341                       "Top",
13342                       "Bottom",
13343                       "Left",
13344                       "Right",
13345                       "Front",
13346                       "Back",
13347                       "User",
13348                       "Camera",
13349                       "Light",
13350                       "Disabled"
13351                      };
13352 
13353   *views_read = *views_read + 1;
13354  
13355   current_pointer = ftell ( filein ) - 2;
13356   temp_pointer = tds_read_u_long_int ( filein );
13357  
13358   attribs = tds_read_u_short_int ( filein );
13359 
13360   if ( attribs == 3 ) {
13361     if ( debug ) {
13362       printf ( "<Snap> active in viewport.\n" );
13363     }
13364   }
13365 
13366   if ( attribs == 5 ) {
13367     if ( debug ) {
13368       printf ( "<Grid> active in viewport.\n" );
13369     }
13370   }
13371 /* 
13372   Read 5 INTS to get to the viewport information. 
13373 */
13374   for ( i = 1; i < 6; i++ ) {
13375     tds_read_u_short_int ( filein ); 
13376   }
13377 
13378   port = tds_read_u_short_int ( filein );
13379 /*
13380   Find camera section. 
13381 */
13382   if ( ( port == 0xffff ) || ( port == 0 ) ) {
13383 
13384     for ( i = 0; i < 12; i++ ) {
13385       tds_read_u_short_int ( filein );
13386     }
13387  
13388     int_val = tds_read_name (filein );
13389  
13390     if ( int_val == -1 ) {
13391       if ( debug ) {
13392         printf ( "      No Camera name found\n" );
13393       }
13394     }
13395 
13396     port = 0x0008;
13397   }
13398  
13399   if ( debug ) {
13400     printf ( "Reading [%s] information with tag:%d\n", viewports[port], port );
13401   }
13402  
13403   pointer = ( long int ) ( current_pointer + temp_pointer );
13404 
13405   fseek ( filein, pointer, SEEK_SET ); 
13406 
13407   return ( temp_pointer );
13408 }
13409 /******************************************************************************/
13410 
13411 int tds_write ( FILE *fileout )
13412 
13413 /******************************************************************************/
13414 
13415 /*
13416   Purpose:
13417 
13418     TDS_WRITE writes graphics information to a 3D Studio Max 3DS file.
13419 
13420   Modified:
13421 
13422     14 October 1998
13423 
13424   Author:
13425 
13426     John Burkardt
13427 
13428 */
13429 {
13430   float               float_val;
13431   int                 i;
13432   int                 icor3;
13433   int                 iface;
13434   int                 j;
13435   long int            l0002;
13436   long int            l0100;
13437   long int            l3d3d;
13438   long int            l3d3e;
13439   long int            l4000;
13440   long int            l4100;
13441   long int            l4110;
13442   long int            l4120;
13443   long int            l4150;
13444   long int            l4160;
13445   long int            l4d4d;
13446   long int            lb000;
13447   long int            lb002;
13448   long int            lb00a;
13449   long int            lb008;
13450   long int            lb009;
13451   long int            lb010;
13452   long int            lb013;
13453   long int            lb020;
13454   long int            lb021;
13455   long int            lb022;
13456   long int            lb030;
13457   long int            long_int_val;
13458   int                 name_length;
13459   short int           short_int_val;
13460   unsigned short int  u_short_int_val;
13461 
13462   bytes_num = 0;
13463   name_length = strlen ( object_name );
13464 
13465   l0002 = 10;
13466 
13467   l4150 = 2 + 4 + face_num * 4;
13468   l4120 = 2 + 4 + 2 + 4 * face_num * 2 + l4150;
13469   l4160 = 2 + 4 + 4 * 12;
13470   l4110 = 2 + 4 + 2 + cor3_num * 3 * 4;
13471   l4100 = 2 + 4 + l4110 + l4160 + l4120;
13472   l4000 = 2 + 4 + ( name_length + 1 ) + l4100;
13473   l0100 = 2 + 4 + 4;
13474   l3d3e = 2 + 4 + 4;
13475   l3d3d = 2 + 4 + l3d3e + l0100 + l4000;
13476 
13477   lb022 = 2 + 4 + 32;
13478   lb021 = 2 + 4 + 9 * 4;
13479   lb020 = 2 + 4 + 8 * 4;
13480   lb013 = 2 + 4 + 6 * 2;
13481   lb010 = 2 + 4 + ( name_length + 1 ) + 3 * 2;
13482   lb030 = 2 + 4 + 2;
13483   lb002 = 2 + 4 + lb030 + lb010 + lb013 + lb020 + lb021 + lb022;
13484   lb009 = 2 + 4 + 4;
13485   lb008 = 2 + 4 + 2 * 4;
13486   lb00a = 2 + 4 + 2 + 9 + 2 * 2;
13487   lb000 = 2 + 4 + lb00a + lb008 + lb009 + lb002;
13488 
13489   l4d4d = 2 + 4 + l0002 + l3d3d + lb000;
13490 /*  
13491   M3DMAGIC begin.
13492     tag, size.
13493 */
13494   short_int_val = ( short ) 0x4d4d;
13495   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13496   bytes_num = bytes_num + long_int_write ( fileout, l4d4d );
13497 /*
13498   M3D_VERSION begin.
13499     tag, size, version.
13500 */
13501   short_int_val = ( short ) 0x0002;
13502   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13503   bytes_num = bytes_num + long_int_write ( fileout, l0002 );
13504   long_int_val = 3;
13505   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
13506 /*  
13507   M3D_VERSION end.
13508   MDATA begin.
13509     tag, size.
13510 */
13511   short_int_val = ( short ) 0x3d3d;
13512   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13513   bytes_num = bytes_num + long_int_write ( fileout, l3d3d );
13514 /*  
13515   MESH_VERSION begin.
13516     tag, size, version.
13517 */
13518   short_int_val = ( short ) 0x3d3e;
13519   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13520   bytes_num = bytes_num + long_int_write ( fileout, l3d3e );
13521   long_int_val = 3;
13522   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
13523 /*  
13524   MESH_VERSION end.  
13525   MASTER_SCALE begin.  
13526     tag, size, scale.
13527 */
13528   short_int_val = ( short ) 0x0100;
13529   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13530   bytes_num = bytes_num + long_int_write ( fileout, l0100 );
13531   float_val = 1.0;
13532   bytes_num = bytes_num + float_write ( fileout, float_val );
13533 /*
13534   MASTER_SCALE end. 
13535   NAMED_OBJECT begin. 
13536     tag, size, name. 
13537 */
13538   short_int_val = ( short ) 0x4000;
13539   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13540   bytes_num = bytes_num + long_int_write ( fileout, l4000 );
13541   bytes_num = bytes_num + tds_write_string ( fileout, object_name );
13542 /*  
13543   N_TRI_OBJECT begin.  
13544     tag, size.
13545 */
13546   short_int_val = ( short ) 0x4100;
13547   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13548   bytes_num = bytes_num + long_int_write ( fileout, l4100 );
13549 /*
13550   POINT_ARRAY begin.  
13551     tag, size, number of points, coordinates of points.
13552   Warning! number of points could exceed a short!
13553 */
13554   short_int_val = ( short ) 0x4110;
13555   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13556   bytes_num = bytes_num + long_int_write ( fileout, l4110 );
13557 
13558   u_short_int_val = ( unsigned short ) cor3_num;
13559   bytes_num = bytes_num + tds_write_u_short_int ( fileout, u_short_int_val );
13560 
13561   for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
13562     for ( j = 0; j < 3; j++ ) {
13563       bytes_num = bytes_num + float_write ( fileout, cor3[j][icor3] );
13564     }
13565   }
13566 /*
13567   POINT_ARRAY end.
13568   MESH_MATRIX begin.  
13569     tag, size, 4 by 3 matrix.
13570 */
13571   short_int_val = ( short ) 0x4160;
13572   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13573   bytes_num = bytes_num + long_int_write ( fileout, l4160 );
13574 
13575   for ( i = 0; i < 4; i++ ) {
13576     for ( j = 0; j < 3; j++ ) {
13577       float_val = transform_matrix[i][j];
13578       bytes_num = bytes_num + float_write ( fileout, float_val );
13579     }
13580   }
13581 /*
13582   MESH_MATRIX end.  
13583   FACE_ARRAY begin. 
13584     tag, size, number of faces, nodes per face. 
13585   Warning: number of faces could exceed a short!
13586 */
13587   short_int_val = ( short ) 0x4120;
13588   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13589   bytes_num = bytes_num + long_int_write ( fileout, l4120 );
13590 
13591   u_short_int_val = ( unsigned short ) face_num;
13592   bytes_num = bytes_num + tds_write_u_short_int ( fileout, u_short_int_val );
13593 
13594   for ( iface = 0; iface < face_num; iface++ ) {
13595     for ( j = 0; j < 3; j++ ) {
13596       short_int_val = face[j][iface];
13597       bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13598     }
13599     short_int_val = face_flags[iface];
13600     bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13601   }
13602 /*
13603   SMOOTH_GROUP begin.
13604     tag, size, group for each face.
13605 */
13606   short_int_val = ( short ) 0x4150;
13607   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13608   bytes_num = bytes_num + long_int_write ( fileout, l4150 );
13609 
13610   for ( iface = 0; iface < face_num; iface++ ) {
13611     long_int_val = face_smooth[iface];
13612     bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
13613   }
13614 /*
13615   SMOOTH_GROUP end.
13616   FACE_ARRAY end.
13617   N_TRI_OBJECT end.
13618   NAMED_OBJECT end.
13619   MDATA end. 
13620   KFDATA begin.
13621 */
13622   short_int_val = ( short ) 0xb000;
13623   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13624   bytes_num = bytes_num + long_int_write ( fileout, lb000 );
13625 /*
13626   KFHDR begin.  
13627     tag, size, revision, filename, animlen.
13628 */
13629   short_int_val = ( short ) 0xb00a;
13630   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13631   bytes_num = bytes_num + long_int_write ( fileout, lb00a );
13632   short_int_val = 5;
13633   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13634   bytes_num = bytes_num + tds_write_string ( fileout, "MAXSCENE" );
13635   short_int_val = 100;
13636   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13637   short_int_val = 0;
13638   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13639 /*
13640   KFHDR end.  
13641   KFSEG begin.  
13642     tag, size, start, end.
13643 */
13644   short_int_val = ( short ) 0xb008;
13645   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13646   bytes_num = bytes_num + long_int_write ( fileout, lb008 );
13647   long_int_val = 0;
13648   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
13649   long_int_val = 100;
13650   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
13651 /*
13652   KFSEG end.  
13653   KFCURTIME begin.
13654     tag, size, current_frame.
13655 */
13656   short_int_val = ( short ) 0xb009;
13657   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13658   bytes_num = bytes_num + long_int_write ( fileout, lb009 );
13659   long_int_val = 0;
13660   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
13661 /*
13662   KFCURTIME end.
13663   OBJECT_NODE_TAG begin.
13664     tag, size.  
13665 */
13666   short_int_val = ( short ) 0xb002;
13667   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13668   bytes_num = bytes_num + long_int_write ( fileout, lb002 );
13669 /*
13670   NODE_ID begin.
13671     tag, size, id.
13672 */
13673   short_int_val = ( short ) 0xb030;
13674   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13675   bytes_num = bytes_num + long_int_write ( fileout, lb030 );
13676   short_int_val = 0;
13677   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13678 /*
13679   NODE_ID end.  
13680   NODE_HDR begin. 
13681     tag, size, object_name, flag1, flag2, hierarchy.
13682 */
13683   short_int_val = ( short ) 0xb010;
13684   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13685   bytes_num = bytes_num + long_int_write ( fileout, lb010 );
13686   bytes_num = bytes_num + tds_write_string ( fileout, object_name );
13687   short_int_val = 16384;
13688   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13689   short_int_val = 0;
13690   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13691   short_int_val = -1;
13692   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13693 /*
13694   NODE_HDR end. 
13695   PIVOT begin. 
13696     tag, size, pivot_x, pivot_y, pivot_z.
13697 */
13698   short_int_val = ( short ) 0xb013;
13699   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13700   bytes_num = bytes_num + long_int_write ( fileout, lb013 );
13701   for ( i = 0; i < 3; i++ ) {
13702     float_val = pivot[i];
13703     bytes_num = bytes_num + float_write ( fileout, float_val );
13704   }
13705 /*
13706   PIVOT end. 
13707   POS_TRACK_TAG begin.  
13708     tag, size, flag, i1, i2, i3, i4, i5, i6, frame, l1, pos_x, pos_y, pos_z.
13709 */
13710   short_int_val = ( short ) 0xb020;
13711   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13712   bytes_num = bytes_num + long_int_write ( fileout, lb020 );
13713   short_int_val = 0;
13714   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13715   short_int_val = 0;
13716   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13717   short_int_val = 0;
13718   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13719   short_int_val = 0;
13720   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13721   short_int_val = 0;
13722   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13723   short_int_val = 1;
13724   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13725   short_int_val = 0;
13726   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13727   short_int_val = 0;
13728   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13729   long_int_val = 0;
13730   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
13731   for ( i = 0; i < 3; i++ ) {
13732     float_val = origin[i];
13733     bytes_num = bytes_num + float_write ( fileout, float_val );
13734   }
13735 /*
13736   POS_TRACK_TAG end. 
13737   ROT_TRACK_TAG begin. 
13738     tag, size, i1, i2, i3, i4, i5, i6, i7, i8, l1, rad, axis_x, axis_y, axis_z. 
13739 */
13740   short_int_val = ( short ) 0xb021;
13741   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13742   bytes_num = bytes_num + long_int_write ( fileout, lb021 );
13743   short_int_val = 0;
13744   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13745   short_int_val = 0;
13746   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13747   short_int_val = 0;
13748   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13749   short_int_val = 0;
13750   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13751   short_int_val = 0;
13752   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13753   short_int_val = 1;
13754   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13755   short_int_val = 0;
13756   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13757   short_int_val = 0;
13758   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13759   long_int_val = 0;
13760   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
13761   float_val = 0.0;
13762   bytes_num = bytes_num + float_write ( fileout, float_val );
13763   bytes_num = bytes_num + float_write ( fileout, float_val );
13764   bytes_num = bytes_num + float_write ( fileout, float_val );
13765   bytes_num = bytes_num + float_write ( fileout, float_val );
13766 /*
13767   ROT_TRACK_TAG end. 
13768   SCL_TRACK_TAG begin.  
13769     tag, size, i1, i2, i3, i4, i5, i6, i7, i8, l1, scale_x, scale_y, scale_z.
13770 */
13771   short_int_val = ( short ) 0xb022;
13772   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13773   bytes_num = bytes_num + long_int_write ( fileout, lb022 );
13774   short_int_val = 0;
13775   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13776   short_int_val = 0;
13777   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13778   short_int_val = 0;
13779   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13780   short_int_val = 0;
13781   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13782   short_int_val = 0;
13783   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13784   short_int_val = 1;
13785   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13786   short_int_val = 0;
13787   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13788   short_int_val = 0;
13789   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
13790   long_int_val = 0;
13791   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
13792   float_val = 1.0;
13793   bytes_num = bytes_num + float_write ( fileout, float_val );
13794   bytes_num = bytes_num + float_write ( fileout, float_val );
13795   bytes_num = bytes_num + float_write ( fileout, float_val );
13796 /*  
13797   SCL_TRACK_TAG end.
13798   OBJECT_NODE_TAG end.
13799   KFDATA end.
13800   M3DMAGIC end. 
13801 */
13802 
13803 /*
13804   Report.
13805 */
13806   printf ( "TDS_WRITE wrote %d bytes.\n", bytes_num );
13807 
13808   return SUCCESS;
13809 }
13810 /******************************************************************************/
13811 
13812 int tds_write_string ( FILE *fileout, char *string )
13813 
13814 /******************************************************************************/
13815 
13816 /*
13817   Modified:
13818 
13819     23 September 1998
13820 
13821   Author:
13822 
13823     John Burkardt
13824 */
13825 {
13826   char *c;
13827   int   nchar;
13828 
13829   nchar = 0;
13830 
13831   for ( c = string; nchar < 12; c++ ) {
13832 
13833     fputc ( *c, fileout );
13834     nchar = nchar + 1;
13835 
13836     if  ( *c == 0 ) {
13837       return nchar;
13838     }
13839 
13840   }
13841 
13842   return nchar;
13843 }
13844 /******************************************************************************/
13845 
13846 int tds_write_u_short_int ( FILE *fileout, unsigned short int short_int_val )
13847 
13848 /******************************************************************************/
13849 
13850 /*
13851   Modified:
13852 
13853     14 October 1998
13854 
13855   Author:
13856 
13857     John Burkardt
13858 */
13859 {
13860   union {
13861     unsigned short int yint;
13862     char ychar[2];
13863   } y;
13864 
13865   y.yint = short_int_val;
13866 
13867   if ( byte_swap == TRUE ) {
13868     fputc ( y.ychar[1], fileout );
13869     fputc ( y.ychar[0], fileout );
13870   }
13871   else {
13872     fputc ( y.ychar[0], fileout );
13873     fputc ( y.ychar[1], fileout );
13874   }
13875 
13876   return 2;
13877 }
13878 /**********************************************************************/
13879 
13880 int tec_write ( FILE *fileout )
13881 
13882 /**********************************************************************/
13883 
13884 /*
13885   Purpose:
13886 
13887     TEC_WRITE writes graphics information to a TECPLOT file.
13888 
13889   Discussion:
13890 
13891     The file format used is appropriate for 3D finite element surface 
13892     zone data.  Polygons are decomposed into triangles where necessary.
13893 
13894   Example:
13895 
13896     TITLE = "cube.tec created by IVCON."
13897     VARIABLES = "X", "Y", "Z", "R", "G", "B"
13898     ZONE T="TRIANGLES", N=8, E=12, F=FEPOINT, ET=TRIANGLE
13899     0.0 0.0 0.0 0.0 0.0 0.0
13900     1.0 0.0 0.0 1.0 0.0 0.0
13901     1.0 1.0 0.0 1.0 1.0 0.0
13902     0.0 1.0 0.0 0.0 1.0 0.0
13903     0.0 0.0 1.0 0.0 0.0 1.0
13904     1.0 0.0 1.0 1.0 0.0 1.0
13905     1.0 1.0 1.0 1.0 1.0 1.0
13906     0.0 1.0 1.0 0.0 1.0 1.0
13907     1 4 2
13908     2 4 3
13909     1 5 8
13910     1 2 5
13911     2 6 5
13912     2 3 6
13913     3 7 6
13914     3 4 7
13915     4 8 7
13916     4 1 8
13917     5 6 8
13918     6 7 8
13919 
13920   Modified:
13921 
13922     09 June 1999
13923 
13924   Author:
13925 
13926     John Burkardt
13927 */
13928 {
13929   float b;
13930   int face2[3];
13931   float g;
13932   int icor3;
13933   int iface;
13934   int imat;
13935   int j;
13936   int face_num2;
13937   int text_num;
13938   float r;
13939 /*
13940   Determine the number of triangular faces.
13941 */
13942   face_num2 = 0;
13943   for ( iface = 0; iface < face_num; iface++ ) {
13944     for ( j = 0; j < face_order[iface] - 2; j++ ) {
13945       face_num2 = face_num2 + 1;
13946     }
13947   }
13948 
13949   text_num = 0;
13950 
13951   fprintf ( fileout, "\"%s created by IVCON.\"\n", fileout_name );
13952   fprintf ( fileout, "VARIABLES = \"X\", \"Y\", \"Z\", \"R\", \"G\", \"B\"\n" );
13953   fprintf ( fileout, 
13954     "ZONE T=\"TRIANGLES\", N=%d, E=%d, F=FEPOINT, ET=TRIANGLE\n",
13955     cor3_num, face_num2 );
13956 
13957   text_num = text_num + 3;
13958 /*
13959   Write out X, Y, Z, R, G, B per node.
13960 */
13961   for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
13962     imat = cor3_material[icor3];
13963     r = material_rgba[0][imat];
13964     g = material_rgba[1][imat];
13965     b = material_rgba[2][imat];
13966     fprintf ( fileout, "%f %f %f %f %f %f\n", cor3[0][icor3], cor3[1][icor3],
13967       cor3[2][icor3], r, g, b );
13968     text_num = text_num + 1;
13969   }
13970 /*
13971   Do the next face.
13972 */
13973   for ( iface = 0; iface < face_num; iface++ ) {
13974 /*
13975   Break the face up into triangles, anchored at node 1.
13976 */
13977     for ( j = 0; j < face_order[iface] - 2; j++ ) {
13978 
13979       face2[0] = face[  0][iface] + 1;
13980       face2[1] = face[j+1][iface] + 1;
13981       face2[2] = face[j+2][iface] + 1;
13982 
13983       fprintf ( fileout, "%d %d %d\n", face2[0], face2[1], face2[2] );
13984       text_num = text_num + 1;
13985 
13986     }
13987 
13988   }
13989 /*
13990   Report.
13991 */
13992   printf ( "\n" );
13993   printf ( "TEC_WRITE - Wrote %d text lines.\n", text_num );
13994 
13995   return SUCCESS;
13996 }
13997 
13998 /*********************************************************************/
13999 
14000 void tmat_init ( float a[4][4] )
14001 
14002 /*********************************************************************/
14003 
14004 /*
14005   Purpose:
14006 
14007     TMAT_INIT initializes the geometric transformation matrix.
14008 
14009   Definition:
14010 
14011     The geometric transformation matrix can be thought of as a 4 by 4
14012     matrix "A" having components:
14013 
14014       r11 r12 r13 t1
14015       r21 r22 r23 t2
14016       r31 r32 r33 t3
14017         0   0   0  1
14018 
14019     This matrix encodes the rotations, scalings and translations that
14020     are applied to graphical objects.
14021 
14022     A point P = (x,y,z) is rewritten in "homogeneous coordinates" as 
14023     PH = (x,y,z,1).  Then to apply the transformations encoded in A to 
14024     the point P, we simply compute A * PH.
14025 
14026     Individual transformations, such as a scaling, can be represented
14027     by simple versions of the transformation matrix.  If the matrix
14028     A represents the current set of transformations, and we wish to 
14029     apply a new transformation B, { the original points are
14030     transformed twice:  B * ( A * PH ).  The new transformation B can
14031     be combined with the original one A, to give a single matrix C that
14032     encodes both transformations: C = B * A.
14033 
14034   Modified:
14035 
14036     19 October 1998
14037 
14038   Author:
14039 
14040     John Burkardt
14041 
14042   Reference:
14043 
14044     Foley, van Dam, Feiner, Hughes,
14045     Computer Graphics, Principles and Practice,
14046     Addison Wesley, Second Edition, 1990.
14047 
14048   Parameters:
14049 
14050     Input, float A[4][4], the geometric transformation matrix.
14051 */
14052 {
14053   int i;
14054   int j;
14055 
14056   for ( i = 0; i < 4; i++ ) {
14057     for ( j = 0; j < 4; j++ ) {
14058       if ( i == j ) {
14059         a[i][j] = 1.0;
14060       }
14061       else {
14062         a[i][j] = 0.0;
14063       }
14064     }
14065   }
14066   return;
14067 }
14068 /*********************************************************************/
14069 
14070 void tmat_mxm ( float a[4][4], float b[4][4], float c[4][4] )
14071 
14072 /*********************************************************************/
14073 
14074 /*
14075   Purpose:
14076 
14077     TMAT_MXM multiplies two geometric transformation matrices.
14078 
14079   Note:
14080 
14081     The product is accumulated in a temporary array, and { assigned
14082     to the result.  Therefore, it is legal for any two, or all three,
14083     of the arguments to share memory.
14084 
14085   Modified:
14086 
14087     19 October 1998
14088 
14089   Author:
14090 
14091     John Burkardt
14092 
14093   Reference:
14094 
14095     Foley, van Dam, Feiner, Hughes,
14096     Computer Graphics, Principles and Practice,
14097     Addison Wesley, Second Edition, 1990.
14098 
14099   Parameters:
14100 
14101     Input, float A[4][4], the first geometric transformation matrix.
14102 
14103     Input, float B[4][4], the second geometric transformation matrix.
14104 
14105     Output, float C[4][4], the product A * B.
14106 */
14107 {
14108   float d[4][4];
14109   int i;
14110   int j;
14111   int k;
14112 
14113   for ( i = 0; i < 4; i++ ) {
14114     for ( k = 0; k < 4; k++ ) {
14115       d[i][k] = 0.0;
14116       for ( j = 0; j < 4; j++ ) {
14117         d[i][k] = d[i][k] + a[i][j] * b[j][k];
14118       }
14119     }
14120   }
14121 
14122   for ( i = 0; i < 4; i++ ) {
14123     for ( j = 0; j < 4; j++ ) {
14124       c[i][j] = d[i][j];
14125     }
14126   }
14127   return;
14128 }
14129 /*********************************************************************/
14130 
14131 void tmat_mxp ( float a[4][4], float x[4], float y[4] )
14132 
14133 /*********************************************************************/
14134 
14135 /*
14136   Purpose:
14137 
14138     TMAT_MXP multiplies a geometric transformation matrix times a point.
14139 
14140   Modified:
14141 
14142     19 October 1998
14143 
14144   Author:
14145 
14146     John Burkardt
14147 
14148   Reference:
14149 
14150     Foley, van Dam, Feiner, Hughes,
14151     Computer Graphics, Principles and Practice,
14152     Addison Wesley, Second Edition, 1990.
14153 
14154   Parameters:
14155 
14156     Input, float A[4][4], the geometric transformation matrix.
14157 
14158     Input, float X[4], the point to be multiplied.  The fourth component
14159     of X is implicitly assigned the value of 1.
14160 
14161     Output, float Y[4], the result of A*X.  The product is accumulated in 
14162     a temporary vector, and { assigned to the result.  Therefore, it 
14163     is legal for X and Y to share memory.
14164 */
14165 {
14166   int i;
14167   int j;
14168   float z[4];
14169 
14170   for ( i = 0; i < 3; i++ ) {
14171     z[i] = a[i][3];
14172     for ( j = 0; j < 3; j++ ) {
14173       z[i] = z[i] + a[i][j] * x[j];
14174     }
14175   }
14176 
14177   for ( i = 0; i < 3; i++ ) {
14178     y[i] = z[i];
14179   }
14180   return;
14181 }
14182 /*********************************************************************/
14183 
14184 void tmat_mxp2 ( float a[4][4], float x[][3], float y[][3], int n )
14185 
14186 /*********************************************************************/
14187 
14188 /*
14189   Purpose:
14190 
14191     TMAT_MXP2 multiplies a geometric transformation matrix times N points.
14192 
14193   Modified:
14194 
14195     20 October 1998
14196 
14197   Author:
14198 
14199     John Burkardt
14200 
14201   Reference:
14202 
14203     Foley, van Dam, Feiner, Hughes,
14204     Computer Graphics, Principles and Practice,
14205     Addison Wesley, Second Edition, 1990.
14206 
14207   Parameters:
14208 
14209     Input, float A[4][4], the geometric transformation matrix.
14210 
14211     Input, float X[N][3], the points to be multiplied.  
14212 
14213     Output, float Y[N][3], the transformed points.  Each product is 
14214     accumulated in a temporary vector, and { assigned to the
14215     result.  Therefore, it is legal for X and Y to share memory.
14216 
14217 */
14218 {
14219   int i;
14220   int j;
14221   int k;
14222   float z[4];
14223 
14224   for ( k = 0; k < n; k++ ) {
14225 
14226     for ( i = 0; i < 3; i++ ) {
14227       z[i] = a[i][3];
14228       for ( j = 0; j < 3; j++ ) {
14229         z[i] = z[i] + a[i][j] * x[k][j];
14230       }
14231     }
14232 
14233     for ( i = 0; i < 3; i++ ) {
14234       y[k][i] = z[i];
14235     }
14236 
14237   }
14238   return;
14239 }
14240 /*********************************************************************/
14241 
14242 void tmat_mxv ( float a[4][4], float x[4], float y[4] )
14243 
14244 /*********************************************************************/
14245 
14246 /*
14247   Purpose:
14248 
14249     TMAT_MXV multiplies a geometric transformation matrix times a vector.
14250 
14251   Modified:
14252 
14253     12 August 1999
14254 
14255   Author:
14256 
14257     John Burkardt
14258 
14259   Reference:
14260 
14261     Foley, van Dam, Feiner, Hughes,
14262     Computer Graphics, Principles and Practice,
14263     Addison Wesley, Second Edition, 1990.
14264 
14265   Parameters:
14266 
14267     Input, float A[4][4], the geometric transformation matrix.
14268 
14269     Input, float X[3], the vector to be multiplied.  The fourth component
14270     of X is implicitly assigned the value of 1.
14271 
14272     Output, float Y[3], the result of A*X.  The product is accumulated in 
14273     a temporary vector, and assigned to the result.  Therefore, it 
14274     is legal for X and Y to share memory.
14275 */
14276 {
14277   int i;
14278   int j;
14279   float z[4];
14280 
14281   for ( i = 0; i < 3; i++ ) {
14282     z[i] = 0.0;
14283     for ( j = 0; j < 3; j++ ) {
14284       z[i] = z[i] + a[i][j] * x[j];
14285     }
14286     z[i] = z[i] + a[i][3];
14287   }
14288 
14289   for ( i = 0; i < 3; i++ ) {
14290     y[i] = z[i];
14291   }
14292   return;
14293 }
14294 /*********************************************************************/
14295 
14296 void tmat_rot_axis ( float a[4][4], float b[4][4], float angle, 
14297   char axis )
14298 
14299 /*********************************************************************/
14300 
14301 /*
14302   Purpose:
14303 
14304     TMAT_ROT_AXIS applies an axis rotation to the geometric transformation matrix.
14305 
14306   Modified:
14307 
14308     19 April 1999
14309 
14310   Author:
14311 
14312     John Burkardt
14313 
14314   Reference:
14315 
14316     Foley, van Dam, Feiner, Hughes,
14317     Computer Graphics, Principles and Practice,
14318     Addison Wesley, Second Edition, 1990.
14319 
14320   Parameters:
14321 
14322     Input, float A[4][4], the current geometric transformation matrix.
14323 
14324     Output, float B[4][4], the modified geometric transformation matrix.
14325     A and B may share the same memory.
14326 
14327     Input, float ANGLE, the angle, in degrees, of the rotation.
14328 
14329     Input, character AXIS, is 'X', 'Y' or 'Z', specifying the coordinate
14330     axis about which the rotation occurs.
14331 */
14332 {
14333   float c[4][4];
14334   float d[4][4];
14335   int i;
14336   int j;
14337   float theta;
14338 
14339   theta = angle * DEG_TO_RAD;
14340 
14341   tmat_init ( c );
14342 
14343   if ( axis == 'X' || axis == 'x' ) {
14344     c[1][1] =   cos ( theta );
14345     c[1][2] = - sin ( theta );
14346     c[2][1] =   sin ( theta );
14347     c[2][2] =   cos ( theta );
14348   }
14349   else if ( axis == 'Y' || axis == 'y' ) {
14350     c[0][0] =   cos ( theta );
14351     c[0][2] =   sin ( theta );
14352     c[2][0] = - sin ( theta );
14353     c[2][2] =   cos ( theta );
14354   }
14355   else if ( axis == 'Z' || axis == 'z' ) {
14356     c[0][0] =   cos ( theta );
14357     c[0][1] = - sin ( theta );
14358     c[1][0] =   sin ( theta );
14359     c[1][1] =   cos ( theta );
14360   }
14361   else {
14362     printf ( "\n" );
14363     printf ( "TMAT_ROT_AXIS - Fatal error!\n" );
14364     printf ( "  Illegal rotation axis: %c.\n", axis );
14365     printf ( "  Legal choices are 'X', 'Y', or 'Z'.\n" );
14366     return;
14367   }
14368 
14369   tmat_mxm ( c, a, d );
14370 
14371   for ( i = 0; i < 4; i++ ) {
14372     for ( j = 0; j < 4; j++ ) {
14373       b[i][j] = d[i][j];
14374     }
14375   }
14376   return;
14377 }
14378 /*********************************************************************/
14379 
14380 void tmat_rot_vector ( float a[4][4], float b[4][4], float angle, 
14381   float v1, float v2, float v3 )
14382 
14383 /*********************************************************************/
14384 
14385 /*
14386   Purpose:
14387 
14388     TMAT_ROT_VECTOR applies a rotation about a vector to the geometric transformation matrix.
14389 
14390   Modified:
14391 
14392     27 July 1999
14393 
14394   Author:
14395 
14396     John Burkardt
14397 
14398   Reference:
14399 
14400     Foley, van Dam, Feiner, Hughes,
14401     Computer Graphics, Principles and Practice,
14402     Addison Wesley, Second Edition, 1990.
14403 
14404   Parameters:
14405 
14406     Input, float A[4][4], the current geometric transformation matrix.
14407 
14408     Output, float B[4][4], the modified geometric transformation matrix.
14409     A and B may share the same memory.
14410 
14411     Input, float ANGLE, the angle, in degrees, of the rotation.
14412 
14413     Input, float V1, V2, V3, the X, Y and Z coordinates of a (nonzero)
14414     point defining a vector from the origin.  The rotation will occur
14415     about this axis.
14416 */
14417 {
14418   float c[4][4];
14419   float ca;
14420   float d[4][4];
14421   int i;
14422   int j;
14423   float sa;
14424   float theta;
14425 
14426   if ( v1 * v1 + v2 * v2 + v3 * v3 == 0.0 ) {
14427     return;
14428   }
14429 
14430   theta = angle * DEG_TO_RAD;
14431 
14432   tmat_init ( c );
14433 
14434   ca = cos ( theta );
14435   sa = sin ( theta );
14436 
14437   c[0][0] =                v1 * v1 + ca * ( 1.0 - v1 * v1 );
14438   c[0][1] = ( 1.0 - ca ) * v1 * v2 - sa * v3;
14439   c[0][2] = ( 1.0 - ca ) * v1 * v3 + sa * v2;
14440 
14441   c[1][0] = ( 1.0 - ca ) * v2 * v1 + sa * v3;
14442   c[1][1] =                v2 * v2 + ca * ( 1.0 - v2 * v2 );
14443   c[1][2] = ( 1.0 - ca ) * v2 * v3 - sa * v1;
14444 
14445   c[2][0] = ( 1.0 - ca ) * v3 * v1 - sa * v2;
14446   c[2][1] = ( 1.0 - ca ) * v3 * v2 + sa * v1;
14447   c[2][2] =                v3 * v3 + ca * ( 1.0 - v3 * v3 );
14448 
14449   tmat_mxm ( c, a, d );
14450 
14451   for ( i = 0; i < 4; i++ ) {
14452     for ( j = 0; j < 4; j++ ) {
14453       b[i][j] = d[i][j];
14454     }
14455   }
14456   return;
14457 }
14458 /*********************************************************************/
14459 
14460 void tmat_scale ( float a[4][4], float b[4][4], float sx, float sy, 
14461   float sz )
14462 
14463 /*********************************************************************/
14464 
14465 /*
14466   Purpose:
14467 
14468     TMAT_SCALE applies a scaling to the geometric transformation matrix.
14469 
14470   Modified:
14471 
14472     19 October 1998
14473 
14474   Author:
14475 
14476     John Burkardt
14477 
14478   Reference:
14479 
14480     Foley, van Dam, Feiner, Hughes,
14481     Computer Graphics, Principles and Practice,
14482     Addison Wesley, Second Edition, 1990.
14483 
14484   Parameters:
14485 
14486     Input, float A[4][4], the current geometric transformation matrix.
14487 
14488     Output, float B[4][4], the modified geometric transformation matrix.
14489     A and B may share the same memory.
14490 
14491     Input, float SX, SY, SZ, the scalings to be applied to the X, Y and
14492     Z coordinates.
14493 */
14494 {
14495   float c[4][4];
14496   float d[4][4];
14497   int i;
14498   int j;
14499 
14500   tmat_init ( c );
14501 
14502   c[0][0] = sx;
14503   c[1][1] = sy;
14504   c[2][2] = sz;
14505 
14506   tmat_mxm ( c, a, d );
14507 
14508   for ( i = 0; i < 4; i++ ) {
14509     for ( j = 0; j < 4; j++ ) {
14510       b[i][j] = d[i][j];
14511     }
14512   }
14513   return;
14514 }
14515 /*********************************************************************/
14516 
14517 void tmat_shear ( float a[4][4], float b[4][4], char *axis, float s )
14518 
14519 /*********************************************************************/
14520 
14521 /*
14522   Purpose:
14523 
14524     TMAT_SHEAR applies a shear to the geometric transformation matrix.
14525 
14526   Modified:
14527 
14528     19 October 1998
14529 
14530   Author:
14531 
14532     John Burkardt
14533 
14534   Reference:
14535 
14536     Foley, van Dam, Feiner, Hughes,
14537     Computer Graphics, Principles and Practice,
14538     Addison Wesley, Second Edition, 1990.
14539 
14540   Parameters:
14541 
14542     Input, float A[4][4], the current geometric transformation matrix.
14543 
14544     Output, float B[4][4], the modified geometric transformation matrix.
14545     A and B may share the same memory.
14546 
14547     Input, character*3 AXIS, is 'XY', 'XZ', 'YX', 'YZ', 'ZX' or 'ZY',
14548     specifying the shear equation:
14549 
14550       XY:  x' = x + s * y;
14551       XZ:  x' = x + s * z;
14552       YX:  y' = y + s * x;
14553       YZ:  y' = y + s * z;
14554       ZX:  z' = z + s * x;
14555       ZY:  z' = z + s * y.
14556 
14557     Input, float S, the shear coefficient.
14558 */
14559 {
14560   float c[4][4];
14561   float d[4][4];
14562   int i;
14563   int j;
14564 
14565   tmat_init ( c );
14566 
14567   if ( strcmp ( axis, "XY" ) == 0 || strcmp ( axis, "xy" ) == 0 ) {
14568     c[0][1] = s;
14569   }
14570   else if ( strcmp ( axis, "XZ" ) == 0 || strcmp ( axis, "xz" ) == 0 ) {
14571     c[0][2] = s;
14572   }
14573   else if ( strcmp ( axis, "YX" ) == 0 || strcmp ( axis, "yx" ) == 0 ) {
14574     c[1][0] = s;
14575   }
14576   else if ( strcmp ( axis, "YZ" ) == 0 || strcmp ( axis, "yz" ) == 0 ) {
14577     c[1][2] = s;
14578   }
14579   else if ( strcmp ( axis, "ZX" ) == 0 || strcmp ( axis, "zx" ) == 0 ) {
14580     c[2][0] = s;
14581   }
14582   else if ( strcmp ( axis, "ZY" ) == 0 || strcmp ( axis, "zy" ) == 0 ) {
14583     c[2][1] = s;
14584   }
14585   else {
14586     printf ( "\n" );
14587     printf ( "TMAT_SHEAR - Fatal error!\n" );
14588     printf ( "  Illegal shear axis: %s.\n", axis );
14589     printf ( "  Legal choices are XY, XZ, YX, YZ, ZX, or ZY.\n" );
14590     return;
14591   }
14592 
14593   tmat_mxm ( c, a, d );
14594 
14595   for ( i = 0; i < 4; i++ ) {
14596     for ( j = 0; j < 4; j++ ) {
14597       b[i][j] = d[i][j];
14598     }
14599   }
14600   return;
14601 }
14602 /*********************************************************************/
14603 
14604 void tmat_trans ( float a[4][4], float b[4][4], float x, float y, 
14605   float z )
14606 
14607 /*********************************************************************/
14608 
14609 /*
14610   Purpose:
14611 
14612     TMAT_TRANS applies a translation to the geometric transformation matrix.
14613 
14614   Modified:
14615 
14616     19 October 1998
14617 
14618   Author:
14619 
14620     John Burkardt
14621 
14622   Reference:
14623 
14624     Foley, van Dam, Feiner, Hughes,
14625     Computer Graphics, Principles and Practice,
14626     Addison Wesley, Second Edition, 1990.
14627 
14628   Parameters:
14629 
14630     Input, float A[4][4], the current geometric transformation matrix.
14631 
14632     Output, float B[4][4], the modified transformation matrix.
14633     A and B may share the same memory.
14634 
14635     Input, float X, Y, Z, the translation.  This may be thought of as the
14636     point that the origin moves to under the translation.
14637 */
14638 {
14639   int i;
14640   int j;
14641 
14642   for ( i = 0; i < 4; i++ ) {
14643     for ( j = 0; j < 4; j++ ) {
14644       b[i][j] = a[i][j];
14645     }
14646   }
14647   b[0][3] = b[0][3] + x;
14648   b[1][3] = b[1][3] + y;
14649   b[2][3] = b[2][3] + z;
14650 
14651   return;
14652 }
14653 /******************************************************************************/
14654 
14655 int tria_read ( FILE *filein )
14656 
14657 /******************************************************************************/
14658 
14659 /*
14660   Purpose:
14661    
14662     TRIA_READ reads an ASCII triangle file.
14663 
14664   Example:
14665 
14666     12                    <-- Number of triangles
14667 
14668                           (x,y,z) and (nx,ny,nz) of normal vector at:
14669 
14670     0.0 0.0 0.0 0.3 0.3 0.3   node 1 of triangle 1.
14671     1.0 0.0 0.0 0.3 0.1 0.3   node 2 of triangle 1,
14672     0.0 1.0 0.0 0.3 0.1 0.3   node 3 of triangle 1,
14673     1.0 0.5 0.0 0.3 0.1 0.3   node 1 of triangle 2,
14674     ...
14675     0.0 0.5 0.5 0.3 0.1 0.3   node 3 of triangle 12.
14676 
14677   Modified:
14678 
14679     22 June 1999
14680 
14681   Author:
14682  
14683     John Burkardt
14684 */
14685 {
14686   float cvec[3];
14687   int   icor3;
14688   int   iface;
14689   int   iface_hi;
14690   int   iface_lo;
14691   int   ivert;
14692   int   face_num2;
14693   float r1;
14694   float r2;
14695   float r3;
14696   float r4;
14697   float r5;
14698   float r6;
14699 /*
14700   Get the number of triangles.
14701 */
14702   fgets ( input, LINE_MAX_LEN, filein );
14703   text_num = text_num + 1;
14704   sscanf ( input, "%d", &face_num2 );
14705 /*
14706   For each triangle:
14707 */
14708   iface_lo = face_num;
14709   iface_hi = face_num + face_num2;
14710 
14711   for ( iface = iface_lo; iface < iface_hi; iface++ ) {
14712 
14713     if ( iface < FACE_MAX ) {
14714       face_order[iface] = 3;
14715       face_material[iface] = 0;
14716     }
14717 /*
14718   For each face:
14719 */
14720     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
14721 
14722       fgets ( input, LINE_MAX_LEN, filein );
14723       text_num = text_num + 1;
14724       sscanf ( input, "%e %e %e %e %e %e", &r1, &r2, &r3, &r4, &r5, &r6 ); 
14725  
14726       cvec[0] = r1;
14727       cvec[1] = r2;
14728       cvec[2] = r3;
14729 
14730       if ( cor3_num < 1000 ) {
14731         icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
14732       }
14733       else {
14734         icor3 = -1;
14735       }
14736 
14737       if ( icor3 == -1 ) {
14738         icor3 = cor3_num;
14739         if ( cor3_num < COR3_MAX ) {
14740           cor3[0][cor3_num] = cvec[0];
14741           cor3[1][cor3_num] = cvec[1];
14742           cor3[2][cor3_num] = cvec[2];
14743         }
14744         cor3_num = cor3_num + 1;
14745       }
14746       else {
14747         dup_num = dup_num + 1;
14748       }
14749 
14750       if ( iface < FACE_MAX ) {
14751 
14752         face[ivert][iface] = icor3;
14753         vertex_material[ivert][iface] = 0;
14754         vertex_normal[0][ivert][iface] = r4;
14755         vertex_normal[1][ivert][iface] = r5;
14756         vertex_normal[2][ivert][iface] = r6;
14757       }
14758 
14759     }
14760   }
14761   face_num = face_num + face_num2;
14762 
14763   return SUCCESS;
14764 }
14765 /**********************************************************************/
14766 
14767 int tria_write ( FILE *fileout )
14768 
14769 /**********************************************************************/
14770 
14771 /*
14772   Purpose:
14773 
14774     TRIA_WRITE writes the graphics data to an ASCII "triangle" file.
14775 
14776   Discussion:
14777 
14778     This is just a private format that Greg Hood requested from me.
14779 
14780   Example:
14781 
14782     12                    <-- Number of triangles
14783 
14784                           (x,y,z) and (nx,ny,nz) of normal vector at:
14785 
14786     0.0 0.0 0.0 0.3 0.3 0.3   node 1 of triangle 1.
14787     1.0 0.0 0.0 0.3 0.1 0.3   node 2 of triangle 1,
14788     0.0 1.0 0.0 0.3 0.1 0.3   node 3 of triangle 1,
14789     1.0 0.5 0.0 0.3 0.1 0.3   node 1 of triangle 2,
14790     ...
14791     0.0 0.5 0.5 0.3 0.1 0.3   node 3 of triangle 12.
14792 
14793   Modified:
14794 
14795     10 June 1999
14796 
14797   Author:
14798 
14799     John Burkardt
14800 */
14801 {
14802   int face2[3];
14803   int icor3;
14804   int iface;
14805   int jlo;
14806   int k;
14807   int face_num2;
14808   int text_num;
14809   float nx;
14810   float ny;
14811   float nz;
14812   float x;
14813   float y;
14814   float z;
14815 
14816   text_num = 0;
14817 /*
14818   Determine the number of triangular faces.
14819 */
14820   face_num2 = 0;
14821   for ( iface = 0; iface < face_num; iface++ ) {
14822     for ( jlo = 0; jlo < face_order[iface] - 2; jlo ++ ) {
14823       face_num2 = face_num2 + 1;
14824     }
14825   }
14826 
14827   fprintf ( fileout,  "%d\n", face_num2 );
14828   text_num = text_num + 1;
14829 /*
14830   Do the next face.
14831 */
14832   for ( iface = 0; iface < face_num; iface++ ) {
14833 /*
14834   Break the face up into triangles, anchored at node 1.
14835 */
14836     for ( jlo = 0; jlo < face_order[iface] - 2; jlo ++ ) {
14837 
14838       face2[0] = face[    0][iface];
14839       face2[1] = face[jlo+1][iface];
14840       face2[2] = face[jlo+2][iface];
14841 
14842       for ( k = 0; k < 3; k++ ) {
14843 
14844         icor3 = face2[k];
14845 
14846         x = cor3[0][icor3];
14847         y = cor3[1][icor3];
14848         z = cor3[2][icor3];
14849 
14850         nx = cor3_normal[0][icor3];
14851         ny = cor3_normal[1][icor3];
14852         nz = cor3_normal[2][icor3];
14853 
14854         fprintf ( fileout,  "%f %f %f %f %f %f\n", x, y, z, nx, ny, nz );
14855 
14856         text_num = text_num + 1;
14857 
14858       }
14859 
14860     }
14861 
14862   }
14863 /*
14864   Report.
14865 */
14866   printf ( "\n" );
14867   printf ( "TRIA_WRITE - Wrote %d text lines.\n", text_num );
14868 
14869   return SUCCESS;
14870 }
14871 /******************************************************************************/
14872 
14873 int trib_read ( FILE *filein )
14874 
14875 /******************************************************************************/
14876 
14877 /*
14878   Purpose:
14879    
14880     TRIB_READ reads a binary triangle file.
14881 
14882   Example:
14883 
14884     4 byte int = number of triangles
14885 
14886     For each triangular face:
14887 
14888       3 4-byte floats = coordinates of first node;
14889       3 4-byte floats = components of normal vector at first node;
14890       3 4-byte floats = coordinates of second node;
14891       3 4-byte floats = components of normal vector at second node;
14892       3 4-byte floats = coordinates of third node;
14893       3 4-byte floats = components of normal vector at third node.
14894 
14895   Modified:
14896 
14897     22 June 1999
14898 
14899   Author:
14900  
14901     John Burkardt
14902 */
14903 {
14904   float cvec[3];
14905   int icor3;
14906   int i;
14907   int iface;
14908   int iface_hi;
14909   int iface_lo;
14910   int ivert;
14911   int face_num2;
14912 /* 
14913   Read the number of triangles in the file.
14914 */
14915   face_num2 = long_int_read ( filein );
14916   bytes_num = bytes_num + 4;
14917 /*
14918   For each (triangular) face,
14919     read the coordinates and normal vectors of three vertices,
14920 */
14921   iface_lo = face_num;
14922   iface_hi = face_num + face_num2;
14923 
14924   for ( iface = iface_lo; iface < iface_hi; iface++ ) {
14925 
14926     if ( iface < FACE_MAX ) {
14927       face_order[iface] = 3;
14928       face_material[iface] = 0;
14929     }
14930 
14931     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
14932 
14933       for ( i = 0; i < 3; i++ ) {
14934         cvec[i] = float_read ( filein );
14935         bytes_num = bytes_num + 4;
14936       }
14937 
14938       if ( cor3_num < 1000 ) {
14939         icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
14940       }
14941       else {
14942         icor3 = -1;
14943       }
14944 
14945       if ( icor3 == -1 ) {
14946         icor3 = cor3_num;
14947         if ( cor3_num < COR3_MAX ) {
14948           cor3[0][cor3_num] = cvec[0];
14949           cor3[1][cor3_num] = cvec[1];
14950           cor3[2][cor3_num] = cvec[2];
14951         }
14952         cor3_num = cor3_num + 1;
14953       }
14954       else {
14955         dup_num = dup_num + 1;
14956       }
14957 
14958       if ( iface < FACE_MAX ) {
14959 
14960         face[ivert][iface] = icor3;
14961         vertex_material[ivert][iface] = 0;
14962 
14963         for ( i = 0; i < 3; i++ ) {
14964           vertex_normal[i][ivert][iface] = float_read ( filein );
14965           bytes_num = bytes_num + 4;
14966         }
14967 
14968       }
14969 
14970     }
14971   }
14972 
14973   face_num = face_num + face_num2;
14974 
14975   return SUCCESS;
14976 }
14977 /**********************************************************************/
14978 
14979 int trib_write ( FILE *fileout )
14980 
14981 /**********************************************************************/
14982 
14983 /*
14984   Purpose:
14985 
14986     TRIB_WRITE writes the graphics data to a binary "triangle" file.
14987 
14988   Discussion:
14989 
14990     This is just a private format that Greg Hood requested from me.
14991 
14992   Example:
14993 
14994     12   Number of triangles
14995     0.0  x at node 1, triangle 1,
14996     0.0  y at node 1, triangle 1,
14997     0.0  z at node 1, triangle 1,
14998     0.3  nx at node 1, triangle 1,
14999     0.3  ny at node 1, triangle 1,
15000     0.3  nz at node 1, triangle 1.
15001     1.0  x at node 2, triangle 1,
15002     ...
15003     0.7  nz at node 3, triangle 1.
15004     1.2  x at node 1, triangle 2,
15005     ...
15006     0.3  nz at node 3, triangle 2.
15007     9.3  x at node 1, triangle 3,
15008     ...
15009     0.3  nz at node 3, triangle 12.
15010 
15011   Modified:
15012 
15013     16 June 1999
15014 
15015   Author:
15016 
15017     John Burkardt
15018 */
15019 {
15020   int face2[3];
15021   int icor3;
15022   int iface;
15023   int jlo;
15024   int k;
15025   int face_num2;
15026   float nx;
15027   float ny;
15028   float nz;
15029   float x;
15030   float y;
15031   float z;
15032 
15033   bytes_num = 0;
15034 /*
15035   Determine the number of triangular faces.
15036 */
15037   face_num2 = 0;
15038   for ( iface = 0; iface < face_num; iface++ ) {
15039     for ( jlo = 0; jlo < face_order[iface] - 2; jlo ++ ) {
15040       face_num2 = face_num2 + 1;
15041     }
15042   }
15043 
15044   bytes_num = bytes_num + long_int_write ( fileout, face_num2 );
15045 /*
15046   Do the next face.
15047 */
15048   for ( iface = 0; iface < face_num; iface++ ) {
15049 /*
15050   Break the face up into triangles, anchored at node 1.
15051 */
15052     for ( jlo = 0; jlo < face_order[iface] - 2; jlo ++ ) {
15053 
15054       face2[0] = face[    0][iface];
15055       face2[1] = face[jlo+1][iface];
15056       face2[2] = face[jlo+2][iface];
15057 
15058       for ( k = 0; k < 3; k++ ) {
15059 
15060         icor3 = face2[k];
15061 
15062         x = cor3[0][icor3];
15063         y = cor3[1][icor3];
15064         z = cor3[2][icor3];
15065 
15066         nx = cor3_normal[0][icor3];
15067         ny = cor3_normal[1][icor3];
15068         nz = cor3_normal[2][icor3];
15069 
15070         bytes_num = bytes_num + float_write ( fileout, x );
15071         bytes_num = bytes_num + float_write ( fileout, y );
15072         bytes_num = bytes_num + float_write ( fileout, z );
15073         bytes_num = bytes_num + float_write ( fileout, nx );
15074         bytes_num = bytes_num + float_write ( fileout, ny );
15075         bytes_num = bytes_num + float_write ( fileout, nz );
15076 
15077       }
15078 
15079     }
15080 
15081   }
15082 /*
15083   Report.
15084 */
15085   printf ( "\n" );
15086   printf ( "TRIB_WRITE - Wrote %d bytes.\n", bytes_num );
15087 
15088   return SUCCESS;
15089 }
15090 /******************************************************************************/
15091 
15092 int txt_write ( FILE *fileout )
15093 
15094 /******************************************************************************/
15095 
15096 /*
15097   Purpose:
15098    
15099     TXT_WRITE writes the graphics data to a text file.
15100 
15101   Modified:
15102 
15103     25 June 1998
15104 
15105   Author:
15106  
15107     John Burkardt
15108 */
15109 {
15110   int i;
15111   int iface;
15112   int iline;
15113   int imat;
15114   int ivert;
15115   int nitem;
15116   int text_num;
15117 
15118   text_num = 0;
15119 
15120   fprintf ( fileout, "%s created by IVCON.\n", fileout_name );
15121   fprintf ( fileout, "Original data in %s.\n", filein_name );
15122   fprintf ( fileout, "Object name is %s.\n", object_name );
15123   fprintf ( fileout, "Object origin at %f %f %f.\n", origin[0], origin[1],
15124     origin[2] );
15125   fprintf ( fileout, "Object pivot at %f %f %f.\n", pivot[0], pivot[1],
15126     pivot[2] );
15127   text_num = text_num + 5;
15128 /*
15129   TRANSFORMATION MATRIX.
15130 */
15131   fprintf ( fileout, "\n" );
15132   fprintf ( fileout, "Transformation matrix:\n" );
15133   fprintf ( fileout, "\n" );
15134   text_num = text_num + 3;
15135 
15136   for ( i = 0; i < 4; i++ ) {
15137     fprintf ( fileout, "  %f %f %f %f\n", transform_matrix[i][0],
15138       transform_matrix[i][1], transform_matrix[i][2], transform_matrix[i][3] );
15139       text_num = text_num + 1;
15140   }
15141 /*
15142   NODES.
15143 */
15144   fprintf ( fileout, "\n" );
15145   fprintf ( fileout, "  %d nodes.\n", cor3_num );
15146   text_num = text_num + 2;
15147 
15148   if ( cor3_num > 0 ) {
15149 
15150     fprintf ( fileout, "\n" );
15151     fprintf ( fileout, "  Node coordinate data:\n" );
15152     fprintf ( fileout, "\n" );
15153     text_num = text_num + 3;
15154 
15155     for ( i = 0; i < cor3_num; i++ ) {
15156       fprintf ( fileout, " %d %f %f %f\n ", i, cor3[0][i], cor3[1][i], 
15157         cor3[2][i] );
15158       text_num = text_num + 1;
15159     }
15160 
15161     fprintf ( fileout, "\n" );
15162     fprintf ( fileout, "  Node normal vectors:\n" );
15163     fprintf ( fileout, "\n" );
15164     text_num = text_num + 3;
15165 
15166     for ( i = 0; i < cor3_num; i++ ) {
15167       fprintf ( fileout, " %d %f %f %f\n ", i, cor3_normal[0][i], 
15168         cor3_normal[1][i], cor3_normal[2][i] );
15169       text_num = text_num + 1;
15170     }
15171 
15172     fprintf ( fileout, "\n" );
15173     fprintf ( fileout, "  Node materials:\n" );
15174     fprintf ( fileout, "\n" );
15175     text_num = text_num + 3;
15176 
15177     for ( i = 0; i < cor3_num; i++ ) {
15178       fprintf ( fileout, " %d %d\n ", i, cor3_material[i] );
15179       text_num = text_num + 1;
15180     }
15181 
15182     if ( texture_num > 0 ) {
15183       fprintf ( fileout, "\n" );
15184       fprintf ( fileout, "  Node texture coordinates:\n" );
15185       fprintf ( fileout, "\n" );
15186       text_num = text_num + 3;
15187 
15188       for ( i = 0; i < cor3_num; i++ ) {
15189         fprintf ( fileout, " %d %f %f\n ", i, cor3_tex_uv[0][i], 
15190           cor3_tex_uv[1][i] );
15191         text_num = text_num + 1;
15192       }
15193     }
15194   }
15195 /*
15196   LINES.
15197 */
15198   fprintf ( fileout, "\n" );
15199   fprintf ( fileout, "  %d line data items.\n", line_num );
15200   text_num = text_num + 2;
15201 
15202   if ( line_num > 0 ) {
15203 
15204     fprintf ( fileout, "\n" );
15205     fprintf ( fileout, "  Line index data:\n" );
15206     fprintf ( fileout, "\n" );
15207     text_num = text_num + 3;
15208 
15209     nitem = 0;
15210 
15211     for ( iline = 0; iline < line_num; iline++ ) {
15212 
15213       fprintf ( fileout, " %d", line_dex[iline] );
15214       nitem = nitem + 1;
15215 
15216       if ( iline == line_num - 1 || line_dex[iline] == -1 || nitem >= 10 ) {
15217         nitem = 0;
15218         fprintf ( fileout, "\n" );
15219         text_num = text_num + 1;
15220       }
15221 
15222     }
15223 
15224     fprintf ( fileout, "\n" );
15225     fprintf ( fileout, "  Line materials:\n" );
15226     fprintf ( fileout, "\n" );
15227     text_num = text_num + 3;
15228 
15229     nitem = 0;
15230 
15231     for ( iline = 0; iline < line_num; iline++ ) {
15232 
15233       fprintf ( fileout, " %d", line_material[iline] );
15234       nitem = nitem + 1;
15235 
15236       if ( iline == line_num - 1 || line_material[iline] == -1 || nitem >= 10 ) {
15237         nitem = 0;
15238         fprintf ( fileout, "\n" );
15239         text_num = text_num + 1;
15240       }
15241     }
15242 
15243   }
15244 /*
15245   COLOR DATA
15246 */
15247   fprintf ( fileout, "\n" );
15248   fprintf ( fileout, "  %d colors.\n", color_num );
15249   text_num = text_num + 2;
15250 /*
15251   FACES.
15252 */
15253   fprintf ( fileout, "\n" );
15254   fprintf ( fileout, "  %d faces.\n", face_num );
15255   text_num = text_num + 2;
15256 
15257   if ( face_num > 0 ) {
15258 
15259     fprintf ( fileout, "\n" );
15260     fprintf ( fileout, "  Face, Material, Number of vertices, Smoothing, Flags:\n" );
15261     fprintf ( fileout, "\n" );
15262     text_num = text_num + 3;
15263 
15264     for ( iface = 0; iface < face_num; iface++ ) {
15265       fprintf ( fileout, " %d %d %d %d %d\n", iface, face_material[iface],
15266         face_order[iface], face_smooth[iface], face_flags[iface] );
15267       text_num = text_num + 1;
15268     }
15269 
15270     fprintf ( fileout, "\n" );
15271     fprintf ( fileout, "  Face, Vertices\n" );
15272     fprintf ( fileout, "\n" );
15273     text_num = text_num + 3;
15274 
15275     for ( iface = 0; iface < face_num; iface++ ) {
15276 
15277       fprintf ( fileout, "%d   ", iface );
15278       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
15279         fprintf ( fileout, " %d", face[ivert][iface] );
15280       }
15281 
15282       fprintf ( fileout, "\n" );
15283       text_num = text_num + 1;
15284     }
15285 
15286     fprintf ( fileout, "\n" );
15287     fprintf ( fileout, "  Face normal vectors:\n" );
15288     fprintf ( fileout, "\n" );
15289     text_num = text_num + 3;
15290 
15291     for ( iface = 0; iface < face_num; iface++ ) {
15292       fprintf ( fileout, " %d %f %f %f\n", iface, face_normal[0][iface],
15293         face_normal[1][iface], face_normal[2][iface] );
15294       text_num = text_num + 1;
15295     }
15296 
15297     if ( texture_num > 0 ) {
15298 
15299       fprintf ( fileout, "\n" );
15300       fprintf ( fileout, "  Face texture coordinates:\n" );
15301       fprintf ( fileout, "\n" );
15302       text_num = text_num + 3;
15303 
15304       for ( iface = 0; iface < face_num; iface++ ) {
15305         fprintf ( fileout, " %d %f %f\n", iface, face_tex_uv[0][iface],
15306           face_tex_uv[1][iface] );
15307         text_num = text_num + 1;
15308       }
15309     }
15310   }
15311 /*
15312   VERTICES.
15313 */
15314   if ( face_num > 0 ) {
15315 
15316     fprintf ( fileout, "\n" );
15317     fprintf ( fileout, "Vertex normal vectors:\n" );
15318     text_num = text_num + 2;
15319 
15320     for ( iface = 0; iface < face_num; iface++ ) {
15321       fprintf ( fileout, "\n" );
15322       text_num = text_num + 1;
15323       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
15324         fprintf ( fileout, " %d %d %f %f %f\n", iface, ivert, 
15325           vertex_normal[0][ivert][iface], vertex_normal[1][ivert][iface],
15326           vertex_normal[2][ivert][iface] );
15327         text_num = text_num + 1;
15328       }
15329     }
15330 
15331     fprintf ( fileout, "\n" );
15332     fprintf ( fileout, "Vertex materials:\n" );
15333     fprintf ( fileout, "\n" );
15334     text_num = text_num + 3;
15335 
15336     for ( iface = 0; iface < face_num; iface++ ) {
15337       fprintf ( fileout, "%d", iface );
15338       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
15339         fprintf ( fileout, " %d", vertex_material[ivert][iface] );
15340       }
15341       fprintf ( fileout, "\n" );
15342       text_num = text_num + 1;
15343     }
15344 
15345     if ( texture_num > 0 ) {
15346 
15347       fprintf ( fileout, "\n" );
15348       fprintf ( fileout, "Vertex UV texture coordinates:\n" );
15349       fprintf ( fileout, "\n" );
15350       text_num = text_num + 3;
15351 
15352       for ( iface = 0; iface < face_num; iface++ ) {
15353         for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
15354           fprintf ( fileout, "%d %d %f %f\n", iface, ivert,
15355             vertex_tex_uv[0][ivert][iface], vertex_tex_uv[1][ivert][iface] );
15356           text_num = text_num + 1;
15357         }
15358       }
15359     }
15360   }
15361 /*
15362   MATERIALS.
15363 */
15364   fprintf ( fileout, "\n" );
15365   fprintf ( fileout, "%d materials.\n", material_num );
15366   fprintf ( fileout, "\n" );
15367   fprintf ( fileout, "Index      Name   R G B A\n" );
15368   fprintf ( fileout, "\n" );
15369 
15370   text_num = text_num + 5;
15371 
15372   for ( imat = 0; imat < material_num; imat++ ) {
15373     fprintf ( fileout, "%d %s %f %f %f %f\n", imat, material_name[imat],
15374       material_rgba[0][imat], material_rgba[1][imat], material_rgba[2][imat],
15375       material_rgba[3][imat] );
15376     text_num = text_num + 1;
15377   }
15378 /*
15379   TEXTURES.
15380 */
15381   fprintf ( fileout, "\n" );
15382   fprintf ( fileout, "%d textures.\n", texture_num );
15383   text_num = text_num + 2;
15384 
15385   if ( texture_num > 0 ) {
15386     fprintf ( fileout, "\n" );
15387     fprintf ( fileout, "Index  Name\n" );
15388     fprintf ( fileout, "\n" );
15389     for ( i = 0; i < texture_num; i++ ) {
15390       fprintf ( fileout, "%d %s\n", i, texture_name[i] );
15391     }
15392     text_num = text_num + 3;
15393   }
15394 /*
15395   Report.
15396 */
15397   printf ( "\n" );
15398   printf ( "TXT_WRITE - Wrote %d text lines.\n", text_num );
15399 
15400   return SUCCESS;
15401 }
15402 /**********************************************************************/
15403 
15404 int ucd_write ( FILE *fileout )
15405 
15406 /**********************************************************************/
15407 
15408 /*
15409   Purpose:
15410 
15411     UCD_WRITE writes graphics data to an AVS UCD file.
15412 
15413   Examples:
15414 
15415     #  cube.ucd created by IVREAD.
15416     #
15417     #  Material RGB to hue map:
15418     #
15419     #  material    R    G  B   Alpha     Hue
15420     #
15421     #    0   0.94  0.70  0.15  1.000   0.116
15422     #    1   0.24  0.70  0.85  1.000   0.541
15423     #    2   0.24  0.00  0.85  1.000   0.666
15424     #
15425     #  The node data is
15426     #    node # / material # / RGBA / Hue
15427     #
15428     8  6  6  0  0
15429     0  0.0  0.0  0.0
15430     1  1.0  0.0  0.0
15431     2  1.0  1.0  0.0
15432     3  0.0  1.0  0.0
15433     4  0.0  0.0  1.0
15434     5  1.0  0.0  1.0
15435     6  1.0  1.0  1.0
15436     7  0.0  1.0  1.0
15437     0  0  quad  0  1  2  3
15438     1  0  quad  0  4  5  1
15439     2  0  quad  1  5  6  2
15440     3  0  quad  2  6  7  3
15441     4  0  quad  3  7  4  0
15442     5  0  quad  4  7  6  5
15443     3  1 4 1
15444     material, 0...2
15445     RGBA, 0-1/0-1/0-1/0-1
15446     Hue, 0-1
15447     0  0  0.94  0.70  0.15  1.0  0.116
15448     1  0  0.94  0.70  0.15  1.0  0.116
15449     2  0  0.94  0.70  0.15  1.0  0.116
15450     3  0  0.94  0.70  0.15  1.0  0.116
15451     4  1  0.24  0.70  0.85  1.0  0.541
15452     5  1  0.24  0.70  0.85  1.0  0.541
15453     6  2  0.24  0.24  0.85  0.0  0.666
15454     7  2  0.24  0.24  0.85  0.0  0.666
15455 
15456   Modified:
15457 
15458     22 May 1999
15459 
15460   Author:
15461 
15462     John Burkardt
15463 
15464 */
15465 {
15466   float a;
15467   float b;
15468   float g;
15469   float h;
15470   int i;
15471   int imat;
15472   int j;
15473   int text_num;
15474   float r;
15475 
15476   text_num = 0;
15477 
15478   fprintf ( fileout, "#  %s created by IVREAD.\n", fileout_name );
15479   fprintf ( fileout, "#\n" );
15480   fprintf ( fileout, "#  Material RGB to Hue map:\n" );
15481   fprintf ( fileout, "#\n" );
15482   fprintf ( fileout, "#  material    R    G      B     Alpha  Hue\n" );
15483   fprintf ( fileout, "#\n" );
15484 
15485   text_num = text_num + 6;
15486 
15487   for ( j = 0; j < material_num; j++ ) {
15488     r = material_rgba[0][j];
15489     g = material_rgba[1][j];
15490     b = material_rgba[2][j];
15491     a = material_rgba[3][j];
15492     h = rgb_to_hue ( r, g, b );
15493     fprintf ( fileout, "#  %d %f %f %f %f %f\n", j, r, g, b, a, h );
15494     text_num = text_num + 1;
15495   }
15496 
15497   fprintf ( fileout, "#\n" );
15498   fprintf ( fileout, "#  The node data is\n" );
15499   fprintf ( fileout, "#    node # / material # / RGBA / Hue\n" );
15500   fprintf ( fileout, "#\n" );
15501   text_num = text_num + 4;
15502 
15503   fprintf ( fileout, "%d %d 6 0 0\n", cor3_num, face_num );
15504   text_num = text_num + 1;
15505 
15506   for ( j = 0; j < cor3_num; j++ ) {
15507     fprintf ( fileout, "%d %f %f %f\n", j, cor3[0][j], cor3[1][j],
15508       cor3[2][j] );
15509     text_num = text_num + 1;
15510   }
15511 /*
15512   NOTE:
15513   UCD only accepts triangles and quadrilaterals, not higher order
15514   polygons.  We would need to break polygons up to proceed.
15515 */
15516   for ( j = 0; j < face_num; j++ ) {
15517 
15518     fprintf ( fileout, "%d %d", j, face_material[j] );
15519 
15520     if ( face_order[j] == 3 ) {
15521       fprintf ( fileout, " tri" );
15522     }
15523     else if ( face_order[j] == 4 ) {
15524       fprintf ( fileout, " quad" );
15525     }
15526     else {
15527       fprintf ( fileout, " ???" );
15528     }
15529 
15530     for ( i = 0; i < face_order[j]; i++ ) {
15531       fprintf ( fileout, "%d", face[i][j] );
15532     }
15533     fprintf ( fileout, "\n" );
15534     text_num = text_num + 1;
15535 
15536   }
15537 
15538   fprintf ( fileout, "3  1  4  1\n" );
15539   fprintf ( fileout, "material, 0...%d\n", material_num - 1 );
15540   fprintf ( fileout, "RGBA, 0-1/0-1/0-1/0-1\n" );
15541   fprintf ( fileout, "Hue, 0-1\n" );
15542   text_num = text_num + 4;
15543 
15544   for ( j = 0; j < cor3_num; j++ ) {
15545     imat = cor3_material[j];
15546     r = material_rgba[0][imat];
15547     g = material_rgba[1][imat];
15548     b = material_rgba[2][imat];
15549     a = material_rgba[3][imat];
15550     h = rgb_to_hue ( r, g, b );
15551 
15552     fprintf ( fileout, "%d %d %f %f %f %f %f\n", j, imat, r, g, b, a, h );
15553     text_num = text_num + 1;
15554   }
15555 /*
15556   Report.
15557 */
15558   printf ( "\n" );
15559   printf ( "UCD_WRITE - Wrote %d text lines.\n", text_num );
15560 
15561   return SUCCESS;
15562 }
15563 /******************************************************************************/
15564 
15565 void vertex_normal_set ( void )
15566 
15567 /******************************************************************************/
15568 
15569 /*
15570   Purpose:
15571 
15572     VERTEX_NORMAL_SET recomputes the face vertex normal vectors.
15573 
15574   Modified:
15575 
15576     12 October 1998
15577 
15578   Author:
15579 
15580     John Burkardt
15581 */
15582 {
15583   int   i;
15584   int   i0;
15585   int   i1;
15586   int   i2;
15587   int   iface;
15588   int   ivert;
15589   int   jp1;
15590   int   jp2;
15591   int   nfix;
15592   float norm;
15593   float temp;
15594   float x0;
15595   float x1;
15596   float x2;
15597   float xc;
15598   float y0;
15599   float y1;
15600   float y2;
15601   float yc;
15602   float z0;
15603   float z1;
15604   float z2;
15605   float zc;
15606 
15607   if ( face_num <= 0 ) {
15608     return;
15609   }
15610 
15611   nfix = 0;
15612 /*
15613   Consider each face.
15614 */
15615   for ( iface = 0; iface < face_num; iface++ ) {
15616 
15617     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
15618 
15619       norm = 0.0;
15620       for ( i = 0; i < 3; i++ ) {
15621         temp = vertex_normal[i][ivert][iface];
15622         norm = norm + temp * temp;
15623       }
15624       norm = ( float ) sqrt ( norm );
15625 
15626       if ( norm == 0.0 ) {
15627 
15628         nfix = nfix + 1;
15629 
15630         i0 = face[ivert][iface];
15631         x0 = cor3[0][i0];
15632         y0 = cor3[1][i0];
15633         z0 = cor3[2][i0];
15634 
15635         jp1 = ivert + 1;
15636         if ( jp1 >= face_order[iface] ) {
15637           jp1 = jp1 - face_order[iface];
15638         }
15639         i1 = face[jp1][iface];
15640         x1 = cor3[0][i1];
15641         y1 = cor3[1][i1];
15642         z1 = cor3[2][i1];
15643 
15644         jp2 = ivert + 2;
15645         if ( jp2 >= face_order[iface] ) {
15646           jp2 = jp2 - face_order[iface];
15647         }
15648         i2 = face[jp2][iface];
15649         x2 = cor3[0][i2];
15650         y2 = cor3[1][i2];
15651         z2 = cor3[2][i2];
15652 
15653         xc = ( y1 - y0 ) * ( z2 - z0 ) - ( z1 - z0 ) * ( y2 - y0 );
15654         yc = ( z1 - z0 ) * ( x2 - x0 ) - ( x1 - x0 ) * ( z2 - z0 );
15655         zc = ( x1 - x0 ) * ( y2 - y0 ) - ( y1 - y0 ) * ( x2 - x0 );
15656 
15657         norm = ( float ) sqrt ( xc * xc + yc * yc + zc * zc );
15658 
15659         if ( norm == 0.0 ) {
15660           xc = ( float ) 1.0 / sqrt ( 3.0 );
15661           yc = ( float ) 1.0 / sqrt ( 3.0 );
15662           zc = ( float ) 1.0 / sqrt ( 3.0 );
15663         }
15664         else {
15665           xc = xc / norm;
15666           yc = yc / norm;
15667           zc = zc / norm;
15668         }
15669 
15670         vertex_normal[0][ivert][iface] = xc;
15671         vertex_normal[1][ivert][iface] = yc;
15672         vertex_normal[2][ivert][iface] = zc;
15673 
15674       }
15675     }
15676   }
15677 
15678   if ( nfix > 0 ) {
15679     printf ( "\n" );
15680     printf ( "VERTEX_NORMAL_SET: Recomputed %d face vertex normals.\n", nfix );
15681   }
15682 
15683   return;
15684 }
15685 /**********************************************************************/
15686 
15687 void vertex_to_face_material ( void )
15688 
15689 /**********************************************************************/
15690 
15691 /*
15692   Purpose:
15693 
15694     VERTEX_TO_FACE_MATERIAL extends vertex material definitions to faces.
15695 
15696   Discussion:
15697 
15698     Assuming material indices are defined for all the vertices, this
15699     routine assigns to each face the material associated with its
15700     first vertex.
15701 
15702   Modified:
15703 
15704     22 May 1999
15705 
15706   Author:
15707 
15708     John Burkardt
15709 */
15710 {
15711   int iface;
15712   int ivert;
15713 
15714   ivert = 0;
15715   for ( iface = 0; iface < face_num; iface++ ) {
15716     face_material[iface] = vertex_material[ivert][iface];
15717   }
15718 
15719   return;
15720 }
15721 /**********************************************************************/
15722 
15723 void vertex_to_node_material ( void )
15724 
15725 /**********************************************************************/
15726 
15727 /*
15728   Purpose:
15729 
15730     VERTEX_TO_NODE_MATERIAL extends vertex material definitions to nodes.
15731 
15732   Discussion:
15733 
15734     A NODE is a point in space.
15735     A VERTEX is a node as used in a particular face.
15736     One node may be used as a vertex in several faces, or none.
15737     This routine simply runs through all the vertices, and assigns
15738     the material of the vertex to the corresponding node.  If a
15739     node appears as a vertex several times, then the node will
15740     end up having the material of the vertex that occurs "last".
15741 
15742   Modified:
15743 
15744     22 May 1999
15745 
15746   Author:
15747 
15748     John Burkardt
15749 */
15750 {
15751   int iface;
15752   int ivert;
15753   int node;
15754 
15755   for ( iface = 0; iface < face_num; iface++ ) {
15756     for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
15757       node = face[ivert][iface];
15758       cor3_material[node] = vertex_material[ivert][iface];
15759     }
15760   }
15761 
15762   return;
15763 }
15764 
15765 /******************************************************************************/
15766 
15767 int vla_read ( FILE *filein )
15768 
15769 /******************************************************************************/
15770 
15771 /*
15772   Purpose:
15773    
15774     VLA_READ reads a VLA file.
15775 
15776   Examples:
15777 
15778      set comment cube.vla created by IVREAD
15779      set comment Original data in cube.iv.
15780      set comment
15781      set intensity EXPLICIT
15782      set parametric NON_PARAMETRIC
15783      set filecontent LINES
15784      set filetype NEW
15785      set depthcue 0
15786      set defaultdraw stellar
15787      set coordsys RIGHT
15788      set author IVREAD
15789      set site Buhl Planetarium
15790      set library_id UNKNOWN
15791      P   8.59816       5.55317      -3.05561       1.00000
15792      L   8.59816       2.49756      0.000000E+00   1.00000
15793      L   8.59816       2.49756      -3.05561       1.00000
15794      L   8.59816       5.55317      -3.05561       1.00000
15795      P   8.59816       5.55317      0.000000E+00   1.00000
15796      ...etc...
15797      L   2.48695       2.49756      -3.05561       1.00000
15798 
15799   Modified:
15800 
15801     23 May 1999
15802 
15803   Author:
15804  
15805     John Burkardt
15806 */
15807 {
15808   int   i;
15809   int   icor3;
15810   int   dup_num;
15811   char *next;
15812   int   text_num;
15813   float r1;
15814   float r2;
15815   float r3;
15816   float temp[3];
15817   char  token[LINE_MAX_LEN];
15818   int   width;
15819 /*
15820   Initialize. 
15821 */
15822   dup_num = 0;
15823   text_num = 0;
15824 /* 
15825   Read the next line of the file into INPUT. 
15826 */
15827   while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL ) {
15828 
15829     text_num = text_num + 1;
15830 /* 
15831   Advance to the first nonspace character in INPUT.
15832 */
15833     for ( next = input; *next != '\0' && isspace(*next); next++ ) {
15834     }
15835 /* 
15836   Skip blank lines and comments. 
15837 */
15838     if ( *next == '\0' || *next == ';' ) {
15839       continue;
15840     }
15841 /* 
15842   Extract the first word in this line. 
15843 */
15844     sscanf ( next, "%s%n", token, &width );
15845 /* 
15846   Set NEXT to point to just after this token. 
15847 */
15848     next = next + width;
15849 /* 
15850   SET (ignore) 
15851 */
15852     if ( leqi ( token, "set" ) == TRUE ) {
15853     }
15854 /* 
15855   P (begin a line)
15856   L (continue a line) 
15857 */
15858     else if ( leqi ( token, "P" ) == TRUE || leqi ( token, "L") == TRUE ) {
15859 
15860       if ( leqi ( token, "P" ) == TRUE ) {
15861         if ( line_num > 0 ) {
15862           if ( line_num < LINES_MAX ) {
15863             line_dex[line_num] = -1;
15864             line_material[line_num] = -1;
15865             line_num = line_num + 1;
15866           }
15867         }
15868       }
15869 
15870       sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
15871 
15872       temp[0] = r1;
15873       temp[1] = r2;
15874       temp[2] = r3;
15875 
15876       if ( cor3_num < 1000 ) {
15877         icor3 = rcol_find ( cor3, 3, cor3_num, temp );
15878       }
15879       else {
15880         icor3 = -1;
15881       }
15882 
15883       if ( icor3 == -1 ) {
15884 
15885         icor3 = cor3_num;
15886 
15887         if ( cor3_num < COR3_MAX ) {
15888           for ( i = 0; i < 3; i++ ) {
15889             cor3[i][cor3_num] = temp[i];
15890           }
15891         }
15892         cor3_num = cor3_num + 1;
15893       }
15894       else {
15895         dup_num = dup_num + 1;
15896       }
15897 
15898       if ( line_num < LINES_MAX ) {
15899         line_dex[line_num] = icor3;
15900         line_material[line_num] = 0;
15901         line_num = line_num + 1;
15902       }
15903     }
15904 /* 
15905   Unexpected or unrecognized. 
15906 */
15907     else {
15908       printf ( "\n" );
15909       printf ( "VLA_READ - Fatal error!\n" );
15910       printf ( "  Unrecognized first word on line.\n" );
15911       return ERROR;
15912     }
15913 
15914   }
15915 
15916   if ( line_num > 0 ) {
15917     if ( line_num < LINES_MAX ) {
15918       line_dex[line_num] = -1;
15919       line_material[line_num] = -1;
15920       line_num = line_num + 1;
15921     }
15922   }
15923 
15924   return SUCCESS;
15925 }
15926 /******************************************************************************/
15927 
15928 int vla_write ( FILE *fileout )
15929 
15930 /******************************************************************************/
15931 
15932 /*
15933   Purpose:
15934    
15935     VLA_WRITE writes internal graphics information to a VLA file.
15936 
15937   Discussion:
15938 
15939     Comments begin with a semicolon in column 1.
15940     The X, Y, Z coordinates of points begin with a "P" to
15941     denote the beginning of a line, and "L" to denote the
15942     continuation of a line.  The fourth entry is intensity, which 
15943     should be between 0.0 and 1.0.
15944 
15945   Examples:
15946 
15947      set comment cube.vla created by IVREAD
15948      set comment Original data in cube.iv.
15949      set comment
15950      set intensity EXPLICIT
15951      set parametric NON_PARAMETRIC
15952      set filecontent LINES
15953      set filetype NEW
15954      set depthcue 0
15955      set defaultdraw stellar
15956      set coordsys RIGHT
15957      set author IVREAD
15958      set site Buhl Planetarium
15959      set library_id UNKNOWN
15960      P   8.59816       5.55317      -3.05561       1.00000
15961      L   8.59816       2.49756      0.000000E+00   1.00000
15962      L   8.59816       2.49756      -3.05561       1.00000
15963      L   8.59816       5.55317      -3.05561       1.00000
15964      P   8.59816       5.55317      0.000000E+00   1.00000
15965      ...etc...
15966      L   2.48695       2.49756      -3.05561       1.00000
15967 
15968   Modified:
15969 
15970     22 May 1999
15971 
15972   Author:
15973  
15974     John Burkardt
15975 */
15976 {
15977   char  c;
15978   int   iline;
15979   float intense = 1.0;
15980   int   k;
15981   int   text_num;
15982 /* 
15983   Initialize. 
15984 */
15985   text_num = 0;
15986 
15987   fprintf ( fileout, "set comment %s created by IVCON.\n", fileout_name );
15988   fprintf ( fileout, "set comment Original data in %s.\n", filein_name );
15989   fprintf ( fileout, "set comment\n" );
15990   fprintf ( fileout, "set intensity EXPLICIT\n" );
15991   fprintf ( fileout, "set parametric NON_PARAMETRIC\n" );
15992   fprintf ( fileout, "set filecontent LINES\n" );
15993   fprintf ( fileout, "set filetype NEW\n" );
15994   fprintf ( fileout, "set depthcue 0\n" );
15995   fprintf ( fileout, "set defaultdraw stellar\n" );
15996   fprintf ( fileout, "set coordsys RIGHT\n" );
15997   fprintf ( fileout, "set author IVCON\n" );
15998   fprintf ( fileout, "set site Buhl Planetarium\n" );
15999   fprintf ( fileout, "set library_id UNKNOWN\n" );
16000 
16001   text_num = text_num + 13;
16002 
16003   c = 'P';
16004 
16005   for ( iline = 0; iline < line_num; iline++ ) {
16006     
16007     k = line_dex[iline];
16008 
16009     if ( k == -1 ) {
16010 
16011       c = 'P';
16012     }
16013     else {
16014 
16015       fprintf ( fileout, "%c %f %f %f %f\n", 
16016         c, cor3[0][k], cor3[1][k], cor3[2][k], intense );
16017 
16018       text_num = text_num + 1;
16019 
16020       c = 'L';
16021     }
16022   }
16023 /*
16024   Report.
16025 */
16026   printf ( "\n" );
16027   printf ( "VLA_WRITE - Wrote %d text lines.\n", text_num );
16028 
16029 
16030   return SUCCESS;
16031 }
16032 
16033 /**********************************************************************/
16034 
16035 int wrl_write ( FILE *fileout )
16036 
16037 /**********************************************************************/
16038 
16039 /*
16040   Purpose:
16041 
16042     WRL_WRITE writes graphics data to a WRL file.
16043 
16044   Example:
16045 
16046     #VRML V2.0 utf8
16047 
16048     WorldInfo {
16049       title "cube.iv."
16050       string "WRL file generated by IVREAD.
16051     }
16052 
16053     Group {
16054       children [
16055 
16056         Shape {
16057 
16058           appearance Appearance {
16059             material Material {
16060               diffuseColor   0.0 0.0 0.0
16061               emissiveColor  0.0 0.0 0.0
16062               shininess      1.0
16063             }
16064           } #end of appearance
16065 
16066           geometry IndexedLineSet {
16067 
16068             coord Coordinate {
16069               point [
16070                 8.59816       5.55317      -3.05561
16071                 8.59816       2.49756      0.000000E+00
16072                 ...etc...
16073                 2.48695       2.49756      -3.05561
16074               ]
16075             }
16076 
16077             coordIndex [
16078                 0     1     2    -1     3     4     5     6     7     8    -
16079                 9    10    -1    11    12    -1    13    14    15    -1    1
16080               ...etc...
16081               191    -1
16082             ]
16083 
16084             colorPerVertex TRUE
16085 
16086             colorIndex [
16087                 0     0     0    -1     2     3     1     1     4     7    -
16088                10     9    -1     7     7    -1     3     2     2    -1    1
16089               ...etc...
16090               180    -1
16091             ]
16092 
16093           }  #end of geometry
16094 
16095         }  #end of Shape
16096 
16097       ]  #end of children
16098 
16099     }  #end of Group
16100 
16101   Modified:
16102 
16103     23 May 1999
16104 
16105   Author:
16106 
16107     John Burkardt
16108 */
16109 {
16110   int icor3;
16111   int iface;
16112   int itemp;
16113   int ivert;
16114   int j;
16115   int length;
16116   int ndx;
16117 
16118   text_num = 0;
16119 
16120   fprintf ( fileout, "#VRML V2.0 utf8\n" );
16121   fprintf ( fileout, "\n" );
16122   fprintf ( fileout, "  WorldInfo {\n" );
16123   fprintf ( fileout, "    title \"%s\"\n", fileout_name );
16124   fprintf ( fileout, "    info \"WRL file generated by IVREAD.\"\n" );
16125   fprintf ( fileout, "    info \"Original data in %s\"\n", filein_name );
16126   fprintf ( fileout, "  }\n" );
16127   fprintf ( fileout, "\n" );
16128   fprintf ( fileout, "  Group {\n" );
16129   fprintf ( fileout, "    children [\n" );
16130   fprintf ( fileout, "      Shape {\n" );
16131   fprintf ( fileout, "        appearance Appearance {\n" );
16132   fprintf ( fileout, "          material Material {\n" );
16133   fprintf ( fileout, "            diffuseColor   0.0 0.0 0.0\n" );
16134   fprintf ( fileout, "            emissiveColor  0.0 0.0 0.0\n" );
16135   fprintf ( fileout, "            shininess      1.0\n" );
16136   fprintf ( fileout, "          }\n" );
16137   fprintf ( fileout, "        }\n" );
16138 
16139   text_num = text_num + 18;
16140 /*
16141   IndexedLineSet
16142 */
16143   if ( line_num > 0 ) {
16144 
16145     fprintf ( fileout, "        geometry IndexedLineSet {\n" );
16146 /*
16147   IndexedLineSet coord
16148 */
16149     fprintf ( fileout, "          coord Coordinate {\n" );
16150     fprintf ( fileout, "            point [\n" );
16151 
16152     text_num = text_num + 3;
16153 
16154     for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
16155       fprintf ( fileout, "              %f %f %f\n", cor3[0][icor3],
16156         cor3[1][icor3], cor3[2][icor3] );
16157       text_num = text_num + 1;
16158     }
16159 
16160     fprintf ( fileout, "            ]\n" );
16161     fprintf ( fileout, "          }\n" );
16162     text_num = text_num + 2;
16163 /*
16164   IndexedLineSet coordIndex.
16165 */
16166     fprintf ( fileout, "          coordIndex [\n" );
16167 
16168     text_num = text_num + 1;
16169 
16170     length = 0;
16171     for ( j = 0; j < line_num; j++ ) {
16172       fprintf ( fileout, "%d ", line_dex[j] );
16173       length = length + 1;
16174       if ( line_dex[j] == -1 || length >= 10 || j == line_num - 1 ) {
16175         fprintf ( fileout, "\n" );
16176         text_num = text_num + 1;
16177         length = 0;
16178       }
16179     }
16180 
16181     fprintf ( fileout, "          ]\n" );
16182     text_num = text_num + 1;
16183 /*
16184   Colors. (materials)
16185 */
16186     fprintf ( fileout, "          color Color {\n" );
16187     fprintf ( fileout, "            color [\n" );
16188     text_num = text_num + 2;
16189 
16190     for ( j = 0; j < material_num; j++ ) {
16191       fprintf ( fileout, "              %f %f %f\n", material_rgba[0][j],
16192         material_rgba[1][j], material_rgba[2][j] );
16193       text_num = text_num + 1;
16194     }
16195 
16196     fprintf ( fileout, "            ]\n" );
16197     fprintf ( fileout, "          }\n" );
16198     fprintf ( fileout, "          colorPerVertex TRUE\n" );
16199 /*
16200   IndexedLineset colorIndex
16201 */
16202     fprintf ( fileout, "          colorIndex [\n" );
16203 
16204     text_num = text_num + 4;
16205 
16206     length = 0;
16207     for ( j = 0; j < line_num; j++ ) {
16208       fprintf ( fileout, "%d ", line_material[j] );
16209       length = length + 1;
16210       if ( line_dex[j] == -1 || length >= 10 || j == line_num - 1 ) {
16211         fprintf ( fileout, "\n" );
16212         text_num = text_num + 1;
16213         length = 0;
16214       }
16215     }
16216 
16217     fprintf ( fileout, "          ]\n" );
16218     fprintf ( fileout, "        }\n" );
16219     text_num = text_num + 2;
16220 
16221   }
16222 /*
16223   End of IndexedLineSet
16224 
16225   IndexedFaceSet
16226 */
16227   if ( face_num > 0 ) {
16228 
16229     fprintf ( fileout, "        geometry IndexedFaceSet {\n" );
16230 /*
16231   IndexedFaceSet coord
16232 */
16233     fprintf ( fileout, "          coord Coordinate {\n" );
16234     fprintf ( fileout, "            point [\n" );
16235 
16236     text_num = text_num + 3;
16237 
16238     for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
16239       fprintf ( fileout, "              %f %f %f\n", cor3[0][icor3],
16240         cor3[1][icor3], cor3[2][icor3] );
16241 
16242       text_num = text_num + 1;
16243     }
16244 
16245     fprintf ( fileout, "            ]\n" );
16246     fprintf ( fileout, "          }\n" );
16247 /*
16248   IndexedFaceSet coordIndex.
16249 */
16250     fprintf ( fileout, "          coordIndex [\n" );
16251 
16252     text_num = text_num + 3;
16253 
16254     length = 0;
16255 
16256     for ( iface = 0; iface < face_num; iface++ ) {
16257 
16258       for ( ivert = 0; ivert <= face_order[iface]; ivert++ ) {
16259 
16260         if ( ivert <= face_order[iface] ) {
16261           itemp = face[ivert][iface];
16262         }
16263         else {
16264           itemp = 0;
16265         }
16266 
16267         fprintf ( fileout, "%d ", itemp );
16268         length = length + 1;
16269 
16270         if ( itemp == -1 || length >= 10 ||
16271           ( iface == face_num - 1 && ivert == face_order[iface]  ) ) {
16272           fprintf ( fileout, "\n" );
16273           text_num = text_num + 1;
16274           length = 0;
16275         }
16276 
16277       }
16278 
16279     }
16280 
16281     fprintf ( fileout, "          ]\n" );
16282     text_num = text_num + 1;
16283 /*
16284   IndexedFaceset colorIndex
16285 */
16286     fprintf ( fileout, "          colorIndex [\n" );
16287     text_num = text_num + 1;
16288 
16289     length = 0;
16290     ndx = 0;
16291 
16292     for ( iface = 0; iface < face_num; iface++ ) {
16293 
16294       for ( ivert = 0; ivert <= face_order[iface]; ivert++ ) {
16295 
16296         if ( ivert <= face_order[iface] ) {
16297           itemp = vertex_material[ivert][iface];
16298           ndx = ndx + 1;
16299         }
16300         else {
16301           itemp = 0;
16302         }
16303 
16304         fprintf ( fileout, "%d ", itemp );
16305         length = length + 1;
16306 
16307         if ( itemp == -1 || length >= 10 ||
16308           ( iface == face_num - 1 && ivert == face_order[iface] )  ) {
16309 
16310           fprintf ( fileout, "\n" );
16311           text_num = text_num + 1;
16312           length = 0;
16313 
16314         }
16315 
16316       }
16317 
16318     }
16319 
16320     fprintf ( fileout, "          ]\n" );
16321     fprintf ( fileout, "        }\n" );
16322     text_num = text_num + 2;
16323 
16324   }
16325 /*
16326   End of IndexedFaceSet
16327 
16328   End of:
16329     Shape
16330   children
16331     Group
16332 */
16333   fprintf ( fileout, "      }\n" );
16334   fprintf ( fileout, "    ]\n" );
16335   fprintf ( fileout, "  }\n" );
16336 
16337   text_num = text_num + 3;
16338 /*
16339   Report.
16340 */
16341   printf ( "\n" );
16342   printf ( "WRL_WRITE - Wrote %d text lines.\n", text_num );
16343 
16344   return SUCCESS;
16345 }
16346 /******************************************************************************/
16347 
16348 int xgl_write ( FILE *fileout )
16349 
16350 /******************************************************************************/
16351 
16352 /*
16353   Purpose:
16354    
16355     XGL_WRITE writes an XGL file.
16356 
16357   Discussion:
16358 
16359     Two corrections to the routine were pointed out by
16360     Mike Phillips, msphil@widowmaker.com, on 17 September 2001,
16361     and are gratefully acknowledged.
16362 
16363   Example:
16364 
16365     <WORLD>
16366      
16367       <BACKGROUND>
16368         <BACKCOLOR> 0.1, 0.1, 0.1 </BACKCOLOR>
16369       </BACKGROUND>
16370      
16371       <LIGHTING>
16372         <AMBIENT> 0.2, 0.1, 0.1 </AMBIENT>
16373         <DIRECTIONALLIGHT>
16374           <DIFFUSE> 0.1, 0.2, 0.1 </DIFFUSE>
16375           <DIRECTION> 0, 0, 100 </DIRECTION>
16376           <SPECULAR> 0.1, 0.1, 0.2 </SPECULAR>
16377         </DIRECTIONALLIGHT>
16378       </LIGHTING>
16379      
16380       <MESH ID = "0">
16381      
16382         <P ID="0"> -0.5, -0.5, 1 </P>
16383         <P ID="1"> 0.5, -0.5, 1 </P>
16384         <P ID="2"> 0.5, 0.5, 1 </P>
16385         <P ID="3"> -0.5, 0.5, 1 </P>
16386         <P ID="4"> 0.5, -0.5, 0 </P>
16387         <P ID="5"> -0.5, -0.5, 0 </P>
16388         <P ID="6"> -0.5, 0.5, 0 </P>
16389         <P ID="7"> 0.5, 0.5, 0 </P>
16390      
16391         <N ID="0"> -0.408248, -0.408248, 0.816497 </N>
16392         <N ID="1"> 0.666667, -0.666667, 0.333333 </N>
16393         <N ID="2"> 0.408248, 0.408248, 0.816497 </N>
16394         <N ID="3"> -0.666667, 0.666667, 0.333333 </N>
16395         <N ID="4"> 0.408248, -0.408248, -0.816497 </N>
16396         <N ID="5"> -0.666667, -0.666667, -0.333333 </N>
16397         <N ID="6"> -0.408248, 0.408248, -0.816497 </N>
16398         <N ID="7"> 0.666667, 0.666667, -0.333333 </N>
16399      
16400         <MAT ID="0">
16401           <ALPHA> 0.9 </ALPHA>
16402           <AMB> 0.1, 0.1, 0.1 </AMB>
16403           <DIFF> 0.2, 0.1, 0.1 </DIFF>
16404           <EMISS> 0.1, 0.2, 0.1 </EMISS>
16405           <SHINE> 0.8 </SHINE>
16406           <SPEC> 0.1, 0.1, 0.2 </SPEC>
16407         </MAT>
16408      
16409         <F>
16410           <MATREF> 0 </MATREF>
16411           <FV1><PREF> 0 </PREF><NREF> 0 </NREF></FV1>
16412           <FV2><PREF> 1 </PREF><NREF> 1 </NREF></FV2>
16413           <FV3><PREF> 2 </PREF><NREF> 2 </NREF></FV3>
16414         </F>
16415         <F>
16416           <MATREF> 0 </MATREF>
16417           <FV1><PREF> 0 </PREF><NREF> 0 </NREF></FV1>
16418           <FV2><PREF> 2 </PREF><NREF> 2 </NREF></FV2>
16419           <FV3><PREF> 3 </PREF><NREF> 3 </NREF></FV3>
16420         </F>
16421         <F>
16422           <MATREF> 0 </MATREF>
16423           <FV1><PREF> 4 </PREF><NREF> 4 </NREF></FV1>
16424           <FV2><PREF> 5 </PREF><NREF> 5 </NREF></FV2>
16425           <FV3><PREF> 6 </PREF><NREF> 6 </NREF></FV3>
16426         </F>
16427         <F>
16428           <MATREF> 0 </MATREF>
16429           <FV1><PREF> 4 </PREF><NREF> 4 </NREF></FV1>
16430           <FV2><PREF> 6 </PREF><NREF> 6 </NREF></FV2>
16431           <FV3><PREF> 7 </PREF><NREF> 7 </NREF></FV3>
16432         </F>
16433         <F>
16434           <MATREF> 0 </MATREF>
16435           <FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
16436           <FV2><PREF> 0 </PREF><NREF> 0 </NREF></FV2>
16437           <FV3><PREF> 3 </PREF><NREF> 3 </NREF></FV3>
16438         </F>
16439         <F>
16440           <MATREF> 0 </MATREF>
16441           <FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
16442           <FV2><PREF> 3 </PREF><NREF> 3 </NREF></FV2>
16443           <FV3><PREF> 6 </PREF><NREF> 6 </NREF></FV3>
16444         </F>
16445         <F>
16446           <MATREF> 0 </MATREF>
16447           <FV1><PREF> 1 </PREF><NREF> 1 </NREF></FV1>
16448           <FV2><PREF> 4 </PREF><NREF> 4 </NREF></FV2>
16449           <FV3><PREF> 7 </PREF><NREF> 7 </NREF></FV3>
16450         </F>
16451         <F>
16452           <MATREF> 0 </MATREF>
16453           <FV1><PREF> 1 </PREF><NREF> 1 </NREF></FV1>
16454           <FV2><PREF> 7 </PREF><NREF> 7 </NREF></FV2>
16455           <FV3><PREF> 2 </PREF><NREF> 2 </NREF></FV3>
16456         </F>
16457         <F>
16458           <MATREF> 0 </MATREF>
16459           <FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
16460           <FV2><PREF> 4 </PREF><NREF> 4 </NREF></FV2>
16461           <FV3><PREF> 1 </PREF><NREF> 1 </NREF></FV3>
16462         </F>
16463         <F>
16464           <MATREF> 0 </MATREF>
16465           <FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
16466           <FV2><PREF> 1 </PREF><NREF> 1 </NREF></FV2>
16467           <FV3><PREF> 0 </PREF><NREF> 0 </NREF></FV3>
16468         </F>
16469         <F>
16470           <MATREF> 0 </MATREF>
16471           <FV1><PREF> 3 </PREF><NREF> 3 </NREF></FV1>
16472           <FV2><PREF> 2 </PREF><NREF> 2 </NREF></FV2>
16473           <FV3><PREF> 7 </PREF><NREF> 7 </NREF></FV3>
16474         </F>
16475         <F>
16476           <MATREF> 0 </MATREF>
16477           <FV1><PREF> 3 </PREF><NREF> 3 </NREF></FV1>
16478           <FV2><PREF> 7 </PREF><NREF> 7 </NREF></FV2>
16479           <FV3><PREF> 6 </PREF><NREF> 6 </NREF></FV3>
16480         </F>
16481       </MESH>
16482      
16483       <OBJECT>
16484         <TRANSFORM>
16485           <FORWARD> 0, 0, 0 </FORWARD>
16486           <POSITION> 0, 0, 0 </POSITION>
16487           <SCALE> 1, 1, 1 </SCALE>
16488           <UP> 1, 1, 1 </UP>
16489         </TRANSFORM>
16490         <MESHREF> 0 </MESHREF>
16491       </OBJECT>
16492      
16493     </WORLD>
16494 
16495   Reference:
16496 
16497     XGL specification at http://www.xglspec.org/
16498 
16499   Modified:
16500 
16501     17 September 2001
16502 
16503   Author:
16504  
16505     John Burkardt
16506 */
16507 {
16508   int iface;
16509   int ivert;
16510   int j;
16511   float light_ambient_rgb[3];
16512   float light_diffuse_rgb[3];
16513   float light_direction[3];
16514   float light_specular_rgb[3];
16515   int material;
16516   float material_alpha;
16517   float material_amb_rgb[3];
16518   float material_diff_rgb[3];
16519   float material_emiss_rgb[3];
16520   float material_shine;
16521   float material_spec_rgb[3];
16522   int mesh;
16523   int mesh_num = 1;
16524   int object;
16525   float transform_forward[3];
16526   float transform_position[3];
16527   float transform_scale[3];
16528   float transform_up[3];
16529 /*
16530   Make up some placeholder values for now.
16531 */
16532   light_ambient_rgb[0] = 0.2;
16533   light_ambient_rgb[1] = 0.1;
16534   light_ambient_rgb[2] = 0.1;
16535 
16536   light_diffuse_rgb[0] = 0.1;
16537   light_diffuse_rgb[1] = 0.2;
16538   light_diffuse_rgb[2] = 0.1;
16539 
16540   light_direction[0] =   0.0;
16541   light_direction[1] =   0.0;
16542   light_direction[2] = 100.0;
16543 
16544   light_specular_rgb[0] = 0.1;
16545   light_specular_rgb[1] = 0.1;
16546   light_specular_rgb[2] = 0.2;
16547 
16548   material_alpha = 0.9;
16549 
16550   material_amb_rgb[0] = 0.1;
16551   material_amb_rgb[1] = 0.1;
16552   material_amb_rgb[2] = 0.1;
16553 
16554   material_diff_rgb[0] = 0.2;
16555   material_diff_rgb[1] = 0.1;
16556   material_diff_rgb[2] = 0.1;
16557 
16558   material_emiss_rgb[0] = 0.1;
16559   material_emiss_rgb[1] = 0.2;
16560   material_emiss_rgb[2] = 0.1;
16561 
16562   material_shine = 0.8;
16563 
16564   material_spec_rgb[0] = 0.1;
16565   material_spec_rgb[1] = 0.1;
16566   material_spec_rgb[2] = 0.2;
16567 
16568   transform_forward[0] = 0.0;
16569   transform_forward[1] = 0.0;
16570   transform_forward[2] = 0.0;
16571 
16572   transform_position[0] = 0.0;
16573   transform_position[1] = 0.0;
16574   transform_position[2] = 0.0;
16575 
16576   transform_scale[0] = 1.0;
16577   transform_scale[1] = 1.0;
16578   transform_scale[2] = 1.0;
16579 
16580   transform_up[0] = 1.0;
16581   transform_up[1] = 1.0;
16582   transform_up[2] = 1.0;
16583 
16584   object_num = 1;
16585 
16586   text_num = 0;
16587 
16588   fprintf ( fileout, "<WORLD>\n" );
16589   fprintf ( fileout, "\n" );
16590 
16591   text_num = text_num + 2;
16592 
16593   fprintf ( fileout, "  <BACKGROUND>\n" );
16594   fprintf ( fileout, "    <BACKCOLOR> %f, %f, %f </BACKCOLOR>\n", 
16595     background_rgb[0], background_rgb[1], background_rgb[2] );
16596   fprintf ( fileout, "  </BACKGROUND>\n" );
16597   fprintf ( fileout, "\n" );
16598   fprintf ( fileout, "  <LIGHTING>\n" );
16599   fprintf ( fileout, "    <AMBIENT> %f, %f, %f </AMBIENT>\n",
16600     light_ambient_rgb[0], light_ambient_rgb[1], light_ambient_rgb[2] );
16601   fprintf ( fileout, "    <DIRECTIONALLIGHT>\n" );
16602   fprintf ( fileout, "      <DIFFUSE> %f, %f, %f </DIFFUSE>\n",
16603     light_diffuse_rgb[0], light_diffuse_rgb[1], light_diffuse_rgb[2] );
16604   fprintf ( fileout, "      <DIRECTION> %f, %f, %f </DIRECTION>\n",
16605     light_direction[0], light_direction[1], light_direction[2] );
16606   fprintf ( fileout, "      <SPECULAR> %f, %f, %f </SPECULAR>\n",
16607     light_specular_rgb[0], light_specular_rgb[1], light_specular_rgb[2] );
16608   fprintf ( fileout, "    </DIRECTIONALLIGHT>\n" );
16609   fprintf ( fileout, "  </LIGHTING>\n" );
16610 
16611   text_num = text_num + 12;
16612 
16613   for ( mesh = 0; mesh < mesh_num; mesh++ ) {
16614 
16615     fprintf ( fileout, "\n" );
16616     fprintf ( fileout, "  <MESH ID = \"%d\">\n", mesh );
16617     fprintf ( fileout, "\n" );
16618     text_num = text_num + 3;
16619 
16620     for ( j = 0; j < cor3_num; j++ ) {
16621       fprintf ( fileout, "    <P ID=\"%d\"> %f, %f, %f </P>\n", j,
16622         cor3[0][j], cor3[1][j], cor3[2][j] );
16623       text_num = text_num + 1;
16624     }
16625 
16626     fprintf ( fileout, "\n" );
16627     text_num = text_num + 1;
16628     for ( j = 0; j < cor3_num; j++ ) {
16629       fprintf ( fileout, "    <N ID=\"%d\"> %f, %f, %f </N>\n", j,
16630         cor3_normal[0][j], cor3_normal[1][j], cor3_normal[2][j] );
16631       text_num = text_num + 1;
16632     }
16633 
16634     for ( material = 0; material < material_num; material++ ) {
16635       fprintf ( fileout, "\n" );
16636       fprintf ( fileout, "    <MAT ID=\"%d\">\n", material );
16637       fprintf ( fileout, "      <ALPHA> %f </ALPHA>\n", material_alpha );
16638       fprintf ( fileout, "      <AMB> %f, %f, %f </AMB>\n",
16639         material_amb_rgb[0], material_amb_rgb[1], material_amb_rgb[2] );
16640       fprintf ( fileout, "      <DIFF> %f, %f, %f </DIFF>\n",
16641         material_diff_rgb[0], material_diff_rgb[1], material_diff_rgb[2] );
16642       fprintf ( fileout, "      <EMISS> %f, %f, %f </EMISS>\n",
16643         material_emiss_rgb[0], material_emiss_rgb[1], material_emiss_rgb[2] );
16644       fprintf ( fileout, "      <SHINE> %f </SHINE>\n", material_shine );
16645       fprintf ( fileout, "      <SPEC> %f, %f, %f </SPEC>\n",
16646         material_spec_rgb[0], material_spec_rgb[1], material_spec_rgb[2] );
16647       fprintf ( fileout, "    </MAT>\n" );
16648       text_num = text_num + 9;
16649     }
16650 
16651     fprintf ( fileout, "\n" );
16652     text_num = text_num + 1;
16653 
16654     for ( iface = 0; iface < face_num; iface++ ) {
16655       fprintf ( fileout, "    <F>\n" );
16656       fprintf ( fileout, "      <MATREF> %d </MATREF>\n", face_material[iface] );
16657       text_num = text_num + 2;
16658       for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
16659         fprintf ( fileout, 
16660           "      <FV%d><PREF> %d </PREF><NREF> %d </NREF></FV%d>\n",
16661           ivert+1, face[ivert][iface], face[ivert][iface], ivert+1 );
16662         text_num = text_num + 1;
16663       }
16664       fprintf ( fileout, "    </F>\n" );
16665       text_num = text_num + 1;
16666     }
16667 
16668     fprintf ( fileout, "  </MESH>\n" );
16669     text_num = text_num + 1;
16670 
16671   }
16672 
16673   fprintf ( fileout, "\n" );
16674   text_num = text_num + 1;
16675 
16676   for ( object = 0; object < object_num; object++ ) {
16677 
16678     fprintf ( fileout, "  <OBJECT>\n" );
16679     fprintf ( fileout, "    <TRANSFORM>\n" );
16680     fprintf ( fileout, "      <FORWARD> %f, %f, %f </FORWARD>\n",
16681       transform_forward[0], transform_forward[1], transform_forward[2] );
16682     fprintf ( fileout, "      <POSITION> %f, %f, %f </POSITION>\n",
16683       transform_position[0], transform_position[1], transform_position[2] );
16684     fprintf ( fileout, "'      <SCALE> %f, %f, %f </SCALE>\n",
16685       transform_scale[0], transform_scale[1], transform_scale[2] );
16686     fprintf ( fileout, "      <UP> %f, %f, %f </UP>\n",
16687       transform_up[0], transform_up[1], transform_up[2] );
16688     fprintf ( fileout, "    </TRANSFORM>\n" );
16689     mesh = 0;
16690     fprintf ( fileout, "    <MESHREF> %d </MESHREF>\n", mesh );
16691     fprintf ( fileout, "  </OBJECT>\n" );
16692     text_num = text_num + 9;
16693 
16694   }
16695 
16696   fprintf ( fileout, "\n" );
16697   fprintf ( fileout, "</WORLD>\n" );
16698   text_num = text_num + 2;
16699 
16700 /*
16701   Report.
16702 */
16703   printf ( "\n" );
16704   printf ( "XGL_WRITE - Wrote %d text lines.\n", text_num );
16705 
16706   return SUCCESS;
16707 }


ivcon
Author(s): John Burkardt
autogenerated on Thu Feb 11 2016 23:11:44