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