ivcon.cpp
Go to the documentation of this file.
00001 //
00002 //  Purpose:
00003 //
00004 //    IVCON converts various 3D graphics files.
00005 //
00006 //  Acknowledgements:
00007 //
00008 //    Coding, comments, and advice were supplied by a number of collaborators.
00009 //
00010 //    Jean-Cristophe Hoelt (hoeltj AT tcd.ie) pointed out that the program was
00011 //    not compiling under GNU C++, and I made the necessary corrections.
00012 //
00013 //    John F Flanagan made some corrections to the 3D Studio Max routines.
00014 //
00015 //    Zik Saleeba (zik AT zikzak.net) enhanced the DXF routines, and added the
00016 //    Golgotha GMOD routines.
00017 //
00018 //    Thanks to Susan M. Fisher, University of North Carolina,
00019 //    Department of Computer Science, for pointing out a coding error
00020 //    in FACE_NULL_DELETE that was overwriting all the data!
00021 //
00022 //  Licensing:
00023 //
00024 //    This code is distributed under the GNU LGPL license.
00025 //
00026 //  Modified:
00027 //
00028 //    19 January 2004
00029 //
00030 //  Author:
00031 //
00032 //    John Burkardt
00033 //
00034 # include <cstdlib>
00035 # include <cmath>
00036 # include <cstdio>
00037 # include <iostream>
00038 # include <iomanip>
00039 # include <fstream>
00040 # include <cstring>
00041 
00042 using namespace std;
00043 
00044 # define ERROR 1
00045 # define G1_SECTION_MODEL_QUADS 18
00046 # define G1_SECTION_MODEL_TEXTURE_NAMES 19
00047 # define G1_SECTION_MODEL_VERT_ANIMATION 20
00048 # define GMOD_MAX_SECTIONS 32
00049 # define GMOD_UNUSED_VERTEX 65535
00050 # define PI 3.141592653589793238462643
00051 
00052 # define DEG_TO_RAD   ( PI / 180.0 )
00053 # define RAD_TO_DEG   ( 180.0 / PI )
00054 
00055 //****************************************************************************80
00056 //
00057 //  GLOBAL DATA
00058 //
00059 //****************************************************************************80
00060 //
00061 //  BACKGROUND_RGB[3], the background color.
00062 //
00063 //  BYTE_SWAP, byte swapping option.
00064 //
00065 //  COR3[3][COR3_MAX], the coordinates of nodes.
00066 //
00067 //  COR3_MATERIAL[COR3_MAX], the index of the material of each node.
00068 //
00069 //  COR3_MAX, the maximum number of points.
00070 //
00071 //  COR3_NORMAL[3][COR3_MAX], normal vectors associated with nodes.
00072 //
00073 //  COR3_NUM, the number of points.
00074 //
00075 //  COR3_RGB[3][COR3_MAX], RGB colors associated with nodes.
00076 //
00077 //  COR3_TEX_UV[2][COR3_MAX], texture coordinates associated with nodes.
00078 //
00079 //  FACE[ORDER_MAX][FACE_MAX] contains the index of the I-th node making up face J.
00080 //
00081 //  FACE_AREA(FACE_MAX), the area of each face.
00082 //
00083 //  FACE_MATERIAL[FACE_MAX]; the material of each face.
00084 //
00085 //  FACE_MAX, the maximum number of faces.
00086 //
00087 //  FACE_NORMAL[3][FACE_MAX], the face normal vectors.
00088 //
00089 //  FACE_NUM, the number of faces.
00090 //
00091 //  FACE_ORDER[FACE_MAX], the number of vertices per face.
00092 //
00093 //  FACE_TEX_UV[2][FACE_MAX], texture coordinates associated with faces.
00094 //
00095 //  LINE_DEX[LINES_MAX], node indices, denoting polylines, each terminated by -1.
00096 //
00097 //  LINE_MATERIAL[LINES_MAX], index into RGBCOLOR for line color.
00098 //
00099 //  LINES_MAX, the maximum number of line definition items.
00100 //
00101 //  LINE_NUM, the number of line definition items.
00102 //
00103 //  LINE_PRUNE, pruning option ( 0 = no pruning, nonzero = pruning).
00104 //
00105 //  MATERIAL_MAX, the maximum number of materials.
00106 //
00107 //  MATERIAL_NUM, the number of materials.
00108 //
00109 //  ORDER_MAX, the maximum number of vertices per face.
00110 //
00111 //  TEXTURE_MAX, the maximum number of textures.
00112 //
00113 //  TEXTURE_NAME[TEXTURE_MAX][LINE_MAX_LEN], ...
00114 //
00115 //  TEXTURE_NUM, the number of textures.
00116 //
00117 //  TRANSFORM_MATRIX[4][4], the current transformation matrix.
00118 //
00119 //  VERTEX_MATERIAL[ORDER_MAX][FACE_MAX]; the material of vertices of faces.
00120 //
00121 //  VERTEX_NORMAL[3][ORDER_MAX][FACE_MAX], normals at vertices of faces.
00122 //
00123 //  VERTEX_RGB[3][ORDER_MAX][FACE_MAX], colors of vertices of faces.
00124 //
00125 //  VERTEX_TEX_UV[2][ORDER_MAX][FACE_MAX], texture coordinates of vertices of faces.
00126 //
00127 
00128 # define COLOR_MAX 1000
00129 # define COR3_MAX 200000
00130 # define FACE_MAX 200000
00131 # define LINE_MAX_LEN 256
00132 # define LEVEL_MAX 10
00133 # define LINES_MAX 100000
00134 # define MATERIAL_MAX 100
00135 # define ORDER_MAX 10
00136 # define TEXTURE_MAX 100
00137 
00138 char anim_name[LINE_MAX_LEN];
00139 float background_rgb[3];
00140 int bad_num;
00141 bool byte_swap;
00142 int bytes_num;
00143 int color_num;
00144 int comment_num;
00145 
00146 float cor3[3][COR3_MAX];
00147 int cor3_material[COR3_MAX];
00148 float cor3_normal[3][COR3_MAX];
00149 int cor3_num;
00150 float cor3_tex_uv[3][COR3_MAX];
00151 
00152 bool debug;
00153 
00154 int dup_num;
00155 
00156 int face[ORDER_MAX][FACE_MAX];
00157 float  face_area[FACE_MAX];
00158 int    face_flags[FACE_MAX];
00159 int    face_material[FACE_MAX];
00160 float  face_normal[3][FACE_MAX];
00161 int    face_num;
00162 int    face_object[FACE_MAX];
00163 int    face_order[FACE_MAX];
00164 int    face_smooth[FACE_MAX];
00165 float  face_tex_uv[2][FACE_MAX];
00166 
00167 char   filein_name[81];
00168 char   fileout_name[81];
00169 
00170 int    group_num;
00171 
00172 int    i;
00173 char   input[LINE_MAX_LEN];
00174 int    k;
00175 char   level_name[LEVEL_MAX][LINE_MAX_LEN];
00176 
00177 int    line_dex[LINES_MAX];
00178 int    line_material[LINES_MAX];
00179 int    line_num;
00180 int    line_prune;
00181 
00182 int    list[COR3_MAX];
00183 
00184 char   material_binding[80];
00185 char   material_name[MATERIAL_MAX][LINE_MAX_LEN];
00186 int    material_num;
00187 float  material_rgba[4][MATERIAL_MAX];
00188 
00189 char   mat_name[81];
00190 int    max_order2;
00191 
00192 char   normal_binding[80];
00193 float  normal_temp[3][ORDER_MAX*FACE_MAX];
00194 
00195 char   object_name[81];
00196 int    object_num;
00197 
00198 float  origin[3];
00199 float  pivot[3];
00200 float  rgbcolor[3][COLOR_MAX];
00201 char   temp_name[81];
00202 
00203 int    text_num;
00204 
00205 char texture_binding[80];
00206 char texture_name[TEXTURE_MAX][LINE_MAX_LEN];
00207 int texture_num;
00208 float texture_temp[2][ORDER_MAX*FACE_MAX];
00209 
00210 float transform_matrix[4][4];
00211 
00212 int vertex_material[ORDER_MAX][FACE_MAX];
00213 float  vertex_normal[3][ORDER_MAX][FACE_MAX];
00214 float  vertex_rgb[3][ORDER_MAX][FACE_MAX];
00215 float  vertex_tex_uv[2][ORDER_MAX][FACE_MAX];
00216 
00217 //****************************************************************************80
00218 //
00219 //  FUNCTION PROTOTYPES
00220 //
00221 //****************************************************************************80
00222 
00223 int main ( int argc, char *argv[] );
00224 int ase_read ( FILE *filein );
00225 int ase_write ( FILE *fileout );
00226 int byu_read ( FILE *filein );
00227 int byu_write ( FILE *fileout );
00228 char ch_cap ( char c );
00229 bool ch_eqi ( char c1, char c2 );
00230 int ch_index_last ( char* string, char c );
00231 bool ch_is_space ( char c );
00232 int ch_pad ( int *char_index, int *null_index, char *s, int max_string );
00233 char ch_read ( FILE *filein );
00234 int ch_to_digit ( char c );
00235 int ch_write ( FILE *fileout, char c );
00236 int command_line ( char **argv );
00237 void cor3_normal_set ( );
00238 void cor3_range ( );
00239 void data_check ( );
00240 void data_init ( );
00241 bool data_read ( );
00242 void data_report ( );
00243 int data_write ( );
00244 int dxf_read ( FILE *filein );
00245 int dxf_write ( FILE *fileout );
00246 int edge_count ( );
00247 void edge_null_delete ( );
00248 void face_area_set ( );
00249 void face_normal_ave ( );
00250 void face_null_delete ( );
00251 int face_print ( int iface );
00252 void face_reverse_order ( );
00253 int face_subset ( );
00254 void face_to_line ( );
00255 void face_to_vertex_material ( );
00256 char *file_ext ( char *file_name );
00257 float float_read ( FILE *filein );
00258 float float_reverse_bytes ( float x );
00259 int float_write ( FILE *fileout, float float_val );
00260 bool gmod_arch_check ( );
00261 int gmod_read ( FILE *filein );
00262 float gmod_read_float ( FILE *filein );
00263 unsigned short gmod_read_w16 ( FILE *filein );
00264 unsigned long gmod_read_w32 ( FILE *filein );
00265 int gmod_write ( FILE *fileout );
00266 void gmod_write_float ( float Val, FILE *fileout );
00267 void gmod_write_w16 ( unsigned short Val, FILE *fileout );
00268 void gmod_write_w32 ( unsigned long Val, FILE *fileout );
00269 void hello ( );
00270 void help ( );
00271 int hrc_read ( FILE *filein );
00272 int hrc_write ( FILE *fileout );
00273 int i4_max ( int i1, int i2 );
00274 int i4_min ( int i1, int i2 );
00275 int i4_modp ( int i, int j );
00276 int i4_wrap ( int ival, int ilo, int ihi );
00277 void init_program_data ( );
00278 int interact ( );
00279 int iv_read ( FILE *filein );
00280 int iv_write ( FILE *fileout );
00281 int i4vec_max ( int n, int *a );
00282 long int long_int_read ( FILE *filein );
00283 int long_int_write ( FILE *fileout, long int int_val );
00284 void news ( );
00285 void node_to_vertex_material ( );
00286 int obj_read ( FILE *filein );
00287 int obj_write ( FILE *fileout );
00288 int off_read ( ifstream &file_in );
00289 int off_write ( FILE *fileout );
00290 int pov_write ( FILE *fileout );
00291 int rcol_find ( float a[][COR3_MAX], int m, int n, float r[] );
00292 float rgb_to_hue ( float r, float g, float b );
00293 bool s_eqi ( char* string1, char* string2 );
00294 int s_len_trim ( char *s );
00295 int s_to_i4 ( char *s, int *last, bool *error );
00296 bool s_to_i4vec ( char *s, int n, int ivec[] );
00297 float s_to_r4 ( char *s, int *lchar, bool *error );
00298 bool s_to_r4vec ( char *s, int n, float rvec[] );
00299 short int short_int_read ( FILE *filein );
00300 int short_int_write ( FILE *fileout, short int int_val );
00301 int smf_read ( FILE *filein );
00302 int smf_write ( FILE *fileout );
00303 void sort_heap_external ( int n, int *indx, int *i, int *j, int isgn );
00304 int stla_read ( FILE *filein );
00305 int stla_write ( FILE *fileout );
00306 int stlb_read ( FILE *filein );
00307 int stlb_write ( FILE *fileout );
00308 void tds_pre_process ( );
00309 int tds_read ( FILE *filein );
00310 unsigned long int tds_read_ambient_section ( FILE *filein );
00311 unsigned long int tds_read_background_section ( FILE *filein );
00312 unsigned long int tds_read_boolean ( unsigned char *boolean, FILE *filein );
00313 unsigned long int tds_read_camera_section ( FILE *filein );
00314 unsigned long int tds_read_edit_section ( FILE *filein, int *views_read );
00315 unsigned long int tds_read_keyframe_section ( FILE *filein, int *views_read );
00316 unsigned long int tds_read_keyframe_objdes_section ( FILE *filein );
00317 unsigned long int tds_read_light_section ( FILE *filein );
00318 unsigned long int tds_read_u_long_int ( FILE *filein );
00319 int tds_read_long_name ( FILE *filein );
00320 unsigned long int tds_read_matdef_section ( FILE *filein );
00321 unsigned long int tds_read_material_section ( FILE *filein );
00322 int tds_read_name ( FILE *filein );
00323 unsigned long int tds_read_obj_section ( FILE *filein );
00324 unsigned long int tds_read_object_section ( FILE *filein );
00325 unsigned long int tds_read_tex_verts_section ( FILE *filein );
00326 unsigned long int tds_read_texmap_section ( FILE *filein );
00327 unsigned short int tds_read_u_short_int ( FILE *filein );
00328 unsigned long int tds_read_spot_section ( FILE *filein );
00329 unsigned long int tds_read_unknown_section ( FILE *filein );
00330 unsigned long int tds_read_view_section ( FILE *filein, int *views_read );
00331 unsigned long int tds_read_vp_section ( FILE *filein, int *views_read );
00332 int tds_write ( FILE *fileout );
00333 int tds_write_string ( FILE *fileout, char *string );
00334 int tds_write_u_short_int ( FILE *fileout, unsigned short int int_val );
00335 int tec_write ( FILE *fileout );
00336 void tmat_init ( float a[4][4] );
00337 void tmat_mxm ( float a[4][4], float b[4][4], float c[4][4] );
00338 void tmat_mxp ( float a[4][4], float x[4], float y[4] );
00339 void tmat_mxp2 ( float a[4][4], float x[][3], float y[][3], int n );
00340 void tmat_mxv ( float a[4][4], float x[4], float y[4] );
00341 void tmat_rot_axis ( float a[4][4], float b[4][4], float angle, char axis );
00342 void tmat_rot_vector ( float a[4][4], float b[4][4], float angle,
00343   float v1, float v2, float v3 );
00344 void tmat_scale ( float a[4][4], float b[4][4], float sx, float sy, float sz );
00345 void tmat_shear ( float a[4][4], float b[4][4], char *axis, float s );
00346 void tmat_trans ( float a[4][4], float b[4][4], float x, float y, float z );
00347 int tria_read ( FILE *filein );
00348 int tria_write ( FILE *fileout );
00349 int trib_read ( FILE *filein );
00350 int trib_write ( FILE *fileout );
00351 int txt_write ( FILE *fileout );
00352 int ucd_write ( FILE *fileout );
00353 void vertex_normal_set ( );
00354 void vertex_to_face_material ( );
00355 void vertex_to_node_material ( );
00356 int vla_read ( FILE *filein );
00357 int vla_write ( FILE *fileout );
00358 int wrl_write ( FILE *filout );
00359 int xgl_write ( FILE *fileout );
00360 
00361 //****************************************************************************80
00362 
00363 int main ( int argc, char *argv[] )
00364 
00365 //****************************************************************************80
00366 //
00367 //  Purpose:
00368 //
00369 //    MAIN is the main program for IVCON.
00370 //
00371 //  Licensing:
00372 //
00373 //    This code is distributed under the GNU LGPL license.
00374 //
00375 //  Modified:
00376 //
00377 //    05 September 2002
00378 //
00379 //  Author:
00380 //
00381 //    John Burkardt
00382 //
00383 {
00384   int result;
00385 
00386   cout << "\n";
00387   cout << "IVCON:\n";
00388   cout << "  C++ version\n";
00389   cout << "  Read, interpret, and write out graphics information\n";
00390   cout << "  in a variety of formats.\n";
00391   cout << "\n";
00392   cout << "  Compiled on " << __DATE__ << " at " << __TIME__ << "\n";
00393 //
00394 //  Initialize the program data.
00395 //
00396   init_program_data ( );
00397 //
00398 //  If there are at least two command line arguments, call COMMAND_LINE.
00399 //  Otherwise call INTERACT and get information from the user.
00400 //
00401   if ( 2 <= argc )
00402   {
00403     result = command_line ( argv );
00404   }
00405   else
00406   {
00407     result = interact (  );
00408   }
00409 
00410   return result;
00411 }
00412 //****************************************************************************80
00413 
00414 int ase_read ( FILE *filein )
00415 
00416 //****************************************************************************80
00417 //
00418 //  Purpose:
00419 //
00420 //    ASE_READ reads an AutoCAD ASE file.
00421 //
00422 //  Licensing:
00423 //
00424 //    This code is distributed under the GNU LGPL license.
00425 //
00426 //  Modified:
00427 //
00428 //    22 May 1999
00429 //
00430 //  Author:
00431 //
00432 //    John Burkardt
00433 //
00434 {
00435   float bval;
00436   int   count;
00437   float gval;
00438   int   i;
00439   int   iface;
00440   int   ivert;
00441   int   iword;
00442   int   level;
00443   char *next;
00444   int   nlbrack;
00445   int   nrbrack;
00446   int   cor3_num_old;
00447   int   face_num_old;
00448   float rval;
00449   float temp;
00450   int   width;
00451   char  word[LINE_MAX_LEN];
00452   char  word1[LINE_MAX_LEN];
00453   char  word2[LINE_MAX_LEN];
00454   char  wordm1[LINE_MAX_LEN];
00455   float x;
00456   float y;
00457   float z;
00458 
00459   level = 0;
00460   strcpy ( level_name[0], "Top" );
00461   cor3_num_old = cor3_num;
00462   face_num_old = face_num;
00463   nlbrack = 0;
00464   nrbrack = 0;
00465 
00466   strcpy ( word, " " );
00467   strcpy ( wordm1, " " );
00468 //
00469 //  Read a line of text from the file.
00470 //
00471   for ( ;; )
00472   {
00473     if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
00474     {
00475       break;
00476     }
00477 
00478     text_num = text_num + 1;
00479     next = input;
00480     iword = 0;
00481 //
00482 //  Read the next word from the line.
00483 //
00484     for ( ;; )
00485     {
00486 
00487       strcpy ( wordm1, word );
00488       strcpy ( word, " " );
00489 
00490       count = sscanf ( next, "%s%n", word, &width );
00491       next = next + width;
00492 
00493       if ( count <= 0 )
00494       {
00495         break;
00496       }
00497 
00498       iword = iword + 1;
00499 
00500       if ( iword == 1 )
00501       {
00502         strcpy ( word1, word );
00503       }
00504 //
00505 //  In case the new word is a bracket, update the bracket count.
00506 //
00507       if ( strcmp ( word, "{" ) == 0 )
00508       {
00509         nlbrack = nlbrack + 1;
00510         level = nlbrack - nrbrack;
00511         strcpy ( level_name[level], wordm1 );
00512       }
00513       else if ( strcmp ( word, "}" ) == 0 )
00514       {
00515         nrbrack = nrbrack + 1;
00516 
00517         if ( nlbrack < nrbrack )
00518         {
00519           cout << "\n";
00520           cout << "ASE_READ - Fatal error!\n";
00521           cout << "  Extraneous right bracket on line " << text_num << "\n";
00522           cout << "  Currently processing field:\n";
00523           cout << level_name[level] << "\n";;
00524           return 1;
00525         }
00526 
00527       }
00528 //
00529 //  *3DSMAX_ASCIIEXPORT  200
00530 //
00531       if ( strcmp ( word1, "*3DSMAX_ASCIIEXPORT" ) == 0 )
00532       {
00533         break;
00534       }
00535 //
00536 //  *COMMENT
00537 //
00538       else if ( strcmp ( word1, "*COMMENT" ) == 0 )
00539       {
00540         break;
00541       }
00542 //
00543 //  *GEOMOBJECT
00544 //
00545       else if ( strcmp ( level_name[level], "*GEOMOBJECT" ) == 0 )
00546       {
00547         if ( strcmp ( word, "{" ) == 0 )
00548         {
00549           continue;
00550         }
00551         else if ( strcmp ( word, "}" ) == 0 )
00552         {
00553           level = nlbrack - nrbrack;
00554           continue;
00555         }
00556 //
00557 //  Why don't you read and save this name?
00558 //
00559         else if ( strcmp ( word, "*NODE_NAME" ) == 0 )
00560         {
00561           break;
00562         }
00563         else if ( strcmp ( word, "*NODE_TM" ) == 0 )
00564         {
00565           continue;
00566         }
00567         else if ( strcmp ( word, "*MESH" ) == 0 )
00568         {
00569           continue;
00570         }
00571         else if ( strcmp ( word, "*PROP_CASTSHADOW" ) == 0 )
00572         {
00573           break;
00574         }
00575         else if ( strcmp ( word, "*PROP_MOTIONBLUR" ) == 0 )
00576         {
00577           break;
00578         }
00579         else if ( strcmp ( word, "*PROP_RECVSHADOW" ) == 0 )
00580         {
00581           break;
00582         }
00583         else
00584         {
00585           bad_num = bad_num + 1;
00586           cout << "\n";
00587           cout << "ASE_READ - Error!\n";
00588           cout << "  Bad data in GEOMOBJECT, line " << text_num << "\n";
00589           break;
00590         }
00591       }
00592 //
00593 //  *MESH
00594 //
00595       else if ( strcmp ( level_name[level], "*MESH" ) == 0 )
00596       {
00597         if ( strcmp ( word, "{" ) == 0 )
00598         {
00599           continue;
00600         }
00601         else if ( strcmp ( word, "}" ) == 0 )
00602         {
00603           level = nlbrack - nrbrack;
00604           continue;
00605         }
00606         else if ( strcmp ( word, "*MESH_CFACELIST" ) == 0 )
00607         {
00608           continue;
00609         }
00610         else if ( strcmp ( word, "*MESH_CVERTLIST" ) == 0 )
00611         {
00612           continue;
00613         }
00614         else if ( strcmp ( word, "*MESH_FACE_LIST" ) == 0 )
00615         {
00616           continue;
00617         }
00618         else if ( strcmp ( word, "*MESH_NORMALS" ) == 0 )
00619         {
00620           continue;
00621         }
00622         else if ( strcmp ( word, "*MESH_NUMCVERTEX" ) == 0 )
00623         {
00624           break;
00625         }
00626         else if ( strcmp ( word, "*MESH_NUMCVFACES" ) == 0 )
00627         {
00628           break;
00629         }
00630         else if ( strcmp ( word, "*MESH_NUMFACES" ) == 0 )
00631         {
00632           break;
00633         }
00634         else if ( strcmp ( word, "*MESH_NUMTVERTEX" ) == 0 )
00635         {
00636           break;
00637         }
00638         else if ( strcmp ( word, "*MESH_NUMTVFACES" ) == 0 )
00639         {
00640           break;
00641         }
00642         else if ( strcmp ( word, "*MESH_NUMVERTEX" ) == 0 )
00643         {
00644           break;
00645         }
00646         else if ( strcmp ( word, "*MESH_TFACELIST" ) == 0 )
00647         {
00648           continue;
00649         }
00650         else if ( strcmp ( word, "*MESH_TVERTLIST" ) == 0 )
00651         {
00652           continue;
00653         }
00654         else if ( strcmp ( word, "*MESH_VERTEX_LIST" ) == 0 )
00655         {
00656           continue;
00657         }
00658         else if ( strcmp ( word, "*TIMEVALUE" ) == 0 )
00659         {
00660           break;
00661         }
00662         else
00663         {
00664           bad_num = bad_num + 1;
00665           cout << "Bad data in MESH, line " << text_num << "\n";
00666           break;
00667         }
00668       }
00669 //
00670 //  *MESH_CFACELIST
00671 //
00672       else if ( strcmp ( level_name[level], "*MESH_CFACELIST" ) == 0 )
00673       {
00674         if ( strcmp ( word, "{" ) == 0 )
00675         {
00676           continue;
00677         }
00678         else if ( strcmp ( word, "}" ) == 0 )
00679         {
00680           level = nlbrack - nrbrack;
00681           continue;
00682         }
00683         else if ( strcmp ( word, "*MESH_CFACE" ) == 0 )
00684         {
00685           break;
00686         }
00687         else
00688         {
00689           bad_num = bad_num + 1;
00690           cout << "Bad data in MESH_CFACE, line " << text_num << "\n";
00691           break;
00692         }
00693       }
00694 //
00695 //  *MESH_CVERTLIST
00696 //
00697 //  Mesh vertex indices must be incremented by COR3_NUM_OLD before being stored
00698 //  in the internal array.
00699 //
00700       else if ( strcmp ( level_name[level], "*MESH_CVERTLIST" ) == 0 )
00701       {
00702         if ( strcmp ( word, "{" ) == 0 )
00703         {
00704           continue;
00705         }
00706         else if ( strcmp ( word, "}" ) == 0 )
00707         {
00708           level = nlbrack - nrbrack;
00709           continue;
00710         }
00711         else if ( strcmp ( word, "*MESH_VERTCOL" ) == 0 )
00712         {
00713           count = sscanf ( next, "%d%n", &i, &width );
00714           next = next + width;
00715 
00716           i = i + cor3_num_old;
00717 
00718           count = sscanf ( next, "%f%n", &rval, &width );
00719           next = next + width;
00720 
00721           count = sscanf ( next, "%f%n", &gval, &width );
00722           next = next + width;
00723 
00724           count = sscanf ( next, "%f%n", &bval, &width );
00725           next = next + width;
00726 
00727           if ( material_num < MATERIAL_MAX )
00728           {
00729             material_rgba[0][material_num] = rval;
00730             material_rgba[1][material_num] = gval;
00731             material_rgba[2][material_num] = bval;
00732             material_rgba[3][material_num] = 1.0;
00733           }
00734 
00735           material_num = material_num + 1;
00736           cor3_material[i] = material_num;
00737         }
00738         else
00739         {
00740           bad_num = bad_num + 1;
00741           cout << "\n";
00742           cout << "ASE_READ - Warning!\n";
00743           cout << "  Bad data in MESH_CVERTLIST, line " << text_num << "\n";
00744           break;
00745         }
00746 
00747       }
00748 //
00749 //  *MESH_FACE_LIST
00750 //  This coding assumes a face is always triangular or quadrilateral.
00751 //
00752       else if ( strcmp ( level_name[level], "*MESH_FACE_LIST" ) == 0 )
00753       {
00754         if ( strcmp ( word, "{" ) == 0 )
00755         {
00756           continue;
00757         }
00758         else if ( strcmp ( word, "}" ) == 0 )
00759         {
00760           level = nlbrack - nrbrack;
00761           continue;
00762         }
00763         else if ( strcmp ( word, "*MESH_FACE" ) == 0 )
00764         {
00765           if ( face_num < FACE_MAX )
00766           {
00767 
00768             face_material[face_num] = 0;
00769             face_order[face_num] = 0;
00770 
00771             count = sscanf ( next, "%d%n", &i, &width );
00772             next = next + width;
00773 
00774             count = sscanf ( next, "%s%n", word2, &width );
00775             next = next + width;
00776             count = sscanf ( next, "%s%n", word2, &width );
00777             next = next + width;
00778 
00779             count = sscanf ( next, "%d%n", &i, &width );
00780             next = next + width;
00781             face[0][face_num] = i + cor3_num_old;
00782             face_order[face_num] = face_order[face_num] + 1;
00783 
00784             count = sscanf ( next, "%s%n", word2, &width );
00785             next = next + width;
00786 
00787             count = sscanf ( next, "%d%n", &i, &width );
00788             next = next + width;
00789             face[1][face_num] = i + cor3_num_old;
00790             face_order[face_num] = face_order[face_num] + 1;
00791 
00792             count = sscanf ( next, "%s%n", word2, &width );
00793             next = next + width;
00794 
00795             count = sscanf ( next, "%d%n", &i, &width );
00796             next = next + width;
00797             face[2][face_num] = i + cor3_num_old;
00798             face_order[face_num] = face_order[face_num] + 1;
00799 
00800             count = sscanf ( next, "%s%n", word2, &width );
00801             next = next + width;
00802 
00803             if ( strcmp ( word2, "D:" ) == 0 )
00804             {
00805               count = sscanf ( next, "%d%n", &i, &width );
00806               next = next + width;
00807               face[3][face_num] = i + cor3_num_old;
00808               face_order[face_num] = face_order[face_num] + 1;
00809             }
00810           }
00811 
00812           face_num = face_num + 1;
00813 
00814           break;
00815 
00816         }
00817         else
00818         {
00819           bad_num = bad_num + 1;
00820           cout << "Bad data in MESH_FACE_LIST, line " << text_num << "\n";
00821           break;
00822         }
00823       }
00824 //
00825 //  *MESH_NORMALS
00826 //
00827       else if ( strcmp ( level_name[level], "*MESH_NORMALS" ) == 0 )
00828       {
00829         if ( strcmp ( word, "{" ) == 0 )
00830         {
00831           continue;
00832         }
00833         else if ( strcmp ( word, "}" ) == 0 )
00834         {
00835           level = nlbrack - nrbrack;
00836           continue;
00837         }
00838         else if ( strcmp ( word, "*MESH_FACENORMAL" ) == 0 )
00839         {
00840           count = sscanf ( next, "%d%n", &iface, &width );
00841           next = next + width;
00842 
00843           count = sscanf ( next, "%f%n", &x, &width );
00844           next = next + width;
00845 
00846           count = sscanf ( next, "%f%n", &y, &width );
00847           next = next + width;
00848 
00849           count = sscanf ( next, "%f%n", &z, &width );
00850           next = next + width;
00851 
00852           iface = iface + face_num_old;
00853           ivert = 0;
00854 
00855           face_normal[0][iface] = x;
00856           face_normal[1][iface] = y;
00857           face_normal[2][iface] = z;
00858 
00859           break;
00860 
00861         }
00862         else if ( strcmp ( word, "*MESH_VERTEXNORMAL" ) == 0 )
00863         {
00864           count = sscanf ( next, "%d%n", &i, &width );
00865           next = next + width;
00866 
00867           count = sscanf ( next, "%f%n", &x, &width );
00868           next = next + width;
00869 
00870           count = sscanf ( next, "%f%n", &y, &width );
00871           next = next + width;
00872 
00873           count = sscanf ( next, "%f%n", &z, &width );
00874           next = next + width;
00875 
00876           vertex_normal[0][ivert][iface] = x;
00877           vertex_normal[1][ivert][iface] = y;
00878           vertex_normal[2][ivert][iface] = z;
00879           ivert = ivert + 1;
00880 
00881           break;
00882         }
00883         else
00884         {
00885           bad_num = bad_num + 1;
00886           cout << "Bad data in MESH_NORMALS, line " << text_num << "\n";
00887           break;
00888         }
00889       }
00890 //
00891 //  *MESH_TFACELIST
00892 //
00893       else if ( strcmp ( level_name[level], "*MESH_TFACELIST" ) == 0 )
00894       {
00895         if ( strcmp ( word, "{" ) == 0 )
00896         {
00897           continue;
00898         }
00899         else if ( strcmp ( word, "}" ) == 0 )
00900         {
00901           level = nlbrack - nrbrack;
00902           continue;
00903         }
00904         else if ( strcmp ( word1, "*MESH_TFACE" ) == 0 )
00905         {
00906           break;
00907         }
00908         else
00909         {
00910           bad_num = bad_num + 1;
00911           cout << "Bad data in MESH_TFACE_LIST, line " << text_num << "\n";
00912           break;
00913         }
00914       }
00915 //
00916 //  *MESH_TVERTLIST
00917 //
00918       else if ( strcmp ( level_name[level], "*MESH_TVERTLIST" ) == 0 )
00919       {
00920         if ( strcmp ( word, "{" ) == 0 )
00921         {
00922           continue;
00923         }
00924         else if ( strcmp ( word, "}" ) == 0 )
00925         {
00926           level = nlbrack - nrbrack;
00927           continue;
00928         }
00929         else if ( strcmp ( word1, "*MESH_TVERT" ) == 0  )
00930         {
00931           break;
00932         }
00933         else
00934         {
00935           bad_num = bad_num + 1;
00936           cout << "Bad data in MESH_TVERTLIST, line " << text_num << "\n";
00937           break;
00938         }
00939       }
00940 //
00941 //  *MESH_VERTEX_LIST
00942 //
00943       else if ( strcmp ( level_name[level], "*MESH_VERTEX_LIST" ) == 0 )
00944       {
00945         if ( strcmp ( word, "{" ) == 0 )
00946         {
00947           cor3_num_old = cor3_num;
00948           continue;
00949         }
00950         else if ( strcmp ( word, "}" ) == 0 )
00951         {
00952           level = nlbrack - nrbrack;
00953           continue;
00954         }
00955         else if ( strcmp ( word1, "*MESH_VERTEX" ) == 0 )
00956         {
00957 
00958           count = sscanf ( next, "%d%n", &i, &width );
00959           next = next + width;
00960 
00961           count = sscanf ( next, "%f%n", &x, &width );
00962           next = next + width;
00963 
00964           count = sscanf ( next, "%f%n", &y, &width );
00965           next = next + width;
00966 
00967           count = sscanf ( next, "%f%n", &z, &width );
00968           next = next + width;
00969 
00970           i = i + cor3_num_old;
00971           if ( cor3_num < i + 1 )
00972           {
00973             cor3_num = i + 1;
00974           }
00975 
00976           if ( i < COR3_MAX )
00977           {
00978             cor3[0][i] =
00979               transform_matrix[0][0] * x
00980             + transform_matrix[0][1] * y
00981             + transform_matrix[0][2] * z
00982             + transform_matrix[0][3];
00983 
00984             cor3[1][i] =
00985               transform_matrix[1][0] * x
00986             + transform_matrix[1][1] * y
00987             + transform_matrix[1][2] * z
00988             + transform_matrix[1][3];
00989 
00990             cor3[2][i] =
00991               transform_matrix[2][0] * x
00992             + transform_matrix[2][1] * y
00993             + transform_matrix[2][2] * z
00994             + transform_matrix[2][3];
00995           }
00996 
00997           break;
00998         }
00999         else
01000         {
01001           bad_num = bad_num + 1;
01002           cout << "Bad data in MESH_VERTEX_LIST, line " << text_num << "\n";
01003           break;
01004         }
01005       }
01006 //
01007 //  *NODE_TM
01008 //
01009 //  Each node should start out with a default transformation matrix.
01010 //
01011       else if ( strcmp ( level_name[level], "*NODE_TM" ) == 0 )
01012       {
01013         if ( strcmp ( word, "{" ) == 0 )
01014         {
01015           tmat_init ( transform_matrix );
01016 
01017           continue;
01018         }
01019         else if ( strcmp ( word, "}" ) == 0 )
01020         {
01021           level = nlbrack - nrbrack;
01022           continue;
01023         }
01024         else if ( strcmp ( word, "*INHERIT_POS" ) == 0 )
01025         {
01026           break;
01027         }
01028         else if ( strcmp ( word, "*INHERIT_ROT" ) == 0 )
01029         {
01030           break;
01031         }
01032         else if ( strcmp ( word, "*INHERIT_SCL" ) == 0 )
01033         {
01034           break;
01035         }
01036         else if ( strcmp ( word, "*NODE_NAME" ) == 0 )
01037         {
01038           break;
01039         }
01040         else if ( strcmp ( word, "*TM_POS" ) == 0 )
01041         {
01042           break;
01043         }
01044         else if ( strcmp ( word, "*TM_ROTANGLE" ) == 0 )
01045         {
01046           break;
01047         }
01048         else if ( strcmp ( word, "*TM_ROTAXIS" ) == 0 )
01049         {
01050           break;
01051         }
01052         else if ( strcmp ( word, "*TM_ROW0" ) == 0 )
01053         {
01054           count = sscanf ( next, "%f%n", &temp, &width );
01055           next = next + width;
01056           transform_matrix[0][0] = temp;
01057 
01058           count = sscanf ( next, "%f%n", &temp, &width );
01059           next = next + width;
01060           transform_matrix[1][0] = temp;
01061 
01062           count = sscanf ( next, "%f%n", &temp, &width );
01063           next = next + width;
01064           transform_matrix[2][0] = temp;
01065 
01066           break;
01067         }
01068         else if ( strcmp ( word, "*TM_ROW1" ) == 0 )
01069         {
01070           count = sscanf ( next, "%f%n", &temp, &width );
01071           next = next + width;
01072           transform_matrix[0][1] = temp;
01073 
01074           count = sscanf ( next, "%f%n", &temp, &width );
01075           next = next + width;
01076           transform_matrix[1][1] = temp;
01077 
01078           count = sscanf ( next, "%f%n", &temp, &width );
01079           next = next + width;
01080           transform_matrix[2][1] = temp;
01081 
01082           break;
01083         }
01084         else if ( strcmp ( word, "*TM_ROW2" ) == 0 )
01085         {
01086           count = sscanf ( next, "%f%n", &temp, &width );
01087           next = next + width;
01088           transform_matrix[0][2] = temp;
01089 
01090           count = sscanf ( next, "%f%n", &temp, &width );
01091           next = next + width;
01092           transform_matrix[1][2] = temp;
01093 
01094           count = sscanf ( next, "%f%n", &temp, &width );
01095           next = next + width;
01096           transform_matrix[2][2] = temp;
01097 
01098           break;
01099         }
01100         else if ( strcmp ( word, "*TM_ROW3" ) == 0 )
01101         {
01102           count = sscanf ( next, "%f%n", &temp, &width );
01103           next = next + width;
01104           transform_matrix[0][3] = temp;
01105 
01106           count = sscanf ( next, "%f%n", &temp, &width );
01107           next = next + width;
01108           transform_matrix[1][3] = temp;
01109 
01110           count = sscanf ( next, "%f%n", &temp, &width );
01111           next = next + width;
01112           transform_matrix[2][3] = temp;
01113 
01114           break;
01115         }
01116         else if ( strcmp ( word, "*TM_SCALE" ) == 0 )
01117         {
01118           break;
01119         }
01120         else if ( strcmp ( word, "*TM_SCALEAXIS" ) == 0 )
01121         {
01122           break;
01123         }
01124         else if ( strcmp ( word, "*TM_SCALEAXISANG" ) == 0 )
01125         {
01126           break;
01127         }
01128         else
01129         {
01130           bad_num = bad_num + 1;
01131           cout << "Bad data in NODE_TM, line " << text_num << "\n";
01132           break;
01133         }
01134       }
01135 //
01136 //  *SCENE
01137 //
01138       else if ( strcmp ( level_name[level], "*SCENE" ) == 0 )
01139       {
01140         if ( strcmp ( word, "{" ) == 0 )
01141         {
01142           continue;
01143         }
01144         else if ( strcmp ( word, "}" ) == 0 )
01145         {
01146           level = nlbrack - nrbrack;
01147           continue;
01148         }
01149         else if ( strcmp ( word, "*SCENE_AMBIENT_STATIC" ) == 0 )
01150         {
01151           break;
01152         }
01153         else if ( strcmp ( word, "*SCENE_BACKGROUND_STATIC" ) == 0 )
01154         {
01155           break;
01156         }
01157         else if ( strcmp ( word, "*SCENE_FILENAME" ) == 0 )
01158         {
01159           break;
01160         }
01161         else if ( strcmp ( word, "*SCENE_FIRSTFRAME" ) == 0 )
01162         {
01163           break;
01164         }
01165         else if ( strcmp ( word, "*SCENE_FRAMESPEED" ) == 0 )
01166         {
01167           break;
01168         }
01169         else if ( strcmp ( word, "*SCENE_LASTFRAME" ) == 0 )
01170         {
01171           break;
01172         }
01173         else if ( strcmp ( word, "*SCENE_TICKSPERFRAME" ) == 0 )
01174         {
01175           break;
01176         }
01177         else
01178         {
01179           bad_num = bad_num + 1;
01180           cout << "Bad data in SCENE, line " << text_num << "\n";
01181           break;
01182         }
01183       }
01184     }
01185 //
01186 //  End of loop reading words from the line.
01187 //
01188   }
01189 //
01190 //  End of loop reading lines from input file.
01191 //
01192 
01193   return 0;
01194 }
01195 //****************************************************************************80
01196 
01197 int ase_write ( FILE *fileout )
01198 
01199 //****************************************************************************80
01200 //
01201 //  Purpose:
01202 //
01203 //    ASE_WRITE writes graphics information to an AutoCAD ASE file.
01204 //
01205 //  Licensing:
01206 //
01207 //    This code is distributed under the GNU LGPL license.
01208 //
01209 //  Modified:
01210 //
01211 //    30 September 1998
01212 //
01213 //  Author:
01214 //
01215 //    John Burkardt
01216 //
01217 //  Parameters:
01218 //
01219 //    Input, FILE *fileout, the output file.
01220 //
01221 {
01222   int i1;
01223   int i2;
01224   int i3;
01225   int i4;
01226   int iface;
01227   int ivert;
01228   int j;
01229   int text_num;
01230 
01231   text_num = 0;
01232 //
01233 //  Write the header.
01234 //
01235   fprintf ( fileout, "*3DSMAX_ASCIIEXPORT 200\n" );
01236   fprintf ( fileout, "*COMMENT \"%s, created by IVCON.\"\n", fileout_name );
01237   fprintf ( fileout, "*COMMENT \"Original data in %s\"\n", filein_name );
01238 
01239   text_num = text_num + 3;
01240 //
01241 //  Write the scene block.
01242 //
01243   fprintf ( fileout, "*SCENE {\n" );
01244   fprintf ( fileout, "  *SCENE_FILENAME \"\"\n" );
01245   fprintf ( fileout, "  *SCENE_FIRSTFRAME 0\n" );
01246   fprintf ( fileout, "  *SCENE_LASTFRAME 100\n" );
01247   fprintf ( fileout, "  *SCENE_FRAMESPEED 30\n" );
01248   fprintf ( fileout, "  *SCENE_TICKSPERFRAME 160\n" );
01249   fprintf ( fileout, "  *SCENE_BACKGROUND_STATIC 0.0000 0.0000 0.0000\n" );
01250   fprintf ( fileout, "  *SCENE_AMBIENT_STATIC 0.0431 0.0431 0.0431\n" );
01251   fprintf ( fileout, "}\n" );
01252 
01253   text_num = text_num + 9;
01254 //
01255 //  Begin the big geometry block.
01256 //
01257   fprintf ( fileout, "*GEOMOBJECT {\n" );
01258   fprintf ( fileout, "  *NODE_NAME \"%s\"\n", object_name );
01259 
01260   text_num = text_num + 2;
01261 //
01262 //  Sub block NODE_TM:
01263 //
01264   fprintf ( fileout, "  *NODE_TM {\n" );
01265   fprintf ( fileout, "    *NODE_NAME \"Object01\"\n" );
01266   fprintf ( fileout, "    *INHERIT_POS 0 0 0\n" );
01267   fprintf ( fileout, "    *INHERIT_ROT 0 0 0\n" );
01268   fprintf ( fileout, "    *INHERIT_SCL 0 0 0\n" );
01269   fprintf ( fileout, "    *TM_ROW0 1.0000 0.0000 0.0000\n" );
01270   fprintf ( fileout, "    *TM_ROW1 0.0000 1.0000 0.0000\n" );
01271   fprintf ( fileout, "    *TM_ROW2 0.0000 0.0000 1.0000\n" );
01272   fprintf ( fileout, "    *TM_ROW3 0.0000 0.0000 0.0000\n" );
01273   fprintf ( fileout, "    *TM_POS 0.0000 0.0000 0.0000\n" );
01274   fprintf ( fileout, "    *TM_ROTAXIS 0.0000 0.0000 0.0000\n" );
01275   fprintf ( fileout, "    *TM_ROTANGLE 0.0000\n" );
01276   fprintf ( fileout, "    *TM_SCALE 1.0000 1.0000 1.0000\n" );
01277   fprintf ( fileout, "    *TM_SCALEAXIS 0.0000 0.0000 0.0000\n" );
01278   fprintf ( fileout, "    *TM_SCALEAXISANG 0.0000\n" );
01279   fprintf ( fileout, "  }\n" );
01280 
01281   text_num = text_num + 16;
01282 //
01283 //  Sub block MESH:
01284 //    Items
01285 //
01286   fprintf ( fileout, "  *MESH {\n" );
01287   fprintf ( fileout, "    *TIMEVALUE 0\n" );
01288   fprintf ( fileout, "    *MESH_NUMVERTEX %d\n", cor3_num );
01289   fprintf ( fileout, "    *MESH_NUMFACES %d\n", face_num );
01290 
01291   text_num = text_num + 4;
01292 //
01293 //  Sub sub block MESH_VERTEX_LIST
01294 //
01295   fprintf ( fileout, "    *MESH_VERTEX_LIST {\n" );
01296   text_num = text_num + 1;
01297 
01298   for ( j = 0; j < cor3_num; j++ )
01299   {
01300     fprintf ( fileout, "      *MESH_VERTEX %d %f %f %f\n", j, cor3[0][j],
01301       cor3[1][j], cor3[2][j] );
01302     text_num = text_num + 1;
01303   }
01304 
01305   fprintf ( fileout, "    }\n" );
01306   text_num = text_num + 1;
01307 //
01308 //  Sub sub block MESH_FACE_LIST
01309 //    Items MESH_FACE
01310 //
01311   fprintf ( fileout, "    *MESH_FACE_LIST {\n" );
01312   text_num = text_num + 1;
01313 
01314   for ( iface = 0; iface < face_num; iface++ )
01315   {
01316     i1 = face[0][iface];
01317     i2 = face[1][iface];
01318     i3 = face[2][iface];
01319 
01320     if ( face_order[iface] == 3 )
01321     {
01322       fprintf ( fileout, "      *MESH_FACE %d: A: %d B: %d C: %d", iface, i1, i2, i3 );
01323       fprintf ( fileout, " AB: 1 BC: 1 CA: 1 *MESH_SMOOTHING *MESH_MTLID 1\n" );
01324       text_num = text_num + 1;
01325     }
01326     else if ( face_order[iface] == 4 )
01327     {
01328       i4 = face[3][iface];
01329       fprintf ( fileout, "      *MESH_FACE %d: A: %d B: %d C: %d D: %d", iface, i1, i2, i3, i4 );
01330       fprintf ( fileout, " AB: 1 BC: 1 CD: 1 DA: 1 *MESH_SMOOTHING *MESH_MTLID 1\n" );
01331       text_num = text_num + 1;
01332     }
01333   }
01334 
01335   fprintf ( fileout, "    }\n" );
01336   text_num = text_num + 1;
01337 //
01338 //  Item MESH_NUMTVERTEX.
01339 //
01340   fprintf ( fileout, "    *MESH_NUMTVERTEX 0\n" );
01341   text_num = text_num + 1;
01342 //
01343 //  Item NUMCVERTEX.
01344 //
01345   fprintf ( fileout, "    *MESH_NUMCVERTEX 0\n" );
01346   text_num = text_num + 1;
01347 //
01348 //  Sub block MESH_NORMALS
01349 //    Items MESH_FACENORMAL, MESH_VERTEXNORMAL (repeated)
01350 //
01351   fprintf ( fileout, "    *MESH_NORMALS {\n" );
01352   text_num = text_num + 1;
01353 
01354   for ( iface = 0; iface < face_num; iface++ )
01355   {
01356     fprintf ( fileout, "      *MESH_FACENORMAL %d %f %f %f\n",
01357       iface, face_normal[0][iface], face_normal[1][iface], face_normal[2][iface] );
01358     text_num = text_num + 1;
01359 
01360     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
01361     {
01362       fprintf ( fileout, "      *MESH_VERTEXNORMAL %d %f %f %f\n",
01363         face[ivert][iface], vertex_normal[0][ivert][iface],
01364         vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
01365       text_num = text_num + 1;
01366     }
01367   }
01368 
01369   fprintf ( fileout, "    }\n" );
01370   text_num = text_num + 1;
01371 //
01372 //  Close the MESH object.
01373 //
01374   fprintf ( fileout, "  }\n" );
01375 //
01376 //  A few closing parameters.
01377 //
01378   fprintf ( fileout, "  *PROP_MOTIONBLUR 0\n" );
01379   fprintf ( fileout, "  *PROP_CASTSHADOW 1\n" );
01380   fprintf ( fileout, "  *PROP_RECVSHADOW 1\n" );
01381 //
01382 //  Close the GEOM object.
01383 //
01384   fprintf ( fileout, "}\n" );
01385 
01386   text_num = text_num + 5;
01387 //
01388 //  Report.
01389 //
01390   cout << "\n";
01391   cout << "ASE_WRITE - Wrote " << text_num << " text lines;\n";
01392 
01393   return 0;
01394 }
01395 //****************************************************************************80
01396 
01397 int byu_read ( FILE *filein )
01398 
01399 //****************************************************************************80
01400 //
01401 //  Purpose:
01402 //
01403 //    BYU_READ reads graphics data from a Movie.BYU surface geometry file.
01404 //
01405 //  Discussion:
01406 //
01407 //    A Movie.BYU surface geometry file contains 4 groups of data.
01408 //
01409 //    The first group of data is a single line, containing 4 integers,
01410 //    each one left justified in 8 columns.  The integers are:
01411 //
01412 //      PART_NUM, VERTEX_NUM, POLY_NUM, EDGE_NUM,
01413 //
01414 //    that is, the number of parts or objects, the number of vertices or nodes,
01415 //    the number of polygons or faces, and the number of edges.
01416 //
01417 //    The second group of data is a single line, containing 2 integers,
01418 //    each one left justified in 8 columnes.  The integers are:
01419 //
01420 //      POLY1, POLY2,
01421 //
01422 //    the starting and ending polygon numbers.  Presumably, this means
01423 //    that the polygons are labeled POLY1, POLY1+1, ..., POLY2, comprising
01424 //    a total of POLY_NUM polygons.
01425 //
01426 //    The third group is the X, Y and Z coordinates of all the vertices.
01427 //    These may be written using a FORTRAN format of 6E12.5, which
01428 //    crams two sets of (X,Y,Z) data onto each line, with each real value
01429 //    written in an exponential format with 5 places after the decimal.
01430 //    However, it is generally possible to write the XYZ coordinate data
01431 //    for each vertex on a separate line.
01432 //
01433 //    The fourth group defines the polygons in terms of the vertex indices.
01434 //    For each polygon, the vertices that make up the polygon are listed in
01435 //    counterclockwise order.  The last vertex listed is given with a negative
01436 //    sign to indicate the end of the list.  All the vertices for all the
01437 //    polygons are listed one after the other, using a format that puts
01438 //    up to 10 left-justified integers on a line, with each integer occupying
01439 //    8 spaces.
01440 //
01441 //    This code will certainly read a BYU file created by BYU_WRITE, but
01442 //    it will not handle more general files.  In particular, an object
01443 //    can have several parts, the coordinate data can be grouped so
01444 //    that there are 2 sets of (x,y,z) data per line, and so on.
01445 //
01446 //  Example:
01447 //
01448 //      1       8       6      24
01449 //      1       6
01450 //    0.00000E+00 0.00000E+00 0.00000E+00
01451 //    1.00000E+00 0.00000E+00 0.00000E+00
01452 //    1.00000E+00 2.00000E+00 0.00000E+00
01453 //    0.00000E+00 2.00000E+00 0.00000E+00
01454 //    0.00000E+00 0.00000E+00 1.00000E+00
01455 //    1.00000E+00 0.00000E+00 1.00000E+00
01456 //    1.00000E+00 2.00000E+00 1.00000E+00
01457 //    0.00000E+00 2.00000E+00 1.00000E+00
01458 //      4       3       2      -1
01459 //      5       6       7      -8
01460 //      1       5       8      -4
01461 //      4       8       7      -3
01462 //      3       7       6      -2
01463 //      2       6       5      -1
01464 //
01465 //  Licensing:
01466 //
01467 //    This code is distributed under the GNU LGPL license.
01468 //
01469 //  Modified:
01470 //
01471 //    24 May 2001
01472 //
01473 //  Author:
01474 //
01475 //    John Burkardt
01476 //
01477 //
01478 {
01479   int cor3_num_new;
01480   int count;
01481   int edge_num;
01482   int face_num_new;
01483   int iface;
01484   int ival;
01485   int ivert;
01486   int j;
01487   char *next;
01488   int part_num;
01489   int poly1;
01490   int poly2;
01491   int text_num;
01492   int width;
01493   float x;
01494   float y;
01495   float z;
01496 
01497   text_num = 0;
01498 
01499   if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
01500   {
01501     return 1;
01502   }
01503   text_num = text_num + 1;
01504 
01505   sscanf ( input, "%d %d %d %d", &part_num, &cor3_num_new, &face_num_new,
01506     &edge_num );
01507 
01508   if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
01509   {
01510     return 1;
01511   }
01512   text_num = text_num + 1;
01513 
01514   sscanf ( input, "%d %d", &poly1, &poly2 );
01515 
01516   for ( j = cor3_num; j < cor3_num + cor3_num_new; j++ )
01517   {
01518     if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
01519     {
01520       return 1;
01521     }
01522     text_num = text_num + 1;
01523 
01524     sscanf ( input, "%f %f %f", &x, &y, &z );
01525     cor3[0][j] = x;
01526     cor3[1][j] = y;
01527     cor3[2][j] = z;
01528   }
01529 
01530   for ( iface = face_num; iface < face_num + face_num_new; iface++ )
01531   {
01532     if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
01533     {
01534       return 1;
01535     }
01536     text_num = text_num + 1;
01537 
01538     next = input;
01539     ivert = 0;
01540 
01541     for (;;)
01542     {
01543       count = sscanf ( next, "%d%n", &ival, &width );
01544       next = next + width;
01545 
01546       if ( count <= 0 )
01547       {
01548         return 1;
01549       }
01550 
01551       if ( 0 < ival )
01552       {
01553         face[ivert][iface] = ival - 1 + cor3_num;
01554       }
01555       else
01556       {
01557         face[ivert][iface] = - ival - 1 - cor3_num;
01558         break;
01559       }
01560 
01561       ivert = ivert + 1;
01562 
01563     }
01564     face_order[iface] = ivert + 1;
01565   }
01566 
01567   cor3_num = cor3_num + cor3_num_new;
01568   face_num = face_num + face_num_new;
01569 //
01570 //  Report.
01571 //
01572   cout << "\n";
01573   cout << "BYU_READ - Read " << text_num << " text lines.\n";
01574 
01575   return 0;
01576 }
01577 //****************************************************************************80
01578 
01579 int byu_write ( FILE *fileout )
01580 
01581 //****************************************************************************80
01582 //
01583 //  Purpose:
01584 //
01585 //    BYU_WRITE writes out the graphics data as a Movie.BYU surface geometry file.
01586 //
01587 //  Discussion:
01588 //
01589 //    A Movie.BYU surface geometry file contains 4 groups of data.
01590 //
01591 //    The first group of data is a single line, containing 4 integers,
01592 //    each one left justified in 8 columns.  The integers are:
01593 //
01594 //      PART_NUM, VERTEX_NUM, POLY_NUM, EDGE_NUM,
01595 //
01596 //    that is, the number of parts or objects, the number of vertices or nodes,
01597 //    the number of polygons or faces, and the number of edges.
01598 //
01599 //    The second group of data is a single line, containing 2 integers,
01600 //    each one left justified in 8 columnes.  The integers are:
01601 //
01602 //      POLY1, POLY2,
01603 //
01604 //    the starting and ending polygon numbers.  Presumably, this means
01605 //    that the polygons are labeled POLY1, POLY1+1, ..., POLY2, comprising
01606 //    a total of POLY_NUM polygons.
01607 //
01608 //    The third group is the X, Y and Z coordinates of all the vertices.
01609 //    These may be written using a FORTRAN format of 6E12.5, which
01610 //    crams two sets of (X,Y,Z) data onto each line, with each real value
01611 //    written in an exponential format with 5 places after the decimal.
01612 //    However, it is generally possible to write the XYZ coordinate data
01613 //    for each vertex on a separate line.
01614 //
01615 //    The fourth group defines the polygons in terms of the vertex indices.
01616 //    For each polygon, the vertices that make up the polygon are listed in
01617 //    counterclockwise order.  The last vertex listed is given with a negative
01618 //    sign to indicate the end of the list.  All the vertices for all the
01619 //    polygons are listed one after the other, using a format that puts
01620 //    up to 10 left-justified integers on a line, with each integer occupying
01621 //    8 spaces.
01622 //
01623 //  Example:
01624 //
01625 //      1       8       6      24
01626 //      1       6
01627 //    0.00000E+00 0.00000E+00 0.00000E+00
01628 //    1.00000E+00 0.00000E+00 0.00000E+00
01629 //    1.00000E+00 2.00000E+00 0.00000E+00
01630 //    0.00000E+00 2.00000E+00 0.00000E+00
01631 //    0.00000E+00 0.00000E+00 1.00000E+00
01632 //    1.00000E+00 0.00000E+00 1.00000E+00
01633 //    1.00000E+00 2.00000E+00 1.00000E+00
01634 //    0.00000E+00 2.00000E+00 1.00000E+00
01635 //      4       3       2      -1
01636 //      5       6       7      -8
01637 //      1       5       8      -4
01638 //      4       8       7      -3
01639 //      3       7       6      -2
01640 //      2       6       5      -1
01641 //
01642 //  Licensing:
01643 //
01644 //    This code is distributed under the GNU LGPL license.
01645 //
01646 //  Modified:
01647 //
01648 //    24 May 2001
01649 //
01650 //  Author:
01651 //
01652 //    John Burkardt
01653 //
01654 {
01655   int edge_num;
01656   int iface;
01657   int ivert;
01658   int j;
01659   int jp;
01660   int part_num;
01661   int text_num;
01662 
01663   text_num = 0;
01664 
01665   edge_num = 0;
01666   for ( iface = 0; iface < face_num; iface++ )
01667   {
01668     edge_num = edge_num + face_order[iface];
01669   }
01670 
01671   part_num = 1;
01672 
01673   fprintf ( fileout, "%d %d %d %d\n", part_num, cor3_num, face_num, edge_num );
01674   text_num = text_num + 1;
01675 
01676   fprintf ( fileout, "1 %d\n", face_num );
01677   text_num = text_num + 1;
01678 
01679   for ( j = 0; j < cor3_num; j++ )
01680   {
01681     fprintf ( fileout, "%f %f %f\n", cor3[0][j], cor3[1][j], cor3[2][j] );
01682     text_num = text_num + 1;
01683   }
01684 
01685   for ( iface = 0; iface < face_num; iface++ )
01686   {
01687     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
01688     {
01689       jp = face[ivert][iface] + 1;
01690       if ( ivert == face_order[iface] - 1 )
01691       {
01692         jp = - jp;
01693       }
01694      fprintf ( fileout, "%d ", jp );
01695     }
01696     fprintf ( fileout, "\n" );
01697     text_num = text_num + 1;
01698   }
01699 //
01700 //  Report.
01701 //
01702   cout << "\n";
01703   cout << "BYU_WRITE - Wrote " << text_num << " text lines.\n";
01704 
01705   return 0;
01706 }
01707 //****************************************************************************80
01708 
01709 char ch_cap ( char c )
01710 
01711 //****************************************************************************80
01712 //
01713 //  Purpose:
01714 //
01715 //    CH_CAP capitalizes a single character.
01716 //
01717 //  Discussion:
01718 //
01719 //    This routine should be equivalent to the library "toupper" function.
01720 //
01721 //  Licensing:
01722 //
01723 //    This code is distributed under the GNU LGPL license.
01724 //
01725 //  Modified:
01726 //
01727 //    19 July 1998
01728 //
01729 //  Author:
01730 //
01731 //    John Burkardt
01732 //
01733 //  Parameters:
01734 //
01735 //    Input, char C, the character to capitalize.
01736 //
01737 //    Output, char CH_CAP, the capitalized character.
01738 //
01739 {
01740   if ( 97 <= c && c <= 122 )
01741   {
01742     c = c - 32;
01743   }
01744 
01745   return c;
01746 }
01747 //****************************************************************************80
01748 
01749 bool ch_eqi ( char c1, char c2 )
01750 
01751 //****************************************************************************80
01752 //
01753 //  Purpose:
01754 //
01755 //    CH_EQI is true if two characters are equal, disregarding case.
01756 //
01757 //  Licensing:
01758 //
01759 //    This code is distributed under the GNU LGPL license.
01760 //
01761 //  Modified:
01762 //
01763 //    13 June 2003
01764 //
01765 //  Author:
01766 //
01767 //    John Burkardt
01768 //
01769 //  Parameters:
01770 //
01771 //    Input, char C1, char C2, the characters to compare.
01772 //
01773 //    Output, bool CH_EQI, is true if the two characters are equal,
01774 //    disregarding case.
01775 //
01776 {
01777   if ( 97 <= c1 && c1 <= 122 )
01778   {
01779     c1 = c1 - 32;
01780   }
01781   if ( 97 <= c2 && c2 <= 122 )
01782   {
01783     c2 = c2 - 32;
01784   }
01785 
01786   return ( c1 == c2 );
01787 }
01788 //****************************************************************************80
01789 
01790 int ch_index_last ( char *s, char c )
01791 
01792 //****************************************************************************80
01793 //
01794 //  Purpose:
01795 //
01796 //    CH_INDEX_LAST finds the last occurrence of a character in a string.
01797 //
01798 //  Licensing:
01799 //
01800 //    This code is distributed under the GNU LGPL license.
01801 //
01802 //  Modified:
01803 //
01804 //    16 October 1998
01805 //
01806 //  Author:
01807 //
01808 //    John Burkardt
01809 //
01810 //  Parameters:
01811 //
01812 //    Input, char *S, a pointer to a string to be searched.
01813 //
01814 //    Input, char C, the character to be searched for in s.
01815 //
01816 //    Output, int CH_INDEX_LAST, the index in s of the last occurrence
01817 //    of C, or -1 if c does not occur in s.
01818 //
01819 {
01820   int i;
01821   int j;
01822   int nchar;
01823 
01824   j = -1;
01825 
01826   nchar = strlen ( s );
01827 
01828   for ( i = 0; i < nchar; i++ )
01829   {
01830     if ( s[i] == c )
01831     {
01832       j = i;
01833     }
01834   }
01835 
01836   return j;
01837 
01838 }
01839 //****************************************************************************80
01840 
01841 bool ch_is_space ( char c )
01842 
01843 //****************************************************************************80
01844 //
01845 //  Purpose:
01846 //
01847 //    CH_IS_SPACE is TRUE if a character represents "white space".
01848 //
01849 //  Discussion:
01850 //
01851 //    A white space character is a space, a form feed, a newline, a carriage
01852 //    return, a horizontal tab, or a vertical tab.
01853 //
01854 //  Licensing:
01855 //
01856 //    This code is distributed under the GNU LGPL license.
01857 //
01858 //  Modified:
01859 //
01860 //    02 October 2004
01861 //
01862 //  Author:
01863 //
01864 //    John Burkardt
01865 //
01866 //  Parameters:
01867 //
01868 //    Input, char C, the character to be analyzed.
01869 //
01870 //    Output, bool CH_IS_SPACE, is TRUE if C is a whitespace character.
01871 //
01872 {
01873   if ( c == ' ' )
01874   {
01875     return true;
01876   }
01877   else if ( c == '\f' )
01878   {
01879     return true;
01880   }
01881   else if ( c == '\n' )
01882   {
01883     return true;
01884   }
01885   else if ( c == '\r' )
01886   {
01887     return true;
01888   }
01889   else if ( c == '\t' )
01890   {
01891     return true;
01892   }
01893   else if ( c == '\v' )
01894   {
01895     return true;
01896   }
01897   else
01898   {
01899     return false;
01900   }
01901 }
01902 //****************************************************************************80
01903 
01904 int ch_pad ( int *char_index, int *null_index, char *s, int max_string )
01905 
01906 //****************************************************************************80
01907 //
01908 //  Purpose:
01909 //
01910 //    CH_PAD "pads" a character in a string with a blank on either side.
01911 //
01912 //  Licensing:
01913 //
01914 //    This code is distributed under the GNU LGPL license.
01915 //
01916 //  Modified:
01917 //
01918 //    16 October 1998
01919 //
01920 //  Author:
01921 //
01922 //    John Burkardt
01923 //
01924 //  Parameters:
01925 //
01926 //    Input/output, int *CHAR_INDEX, the position of the character to be
01927 //    padded.  On output, this is increased by 1.
01928 //
01929 //    Input/output, int *NULL_INDEX, the position of the terminating NULL in
01930 //    the string.  On output, this is increased by 2.
01931 //
01932 //    Input/output, char S[MAX_STRING], the string to be manipulated.
01933 //
01934 //    Input, int MAX_STRING, the maximum number of characters that can be stored
01935 //    in s.
01936 //
01937 //    Output, int CH_PAD, is 0 if the operation worked, and 1 otherwise.
01938 //
01939 {
01940   int i;
01941 
01942   if ( *char_index < 0 ||
01943       *null_index <= *char_index ||
01944       max_string - 1 < *char_index )
01945   {
01946     return 1;
01947   }
01948 
01949   if ( max_string - 1 < (*null_index) + 2 )
01950   {
01951     return 1;
01952   }
01953 
01954   for ( i = *null_index + 2; *char_index + 2 < i; i-- )
01955   {
01956     s[i] = s[i-2];
01957   }
01958   s[*char_index+2] = ' ';
01959   s[*char_index+1] = s[*char_index];
01960   s[*char_index] = ' ';
01961 
01962   *char_index = *char_index + 1;
01963   *null_index = *null_index + 2;
01964 
01965   return 0;
01966 }
01967 //****************************************************************************80
01968 
01969 char ch_read ( FILE *filein )
01970 
01971 //****************************************************************************80
01972 //
01973 //  Purpose:
01974 //
01975 //    CH_READ reads one character from a binary file.
01976 //
01977 //  Licensing:
01978 //
01979 //    This code is distributed under the GNU LGPL license.
01980 //
01981 //  Modified:
01982 //
01983 //    24 May 1999
01984 //
01985 //  Author:
01986 //
01987 //    John Burkardt
01988 //
01989 {
01990   char c;
01991 
01992   c = ( char ) fgetc ( filein );
01993 
01994   return c;
01995 }
01996 //****************************************************************************80
01997 
01998 int ch_to_digit ( char c )
01999 
02000 //****************************************************************************80
02001 //
02002 //  Purpose:
02003 //
02004 //    CH_TO_DIGIT returns the integer value of a base 10 digit.
02005 //
02006 //  Example:
02007 //
02008 //     C   DIGIT
02009 //    ---  -----
02010 //    '0'    0
02011 //    '1'    1
02012 //    ...  ...
02013 //    '9'    9
02014 //    ' '    0
02015 //    'X'   -1
02016 //
02017 //  Licensing:
02018 //
02019 //    This code is distributed under the GNU LGPL license.
02020 //
02021 //  Modified:
02022 //
02023 //    13 June 2003
02024 //
02025 //  Author:
02026 //
02027 //    John Burkardt
02028 //
02029 //  Parameters:
02030 //
02031 //    Input, char C, the decimal digit, '0' through '9' or blank are legal.
02032 //
02033 //    Output, int CH_TO_DIGIT, the corresponding integer value.  If C was
02034 //    'illegal', then DIGIT is -1.
02035 //
02036 {
02037   int digit;
02038 
02039   if ( '0' <= c && c <= '9' )
02040   {
02041     digit = c - '0';
02042   }
02043   else if ( c == ' ' )
02044   {
02045     digit = 0;
02046   }
02047   else
02048   {
02049     digit = -1;
02050   }
02051 
02052   return digit;
02053 }
02054 //****************************************************************************80
02055 
02056 int ch_write ( FILE *fileout, char c )
02057 
02058 //****************************************************************************80
02059 //
02060 //  Purpose:
02061 //
02062 //    CH_WRITE writes one character to a binary file.
02063 //
02064 //  Licensing:
02065 //
02066 //    This code is distributed under the GNU LGPL license.
02067 //
02068 //  Modified:
02069 //
02070 //    24 May 1999
02071 //
02072 //  Author:
02073 //
02074 //    John Burkardt
02075 //
02076 {
02077   fputc ( c, fileout );
02078 
02079   return 1;
02080 }
02081 //****************************************************************************80
02082 
02083 int command_line ( char **argv )
02084 
02085 //****************************************************************************80
02086 //
02087 //  Purpose:
02088 //
02089 //    COMMAND_LINE carries out a command-line session of file conversion.
02090 //
02091 //  Discussion:
02092 //
02093 //    This routine is invoked when the user command is something like
02094 //
02095 //      ivcon filein_name fileout_name
02096 //
02097 //    or
02098 //
02099 //      ivcon -rn filein_name fileout_name
02100 //
02101 //    where "-rn" signals the "reverse normals" option, or
02102 //
02103 //      ivcon -rf filein_name fileout_name
02104 //
02105 //    where "-rf" signals the "reverse faces" option.
02106 //
02107 //  Licensing:
02108 //
02109 //    This code is distributed under the GNU LGPL license.
02110 //
02111 //  Modified:
02112 //
02113 //    28 June 1999
02114 //
02115 //  Author:
02116 //
02117 //    John Burkardt
02118 //
02119 {
02120   int i;
02121   int iarg;
02122   int icor3;
02123   int ierror;
02124   int iface;
02125   int ivert;
02126   bool reverse_faces;
02127   bool reverse_normals;
02128   bool success;
02129 //
02130 //  Initialize local data.
02131 //
02132   iarg = 0;
02133   ierror = 0;
02134   reverse_faces = false;
02135   reverse_normals = false;
02136 //
02137 //  Initialize the graphics data.
02138 //
02139   data_init ( );
02140 //
02141 //  Get the -RN option, -RF option, and the input file name.
02142 //
02143   iarg = iarg + 1;
02144   strcpy ( filein_name, argv[iarg] );
02145 
02146   if ( s_eqi ( filein_name, "-RN" ) )
02147   {
02148     reverse_normals = true;
02149     cout << "\n";
02150     cout << "COMMAND_LINE: Reverse_Normals option requested.\n";
02151     iarg = iarg + 1;
02152     strcpy ( filein_name, argv[iarg] );
02153   }
02154 
02155   if ( s_eqi ( filein_name, "-RF" ) )
02156   {
02157     reverse_faces = true;
02158     cout << "\n";
02159     cout << "COMMAND_LINE: Reverse_Faces option requested.\n";
02160     iarg = iarg + 1;
02161     strcpy ( filein_name, argv[iarg] );
02162   }
02163 //
02164 //  Read the input.
02165 //
02166   success = data_read ( );
02167 
02168   if ( !success )
02169   {
02170     cout << "\n";
02171     cout << "COMMAND_LINE - Fatal error!\n";
02172     cout << "  Failure reported from DATA_READ.\n";
02173     return 1;
02174   }
02175 //
02176 //  Reverse the normal vectors if requested.
02177 //
02178   if ( reverse_normals )
02179   {
02180 
02181     for ( icor3 = 0; icor3 < cor3_num; icor3++ )
02182     {
02183       for ( i = 0; i < 3; i++ )
02184       {
02185         cor3_normal[i][icor3] = - cor3_normal[i][icor3];
02186       }
02187     }
02188 
02189     for ( iface = 0; iface < face_num; iface++ )
02190     {
02191       for ( i = 0; i < 3; i++ )
02192       {
02193         face_normal[i][iface] = - face_normal[i][iface];
02194       }
02195     }
02196 
02197     for ( iface = 0; iface < face_num; iface++ )
02198     {
02199       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
02200       {
02201         for ( i = 0; i < 3; i++ )
02202         {
02203           vertex_normal[i][ivert][iface] =
02204             - vertex_normal[i][ivert][iface];
02205         }
02206       }
02207     }
02208     cout << "\n";
02209     cout << "COMMAND_LINE - Note:\n";
02210     cout << "  Reversed node, face, and vertex normals.\n";
02211   }
02212 //
02213 //  Reverse the faces if requested.
02214 //
02215   if ( reverse_faces )
02216   {
02217     face_reverse_order ( );
02218 
02219     cout << "\n";
02220     cout << "COMMAND_LINE - Note:\n";
02221     cout << "  Reversed the face definitions.\n";
02222   }
02223 //
02224 //  Write the output file.
02225 //
02226   iarg = iarg + 1;
02227   strcpy ( fileout_name, argv[iarg] );
02228 
02229   ierror = data_write ( );
02230 
02231   if ( ierror == 1 )
02232   {
02233     cout << "\n";
02234     cout << "COMMAND_LINE - Fatal error!\n";
02235     cout << "  Failure while writing output data.\n";
02236     return 1;
02237   }
02238   return 0;
02239 }
02240 //****************************************************************************80
02241 
02242 void cor3_normal_set ( )
02243 
02244 //****************************************************************************80
02245 //
02246 //  Purpose:
02247 //
02248 //    COR3_NORMAL_SET computes node normal vectors.
02249 //
02250 //  Licensing:
02251 //
02252 //    This code is distributed under the GNU LGPL license.
02253 //
02254 //  Modified:
02255 //
02256 //    18 November 1998
02257 //
02258 //  Author:
02259 //
02260 //    John Burkardt
02261 //
02262 {
02263   int   icor3;
02264   int   iface;
02265   int   ivert;
02266   int   j;
02267   float norm;
02268   float temp;
02269 
02270   for ( icor3 = 0; icor3 < cor3_num; icor3++ )
02271   {
02272     for ( j = 0; j < 3; j++ )
02273     {
02274       cor3_normal[j][icor3] = 0.0;
02275     }
02276   }
02277 //
02278 //  Add up the normals at all the faces to which the node belongs.
02279 //
02280   for ( iface = 0; iface < face_num; iface++ )
02281   {
02282     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
02283     {
02284       icor3 = face[ivert][iface];
02285       for ( j = 0; j < 3; j++ )
02286       {
02287         cor3_normal[j][icor3] = cor3_normal[j][icor3]
02288           + vertex_normal[j][ivert][iface];
02289       }
02290     }
02291   }
02292 //
02293 //  Renormalize.
02294 //
02295   for ( icor3 = 0; icor3 < cor3_num; icor3++ )
02296   {
02297     norm = 0.0;
02298     for ( j = 0; j < 3; j++ )
02299     {
02300       temp = cor3_normal[j][icor3];
02301       norm = norm + temp * temp;
02302     }
02303 
02304     if ( norm == 0.0 )
02305     {
02306       norm = 3.0;
02307       for ( j = 0; j < 3; j++ )
02308       {
02309         cor3_normal[j][icor3] = 1.0;
02310       }
02311     }
02312 
02313     norm = ( float ) sqrt ( norm );
02314 
02315     for ( j = 0; j < 3; j++ )
02316     {
02317       cor3_normal[j][icor3] = cor3_normal[j][icor3] / norm;
02318     }
02319   }
02320 
02321   return;
02322 }
02323 //****************************************************************************80
02324 
02325 void cor3_range ( )
02326 
02327 //****************************************************************************80
02328 //
02329 //  Purpose:
02330 //
02331 //    COR3_RANGE computes the coordinate minima and maxima.
02332 //
02333 //  Licensing:
02334 //
02335 //    This code is distributed under the GNU LGPL license.
02336 //
02337 //  Modified:
02338 //
02339 //    31 August 1998
02340 //
02341 //  Author:
02342 //
02343 //    John Burkardt
02344 //
02345 {
02346   int   i;
02347   float xave;
02348   float xmax;
02349   float xmin;
02350   float yave;
02351   float ymax;
02352   float ymin;
02353   float zave;
02354   float zmax;
02355   float zmin;
02356 
02357   xave = cor3[0][0];
02358   xmax = cor3[0][0];
02359   xmin = cor3[0][0];
02360 
02361   yave = cor3[1][0];
02362   ymax = cor3[1][0];
02363   ymin = cor3[1][0];
02364 
02365   zave = cor3[2][0];
02366   zmax = cor3[2][0];
02367   zmin = cor3[2][0];
02368 
02369   for ( i = 1; i < cor3_num; i++ )
02370   {
02371     xave = xave + cor3[0][i];
02372     if ( cor3[0][i] < xmin )
02373     {
02374       xmin = cor3[0][i];
02375     }
02376     if ( xmax < cor3[0][i] )
02377     {
02378       xmax = cor3[0][i];
02379     }
02380 
02381     yave = yave + cor3[1][i];
02382     if ( cor3[1][i] < ymin )
02383     {
02384       ymin = cor3[1][i];
02385     }
02386     if ( ymax < cor3[1][i] )
02387     {
02388       ymax = cor3[1][i];
02389     }
02390 
02391     zave = zave + cor3[2][i];
02392     if ( cor3[2][i] < zmin )
02393     {
02394       zmin = cor3[2][i];
02395     }
02396     if ( zmax < cor3[2][i] )
02397     {
02398       zmax = cor3[2][i];
02399     }
02400   }
02401 
02402   xave = xave / cor3_num;
02403   yave = yave / cor3_num;
02404   zave = zave / cor3_num;
02405 
02406   cout << "\n";
02407   cout << "COR3_RANGE - Data range:\n";
02408   cout << "\n";
02409   cout << "   Minimum   Average   Maximum  Range\n";
02410   cout << "\n";
02411   cout << "X  " << setw(10) << xmin        << "  "
02412                 << setw(10) << xave        << "  "
02413                 << setw(10) << xmax        << "  "
02414                 << setw(10) << xmax - xmin << "\n";
02415   cout << "Y  " << setw(10) << ymin        << "  "
02416                 << setw(10) << yave        << "  "
02417                 << setw(10) << ymax        << "  "
02418                 << setw(10) << ymax - ymin << "\n";
02419   cout << "Z  " << setw(10) << zmin        << "  "
02420                 << setw(10) << zave        << "  "
02421                 << setw(10) << zmax        << "  "
02422                 << setw(10) << zmax - zmin << "\n";
02423 
02424   return;
02425 }
02426 //****************************************************************************80
02427 
02428 void data_check ( )
02429 
02430 //****************************************************************************80
02431 //
02432 //  Purpose:
02433 //
02434 //    DATA_CHECK checks the input data.
02435 //
02436 //  Licensing:
02437 //
02438 //    This code is distributed under the GNU LGPL license.
02439 //
02440 //  Modified:
02441 //
02442 //    02 May 2005
02443 //
02444 //  Author:
02445 //
02446 //    John Burkardt
02447 //
02448 {
02449   int iface;
02450   int nfix;
02451 
02452   if ( COLOR_MAX < color_num )
02453   {
02454     cout << "\n";
02455     cout << "DATA_CHECK - Warning!\n";
02456     cout << "  The input data requires " << color_num << " colors.\n";
02457     cout << "  There was only room for " << COLOR_MAX << "\n";
02458     cout << "\n";
02459     cout << "  To correct this problem, you can change the internal\n";
02460     cout << "  value of COLOR_MAX, recompile, and rerun the program.\n";
02461     color_num = COLOR_MAX;
02462   }
02463 
02464   if ( COR3_MAX < cor3_num )
02465   {
02466     cout << "\n";
02467     cout << "DATA_CHECK - Warning!\n";
02468     cout << "  The input data requires " << cor3_num << " points.\n";
02469     cout << "  There was only room for " << COR3_MAX << "\n";
02470     cout << "\n";
02471     cout << "  To correct this problem, you can change the internal\n";
02472     cout << "  value of COR3_MAX, recompile, and rerun the program.\n";
02473     cor3_num = COR3_MAX;
02474   }
02475 
02476   if ( FACE_MAX < face_num )
02477   {
02478     cout << "\n";
02479     cout << "DATA_CHECK - Warning!\n";
02480     cout << "  The input data requires " << face_num << " faces.\n";
02481     cout << "  There was only room for " << FACE_MAX << "\n";
02482     cout << "\n";
02483     cout << "  To correct this problem, you can change the internal\n";
02484     cout << "  value of FACE_MAX, recompile, and rerun the program.\n";
02485     face_num = FACE_MAX;
02486   }
02487 
02488   if ( LINES_MAX < line_num )
02489   {
02490     cout << "\n";
02491     cout << "DATA_CHECK - Warning!\n";
02492     cout << "  The input data requires " << line_num << " line items.\n";
02493     cout << "  There was only room for " << LINES_MAX << ".\n";
02494     cout << "\n";
02495     cout << "  To correct this problem, you can change the internal\n";
02496     cout << "  value of LINES_MAX, recompile, and rerun the program.\n";
02497     line_num = LINES_MAX;
02498   }
02499 
02500   nfix = 0;
02501 
02502   for ( iface = 0; iface < face_num; iface++ )
02503   {
02504     if ( ORDER_MAX < face_order[iface] )
02505     {
02506       face_order[iface] = ORDER_MAX;
02507       nfix = nfix + 1;
02508     }
02509   }
02510 
02511   if ( 0 < nfix )
02512   {
02513     cout << "\n";
02514     cout << "DATA_CHECK - Warning!\n";
02515     cout << "  Corrected " << nfix
02516          << " faces using more than " << ORDER_MAX
02517          << " vertices per face.\n";
02518   }
02519 
02520   for ( i = 0; i < material_num; i++ )
02521   {
02522     if ( strcmp ( material_name[i], "" ) == 0 )
02523     {
02524       strcpy ( material_name[i], "Material_0000" );
02525     }
02526   }
02527 
02528   for ( i = 0; i < texture_num; i++ )
02529   {
02530     if ( strcmp ( texture_name[i], "" ) == 0 )
02531     {
02532       strcpy ( texture_name[i], "Texture_0000" );
02533     }
02534   }
02535 
02536   cout << "\n";
02537   cout << "DATA_CHECK - Data checked.\n";
02538 
02539   return;
02540 }
02541 //****************************************************************************80
02542 
02543 void data_init ( )
02544 
02545 //****************************************************************************80
02546 //
02547 //  Purpose:
02548 //
02549 //    DATA_INIT initializes the internal graphics data.
02550 //
02551 //  Licensing:
02552 //
02553 //    This code is distributed under the GNU LGPL license.
02554 //
02555 //  Modified:
02556 //
02557 //    04 July 2000
02558 //
02559 //  Author:
02560 //
02561 //    John Burkardt
02562 //
02563 {
02564   int i;
02565   int iface;
02566   int ivert;
02567   int j;
02568   int k;
02569 
02570   strcpy( anim_name, "" );
02571 
02572   for ( i = 0; i < 3; i++ )
02573   {
02574     background_rgb[i] = 0.0;
02575   }
02576 
02577   for ( i = 0; i < 3; i++ )
02578   {
02579     for ( j = 0; j < COR3_MAX; j++ )
02580     {
02581       cor3[i][j] = 0.0;
02582     }
02583   }
02584 
02585   for ( i = 0; i < COR3_MAX; i++ )
02586   {
02587     cor3_material[i] = 0;
02588   }
02589 
02590   for ( i = 0; i < 3; i++ )
02591   {
02592     for ( j = 0; j < COR3_MAX; j++ )
02593     {
02594       cor3_normal[i][j] = 0.0;
02595     }
02596   }
02597 
02598   for ( j = 0; j < COR3_MAX; j++ )
02599   {
02600     cor3_tex_uv[0][j] = 0.0;
02601     cor3_tex_uv[1][j] = 0.0;
02602   }
02603 
02604   for ( iface = 0; iface < FACE_MAX; iface++ )
02605   {
02606     for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
02607     {
02608       face[ivert][iface] = 0;
02609     }
02610   }
02611 
02612   for ( iface = 0; iface < FACE_MAX; iface++ )
02613   {
02614     face_flags[iface] = 6;
02615   }
02616 
02617   for ( iface = 0; iface < FACE_MAX; iface++ )
02618   {
02619     face_material[iface] = 0;
02620   }
02621 
02622   for ( iface = 0; iface < FACE_MAX; iface++ )
02623   {
02624     for ( i = 0; i < 3; i++ )
02625     {
02626       face_normal[i][iface] = 0;
02627     }
02628   }
02629 
02630   for ( iface = 0; iface < FACE_MAX; iface++ )
02631   {
02632     face_object[iface] = -1;
02633   }
02634 
02635   for ( iface = 0; iface < FACE_MAX; iface++ )
02636   {
02637     face_order[iface] = 0;
02638   }
02639 
02640   for ( iface = 0; iface < FACE_MAX; iface++ )
02641   {
02642     face_smooth[iface] = 1;
02643   }
02644 
02645   for ( i = 0; i < LINES_MAX; i++ )
02646   {
02647     line_dex[i] = -1;
02648   }
02649 
02650   for ( i = 0; i < LINES_MAX; i++ )
02651   {
02652     line_material[i] = 0;
02653   }
02654 
02655   strcpy ( material_binding, "DEFAULT" );
02656 
02657   for ( j = 0; j < MATERIAL_MAX; j++ )
02658   {
02659     strcpy ( material_name[j], "Material_0000" );
02660   }
02661 
02662   for ( i = 0; i < 4; i++ )
02663   {
02664     for ( j = 0; j < MATERIAL_MAX; j++ )
02665     {
02666       material_rgba[i][j] = 0.0;
02667     }
02668   }
02669 
02670   strcpy ( normal_binding, "DEFAULT" );
02671 
02672   for ( j = 0; j < ORDER_MAX*FACE_MAX; j++ )
02673   {
02674     for ( i = 0; i < 3; i++ )
02675     {
02676       normal_temp[i][j] = 0;
02677     }
02678   }
02679 
02680   color_num = 0;
02681   cor3_num = 0;
02682   face_num = 0;
02683   group_num = 0;
02684   line_num = 0;
02685   material_num = 0;
02686   object_num = 0;
02687   texture_num = 0;
02688 
02689   strcpy ( object_name, "IVCON" );
02690 
02691   for ( i = 0; i < 3; i++ )
02692   {
02693     origin[i] = 0.0;
02694   }
02695 
02696   for ( i = 0; i < 3; i++ )
02697   {
02698     pivot[i] = 0.0;
02699   }
02700 
02701   for ( j = 0; j < COLOR_MAX; j++ )
02702   {
02703     rgbcolor[0][j] = 0.299;
02704     rgbcolor[1][j] = 0.587;
02705     rgbcolor[2][j] = 0.114;
02706   }
02707 
02708   strcpy ( texture_binding, "DEFAULT" );
02709 
02710   for ( j = 0; j < TEXTURE_MAX; j++ )
02711   {
02712     strcpy ( texture_name[j], "Texture_0000" );
02713   }
02714 
02715   tmat_init ( transform_matrix );
02716 
02717   for ( iface = 0; iface < FACE_MAX; iface++ )
02718   {
02719     for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
02720     {
02721       vertex_material[ivert][iface] = 0;
02722     }
02723   }
02724 
02725   for ( iface = 0; iface < FACE_MAX; iface++ )
02726   {
02727     for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
02728     {
02729       for ( i = 0; i < 3; i++ )
02730       {
02731         vertex_normal[i][ivert][iface] = 0.0;
02732       }
02733     }
02734   }
02735 
02736   for ( j = 0; j < 3; j++ )
02737   {
02738     for ( k = 0; k < FACE_MAX; k++ )
02739     {
02740       vertex_rgb[0][j][k] = 0.299;
02741       vertex_rgb[1][j][k] = 0.587;
02742       vertex_rgb[2][j][k] = 0.114;
02743     }
02744   }
02745 
02746   for ( iface = 0; iface < FACE_MAX; iface++ )
02747   {
02748     for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
02749     {
02750       for ( i = 0; i < 2; i++ )
02751       {
02752         vertex_tex_uv[i][ivert][iface] = 0.0;
02753       }
02754     }
02755   }
02756 
02757   if ( debug )
02758   {
02759     cout << "\n";
02760     cout << "DATA_INIT: Graphics data initialized.\n";
02761   }
02762 
02763   return;
02764 }
02765 //****************************************************************************80
02766 
02767 bool data_read ( )
02768 
02769 //****************************************************************************80
02770 //
02771 //  Purpose:
02772 //
02773 //    DATA_READ reads a file into internal graphics data.
02774 //
02775 //  Licensing:
02776 //
02777 //    This code is distributed under the GNU LGPL license.
02778 //
02779 //  Modified:
02780 //
02781 //    08 September 2003
02782 //
02783 //  Author:
02784 //
02785 //    John Burkardt
02786 //
02787 //  Parameters:
02788 //
02789 //    Output, bool DATA_READ, is TRUE if the data was read successfully.
02790 //
02791 {
02792   ifstream file_in;
02793   FILE *filein;
02794   char *filein_type;
02795   int icor3;
02796   int ierror;
02797   int iface;
02798   int iline;
02799   int ivert;
02800   int ntemp;
02801 //
02802 //  Retrieve the input file type.
02803 //
02804   filein_type = file_ext ( filein_name );
02805 
02806   if ( filein_type == NULL )
02807   {
02808     cout << "\n";
02809     cout << "DATA_READ - Fatal error!\n";
02810     cout << "  Could not determine the type of '" << filein_name << "'.\n";
02811     return false;
02812   }
02813   else if ( debug )
02814   {
02815     cout << "\n";
02816     cout << "DATA_READ: Input file has type " << filein_type << ".\n";
02817   }
02818 //
02819 //  Initialize some data.
02820 //
02821   max_order2 = 0;
02822   bad_num = 0;
02823   bytes_num = 0;
02824   comment_num = 0;
02825   dup_num = 0;
02826   text_num = 0;
02827 //
02828 //  Open the file.
02829 //
02830   if ( s_eqi ( filein_type, "3DS" ) ||
02831        s_eqi ( filein_type, "STLB" ) ||
02832        s_eqi ( filein_type, "TRIB" ) )
02833   {
02834     filein = fopen ( filein_name, "rb" );
02835 
02836     if ( filein == NULL )
02837     {
02838       cout << "\n";
02839       cout << "DATA_READ - Fatal error!\n";
02840       cout << "  Could not open the input file '" << filein_name << "'!\n";
02841       return false;
02842     }
02843   }
02844   else if ( s_eqi ( filein_type, "OFF" ) )
02845   {
02846      file_in.open ( filein_name );
02847 
02848     if ( !file_in )
02849     {
02850       cout << "\n";
02851       cout << "DATA_READ - Fatal error!\n";
02852       cout << "  Could not open the input file '" << filein_name << "'!\n";
02853       return false;
02854     }
02855   }
02856   else
02857   {
02858     filein = fopen ( filein_name, "r" );
02859 
02860     if ( filein == NULL )
02861     {
02862       cout << "\n";
02863       cout << "DATA_READ - Fatal error!\n";
02864       cout << "  Could not open the input file '" << filein_name << "'!\n";
02865       return false;
02866     }
02867   }
02868 //
02869 //  Read the information in the file.
02870 //
02871   if ( s_eqi ( filein_type, "3DS" ) )
02872   {
02873     ierror = tds_read ( filein );
02874 //
02875 //  Cleanup: distribute the node textures to the vertices.
02876 //
02877     if ( ierror == 0 )
02878     {
02879       for ( iface = 0; iface < face_num; iface++ )
02880       {
02881         for ( ivert = 0; ivert < face_order[iface]; ivert++ )
02882         {
02883           icor3 = face[ivert][iface];
02884           vertex_tex_uv[0][ivert][iface] = cor3_tex_uv[0][icor3];
02885           vertex_tex_uv[1][ivert][iface] = cor3_tex_uv[1][icor3];
02886         }
02887       }
02888 
02889     }
02890 
02891   }
02892   else if ( s_eqi ( filein_type, "ASE" ) )
02893   {
02894     ierror = ase_read ( filein );
02895 
02896     if ( ierror == 0 )
02897     {
02898       node_to_vertex_material ( );
02899       vertex_to_face_material ( );
02900     }
02901 
02902   }
02903   else if ( s_eqi ( filein_type, "BYU" ) )
02904   {
02905     ierror = byu_read ( filein );
02906   }
02907   else if ( s_eqi ( filein_type, "DXF" ) )
02908   {
02909     ierror = dxf_read ( filein );
02910   }
02911   else if ( s_eqi ( filein_type, "GMOD" ) )
02912   {
02913     ierror = gmod_read ( filein );
02914   }
02915   else if ( s_eqi ( filein_type, "HRC" ) )
02916   {
02917     ierror = hrc_read ( filein );
02918   }
02919   else if ( s_eqi ( filein_type, "IV" ) )
02920   {
02921     ierror = iv_read ( filein );
02922   }
02923   else if ( s_eqi ( filein_type, "OBJ" ) )
02924   {
02925     ierror = obj_read ( filein );
02926   }
02927   else if ( s_eqi ( filein_type, "OFF" ) )
02928   {
02929     ierror = off_read ( file_in );
02930   }
02931   else if ( s_eqi ( filein_type, "SMF" ) )
02932   {
02933     ierror = smf_read ( filein );
02934   }
02935   else if (
02936     s_eqi ( filein_type, "STL" ) ||
02937     s_eqi ( filein_type, "STLA") )
02938   {
02939     ierror = stla_read ( filein );
02940   }
02941   else if ( s_eqi ( filein_type, "STLB") )
02942   {
02943     ierror = stlb_read ( filein );
02944   }
02945   else if (
02946     s_eqi ( filein_type, "TRI" ) ||
02947     s_eqi ( filein_type, "TRIA") )
02948   {
02949     ierror = tria_read ( filein );
02950   }
02951   else if ( s_eqi ( filein_type, "TRIB") )
02952   {
02953     ierror = trib_read ( filein );
02954   }
02955   else if ( s_eqi ( filein_type, "VLA" ) )
02956   {
02957     ierror = vla_read ( filein );
02958   }
02959   else
02960   {
02961     cout << "\n";
02962     cout << "DATA_READ - Fatal error!\n";
02963     cout << "  Unacceptable input file type.\n";
02964     return false;
02965   }
02966 
02967   if ( s_eqi ( filein_type, "OFF" ) )
02968   {
02969     file_in.close ( );
02970   }
02971   else
02972   {
02973     fclose ( filein );
02974   }
02975 
02976   if ( debug )
02977   {
02978     cout << "DATA_READ: Finished reading the data file.\n";
02979   }
02980 //
02981 //  Catch errors reported by the various reading routines.
02982 //
02983   if ( ierror == ERROR )
02984   {
02985     cout << "\n";
02986     cout << "DATA_READ - Fatal error!\n";
02987     cout << "  There was an error reported while reading input data.\n";
02988     return false;
02989   }
02990 //
02991 //  Restore the transformation matrix.
02992 //
02993   tmat_init ( transform_matrix );
02994 //
02995 //  Report on what we read.
02996 //
02997   if ( face_num < FACE_MAX )
02998   {
02999     ntemp = face_num;
03000   }
03001   else
03002   {
03003     ntemp = FACE_MAX;
03004   }
03005 
03006   max_order2 = i4vec_max ( ntemp, face_order );
03007 
03008   data_report ( );
03009 //
03010 //  Warn about any errors that occurred during reading.
03011 //
03012   if ( ierror == ERROR )
03013   {
03014     cout << "\n";
03015     cout << "DATA_READ - Fatal error!\n";
03016     cout << "  An error occurred while reading the input file.\n";
03017     return false;
03018   }
03019 //
03020 //  Check the data.
03021 //  You MUST wait until after this check before doing other computations,
03022 //  since COR3_NUM and other variables could be much larger than the legal
03023 //  maximums, until corrected by DATA_CHECK.
03024 //
03025   data_check ( );
03026 //
03027 //  MATERIALS FIXUPS:
03028 //
03029 //  If there are no materials at all, define one.
03030 //
03031   if ( material_num < 1 )
03032   {
03033     material_num = 1;
03034     strcpy ( material_name[0], "Material_0000" );
03035     material_rgba[0][0] = 0.7;
03036     material_rgba[1][0] = 0.7;
03037     material_rgba[2][0] = 0.7;
03038     material_rgba[3][0] = 1.0;
03039   }
03040 //
03041 //  If a node has not been assigned a material, set it to material 0.
03042 //
03043   for ( icor3 = 0; icor3 < cor3_num; icor3++ )
03044   {
03045     if ( cor3_material[icor3] < 0 || material_num - 1 < cor3_material[icor3] )
03046     {
03047       cor3_material[icor3] = 0;
03048     }
03049   }
03050 //
03051 //  If a vertex has not been assigned a material, set it to material 0.
03052 //
03053   for ( iface = 0; iface < face_num; iface++ )
03054   {
03055     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
03056     {
03057       if ( vertex_material[ivert][iface] < 0 ||
03058            material_num - 1 < vertex_material[ivert][iface] )
03059       {
03060         vertex_material[ivert][iface] = 0;
03061       }
03062     }
03063   }
03064 //
03065 //  If a face has not been assigned a material, set it to material 0.
03066 //
03067   for ( iface = 0; iface < face_num; iface++ )
03068   {
03069     if ( face_material[iface] < 0 || material_num - 1 < face_material[iface] )
03070     {
03071       face_material[iface] = 0;
03072     }
03073   }
03074 //
03075 //  If a line item has not been assigned a material, set it to material 0.
03076 //
03077   for ( iline = 0; iline < line_num; iline++ )
03078   {
03079     if ( line_dex[iline] == -1 )
03080     {
03081       line_material[iline] = -1;
03082     }
03083     else if ( line_material[iline] < 0 ||
03084              material_num - 1 < line_material[iline] )
03085     {
03086       line_material[iline] = 0;
03087     }
03088   }
03089 //
03090 //  Delete edges of zero length.
03091 //
03092   edge_null_delete ( );
03093 //
03094 //  Compute the area of each face.
03095 //
03096   face_area_set ( );
03097 //
03098 //  Delete faces with zero area.
03099 //
03100   face_null_delete ( );
03101 //
03102 //  Recompute zero face-vertex normals from vertex positions.
03103 //
03104   vertex_normal_set ( );
03105 //
03106 //  Compute the node normals from the vertex normals.
03107 //
03108   cor3_normal_set ( );
03109 //
03110 //  Recompute zero face normals by averaging face-vertex normals.
03111 //
03112   face_normal_ave ( );
03113 //
03114 //  Report on the nodal coordinate range.
03115 //
03116   cor3_range ( );
03117 
03118   return true;
03119 }
03120 //****************************************************************************80
03121 
03122 void data_report ( )
03123 
03124 //****************************************************************************80
03125 //
03126 //  Purpose:
03127 //
03128 //    DATA_REPORT gives a summary of the contents of the data file.
03129 //
03130 //  Licensing:
03131 //
03132 //    This code is distributed under the GNU LGPL license.
03133 //
03134 //  Modified:
03135 //
03136 //    24 May 1999
03137 //
03138 //  Author:
03139 //
03140 //    John Burkardt
03141 //
03142 {
03143   cout << "\n";
03144   cout << "DATA_REPORT - The input file contains:\n";
03145   cout << "\n";
03146   cout << "  Bad data items             " << bad_num << "\n";
03147   cout << "  Text lines                 " << text_num << "\n";
03148   cout << "  Text bytes (binary data)   " << bytes_num << "\n";
03149   cout << "  Colors                     " << color_num << "\n";
03150   cout << "  Comments                   " << comment_num << "\n";
03151   cout << "  Duplicate points           " << dup_num << "\n";
03152   cout << "  Faces                      " << face_num << "\n";
03153   cout << "  Groups                     " << group_num << "\n";
03154   cout << "  Vertices per face, maximum " << max_order2 << "\n";
03155   cout << "  Line items                 " << line_num << "\n";
03156   cout << "  Points                     " << cor3_num << "\n";
03157   cout << "  Objects                    " << object_num << "\n";
03158 
03159   return;
03160 }
03161 //****************************************************************************80
03162 
03163 int data_write ( )
03164 
03165 //****************************************************************************80
03166 //
03167 //  Purpose:
03168 //
03169 //    DATA_WRITE writes the internal graphics data to a file.
03170 //
03171 //  Licensing:
03172 //
03173 //    This code is distributed under the GNU LGPL license.
03174 //
03175 //  Modified:
03176 //
03177 //    22 May 1999
03178 //
03179 //  Author:
03180 //
03181 //    John Burkardt
03182 //
03183 {
03184   FILE *fileout;
03185   char *fileout_type;
03186   int   line_num_save;
03187   int   result;
03188 
03189   result = 0;
03190 //
03191 //  Retrieve the output file type.
03192 //
03193   fileout_type = file_ext ( fileout_name );
03194 
03195   if ( fileout_type == NULL )
03196   {
03197     cout << "\n";
03198     cout << "DATA_WRITE - Fatal error!\n";
03199     cout << "  Could not determine the output file type.\n";
03200     return 1;
03201   }
03202 //
03203 //  Open the output file.
03204 //
03205   if ( s_eqi ( fileout_type, "3DS" ) ||
03206        s_eqi ( fileout_type, "STLB" ) ||
03207        s_eqi ( fileout_type, "TRIB" ) )
03208   {
03209     fileout = fopen ( fileout_name, "wb" );
03210   }
03211   else
03212   {
03213     fileout = fopen ( fileout_name, "w" );
03214   }
03215 
03216   if ( fileout == NULL )
03217   {
03218     cout << "\n";
03219     cout << "DATA_WRITE - Fatal error!\n";
03220     cout << "  Could not open the output file!\n";
03221     return 1;
03222   }
03223 //
03224 //  Write the output file.
03225 //
03226   if ( s_eqi ( fileout_type, "3DS" ) )
03227   {
03228     tds_pre_process();
03229     result = tds_write ( fileout );
03230   }
03231   else if ( s_eqi ( fileout_type, "ASE" ) )
03232   {
03233     result = ase_write ( fileout );
03234   }
03235   else if ( s_eqi ( fileout_type, "BYU" ) )
03236   {
03237     result = byu_write ( fileout );
03238   }
03239   else if ( s_eqi ( fileout_type, "DXF" ) )
03240   {
03241     result = dxf_write ( fileout );
03242   }
03243   else if ( s_eqi ( fileout_type, "GMOD" ) )
03244   {
03245     result = gmod_write ( fileout );
03246   }
03247   else if ( s_eqi ( fileout_type, "HRC" ) )
03248   {
03249     result = hrc_write ( fileout );
03250   }
03251   else if ( s_eqi ( fileout_type, "IV" ) )
03252   {
03253     result = iv_write ( fileout );
03254   }
03255   else if ( s_eqi ( fileout_type, "OBJ" ) )
03256   {
03257     result = obj_write ( fileout );
03258   }
03259   else if ( s_eqi ( fileout_type, "OFF" ) )
03260   {
03261     result = off_write ( fileout );
03262   }
03263   else if ( s_eqi ( fileout_type, "POV" ) )
03264   {
03265     result = pov_write ( fileout );
03266   }
03267   else if ( s_eqi ( fileout_type, "SMF" ) )
03268   {
03269     result = smf_write ( fileout );
03270   }
03271   else if (
03272     s_eqi ( fileout_type, "STL" ) ||
03273     s_eqi ( fileout_type, "STLA" ) )
03274   {
03275     result = stla_write ( fileout );
03276   }
03277   else if ( s_eqi ( fileout_type, "STLB" ) )
03278   {
03279     result = stlb_write ( fileout );
03280   }
03281   else if ( s_eqi ( fileout_type, "TEC" ) )
03282   {
03283     result = tec_write ( fileout );
03284   }
03285   else if (
03286     s_eqi ( fileout_type, "TRI" ) ||
03287     s_eqi ( fileout_type, "TRIA" ) )
03288   {
03289     result = tria_write ( fileout );
03290   }
03291   else if ( s_eqi ( fileout_type, "TRIB" ) )
03292   {
03293     result = trib_write ( fileout );
03294   }
03295   else if ( s_eqi ( fileout_type, "TXT" ) )
03296   {
03297     result = txt_write ( fileout );
03298   }
03299   else if ( s_eqi ( fileout_type, "UCD" ) )
03300   {
03301     result = ucd_write ( fileout );
03302   }
03303   else if ( s_eqi ( fileout_type, "VLA" ) )
03304   {
03305     line_num_save = line_num;
03306 
03307     if ( 0 < face_num )
03308     {
03309       cout << "\n";
03310       cout << "DATA_WRITE - Note:\n";
03311       cout << "  Face information will temporarily be converted to\n";
03312       cout << "  line information for output to a VLA file.\n";
03313 
03314       face_to_line ( );
03315 
03316       if ( LINES_MAX < line_num )
03317       {
03318         cout << "\n";
03319         cout << "DATA_WRITE - Warning:\n";
03320         cout << "  Some face information was lost.\n";
03321         cout << "  The maximum number of lines is " << LINES_MAX << ".\n";
03322         cout << "  The number of lines needed is " << line_num << ".\n";
03323         line_num = LINES_MAX;
03324       }
03325 
03326     }
03327 
03328     result = vla_write ( fileout );
03329 
03330     line_num = line_num_save;
03331 
03332   }
03333   else if ( s_eqi ( fileout_type, "WRL" ) )
03334   {
03335     result = wrl_write ( fileout );
03336   }
03337   else if ( s_eqi ( fileout_type, "XGL" ) )
03338   {
03339     result = xgl_write ( fileout );
03340   }
03341   else
03342   {
03343     result = ERROR;
03344     cout << "\n";
03345     cout << "DATA_WRITE - Fatal error!\n";
03346     cout << "  Unacceptable output file type '" << fileout_type << "'.\n";
03347   }
03348 //
03349 //  Close the output file.
03350 //
03351   fclose ( fileout );
03352 
03353   if ( result == ERROR )
03354   {
03355     return 1;
03356   }
03357   else
03358   {
03359     return 0;
03360   }
03361 }
03362 //****************************************************************************80
03363 
03364 int dxf_read ( FILE *filein )
03365 
03366 //****************************************************************************80
03367 //
03368 //  Purpose:
03369 //
03370 //    DXF_READ reads an AutoCAD DXF file.
03371 //
03372 //  Example:
03373 //
03374 //      0
03375 //    SECTION
03376 //      2
03377 //    HEADER
03378 //    999
03379 //    diamond.dxf created by IVREAD.
03380 //    999
03381 //    Original data in diamond.obj.
03382 //      0
03383 //    ENDSEC
03384 //      0
03385 //    SECTION
03386 //      2
03387 //    TABLES
03388 //      0
03389 //    ENDSEC
03390 //      0
03391 //    SECTION
03392 //      2
03393 //    BLOCKS
03394 //      0
03395 //    ENDSEC
03396 //      0
03397 //    SECTION
03398 //      2
03399 //    ENTITIES
03400 //      0
03401 //    LINE
03402 //      8
03403 //    0
03404 //     10
03405 //      0.00  (X coordinate of beginning of line.)
03406 //     20
03407 //      0.00  (Y coordinate of beginning of line.)
03408 //     30
03409 //      0.00  (Z coordinate of beginning of line.)
03410 //     11
03411 //      1.32  (X coordinate of end of line.)
03412 //     21
03413 //      1.73  (Y coordinate of end of line.)
03414 //     31
03415 //      2.25  (Z coordinate of end of line.)
03416 //      0
03417 //    3DFACE
03418 //      8
03419 //     Cube
03420 //    10
03421 //    -0.50  (X coordinate of vertex 1)
03422 //    20
03423 //     0.50  (Y coordinate of vertex 1)
03424 //    30
03425 //      1.0  (Z coordinate of vertex 1)
03426 //    11
03427 //     0.50  (X coordinate of vertex 2)
03428 //    21
03429 //     0.50  (Y coordinate of vertex 2)
03430 //    31
03431 //      1.0  (Z coordinate of vertex 2)
03432 //    12
03433 //     0.50  (X coordinate of vertex 3)
03434 //    22
03435 //     0.50  (Y coordinate of vertex 3)
03436 //    32
03437 //     0.00  (Z coordinate of vertex 3)
03438 //      0
03439 //    ENDSEC
03440 //      0
03441 //    EOF
03442 //
03443 //  Licensing:
03444 //
03445 //    This code is distributed under the GNU LGPL license.
03446 //
03447 //  Modified:
03448 //
03449 //    23 May 1999
03450 //
03451 //  Author:
03452 //
03453 //    John Burkardt
03454 //
03455 {
03456   int   code;
03457   int   count;
03458   float cvec[3];
03459   int   icor3;
03460   char  input1[LINE_MAX_LEN];
03461   char  input2[LINE_MAX_LEN];
03462   int   ivert;
03463   float rval;
03464   int   width;
03465   int   linemode;
03466   int   cpos;
03467 
03468   linemode = 0;
03469   ivert = 0;
03470 //
03471 //  Read the next two lines of the file into INPUT1 and INPUT2.
03472 //
03473 
03474   for ( ;; )
03475   {
03476 
03477 //
03478 //  INPUT1 should contain a single integer, which tells what INPUT2
03479 //  will contain.
03480 //
03481     if ( fgets ( input1, LINE_MAX_LEN, filein ) == NULL )
03482     {
03483       break;
03484     }
03485 
03486     text_num = text_num + 1;
03487 
03488     count = sscanf ( input1, "%d%n", &code, &width );
03489     if ( count <= 0 )
03490     {
03491       break;
03492     }
03493 //
03494 //  Read the second line, and interpret it according to the code.
03495 //
03496     if ( fgets ( input2, LINE_MAX_LEN, filein ) == NULL )
03497     {
03498       break;
03499     }
03500 
03501     text_num = text_num + 1;
03502 
03503     if ( code == 0 )
03504     {
03505 
03506 //
03507 //  Finish off the face.
03508 //
03509       if ( 0 < ivert )
03510       {
03511         face_order[face_num] = ivert;
03512         face_num = face_num + 1;
03513         ivert = 0;
03514       }
03515 
03516       if ( strncmp( input2, "LINE", 4 ) == 0 )
03517       {
03518         linemode = 1;
03519       }
03520       else if ( strncmp( input2, "3DFACE", 6 ) == 0 )
03521       {
03522         linemode = 0;
03523         ivert = 0;
03524       }
03525     }
03526     else
03527     {
03528       for (cpos = 0; input1[cpos] == ' '; cpos++)
03529       { };
03530 
03531       if ( input1[cpos] == '1' || input1[cpos] == '2' || input1[cpos] == '3' )
03532       {
03533         count = sscanf ( input2, "%e%n", &rval, &width );
03534 
03535         switch ( input1[cpos] )
03536         {
03537           case '1':
03538             if ( 0 < line_num )
03539             {
03540               if ( linemode )
03541               {
03542                 line_dex[line_num] = - 1;
03543                 line_material[line_num] = - 1;
03544                 line_num = line_num + 1;
03545               }
03546             }
03547             cvec[0] = rval;
03548             break;
03549 
03550           case '2':
03551             cvec[1] = rval;
03552             break;
03553 
03554           case '3':
03555             cvec[2] = rval;
03556 
03557             if ( cor3_num < 1000 )
03558             {
03559               icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
03560             }
03561             else
03562             {
03563               icor3 = -1;
03564             }
03565 
03566             if ( icor3 == -1 )
03567             {
03568               icor3 = cor3_num;
03569               if ( cor3_num < COR3_MAX )
03570               {
03571                 cor3[0][cor3_num] = cvec[0];
03572                 cor3[1][cor3_num] = cvec[1];
03573                 cor3[2][cor3_num] = cvec[2];
03574               }
03575               cor3_num = cor3_num + 1;
03576             }
03577             else
03578             {
03579               dup_num = dup_num + 1;
03580             }
03581 
03582             if ( linemode )
03583             {
03584               line_dex[line_num] = icor3;
03585               line_material[line_num] = 0;
03586               line_num = line_num + 1;
03587             }
03588             else
03589             {
03590               face[ivert][face_num] = icor3;
03591               ivert = ivert + 1;
03592             }
03593             break;
03594 
03595           default:
03596             break;
03597         }
03598       }
03599     }
03600   }
03601 
03602   if ( 0 < line_num )
03603   {
03604     if ( linemode )
03605     {
03606       line_dex[line_num] = - 1;
03607       line_material[line_num] = - 1;
03608       line_num = line_num + 1;
03609     }
03610   }
03611   return 0;
03612 }
03613 //****************************************************************************80
03614 
03615 int dxf_write ( FILE *fileout )
03616 
03617 //****************************************************************************80
03618 //
03619 //  Purpose:
03620 //
03621 //    DXF_WRITE writes graphics information to an AutoCAD DXF file.
03622 //
03623 //  Example:
03624 //
03625 //      0
03626 //    SECTION
03627 //      2
03628 //    HEADER
03629 //    999
03630 //    diamond.dxf created by IVREAD.
03631 //    999
03632 //    Original data in diamond.obj.
03633 //      0
03634 //    ENDSEC
03635 //      0
03636 //    SECTION
03637 //      2
03638 //    TABLES
03639 //      0
03640 //    ENDSEC
03641 //      0
03642 //    SECTION
03643 //      2
03644 //    BLOCKS
03645 //      0
03646 //    ENDSEC
03647 //      0
03648 //    SECTION
03649 //      2
03650 //    ENTITIES
03651 //      0
03652 //    LINE
03653 //      8
03654 //    0
03655 //     10
03656 //      0.00  (X coordinate of beginning of line.)
03657 //     20
03658 //      0.00  (Y coordinate of beginning of line.)
03659 //     30
03660 //      0.00  (Z coordinate of beginning of line.)
03661 //     11
03662 //      1.32  (X coordinate of end of line.)
03663 //     21
03664 //      1.73  (Y coordinate of end of line.)
03665 //     31
03666 //      2.25  (Z coordinate of end of line.)
03667 //      0
03668 //    3DFACE
03669 //      8
03670 //     Cube
03671 //    10
03672 //    -0.50  (X coordinate of vertex 1)
03673 //    20
03674 //     0.50  (Y coordinate of vertex 1)
03675 //    30
03676 //      1.0  (Z coordinate of vertex 1)
03677 //    11
03678 //     0.50  (X coordinate of vertex 2)
03679 //    21
03680 //     0.50  (Y coordinate of vertex 2)
03681 //    31
03682 //      1.0  (Z coordinate of vertex 2)
03683 //    12
03684 //     0.50  (X coordinate of vertex 3)
03685 //    22
03686 //     0.50  (Y coordinate of vertex 3)
03687 //    32
03688 //     0.00  (Z coordinate of vertex 3)
03689 //      0
03690 //    ENDSEC
03691 //      0
03692 //    EOF
03693 //
03694 //  Licensing:
03695 //
03696 //    This code is distributed under the GNU LGPL license.
03697 //
03698 //  Modified:
03699 //
03700 //    16 May 1999
03701 //
03702 //  Author:
03703 //
03704 //    John Burkardt
03705 //
03706 {
03707   int icor3;
03708   int iline;
03709   int iface;
03710   int ivert;
03711   int jcor3;
03712   bool newline;
03713   int text_num;
03714 //
03715 //  Initialize.
03716 //
03717   text_num = 0;
03718 
03719   fprintf ( fileout, "  0\n" );
03720   fprintf ( fileout, "SECTION\n" );
03721   fprintf ( fileout, "  2\n" );
03722   fprintf ( fileout, "HEADER\n" );
03723   fprintf ( fileout, "999\n" );
03724   fprintf ( fileout, "%s created by IVCON.\n", fileout_name );
03725   fprintf ( fileout, "999\n" );
03726   fprintf ( fileout, "Original data in %s.\n", filein_name );
03727   fprintf ( fileout, "  0\n" );
03728   fprintf ( fileout, "ENDSEC\n" );
03729   text_num = text_num + 10;
03730 
03731   fprintf ( fileout, "  0\n" );
03732   fprintf ( fileout, "SECTION\n" );
03733   fprintf ( fileout, "  2\n" );
03734   fprintf ( fileout, "TABLES\n" );
03735   fprintf ( fileout, "  0\n" );
03736   fprintf ( fileout, "ENDSEC\n" );
03737   text_num = text_num + 6;
03738 
03739   fprintf ( fileout, "  0\n" );
03740   fprintf ( fileout, "SECTION\n" );
03741   fprintf ( fileout, "  2\n" );
03742   fprintf ( fileout, "BLOCKS\n" );
03743   fprintf ( fileout, "  0\n" );
03744   fprintf ( fileout, "ENDSEC\n" );
03745   text_num = text_num + 6;
03746 
03747   fprintf ( fileout, "  0\n" );
03748   fprintf ( fileout, "SECTION\n" );
03749   fprintf ( fileout, "  2\n" );
03750   fprintf ( fileout, "ENTITIES\n" );
03751   text_num = text_num + 4;
03752 //
03753 //  Handle lines.
03754 //
03755   jcor3 = 0;
03756   newline = true;
03757 
03758   for ( iline = 0; iline < line_num; iline++ )
03759   {
03760     icor3 = line_dex[iline];
03761 
03762     if ( icor3 == -1 )
03763     {
03764       newline = true;
03765     }
03766     else
03767     {
03768       if ( !newline )
03769       {
03770         fprintf ( fileout, "  0\n" );
03771         fprintf ( fileout, "LINE\n" );
03772         fprintf ( fileout, "  8\n" );
03773         fprintf ( fileout, "  0\n" );
03774         fprintf ( fileout, " 10\n" );
03775         fprintf ( fileout, "%f\n", cor3[0][jcor3] );
03776         fprintf ( fileout, " 20\n" );
03777         fprintf ( fileout, "%f\n", cor3[1][jcor3] );
03778         fprintf ( fileout, " 30\n" );
03779         fprintf ( fileout, "%f\n", cor3[2][jcor3] );
03780         fprintf ( fileout, " 11\n" );
03781         fprintf ( fileout, "%f\n", cor3[0][icor3] );
03782         fprintf ( fileout, " 21\n" );
03783         fprintf ( fileout, "%f\n", cor3[1][icor3] );
03784         fprintf ( fileout, " 31\n" );
03785         fprintf ( fileout, "%f\n", cor3[2][icor3] );
03786 
03787         text_num = text_num + 16;
03788       }
03789       jcor3 = icor3;
03790       newline = false;
03791     }
03792   }
03793 //
03794 //  Handle faces.
03795 //  (If FACE_ORDER is greater than 10, you're sure to have problems here)
03796 //
03797   for ( iface = 0; iface < face_num; iface++ )
03798   {
03799     fprintf ( fileout, "  0\n" );
03800     fprintf ( fileout, "3DFACE\n" );
03801     fprintf ( fileout, "  8\n" );
03802     fprintf ( fileout, "  Cube\n" );
03803     text_num = text_num + 4;
03804 
03805     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
03806     {
03807       icor3 = face[ivert][iface];
03808 
03809       fprintf ( fileout, "1%d\n", ivert );
03810       fprintf ( fileout, "%f\n", cor3[0][icor3] );
03811       fprintf ( fileout, "2%d\n", ivert );
03812       fprintf ( fileout, "%f\n", cor3[1][icor3] );
03813       fprintf ( fileout, "3%d\n", ivert );
03814       fprintf ( fileout, "%f\n", cor3[2][icor3] );
03815 
03816       text_num = text_num + 6;
03817     }
03818   }
03819 
03820   fprintf ( fileout, "  0\n" );
03821   fprintf ( fileout, "ENDSEC\n" );
03822   fprintf ( fileout, "  0\n" );
03823   fprintf ( fileout, "EOF\n" );
03824   text_num = text_num + 4;
03825 //
03826 //  Report.
03827 //
03828   cout << "\n";
03829   cout << "DXF_WRITE - Wrote " << text_num << " text lines.\n";
03830 
03831   return 0;
03832 }
03833 //****************************************************************************80
03834 
03835 int edge_count ( )
03836 
03837 //****************************************************************************80
03838 //
03839 //  Purpose:
03840 //
03841 //    EDGE_COUNT determines the number of edges in a graph.
03842 //
03843 //  Discussion:
03844 //
03845 //    The routine extracts the successive pairs of vertices that
03846 //    define each edge of a face.  It reorders each pair so that
03847 //    the lesser element is listed first.  It sorts the entire list.
03848 //    Then it counts the unique entries.
03849 //
03850 //  Licensing:
03851 //
03852 //    This code is distributed under the GNU LGPL license.
03853 //
03854 //  Modified:
03855 //
03856 //    08 September 2003
03857 //
03858 //  Author:
03859 //
03860 //    John Burkardt
03861 //
03862 //  Parameters:
03863 //
03864 //    Output, int EDGE_COUNT, the number of unique edges.
03865 //
03866 {
03867   int *edge;
03868   int edge_num;
03869   int edge_num_old;
03870   int i;
03871   int iface;
03872   int indx;
03873   int isgn;
03874   int j;
03875   int k;
03876   int vert;
03877   int vert2;
03878 //
03879 //  First count the number of edges with duplication.
03880 //
03881   edge_num = 0;
03882   for ( iface = 0; iface < face_num; iface++ )
03883   {
03884     edge_num = edge_num + face_order[iface];
03885   }
03886 //
03887 //  Allocate space, and store the edges.
03888 //
03889   edge = new int[edge_num*2];
03890 
03891   edge_num = 0;
03892   for ( iface = 0; iface < face_num; iface++ )
03893   {
03894     for ( vert = 0; vert < face_order[iface]; vert++ )
03895     {
03896       i = face[vert][iface];
03897       vert2 = i4_wrap ( vert+1, 0, face_order[iface]-1 );
03898       j = face[vert2][iface];
03899       edge[0+edge_num*2] = i4_min ( i, j );
03900       edge[1+edge_num*2] = i4_max ( i, j );
03901       edge_num = edge_num + 1;
03902     }
03903   }
03904 //
03905 //  Sort the edges.
03906 //
03907   i = 0;
03908   indx = 0;
03909   isgn = 0;
03910   j = 0;
03911 //
03912 //  Call the external heap sorter.
03913 //
03914   for ( ; ; )
03915   {
03916     sort_heap_external ( edge_num, &indx, &i, &j, isgn );
03917 //
03918 //  Interchange the I and J objects.
03919 //
03920     if ( 0 < indx )
03921     {
03922       k           = edge[0+i*2];
03923       edge[0+i*2] = edge[0+j*2];
03924       edge[0+j*2] = k;
03925       k           = edge[1+i*2];
03926       edge[1+i*2] = edge[1+j*2];
03927       edge[1+j*2] = k;
03928     }
03929 //
03930 //  Compare the I and J objects.
03931 //
03932     else if ( indx < 0 )
03933     {
03934       if ( edge[0+i*2] < edge[0+j*2] )
03935       {
03936         isgn = -1;
03937       }
03938       else if ( edge[0+i*2] == edge[0+j*2] )
03939       {
03940         if ( edge[1+i*2] < edge[1+j*2] )
03941         {
03942           isgn = -1;
03943         }
03944         else if ( edge[1+i*2] == edge[1+j*2] )
03945         {
03946           isgn = 0;
03947         }
03948         else
03949         {
03950           isgn = 1;
03951         }
03952       }
03953       else
03954       {
03955         isgn = 1;
03956       }
03957     }
03958     else if ( indx == 0 )
03959     {
03960       break;
03961     }
03962 
03963   }
03964 //
03965 //  Count the unique entries.
03966 //
03967   edge_num_old = edge_num;
03968 
03969   edge_num = 0;
03970 
03971   for ( i = 0; i < edge_num_old; i++ )
03972   {
03973     if ( i == 0 )
03974     {
03975       edge_num = 1;
03976     }
03977     else
03978     {
03979       if ( edge[0+(i-1)*2] != edge[0+i*2] ||
03980           edge[1+(i-1)*2] != edge[1+i*2] )
03981       {
03982         edge_num = edge_num + 1;
03983       }
03984     }
03985 
03986   }
03987 
03988   delete [] edge;
03989 
03990   return edge_num;
03991 }
03992 //****************************************************************************80
03993 
03994 void edge_null_delete ( )
03995 
03996 //****************************************************************************80
03997 //
03998 //  Purpose:
03999 //
04000 //    EDGE_NULL_DELETE deletes face edges with zero length.
04001 //
04002 //  Licensing:
04003 //
04004 //    This code is distributed under the GNU LGPL license.
04005 //
04006 //  Modified:
04007 //
04008 //    16 July 1999
04009 //
04010 //  Author:
04011 //
04012 //    John Burkardt
04013 //
04014 {
04015   float distsq;
04016   int face2[ORDER_MAX];
04017   int face_order2;
04018   int iface;
04019   int inode;
04020   int ivert;
04021   int j;
04022   int jnode;
04023   int jvert;
04024   int edge_num;
04025   int edge_num_del;
04026   float vertex_normal2[3][ORDER_MAX];
04027   float x;
04028   float y;
04029   float z;
04030 
04031   edge_num = 0;
04032   edge_num_del = 0;
04033 //
04034 //  Consider each face.
04035 //
04036   for ( iface = 0; iface < face_num; iface++ )
04037   {
04038 //
04039 //  Consider each pair of consecutive vertices.
04040 //
04041     face_order2 = 0;
04042 
04043     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
04044     {
04045       edge_num = edge_num + 1;
04046 
04047       jvert = ivert + 1;
04048       if ( face_order[iface] <= jvert )
04049       {
04050         jvert = 0;
04051       }
04052 
04053       inode = face[ivert][iface];
04054       jnode = face[jvert][iface];
04055 
04056 
04057       x = cor3[0][inode] - cor3[0][jnode];
04058       y = cor3[1][inode] - cor3[1][jnode];
04059       z = cor3[2][inode] - cor3[2][jnode];
04060 
04061       distsq = x * x + y * y + z * z;
04062 
04063       if ( distsq != 0.0 )
04064       {
04065         face2[face_order2] = face[ivert][iface];
04066         vertex_normal2[0][face_order2] = vertex_normal[0][ivert][iface];
04067         vertex_normal2[1][face_order2] = vertex_normal[1][ivert][iface];
04068         vertex_normal2[2][face_order2] = vertex_normal[2][ivert][iface];
04069         face_order2 = face_order2 + 1;
04070       }
04071       else
04072       {
04073         edge_num_del = edge_num_del + 1;
04074       }
04075 
04076     }
04077 
04078     face_order[iface] = face_order2;
04079     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
04080     {
04081       face[ivert][iface] = face2[ivert];
04082       for ( j = 0; j < 3; j++ )
04083       {
04084         vertex_normal[j][ivert][iface] = vertex_normal2[j][ivert];
04085       }
04086     }
04087 
04088   }
04089 
04090   cout << "\n";
04091   cout << "EDGE_NULL_DELETE:\n";
04092   cout << "  There are a total of " << edge_num << " edges.\n";
04093   cout << "  Of these, " << edge_num_del << " were of zero length,\n";
04094   cout << "  and were deleted.\n";
04095 
04096   return;
04097 }
04098 //****************************************************************************80
04099 
04100 void face_area_set ( )
04101 
04102 //****************************************************************************80
04103 //
04104 //  Purpose:
04105 //
04106 //    FACE_AREA_SET computes the area of the faces.
04107 //
04108 //  Discussion:
04109 //
04110 //    The area is the sum of the areas of the triangles formed by
04111 //    node N with consecutive pairs of nodes.
04112 //
04113 //  Licensing:
04114 //
04115 //    This code is distributed under the GNU LGPL license.
04116 //
04117 //  Modified:
04118 //
04119 //    17 July 1999
04120 //
04121 //  Author:
04122 //
04123 //    John Burkardt
04124 //
04125 //  Reference:
04126 //
04127 //    Adrian Bowyer and John Woodwark,
04128 //    A Programmer's Geometry,
04129 //    Butterworths, 1983.
04130 //
04131 {
04132   float alpha;
04133   float area_max;
04134   float area_min;
04135   float area_tri;
04136   float base;
04137   float dot;
04138   float height;
04139   int i;
04140   int i1;
04141   int i2;
04142   int i3;
04143   int iface;
04144   int face_num_del;
04145   float tol;
04146   float x;
04147   float x1;
04148   float x2;
04149   float x3;
04150   float y;
04151   float y1;
04152   float y2;
04153   float y3;
04154   float z;
04155   float z1;
04156   float z2;
04157   float z3;
04158 
04159   for ( iface = 0; iface < face_num; iface++ )
04160   {
04161     face_area[iface] = 0.0;
04162 
04163     for ( i = 0; i < face_order[iface]-2; i++ )
04164     {
04165       i1 = face[i][iface];
04166       i2 = face[i+1][iface];
04167       i3 = face[i+2][iface];
04168 
04169       x1 = cor3[0][i1];
04170       y1 = cor3[1][i1];
04171       z1 = cor3[2][i1];
04172 
04173       x2 = cor3[0][i2];
04174       y2 = cor3[1][i2];
04175       z2 = cor3[2][i2];
04176 
04177       x3 = cor3[0][i3];
04178       y3 = cor3[1][i3];
04179       z3 = cor3[2][i3];
04180 //
04181 //  Find the projection of (P3-P1) onto (P2-P1).
04182 //
04183       dot =
04184         ( x2 - x1 ) * ( x3 - x1 ) +
04185         ( y2 - y1 ) * ( y3 - y1 ) +
04186         ( z2 - z1 ) * ( z3 - z1 );
04187 
04188       base = sqrt (
04189           ( x2 - x1 ) * ( x2 - x1 )
04190         + ( y2 - y1 ) * ( y2 - y1 )
04191         + ( z2 - z1 ) * ( z2 - z1 ) );
04192 //
04193 //  The height of the triangle is the length of (P3-P1) after its
04194 //  projection onto (P2-P1) has been subtracted.
04195 //
04196       if ( base == 0.0 )
04197       {
04198         height = 0.0;
04199       }
04200       else
04201       {
04202         alpha = dot / ( base * base );
04203 
04204         x = x3 - x1 - alpha * ( x2 - x1 );
04205         y = y3 - y1 - alpha * ( y2 - y1 );
04206         z = z3 - z1 - alpha * ( z2 - z1 );
04207 
04208         height = sqrt ( x * x + y * y + z * z );
04209       }
04210 
04211       area_tri = 0.5 * base * height;
04212       face_area[iface] = face_area[iface] + area_tri;
04213 
04214     }
04215 
04216   }
04217 
04218   area_min = face_area[0];
04219   area_max = face_area[0];
04220 
04221   for ( iface = 1; iface < face_num; iface++ )
04222   {
04223     if ( face_area[iface] < area_min )
04224     {
04225       area_min = face_area[iface];
04226     }
04227     if ( area_max < face_area[iface] )
04228     {
04229       area_max = face_area[iface];
04230     }
04231   }
04232 
04233   cout << "\n";
04234   cout << "FACE_AREA_SET:\n";
04235   cout << "  Minimum face area is " << area_min << "\n";
04236   cout << "  Maximum face area is " << area_max << "\n";
04237 
04238   tol = area_max / 10000.0;
04239 
04240   if ( area_min < tol )
04241   {
04242     face_num_del = 0;
04243 
04244     for ( iface = 0; iface < face_num; iface++ )
04245     {
04246       if ( face_area[iface] < tol )
04247       {
04248         face_order[iface] = 0;
04249         face_num_del = face_num_del + 1;
04250       }
04251     }
04252 
04253     cout << "  Marked " << face_num_del << " tiny faces for deletion.\n";
04254 
04255   }
04256 
04257   return;
04258 }
04259 //****************************************************************************80
04260 
04261 void face_normal_ave ( )
04262 
04263 //****************************************************************************80
04264 //
04265 //  Purpose:
04266 //
04267 //    FACE_NORMAL_AVE sets face normals as average of face vertex normals.
04268 //
04269 //  Licensing:
04270 //
04271 //    This code is distributed under the GNU LGPL license.
04272 //
04273 //  Modified:
04274 //
04275 //    09 October 1998
04276 //
04277 //  Author:
04278 //
04279 //    John Burkardt
04280 //
04281 {
04282   int i;
04283   int iface;
04284   int ivert;
04285   int nfix;
04286   float norm;
04287   float x;
04288   float y;
04289   float z;
04290 
04291   if ( face_num <= 0 )
04292   {
04293     return;
04294   }
04295 
04296   nfix = 0;
04297 
04298   for ( iface = 0; iface < face_num; iface++ )
04299   {
04300 //
04301 //  Check the norm of the current normal vector.
04302 //
04303     x = face_normal[0][iface];
04304     y = face_normal[1][iface];
04305     z = face_normal[2][iface];
04306     norm = ( float ) sqrt ( x * x + y * y + z * z );
04307 
04308     if ( norm == 0.0 )
04309     {
04310       nfix = nfix + 1;
04311 
04312       for ( i = 0; i < 3; i++ )
04313       {
04314         face_normal[i][iface] = 0.0;
04315       }
04316 
04317       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
04318       {
04319         for ( i = 0; i < 3; i++ )
04320         {
04321           face_normal[i][iface] = face_normal[i][iface] +
04322             vertex_normal[i][ivert][iface];
04323         }
04324       }
04325 
04326       x = face_normal[0][iface];
04327       y = face_normal[1][iface];
04328       z = face_normal[2][iface];
04329       norm = ( float ) sqrt ( x * x + y * y + z * z );
04330 
04331       if ( norm == 0.0 )
04332       {
04333         for ( i = 0; i < 3; i++ )
04334         {
04335           face_normal[i][iface] = ( float ) ( 1.0 / sqrt ( 3.0 ) );
04336         }
04337       }
04338       else
04339       {
04340         for ( i = 0; i < 3; i++ )
04341         {
04342           face_normal[i][iface] = face_normal[i][iface] / norm;
04343         }
04344       }
04345     }
04346   }
04347 
04348   if ( 0 < nfix )
04349   {
04350     cout << "\n";
04351     cout << "FACE_NORMAL_AVE: Recomputed " << nfix << " face normals\n";
04352     cout << "  by averaging face vertex normals.\n";
04353   }
04354   return;
04355 }
04356 //****************************************************************************80
04357 
04358 void face_null_delete ( )
04359 
04360 //****************************************************************************80
04361 //
04362 //  Purpose:
04363 //
04364 //    FACE_NULL_DELETE deletes faces of order less than 3.
04365 //
04366 //  Discussion:
04367 //
04368 //    Thanks to Susan M. Fisher, University of North Carolina,
04369 //    Department of Computer Science, for pointing out a coding error
04370 //    in FACE_NULL_DELETE that was overwriting all the data!
04371 //
04372 //  Licensing:
04373 //
04374 //    This code is distributed under the GNU LGPL license.
04375 //
04376 //  Modified:
04377 //
04378 //    30 November 1999
04379 //
04380 //  Author:
04381 //
04382 //    John Burkardt
04383 //
04384 {
04385   int iface;
04386   int ivert;
04387   int j;
04388   int face_num2;
04389 //
04390 //  FACE_NUM2 is the number of faces we'll keep.
04391 //
04392   face_num2 = 0;
04393 //
04394 //  Check every face.
04395 //
04396   for ( iface = 0; iface < face_num; iface++ )
04397   {
04398 //
04399 //  Keep it only if it has order 3 or more.
04400 //
04401     if ( 3 <= face_order[iface] )
04402     {
04403 //
04404 //  We don't have to slide data down in the array until
04405 //  NUMFACE2 and IFACE get out of synch, that is, after
04406 //  we've discarded at least one face.
04407 //
04408       if ( face_num2 != iface )
04409       {
04410         face_area[face_num2] = face_area[iface];
04411         face_material[face_num2] = face_material[iface];
04412         face_order[face_num2] = face_order[iface];
04413         for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
04414         {
04415           face[ivert][face_num2] = face[ivert][iface];
04416           vertex_material[ivert][face_num2] = vertex_material[ivert][iface];
04417           for ( j = 0; j < 3; j++ )
04418           {
04419             vertex_normal[j][ivert][face_num2] = vertex_normal[j][ivert][iface];
04420           }
04421         }
04422 
04423       }
04424 //
04425 //  Update the count only after we've used the un-incremented value
04426 //  as a pointer.
04427 //
04428       face_num2 = face_num2 + 1;
04429 
04430     }
04431 
04432   }
04433 
04434   cout << "\n";
04435   cout << "FACE_NULL_DELETE\n";
04436   cout << "  There are a total of " << face_num << " faces.\n";
04437   cout << "  Of these, " << face_num2 << " passed the order test.\n";
04438 
04439   face_num = face_num2;
04440 
04441   return;
04442 }
04443 //****************************************************************************80
04444 
04445 int face_print ( int iface )
04446 
04447 //****************************************************************************80
04448 //
04449 //  Purpose:
04450 //
04451 //    FACE_PRINT prints out information about a face.
04452 //
04453 //  Licensing:
04454 //
04455 //    This code is distributed under the GNU LGPL license.
04456 //
04457 //  Modified:
04458 //
04459 //    31 August 1998
04460 //
04461 //  Author:
04462 //
04463 //    John Burkardt
04464 //
04465 {
04466   int ivert;
04467   int j;
04468   int k;
04469 
04470   if ( iface < 0 || face_num-1 < iface )
04471   {
04472     cout << "\n";
04473     cout << "FACE_PRINT - Fatal error!\n";
04474     cout << "  Face indices must be between 1 and " << face_num << "\n";
04475     cout << "  But your requested value was " << iface << "\n";
04476     return 1;
04477   }
04478 
04479   cout << "\n";
04480   cout << "FACE_PRINT\n";
04481   cout << "  Information about face " << iface << "\n";
04482   cout << "\n";
04483   cout << "  Number of vertices is " << face_order[iface] << "\n";
04484   cout << "\n";
04485   cout << "  Vertex list:\n";
04486   cout << "    Vertex #, Node #, Material #, X, Y, Z:\n";
04487   cout << "\n";
04488   for ( ivert = 0; ivert < face_order[iface]; ivert++ )
04489   {
04490     j = face[ivert][iface];
04491     k = vertex_material[ivert][iface];
04492     cout
04493      << setw(6)  << ivert      << "  "
04494      << setw(6)  << j          << "  "
04495      << setw(6)  << k          << "  "
04496      << setw(10) << cor3[0][j] << "  "
04497      << setw(10) << cor3[1][j] << "  "
04498      << setw(10) << cor3[2][j] << "\n";
04499   }
04500 
04501   cout << "\n";
04502   cout << "  Face normal vector:\n";
04503   cout << "\n";
04504   cout
04505     << setw(10) << face_normal[0][iface] << "  "
04506     << setw(10) << face_normal[1][iface] << "  "
04507     << setw(10) << face_normal[2][iface] << "\n";
04508 
04509   cout << "\n";
04510   cout << "  Vertex face normals:\n";;
04511   cout << "\n";
04512   for ( ivert = 0; ivert < face_order[iface]; ivert++ )
04513   {
04514     cout
04515       << setw(6)  << ivert                          << "  "
04516       << setw(10) << vertex_normal[0][ivert][iface] << "  "
04517       << setw(10) << vertex_normal[1][ivert][iface] << "  "
04518       << setw(10) << vertex_normal[2][ivert][iface] << "\n";
04519   }
04520 
04521   return 0;
04522 
04523 }
04524 //****************************************************************************80
04525 
04526 void face_reverse_order ( )
04527 
04528 //****************************************************************************80
04529 //
04530 //  Purpose:
04531 //
04532 //    FACE_REVERSE_ORDER reverses the order of the nodes in each face.
04533 //
04534 //  Discussion:
04535 //
04536 //    Reversing the order of the nodes requires that the normal vectors
04537 //    be reversed as well, so this routine will automatically reverse
04538 //    the normals associated with nodes, vertices and faces.
04539 //
04540 //  Licensing:
04541 //
04542 //    This code is distributed under the GNU LGPL license.
04543 //
04544 //  Modified:
04545 //
04546 //    28 June 1999
04547 //
04548 //  Author:
04549 //
04550 //    John Burkardt
04551 //
04552 {
04553   int i;
04554   int iface;
04555   int itemp;
04556   int ivert;
04557   int j;
04558   int m;
04559   float temp;
04560 
04561   for ( iface = 0; iface < face_num; iface++ )
04562   {
04563     m = face_order[iface];
04564 
04565     for ( ivert = 0; ivert < ( m / 2 ); ivert++ )
04566     {
04567       itemp = face[ivert][iface];
04568       face[ivert][iface] = face[m-1-ivert][iface];
04569       face[m-1-ivert][iface] = itemp;
04570 
04571       itemp = vertex_material[ivert][iface];
04572       vertex_material[ivert][iface] = vertex_material[m-1-ivert][iface];
04573       vertex_material[m-1-ivert][iface] = itemp;
04574 
04575       for ( j = 0; j < 3; j++ )
04576       {
04577         temp = vertex_normal[j][ivert][iface];
04578         vertex_normal[j][ivert][iface] = vertex_normal[j][m-1-ivert][iface];
04579         vertex_normal[j][m-1-ivert][iface] = temp;
04580       }
04581 
04582       for ( j = 0; j < 2; j++ )
04583       {
04584         temp = vertex_tex_uv[j][ivert][iface];
04585         vertex_tex_uv[j][ivert][iface] = vertex_tex_uv[j][m-1-ivert][iface];
04586         vertex_tex_uv[j][m-1-ivert][iface] = temp;
04587       }
04588 
04589     }
04590 
04591   }
04592 
04593   for ( i = 0; i < cor3_num; i++ )
04594   {
04595     for ( j = 0; j < 3; j++ )
04596     {
04597       cor3_normal[j][i] = - cor3_normal[j][i];
04598     }
04599   }
04600 
04601   for ( i = 0; i < face_num; i++ )
04602   {
04603     for ( j = 0; j < 3; j++ )
04604     {
04605       face_normal[j][i] = - face_normal[j][i];
04606     }
04607   }
04608 
04609   cout << "\n";
04610   cout << "FACE_REVERSE_ORDER\n";
04611   cout << "  Each list of nodes defining a face\n";
04612   cout << "  has been reversed; related information,\n";
04613   cout << "  including normal vectors, was also updated.\n";
04614 
04615   return;
04616 }
04617 //****************************************************************************80
04618 
04619 int face_subset ( )
04620 
04621 //****************************************************************************80
04622 //
04623 //  Purpose:
04624 //
04625 //    FACE_SUBSET selects a subset of the current faces as the new object.
04626 //
04627 //  Discussion:
04628 //
04629 //    The original graphic object is overwritten by the new one.
04630 //
04631 //  Licensing:
04632 //
04633 //    This code is distributed under the GNU LGPL license.
04634 //
04635 //  Modified:
04636 //
04637 //    12 October 1998
04638 //
04639 //  Author:
04640 //
04641 //    John Burkardt
04642 //
04643 //
04644 {
04645   int i;
04646   int iface;
04647   int iface1;
04648   int iface2;
04649   int inc;
04650   int ivert;
04651   int j;
04652   int k;
04653   int cor3_num2;
04654 
04655   line_num = 0;
04656 //
04657 //  Get the first and last faces to save, IFACE1 and IFACE2.
04658 //
04659   cout << "\n";
04660   cout << "Enter lowest face number to save between 0 and "
04661        << face_num - 1 << ":  ";
04662   scanf ( "%d", &iface1 );
04663   if ( iface1 < 0 || face_num - 1 < iface1 )
04664   {
04665     cout << "Illegal choice!\n";
04666     return 1;
04667   }
04668 
04669   cout << "\n";
04670   cout << "Enter highest face number to save between "
04671     << iface1 << " and " << face_num - 1 << ":  ";
04672   scanf ( "%d", &iface2 );
04673   if ( iface2 < iface1 || face_num - 1 < iface2 )
04674   {
04675     cout << "Illegal choice!\n";
04676     return 1;
04677   }
04678 
04679   inc = iface1;
04680 //
04681 //  "Slide" the data for the saved faces down the face arrays.
04682 //
04683   for ( iface = 0; iface < iface2 + 1 - iface1; iface++ )
04684   {
04685     face_order[iface] = face_order[iface+inc];
04686     for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
04687     {
04688       face[ivert][iface] = face[ivert][iface+inc];
04689       vertex_material[ivert][iface] = vertex_material[ivert][iface+inc];
04690       for ( i = 0; i < 3; i++ )
04691       {
04692         vertex_normal[i][ivert][iface] =
04693           vertex_normal[i][ivert][iface+inc];
04694         vertex_rgb[i][ivert][iface] = vertex_rgb[i][ivert][iface+inc];
04695       }
04696     }
04697     for ( i = 0; i < 3; i++ )
04698     {
04699       face_normal[i][iface] = face_normal[i][iface+inc];
04700     }
04701   }
04702 //
04703 //  Now reset the number of faces.
04704 //
04705   face_num = iface2 + 1 - iface1;
04706 //
04707 //  Now, for each point I, set LIST(I) = J if point I is the J-th
04708 //  point we are going to save, and 0 otherwise.  Then J will be
04709 //  the new label of point I.
04710 //
04711   for ( i = 0; i < cor3_num; i++ )
04712   {
04713     list[i] = -1;
04714   }
04715 
04716   cor3_num2 = 0;
04717 
04718   for ( iface = 0; iface < face_num; iface++ )
04719   {
04720     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
04721     {
04722       j = face[ivert][iface];
04723       if ( list[j] == -1 )
04724       {
04725         cor3_num2 = cor3_num2 + 1;
04726         list[j] = cor3_num2;
04727       }
04728     }
04729   }
04730 //
04731 //  Now make the nonzero list entries rise in order, so that
04732 //  we can compress the COR3 data in a minute.
04733 //
04734   cor3_num2 = 0;
04735 
04736   for ( i = 0; i < cor3_num; i++ )
04737   {
04738     if ( list[i] != -1 )
04739     {
04740       list[i] = cor3_num2;
04741       cor3_num2 = cor3_num2 + 1;
04742     }
04743   }
04744 //
04745 //  Relabel the FACE array with the new node indices.
04746 //
04747   for ( iface = 0; iface < face_num; iface++ )
04748   {
04749     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
04750     {
04751       j = face[ivert][iface];
04752       face[ivert][iface] = list[j];
04753     }
04754   }
04755 //
04756 //  Rebuild the COR3 array by sliding data down.
04757 //
04758   for ( i = 0; i < cor3_num; i++ )
04759   {
04760     k = list[i];
04761     if ( k != -1 )
04762     {
04763       for ( j = 0; j < 3; j++ )
04764       {
04765         cor3[j][k] = cor3[j][i];
04766       }
04767     }
04768   }
04769 
04770   cor3_num = cor3_num2;
04771 
04772   return 0;
04773 }
04774 //****************************************************************************80
04775 
04776 void face_to_line ( )
04777 
04778 //****************************************************************************80
04779 //
04780 //  Purpose:
04781 //
04782 //    FACE_TO_LINE converts face information to line information.
04783 //
04784 //  Discussion:
04785 //
04786 //    In some cases, the graphic information represented by polygonal faces
04787 //    must be converted to a representation based solely on line segments.
04788 //    This is particularly true if a VLA file is being written.
04789 //
04790 //  Licensing:
04791 //
04792 //    This code is distributed under the GNU LGPL license.
04793 //
04794 //  Modified:
04795 //
04796 //    26 May 1999
04797 //
04798 //  Author:
04799 //
04800 //    John Burkardt
04801 //
04802 {
04803   int icor3;
04804   int iface;
04805   int ivert;
04806   int jcor3;
04807   int jvert;
04808 //
04809 //  Case 0:
04810 //  No line pruning.
04811 //
04812   if ( line_prune == 0 )
04813   {
04814     for ( iface = 0; iface < face_num; iface++ )
04815     {
04816       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
04817       {
04818         icor3 = face[ivert][iface];
04819 
04820         line_num = line_num + 1;
04821         if ( line_num <= LINES_MAX )
04822         {
04823           line_dex[line_num] = icor3;
04824           line_material[line_num] = vertex_material[ivert][iface];
04825         }
04826       }
04827 
04828       ivert = 0;
04829       icor3 = face[ivert][iface];
04830 
04831       line_num = line_num + 1;
04832       if ( line_num <= LINES_MAX )
04833       {
04834         line_dex[line_num] = icor3;
04835         line_material[line_num] = vertex_material[ivert][iface];
04836       }
04837 
04838       line_num = line_num + 1;
04839       if ( line_num <= LINES_MAX )
04840       {
04841         line_dex[line_num] = -1;
04842         line_material[line_num] = -1;
04843       }
04844     }
04845 
04846   }
04847 //
04848 //  Case 2:
04849 //  Simple-minded line pruning.
04850 //  Only draw line (I,J) if I < J.
04851 //
04852   else
04853   {
04854     for ( iface = 0; iface < face_num; iface++ )
04855     {
04856       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
04857       {
04858         icor3 = face[ivert][iface];
04859 
04860         if ( ivert + 1 < face_order[iface] )
04861         {
04862           jvert = ivert + 1;
04863         }
04864         else
04865         {
04866           jvert = 0;
04867         }
04868 
04869         jcor3 = face[jvert][iface];
04870 
04871         if ( icor3 < jcor3 )
04872         {
04873           if ( line_num + 3 < LINES_MAX )
04874           {
04875             line_num = line_num + 1;
04876             line_dex[line_num] = icor3;
04877             line_material[line_num] = vertex_material[ivert][iface];
04878 
04879             line_num = line_num + 1;
04880             line_dex[line_num] = jcor3;
04881             line_material[line_num] = vertex_material[jvert][iface];
04882 
04883             line_num = line_num + 1;
04884             line_dex[line_num] = -1;
04885             line_material[line_num] = -1;
04886 
04887           }
04888         }
04889       }
04890     }
04891 
04892   }
04893 
04894   return;
04895 }
04896 //****************************************************************************80
04897 
04898 void face_to_vertex_material ( )
04899 
04900 //****************************************************************************80
04901 //
04902 //  Purpose:
04903 //
04904 //    FACE_TO_VERTEX_MAT extends face material definitions to vertices.
04905 //
04906 //  Discussion:
04907 //
04908 //    Assuming material indices are defined for all the faces, this
04909 //    routine assigns to each vertex of a face the material of that face.
04910 //
04911 //  Licensing:
04912 //
04913 //    This code is distributed under the GNU LGPL license.
04914 //
04915 //  Modified:
04916 //
04917 //    22 May 1999
04918 //
04919 //  Author:
04920 //
04921 //    John Burkardt
04922 //
04923 {
04924   int iface;
04925   int ivert;
04926 
04927   for ( iface = 0; iface < face_num; iface++ )
04928   {
04929     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
04930     {
04931       vertex_material[ivert][iface] = face_material[iface];
04932     }
04933   }
04934 
04935   return;
04936 }
04937 //****************************************************************************80
04938 
04939 char *file_ext ( char *file_name )
04940 
04941 //****************************************************************************80
04942 //
04943 //  Purpose:
04944 //
04945 //    FILE_EXT picks out the extension in a file name.
04946 //
04947 //  Licensing:
04948 //
04949 //    This code is distributed under the GNU LGPL license.
04950 //
04951 //  Modified:
04952 //
04953 //    21 July 1998
04954 //
04955 //  Author:
04956 //
04957 //    John Burkardt
04958 //
04959 {
04960   int i;
04961 
04962   i = ch_index_last ( file_name, '.' );
04963 
04964   if ( i == -1 )
04965   {
04966     return NULL;
04967   }
04968   else
04969   {
04970     return file_name + i + 1;
04971   }
04972 }
04973 //****************************************************************************80
04974 
04975 float float_read ( FILE *filein )
04976 
04977 //****************************************************************************80
04978 //
04979 //  Purpose:
04980 //
04981 //    FLOAT_READ reads 1 float from a binary file.
04982 //
04983 //  Licensing:
04984 //
04985 //    This code is distributed under the GNU LGPL license.
04986 //
04987 //  Modified:
04988 //
04989 //    24 May 1999
04990 //
04991 //  Author:
04992 //
04993 //    John Burkardt
04994 //
04995 {
04996   float rval;
04997   float temp;
04998 
04999   fread ( &temp, sizeof ( float ), 1, filein );
05000 
05001   if ( byte_swap )
05002   {
05003     rval = float_reverse_bytes ( temp );
05004   }
05005   else
05006   {
05007     rval = temp;
05008   }
05009 
05010   return rval;
05011 }
05012 //****************************************************************************80
05013 
05014 float float_reverse_bytes ( float x )
05015 
05016 //****************************************************************************80
05017 //
05018 //  Purpose:
05019 //
05020 //    FLOAT_REVERSE_BYTES reverses the four bytes in a float.
05021 //
05022 //  Licensing:
05023 //
05024 //    This code is distributed under the GNU LGPL license.
05025 //
05026 //  Modified:
05027 //
05028 //    24 May 1999
05029 //
05030 //  Author:
05031 //
05032 //    John Burkardt
05033 //
05034 //  Parameters:
05035 //
05036 //    X, a float whose bytes are to be reversed.
05037 //
05038 //    FLOAT_REVERSE_BYTES, a float with bytes in reverse order from those in X.
05039 //
05040 {
05041   char c;
05042   union {
05043     float yfloat;
05044     char ychar[4];
05045   } y;
05046 
05047   y.yfloat = x;
05048 
05049   c = y.ychar[0];
05050   y.ychar[0] = y.ychar[3];
05051   y.ychar[3] = c;
05052 
05053   c = y.ychar[1];
05054   y.ychar[1] = y.ychar[2];
05055   y.ychar[2] = c;
05056 
05057   return ( y.yfloat );
05058 }
05059 //****************************************************************************80
05060 
05061 int float_write ( FILE *fileout, float float_val )
05062 
05063 //****************************************************************************80
05064 //
05065 //  Purpose:
05066 //
05067 //    FLOAT_WRITE writes 1 float to a binary file.
05068 //
05069 //  Licensing:
05070 //
05071 //    This code is distributed under the GNU LGPL license.
05072 //
05073 //  Modified:
05074 //
05075 //    23 September 1998
05076 //
05077 //  Author:
05078 //
05079 //    John Burkardt
05080 //
05081 {
05082   int nbyte = sizeof ( float );
05083   float temp;
05084 
05085   if ( byte_swap )
05086   {
05087     temp = float_reverse_bytes ( float_val );
05088   }
05089   else
05090   {
05091     temp = float_val;
05092   }
05093 
05094   fwrite ( &temp, nbyte, 1, fileout );
05095 
05096   return nbyte;
05097 }
05098 //****************************************************************************80
05099 
05100 bool gmod_arch_check ( )
05101 
05102 //****************************************************************************80
05103 //
05104 //  Purpose:
05105 //
05106 //    GMOD_ARCH_CHECK inquires into some features of the computer architecture.
05107 //
05108 //  Licensing:
05109 //
05110 //    This code is distributed under the GNU LGPL license.
05111 //
05112 //  Modified:
05113 //
05114 //    02 September 2003
05115 //
05116 //  Author:
05117 //
05118 //    Zik Saleeba
05119 //
05120 //  Parameters:
05121 //
05122 //    Output, bool GMOD_ARCH_CHECK is TRUE if the size of a float is four bytes
05123 //    and we use IEEE floats (either big-endian or little-endian).
05124 //
05125 {
05126   static unsigned char one[4];
05127   int temp;
05128 
05129   temp = sizeof ( float );
05130   if ( temp != 4 )
05131   {
05132     return false;
05133   }
05134 
05135   *(float *)one = 1.0;
05136 //
05137 //  Little endian IEEE floats.
05138 //
05139   if ( one[0] == 0 && one[1] == 0 && one[2] == 128 && one[3] == 63 )
05140   {
05141     return true;
05142   }
05143 //
05144 //  Big endian IEEE floats.
05145 //
05146   if ( one[0] == 63 && one[1] == 128 && one[2] == 0 && one[3] == 0 )
05147   {
05148     return true;
05149   }
05150 
05151   return false;
05152 }
05153 //****************************************************************************80
05154 
05155 int gmod_read ( FILE *filein )
05156 
05157 //****************************************************************************80
05158 //
05159 //  Purpose:
05160 //
05161 //    GMOD_READ reads a golgotha GMOD file.
05162 //
05163 //  Licensing:
05164 //
05165 //    This code is distributed under the GNU LGPL license.
05166 //
05167 //  Modified:
05168 //
05169 //    19 May 1999
05170 //
05171 //  Author:
05172 //
05173 //    Zik Saleeba
05174 //
05175 
05176 //
05177 //golgotha GMOD file format:
05178 //
05179 //
05180 //        FILE HEADER
05181 //
05182 //w32     magic number           f9 fa 63 1e
05183 //w32     number of sections
05184 //[ number of sections
05185 //    w32     section id
05186 //    w32     section offset
05187 //]
05188 //
05189 //
05190 //        TEXTURE NAME SECTION - section id = 0x13 (19)
05191 //
05192 //w16     number of faces
05193 //[ number of faces
05194 //    w16     texture name length
05195 //    [ texture name length
05196 //        w8      texture name character
05197 //    ]
05198 //]
05199 //
05200 //
05201 //
05202 //        MODEL QUADS SECTION - section id = 0x12 (18)
05203 //
05204 //w16     number of faces
05205 //[ number of faces
05206 //    [ four vertices
05207 //        w16     vertex index
05208 //        float   xpos (0.0-1.0)
05209 //        float   ypos (0.0-1.0)
05210 //    ]
05211 //    float   scale
05212 //    w16     flags
05213 //    float   xnormal     (normal should be normalised)
05214 //    float   ynormal
05215 //    float   znormal
05216 //]
05217 //
05218 //
05219 //        VERTEX ARRAY SECTION - section id = 0x14 (20)
05220 //
05221 //w16     number of vertices
05222 //w16     number of animations
05223 //w16     length of animation name
05224 //[ length of animation name
05225 //    w8      animation name character
05226 //]
05227 //w16     number of frames in animation
05228 //[ number of frames in animation
05229 //    [ number of vertices
05230 //        float   xpos
05231 //        float   ypos
05232 //        float   zpos
05233 //        float   xnormal
05234 //        float   ynormal
05235 //        float   znormal
05236 //    ]
05237 //]
05238 //
05239 {
05240   unsigned char MagicNumber[4];
05241   unsigned long int NumSections;
05242   int SectionCount;
05243   unsigned long int SectionID[GMOD_MAX_SECTIONS];
05244   unsigned long int SectionOffset[GMOD_MAX_SECTIONS];
05245 
05246   unsigned short NumAnimations;
05247   unsigned short NumFrames;
05248   unsigned short FaceCount;
05249   unsigned short TextureCount;
05250   int VertexCount;
05251 
05252   float Scale;
05253   unsigned short Flags;
05254   unsigned short TextureNameLen;
05255   unsigned short AnimationNameLen;
05256   int Order;
05257   int MaxCor = 0;
05258 //
05259 //  Check if we can handle this architecture
05260 //
05261   if ( !gmod_arch_check ( ) )
05262   {
05263     cout << "\n";
05264     cout << "GMOD_READ - This architecture not supported.\n";
05265     return 1;
05266   }
05267 
05268 //
05269 //  Read the file header
05270 //
05271 //
05272 //  Read the magic number
05273 //
05274   fread(MagicNumber, 1, 4, filein);
05275   if ( MagicNumber[0] != 0xf9 ||
05276       MagicNumber[1] != 0xfa ||
05277       MagicNumber[2] != 0x63 ||
05278       MagicNumber[3] != 0x1e)
05279   {
05280     cout << "GMOD_READ - Bad magic number on GMOD file.\n";
05281     return 1;
05282   }
05283 
05284   NumSections = gmod_read_w32(filein);
05285   if ( GMOD_MAX_SECTIONS <= NumSections )
05286   {
05287     cout << "\n";
05288     cout << "GMOD_READ - Fatal error!\n";
05289     cout << "  Too many sections (" << NumSections << ") in GMOD file.\n";
05290     cout << "  Please increase static limit GMOD_MAX_SECTIONS\n";
05291     return 1;
05292   }
05293 
05294 //
05295 //  Read the sections.
05296 //
05297 
05298   for ( SectionCount = 0; SectionCount < ( int ) NumSections; SectionCount++ )
05299   {
05300     SectionID[SectionCount] = gmod_read_w32(filein);
05301     SectionOffset[SectionCount] = gmod_read_w32(filein);
05302   }
05303 //
05304 //  Read each successive section.
05305 //
05306   for ( SectionCount = 0; SectionCount < ( int ) NumSections; SectionCount++ )
05307   {
05308 //
05309 //  Go to the start of the section.
05310 //
05311     fseek ( filein, ( long int ) SectionOffset[SectionCount], SEEK_SET );
05312 //
05313 //  What type of section is it?
05314 //
05315     switch (SectionID[SectionCount])
05316     {
05317 //
05318 //  Model section.
05319 //
05320       case G1_SECTION_MODEL_QUADS:
05321 //
05322 //  Get the number of faces.
05323 //
05324         face_num = gmod_read_w16 ( filein );
05325 
05326         if ( FACE_MAX < face_num )
05327         {
05328           cout << "\n";
05329           cout << "GMOD_READ - Fatal error!\n";
05330           cout << "  Too many faces (" << face_num << ") in GMOD file.\n";
05331           cout << "  Increase the size of FACE_MAX.\n";
05332           return 1;
05333         }
05334 //
05335 //  Get the information on each face.
05336 //
05337         for ( FaceCount = 0; FaceCount < ( unsigned short ) face_num; FaceCount++ )
05338         {
05339           Order = 0;
05340           for ( VertexCount = 0; VertexCount < 4; VertexCount++ )
05341           {
05342 //
05343 //  Read the vertex index
05344 //
05345             face[VertexCount][FaceCount] = gmod_read_w16(filein);
05346 
05347             if (face[VertexCount][FaceCount] != GMOD_UNUSED_VERTEX)
05348             {
05349               Order = VertexCount+1;
05350               if ( MaxCor < face[VertexCount][FaceCount] )
05351               {
05352                 MaxCor = face[VertexCount][FaceCount];
05353               }
05354             }
05355 //
05356 //  Read the texture position.
05357 //
05358             vertex_tex_uv[0][VertexCount][FaceCount] = gmod_read_float(filein);
05359             vertex_tex_uv[1][VertexCount][FaceCount] = gmod_read_float(filein);
05360           }
05361 //
05362 //  Scale and flags.
05363 //
05364           fread(&Scale, sizeof(Scale), 1, filein);
05365           Flags = gmod_read_w16(filein);
05366 
05367           if ( debug )
05368           {
05369             cout << "Flags = " << Flags << "\n";
05370           }
05371 //
05372 //  Normal vector.
05373 //
05374           face_normal[0][FaceCount] = gmod_read_float(filein);
05375           face_normal[1][FaceCount] = gmod_read_float(filein);
05376           face_normal[2][FaceCount] = gmod_read_float(filein);
05377 //
05378 //  The order is the number of used vertices.
05379 //
05380           face_order[FaceCount] = Order;
05381         }
05382         break;
05383 //
05384 //  Texture name section.
05385 //
05386       case G1_SECTION_MODEL_TEXTURE_NAMES:
05387 //
05388 //  Get the number of textures.
05389 //
05390         texture_num = gmod_read_w16(filein);
05391         if ( TEXTURE_MAX < texture_num )
05392         {
05393           cout << "GMOD_READ - Fatal error!\n";
05394           cout << "  Too many texture maps (" << texture_num << ").\n";
05395           cout << "  Increase static limit TEXTURE_MAX.\n";
05396           return 1;
05397         }
05398         face_num = texture_num;
05399 
05400         for (TextureCount = 0; TextureCount < ( unsigned short ) texture_num;
05401           TextureCount++)
05402         {
05403 //
05404 //  read the texture name
05405 //
05406           TextureNameLen = gmod_read_w16(filein);
05407           fread ( texture_name[TextureCount], sizeof(char), TextureNameLen, filein);
05408           texture_name[TextureCount][TextureNameLen] = '\0';
05409         }
05410         break;
05411 //
05412 //  Vertex section.
05413 //
05414       case G1_SECTION_MODEL_VERT_ANIMATION:
05415 //
05416 //  Get the number of vertices.
05417 //
05418         cor3_num = gmod_read_w16(filein);
05419         if ( COR3_MAX < cor3_num )
05420         {
05421           cout << "GMOD_READ - Fatal error!\n";
05422           cout << "  Too many vertices (" << cor3_num << ").\n";
05423           cout << "  Increase static limit COR3_MAX.\n";
05424           return 1;
05425         }
05426 //
05427 //  Get the number of animations.
05428 //
05429         NumAnimations = gmod_read_w16(filein);
05430 
05431         if ( 1 < NumAnimations )
05432         {
05433           cout << "\n";
05434           cout << "GMOD_READ - Fatal error!\n";
05435           cout << "  GMOD files can only handle one animation.\n";
05436           cout << "  This file contains " << NumAnimations << ".\n";
05437           return 1;
05438         }
05439 //
05440 //  Read the animation name.
05441 //
05442         AnimationNameLen = gmod_read_w16(filein);
05443         fread ( anim_name, sizeof(char), AnimationNameLen, filein);
05444         anim_name[AnimationNameLen] = '\0';
05445 //
05446 //  Get the number of frames of animation.
05447 //
05448         NumFrames = gmod_read_w16(filein);
05449         if ( 1 < NumFrames )
05450         {
05451           cout << "\n";
05452           cout << "GMOD_READ - Warning!\n";
05453           cout << "  Too many frames of animation (" << NumFrames << ").\n";
05454           cout << "  Will only use 1.\n";
05455         }
05456 //
05457 //  Go through all the vertices, reading each one
05458 //
05459         for (VertexCount = 0; VertexCount < cor3_num; VertexCount++)
05460         {
05461 //
05462 //  Read the vertex.
05463 //
05464           cor3[0][VertexCount] = gmod_read_float(filein);
05465           cor3[1][VertexCount] = gmod_read_float(filein);
05466           cor3[2][VertexCount] = gmod_read_float(filein);
05467 //
05468 //  Read the normal.
05469 //
05470           cor3_normal[0][VertexCount] = gmod_read_float(filein);
05471           cor3_normal[1][VertexCount] = gmod_read_float(filein);
05472           cor3_normal[2][VertexCount] = gmod_read_float(filein);
05473         }
05474         break;
05475 
05476       default:
05477         continue;
05478     }
05479   }
05480 
05481 //
05482 //  Set some other stray info.
05483 //
05484   line_num = 0;
05485 
05486 //
05487 //  Check for sanity.
05488 //
05489   if ( cor3_num <= MaxCor )
05490   {
05491     cout << "\n";
05492     cout << "GMOD_READ - Fatal error!\n";
05493     cout << "  Maximum coordinate index (" << MaxCor << ")\n";
05494     cout << "  exceeds number of coordinates (" << cor3_num << ").\n";
05495     return 1;
05496   }
05497 
05498   return 0;
05499 }
05500 //****************************************************************************80
05501 
05502 float gmod_read_float ( FILE *filein )
05503 
05504 //****************************************************************************80
05505 //
05506 //  Purpose:
05507 //
05508 //    GMOD_READ_FLOAT reads a float from a Golgotha GMOD file.
05509 //
05510 //  Licensing:
05511 //
05512 //    This code is distributed under the GNU LGPL license.
05513 //
05514 //  Modified:
05515 //
05516 //    19 May 1999
05517 //
05518 //  Author:
05519 //
05520 //    Zik Saleeba
05521 //
05522 {
05523   int endian = 1;
05524   unsigned char *out_pos;
05525   int i;
05526   float Val;
05527 //
05528 //  We're little-endian, which is native for GMOD floats.
05529 //
05530   if (*(char *)&endian == 1)
05531   {
05532     fread(&Val, sizeof(Val), 1, filein);
05533   }
05534 //
05535 //  We're big-endian.  Flip them.
05536 //
05537   else
05538  {
05539     out_pos = (unsigned char *)&Val;
05540     for ( i = sizeof(Val)-1; 0 <= i ; i-- )
05541     {
05542       *(out_pos+i) = fgetc(filein);
05543     }
05544   }
05545 
05546   return Val;
05547 }
05548 //****************************************************************************80
05549 
05550 unsigned short gmod_read_w16 ( FILE *filein )
05551 
05552 //****************************************************************************80
05553 //
05554 //  Purpose:
05555 //
05556 //    GMOD_READ_W16 reads a 16 bit word from a Golgotha GMOD file.
05557 //
05558 //  Licensing:
05559 //
05560 //    This code is distributed under the GNU LGPL license.
05561 //
05562 //  Modified:
05563 //
05564 //    19 May 1999
05565 //
05566 //  Author:
05567 //
05568 //    Zik Saleeba
05569 //
05570 {
05571   unsigned char Byte1;
05572   unsigned char Byte2;
05573 
05574   Byte1 = fgetc ( filein );
05575   Byte2 = fgetc ( filein );
05576 
05577   return Byte1 | (((unsigned short)Byte2) << 8);
05578 }
05579 //****************************************************************************80
05580 
05581 unsigned long gmod_read_w32 ( FILE *filein )
05582 
05583 //****************************************************************************80
05584 //
05585 //  Purpose:
05586 //
05587 //    GMOD_READ_W32 reads a 32 bit word from a Golgotha GMOD file.
05588 //
05589 //  Licensing:
05590 //
05591 //    This code is distributed under the GNU LGPL license.
05592 //
05593 //  Modified:
05594 //
05595 //    19 May 1999
05596 //
05597 //  Author:
05598 //
05599 //    Zik Saleeba
05600 //
05601 {
05602   unsigned char Byte1, Byte2, Byte3, Byte4;
05603 
05604   Byte1 = fgetc(filein);
05605   Byte2 = fgetc(filein);
05606   Byte3 = fgetc(filein);
05607   Byte4 = fgetc(filein);
05608 
05609   return Byte1 |
05610          (((unsigned long)Byte2) << 8) |
05611          (((unsigned long)Byte3) << 16) |
05612          (((unsigned long)Byte4) << 24);
05613 }
05614 //****************************************************************************80
05615 
05616 int gmod_write ( FILE *fileout )
05617 
05618 //****************************************************************************80
05619 //
05620 //  Purpose:
05621 //
05622 //    GMOD_WRITE writes a Golgotha GMOD file.
05623 //
05624 //  Licensing:
05625 //
05626 //    This code is distributed under the GNU LGPL license.
05627 //
05628 //  Modified:
05629 //
05630 //    19 May 1999
05631 //
05632 //  Author:
05633 //
05634 //    Zik Saleeba
05635 //
05636 {
05637   static unsigned char MagicNumber[4] = { 0xf9, 0xfa, 0x63, 0x1e };
05638   unsigned long NumSections;
05639   unsigned long SectionHeaderPos;
05640   unsigned long TextureNameSectionPos;
05641   unsigned long ModelSectionPos;
05642   unsigned long VertexSectionPos;
05643 
05644   int VertexCount;
05645   int FaceCount;
05646   int TextureCount;
05647   unsigned long SectionCount;
05648   float Scale;
05649   float Min[3];
05650   float Max[3];
05651   int CorNumber;
05652   int DimensionCount;
05653   float MaxWidth;
05654 //
05655 //  Check if we can handle this architecture.
05656 //
05657   if ( !gmod_arch_check ( ) )
05658   {
05659     cout << "\n";
05660     cout << "GMOD_WRITE - Fatal error!\n";
05661     cout << "  This architecture not supported.\n";
05662     return 1;
05663   }
05664 //
05665 //  Write the file header.
05666 //
05667 
05668 //
05669 //  Write the magic number.
05670 //
05671   fwrite ( MagicNumber, sizeof(char), 4, fileout );
05672 //
05673 //  Write the number of sections.
05674 //
05675   NumSections = 3;
05676   gmod_write_w32 ( NumSections, fileout );
05677 //
05678 //  Write a dummy section header which we'll overwrite later.
05679 //
05680   SectionHeaderPos = ftell ( fileout );
05681   for (SectionCount = 0; SectionCount < NumSections; SectionCount++)
05682   {
05683     gmod_write_w32 ( 0, fileout );
05684     gmod_write_w32 ( 0, fileout );
05685   }
05686 //
05687 //  Texture name section.
05688 //
05689 
05690 //
05691 //  Take note of where we are in the file.
05692 //
05693   TextureNameSectionPos = ftell ( fileout );
05694 //
05695 //  Write the number of textures.
05696 //
05697   gmod_write_w16 ( ( unsigned short ) face_num, fileout );
05698 //
05699 //  Write the texture names.
05700 //
05701   for ( TextureCount = 0; TextureCount < face_num; TextureCount++ )
05702   {
05703     gmod_write_w16 ( ( unsigned short ) strlen ( texture_name[TextureCount] ),
05704       fileout );
05705 
05706     fwrite ( texture_name[TextureCount], strlen ( texture_name[TextureCount] ),
05707       1, fileout );
05708   }
05709 //
05710 //  Model section.
05711 //
05712 
05713 //
05714 //  Take note of where we are in the file.
05715 //
05716 
05717   ModelSectionPos = ftell(fileout);
05718 
05719 //
05720 //  Write the number of faces.
05721 //
05722   gmod_write_w16 ( ( unsigned short ) face_num, fileout );
05723 //
05724 //  Write the information on each face.
05725 //
05726   for ( FaceCount = 0; FaceCount < face_num; FaceCount++ )
05727   {
05728 
05729     for (VertexCount = 0; VertexCount < ((face_order[FaceCount] < 4) ? face_order[FaceCount] : 4); VertexCount++)
05730     {
05731 //
05732 //  Write the vertex index.
05733 //
05734       gmod_write_w16 ( ( unsigned short ) face[VertexCount][FaceCount], fileout );
05735 //
05736 //  Write the texture position.
05737 //
05738       gmod_write_float ( vertex_tex_uv[0][VertexCount][FaceCount], fileout );
05739       gmod_write_float ( vertex_tex_uv[1][VertexCount][FaceCount], fileout );
05740     }
05741 
05742 //
05743 //  Write any extra vertices which are unused.
05744 //
05745     for ( ; VertexCount < 4; VertexCount++ )
05746     {
05747 //
05748 //  Write the vertex index.
05749 //
05750       gmod_write_w16 ( GMOD_UNUSED_VERTEX, fileout );
05751 //
05752 //  Write the texture position.
05753 //
05754       gmod_write_float ( vertex_tex_uv[0][VertexCount][FaceCount], fileout );
05755 
05756       gmod_write_float ( vertex_tex_uv[1][VertexCount][FaceCount], fileout );
05757     }
05758 //
05759 //  Scale and flags.
05760 //
05761 
05762 //
05763 //  Find the bounding box.
05764 //
05765     for ( DimensionCount = 0; DimensionCount < 3; DimensionCount++ )
05766     {
05767       CorNumber = face[0][FaceCount];
05768       Min[DimensionCount] = cor3[DimensionCount][CorNumber];
05769       Max[DimensionCount] = cor3[DimensionCount][CorNumber];
05770 
05771       for (VertexCount = 1; VertexCount < ((face_order[FaceCount] < 4) ? face_order[FaceCount] : 4); VertexCount++)
05772       {
05773 
05774         CorNumber = face[VertexCount][FaceCount];
05775 
05776         if ( cor3[DimensionCount][CorNumber] < Min[DimensionCount] )
05777           Min[DimensionCount] = cor3[DimensionCount][CorNumber];
05778 
05779         if (Max[DimensionCount] < cor3[DimensionCount][CorNumber])
05780           Max[DimensionCount] = cor3[DimensionCount][CorNumber];
05781       }
05782     }
05783 //
05784 //  The scale is the "width" of the face for mipmapping -
05785 //  I just take the maximum bounding box dimension.
05786 //
05787     MaxWidth = Max[0] - Min[0];
05788     for ( DimensionCount = 1; DimensionCount < 3; DimensionCount++ )
05789     {
05790 
05791        if ( MaxWidth < Max[DimensionCount] - Min[DimensionCount] )
05792            MaxWidth = Max[DimensionCount] - Min[DimensionCount];
05793     }
05794     Scale = MaxWidth;
05795     fwrite ( &Scale, sizeof(Scale), 1, fileout );
05796 //
05797 //  Flags are just nothing.
05798 //
05799     gmod_write_w16 ( 0, fileout );
05800 //
05801 //  Normal vector.
05802 //
05803     gmod_write_float ( face_normal[0][FaceCount], fileout );
05804     gmod_write_float ( face_normal[1][FaceCount], fileout );
05805     gmod_write_float ( face_normal[2][FaceCount], fileout );
05806   }
05807 //
05808 //  Vertex section.
05809 //
05810 
05811 //
05812 //  Take note of where we are in the file.
05813 //
05814   VertexSectionPos = ftell ( fileout );
05815 //
05816 //  Write the number of vertices.
05817 //
05818   gmod_write_w16 ( ( unsigned short ) cor3_num, fileout );
05819 //
05820 //  Write the number of animations.
05821 //
05822   gmod_write_w16 ( 1, fileout );
05823 //
05824 //  Write the animation name.
05825 //
05826   gmod_write_w16 ( 0, fileout );
05827 //
05828 //  Write the number of frames of animation.
05829 //
05830   gmod_write_w16 ( 1, fileout );
05831 //
05832 //  Go through all the vertices, writing each one.
05833 //
05834   for ( VertexCount = 0; VertexCount < cor3_num; VertexCount++ )
05835   {
05836 //
05837 //  Write the vertex.
05838 //
05839     gmod_write_float ( cor3[0][VertexCount], fileout );
05840     gmod_write_float ( cor3[1][VertexCount], fileout );
05841     gmod_write_float ( cor3[2][VertexCount], fileout );
05842 //
05843 //  Write the normal.
05844 //
05845     gmod_write_float ( cor3_normal[0][VertexCount], fileout );
05846     gmod_write_float ( cor3_normal[1][VertexCount], fileout );
05847     gmod_write_float ( cor3_normal[2][VertexCount], fileout );
05848   }
05849 //
05850 //  Now rewrite the section header.
05851 //
05852 
05853 //
05854 //  Go back to the section header.
05855 //
05856   fseek ( fileout, ( long int ) SectionHeaderPos, SEEK_SET );
05857 //
05858 //  Write the texture name section header.
05859 //
05860   gmod_write_w32 ( G1_SECTION_MODEL_TEXTURE_NAMES, fileout );
05861   gmod_write_w32 ( TextureNameSectionPos, fileout );
05862 //
05863 //  Write the model section header.
05864 //
05865   gmod_write_w32 ( G1_SECTION_MODEL_QUADS, fileout );
05866   gmod_write_w32 ( ModelSectionPos, fileout );
05867 //
05868 //  Write the vertex section header.
05869 //
05870   gmod_write_w32 ( G1_SECTION_MODEL_VERT_ANIMATION, fileout );
05871   gmod_write_w32 ( VertexSectionPos, fileout );
05872 
05873   return 0;
05874 }
05875 //****************************************************************************80
05876 
05877 void gmod_write_float ( float Val, FILE *fileout )
05878 
05879 //****************************************************************************80
05880 //
05881 //  Purpose:
05882 //
05883 //    GMOD_WRITE_FLOAT writes a float to a Golgotha GMOD file.
05884 //
05885 //  Licensing:
05886 //
05887 //    This code is distributed under the GNU LGPL license.
05888 //
05889 //  Modified:
05890 //
05891 //    19 May 1999
05892 //
05893 //  Author:
05894 //
05895 //    Zik Saleeba
05896 //
05897 {
05898   int endian = 1;
05899   unsigned char *out_pos;
05900   int i;
05901 //
05902 //  We're little-endian, which is native for GMOD floats.
05903 //
05904   if (*(char *)&endian == 1)
05905   {
05906 
05907     fwrite ( &Val, sizeof(Val), 1, fileout );
05908   }
05909 //
05910 //  We're big-endian, flip `em.
05911 //
05912   else
05913   {
05914     out_pos = (unsigned char *)&Val;
05915     for ( i = sizeof(Val)-1; 0 <= i; i-- )
05916     {
05917       fputc(*(out_pos+i), fileout);
05918     }
05919   }
05920   return;
05921 }
05922 //****************************************************************************80
05923 
05924 void gmod_write_w16 ( unsigned short Val, FILE *fileout )
05925 
05926 //****************************************************************************80
05927 //
05928 //  Purpose:
05929 //
05930 //    GMOD_WRITE_W16 writes a 16 bit word to a Golgotha GMOD file.
05931 //
05932 //  Licensing:
05933 //
05934 //    This code is distributed under the GNU LGPL license.
05935 //
05936 //  Modified:
05937 //
05938 //    13 September 2000
05939 //
05940 //  Author:
05941 //
05942 //    Zik Saleeba
05943 //
05944 {
05945   unsigned char OutByte[2];
05946 
05947   OutByte[0] = (unsigned char)(Val & 0xff);
05948   OutByte[1] = (unsigned char)(Val >> 8);
05949 
05950   fwrite ( OutByte, sizeof(unsigned char), 2, fileout );
05951 
05952   return;
05953 }
05954 //****************************************************************************80
05955 
05956 void gmod_write_w32 ( unsigned long Val, FILE *fileout )
05957 
05958 //****************************************************************************80
05959 //
05960 //  Purpose:
05961 //
05962 //    GMOD_WRITE writes a 32 bit word to a Golgotha GMOD file.
05963 //
05964 //  Licensing:
05965 //
05966 //    This code is distributed under the GNU LGPL license.
05967 //
05968 //  Modified:
05969 //
05970 //    19 May 1999
05971 //
05972 //  Author:
05973 //
05974 //    Zik Saleeba
05975 //
05976 {
05977   unsigned char OutByte[4];
05978 
05979   OutByte[0] = (unsigned char)(Val & 0xff);
05980   OutByte[1] = (unsigned char)((Val >> 8) & 0xff);
05981   OutByte[2] = (unsigned char)((Val >> 16) & 0xff);
05982   OutByte[3] = (unsigned char)((Val >> 24) & 0xff);
05983 
05984   fwrite ( OutByte, sizeof(unsigned char), 4, fileout );
05985 
05986   return;
05987 }
05988 //****************************************************************************80
05989 
05990 void hello ( )
05991 
05992 //****************************************************************************80
05993 //
05994 //  Purpose:
05995 //
05996 //    HELLO prints an explanatory header message.
05997 //
05998 //  Licensing:
05999 //
06000 //    This code is distributed under the GNU LGPL license.
06001 //
06002 //  Modified:
06003 //
06004 //    04 July 2000
06005 //
06006 //  Author:
06007 //
06008 //    John Burkardt
06009 //
06010 {
06011   cout << "\n";
06012   cout << "Hello:  This is IVCON,\n";
06013   cout << "  for 3D graphics file conversion.\n";
06014   cout << "\n";
06015   cout << "    \".3ds\"   3D Studio Max binary;\n";
06016   cout << "    \".ase\"   3D Studio Max ASCII export;\n";
06017   cout << "    \".byu\"   Movie.BYU surface geometry;\n";
06018   cout << "    \".dxf\"   DXF;\n";
06019   cout <<  "    \".gmod\"  Golgotha model;\n";
06020   cout << "    \".hrc\"   SoftImage hierarchy;\n";
06021   cout << "    \".iv\"    SGI Open Inventor;\n";
06022   cout << "    \".obj\"   WaveFront Advanced Visualizer;\n";
06023   cout << "    \".off\"   GEOMVIEW Object File Format;\n";
06024   cout << "    \".pov\"   Persistence of Vision (output only);\n";
06025   cout << "    \".smf\"   Michael Garland's format;\n";
06026   cout << "    \".stl\"   ASCII StereoLithography;\n";
06027   cout << "    \".stla\"  ASCII StereoLithography;\n";
06028   cout << "    \".stlb\"  Binary StereoLithography;\n";
06029   cout << "    \".tec\"   TECPLOT (output only);\n";
06030   cout << "    \".tri\"   [Greg Hood ASCII triangle format];\n";
06031   cout << "    \".tria\"  [Greg Hood ASCII triangle format];\n";
06032   cout << "    \".trib\"  [Greg Hood binary triangle format];\n";
06033   cout << "    \".txt\"   Text (output only);\n";
06034   cout << "    \".ucd\"   AVS UCD file(output only);\n";
06035   cout << "    \".vla\"   VLA;\n";
06036   cout << "    \".wrl\"   VRML (Virtual Reality Modeling Language) (output only).\n";
06037   cout << "    \".xgl\"   XML/OpenGL format (output only);\n";
06038   cout << "\n";
06039   cout << "  Current limits include:\n";
06040   cout << "    " << FACE_MAX << " faces.\n";
06041   cout << "    " << LINES_MAX << " line items.\n";
06042   cout << "    " << COR3_MAX << " points.\n";
06043   cout << "    " << ORDER_MAX << " face order.\n";
06044   cout << "    " << MATERIAL_MAX << " materials.\n";
06045   cout << "    " << TEXTURE_MAX << " textures.\n";
06046   cout << "\n";
06047   cout << "  Last modification: 04 September 2003.\n";
06048 
06049   return;
06050 }
06051 //****************************************************************************80
06052 
06053 void help ( )
06054 
06055 //****************************************************************************80
06056 //
06057 //  Purpose:
06058 //
06059 //    HELP prints a list of the interactive commands.
06060 //
06061 //  Licensing:
06062 //
06063 //    This code is distributed under the GNU LGPL license.
06064 //
06065 //  Modified:
06066 //
06067 //    26 May 1999
06068 //
06069 //  Author:
06070 //
06071 //    John Burkardt
06072 //
06073 {
06074   cout << "\n";
06075   cout << "Commands:\n";
06076   cout << "\n";
06077   cout << "< file   Read data from input file;\n";
06078   cout << "<< file  Append data in input file to current data;\n";
06079   cout << "> file   Write output file;\n";
06080   cout << "B        Switch the binary file byte-swapping mode;\n";
06081   cout << "D        Switch the debugging mode;\n";
06082   cout << "F        Print information about one face;\n";
06083   cout << "H        Print this help list;\n";
06084   cout << "I        Info, print out recent changes;\n";
06085   cout << "LINES    Convert face information to lines;\n";
06086   cout << "N        Recompute normal vectors;\n";
06087   cout << "P        Set LINE_PRUNE option.\n";
06088   cout << "Q        Quit;\n";
06089   cout << "R        Reverse the normal vectors.\n";
06090   cout << "S        Select face subset (NOT WORKING).\n";
06091   cout << "T        Transform the data.\n";
06092   cout << "W        Reverse the face node ordering.\n";
06093 
06094   return;
06095 }
06096 //****************************************************************************80
06097 
06098 int hrc_read ( FILE *filein )
06099 
06100 //****************************************************************************80
06101 //
06102 //  Purpose:
06103 //
06104 //    HRC_READ reads graphics information from a SoftImage HRC file.
06105 //
06106 //  Example:
06107 //
06108 //    HRCH: Softimage 4D Creative Environment v3.00
06109 //
06110 //
06111 //    model
06112 //    {
06113 //      name         "cube_10x10"
06114 //      scaling      1.000 1.000 1.000
06115 //      rotation     0.000 0.000 0.000
06116 //      translation  0.000 0.000 0.000
06117 //
06118 //      mesh
06119 //      {
06120 //        flag    ( PROCESS )
06121 //        discontinuity  60.000
06122 //
06123 //        vertices   8
06124 //        {
06125 //          [0] position  -5.000  -5.000  -5.000
06126 //          [1] position  -5.000  -5.000  5.000
06127 //          [2] position  -5.000  5.000  -5.000
06128 //          [3] position  -5.000  5.000  5.000
06129 //          [4] position  5.000  -5.000  -5.000
06130 //          [5] position  5.000  -5.000  5.000
06131 //          [6] position  5.000  5.000  -5.000
06132 //          [7] position  5.000  5.000  5.000
06133 //        }
06134 //
06135 //        polygons   6
06136 //        {
06137 //          [0] nodes  4
06138 //              {
06139 //                [0] vertex  0
06140 //                    normal  -1.000  0.000  0.000
06141 //                    uvTexture  0.000  0.000
06142 //                    vertexColor 255 178 178 178
06143 //                [1] vertex  1
06144 //                    normal  -1.000  0.000  0.000
06145 //                    uvTexture  0.000  0.000
06146 //                    vertexColor 255 178 178 178
06147 //                [2] vertex  3
06148 //                    normal  -1.000  0.000  0.000
06149 //                    uvTexture  0.000  0.000
06150 //                    vertexColor 255 178 178 178
06151 //                [3] vertex  2
06152 //                    normal  -1.000  0.000  0.000
06153 //                    uvTexture  0.000  0.000
06154 //                    vertexColor 255 178 178 178
06155 //              }
06156 //              material  0
06157 //          [1] nodes  4
06158 //             {
06159 //                [0] vertex  1
06160 //                    normal  0.000  0.000  1.000
06161 //                    uvTexture  0.000  0.000
06162 //                    vertexColor 255 178 178 178
06163 //                [1] vertex  5
06164 //
06165 //    ...etc.....
06166 //
06167 //          [5] nodes  4
06168 //              {
06169 //                [0] vertex  2
06170 //                    normal  0.000  1.000  0.000
06171 //                    uvTexture  0.000  0.000
06172 //                    vertexColor 255 178 178 178
06173 //                [1] vertex  3
06174 //                    normal  0.000  1.000  0.000
06175 //                    uvTexture  0.000  0.000
06176 //                    vertexColor 255 178 178 178
06177 //                [2] vertex  7
06178 //                    normal  0.000  1.000  0.000
06179 //                    uvTexture  0.000  0.000
06180 //                    vertexColor 255 178 178 178
06181 //                [3] vertex  6
06182 //                    normal  0.000  1.000  0.000
06183 //                    uvTexture  0.000  0.000
06184 //                    vertexColor 255 178 178 178
06185 //              }
06186 //              material  0
06187 //        }
06188 //
06189 //        edges   12
06190 //        {
06191 //          [1] vertices  3  2
06192 //          [2] vertices  2  0
06193 //          [3] vertices  0  1
06194 //          [4] vertices  1  3
06195 //          [5] vertices  7  3
06196 //          [6] vertices  1  5
06197 //          [7] vertices  5  7
06198 //          [8] vertices  6  7
06199 //          [9] vertices  5  4
06200 //          [10] vertices  4  6
06201 //          [11] vertices  2  6
06202 //          [12] vertices  4  0
06203 //        }
06204 //      }
06205 //
06206 //      material [0]
06207 //      {
06208 //      name           "kazoo"
06209 //      type           PHONG
06210 //      ambient        0.0  1.0  0.0
06211 //      diffuse        1.0  0.0  0.0
06212 //      specular       0.0  0.0  1.0
06213 //      exponent      50.0
06214 //      reflectivity   0.0
06215 //      transparency   0.0
06216 //      refracIndex    1.0
06217 //      glow           0
06218 //      coc            0.0
06219 //      }
06220 //
06221 //      texture [0]
06222 //      {
06223 //      name          "/usr/users/foss/HOUSE/PICTURES/mellon"
06224 //      glbname       "t2d1"
06225 //      anim          STATIC
06226 //      method        XY
06227 //      repeat        1  1
06228 //      scaling       1.000  1.000
06229 //      offset        0.000  0.000
06230 //      pixelInterp
06231 //      effect        INTENSITY
06232 //      blending      1.000
06233 //      ambient       0.977
06234 //      diffuse       1.000
06235 //      specular      0.966
06236 //      reflect       0.000
06237 //      transp        0.000
06238 //      roughness     0.000
06239 //      reflMap       1.000
06240 //      rotation      0.000
06241 //      txtsup_rot    0.000  0.000  0.000
06242 //      txtsup_trans  0.000  0.000  0.000
06243 //      txtsup_scal   1.000  1.000  1.000
06244 //      }
06245 //    }
06246 //
06247 //  Licensing:
06248 //
06249 //    This code is distributed under the GNU LGPL license.
06250 //
06251 //  Modified:
06252 //
06253 //    25 June 1999
06254 //
06255 //  Author:
06256 //
06257 //    John Burkardt
06258 //
06259 {
06260   float b;
06261   int   count;
06262   float g;
06263   int   i;
06264   int   icor3;
06265   int   ivert;
06266   int   iword;
06267   int   jval;
06268   int   level;
06269   char *next;
06270   int   nlbrack;
06271   int   nrbrack;
06272   int   cor3_num_old;
06273   float r;
06274   float t;
06275   float temp[3];
06276   int   width;
06277   char  word[LINE_MAX_LEN];
06278   char  word1[LINE_MAX_LEN];
06279   char  word2[LINE_MAX_LEN];
06280   char  wordm1[LINE_MAX_LEN];
06281   float x;
06282   float y;
06283   float z;
06284 
06285   level = 0;
06286   strcpy ( level_name[0], "Top" );
06287   nlbrack = 0;
06288   nrbrack = 0;
06289   cor3_num_old = cor3_num;
06290   strcpy ( word, " " );
06291   strcpy ( wordm1, " " );
06292 //
06293 //  Read a line of text from the file.
06294 //
06295   for ( ;; )
06296   {
06297 
06298     if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
06299     {
06300       break;
06301     }
06302 
06303     text_num = text_num + 1;
06304     next = input;
06305     iword = 0;
06306 //
06307 //  Read a word from the line.
06308 //
06309     for ( ;; )
06310     {
06311       strcpy ( wordm1, word );
06312 
06313       count = sscanf ( next, "%s%n", word2, &width );
06314       next = next + width;
06315 
06316       if ( count <= 0 )
06317       {
06318         break;
06319       }
06320 
06321       strcpy ( word, word2 );
06322 
06323       iword = iword + 1;
06324 
06325       if ( iword == 1 )
06326       {
06327         strcpy ( word1, word );
06328       }
06329 //
06330 //  The first line of the file must be the header.
06331 //
06332       if ( text_num == 1 )
06333       {
06334         if ( strcmp ( word1, "HRCH:" ) != 0 )
06335         {
06336           cout << "\n";
06337           cout << "HRC_READ - Fatal error!\n";
06338           cout << "  The input file has a bad header.\n";;
06339           return 1;
06340         }
06341         else
06342         {
06343           comment_num = comment_num + 1;
06344         }
06345         break;
06346       }
06347 //
06348 //  If the word is a curly bracket, count it.
06349 //
06350       if ( strcmp ( word, "{" ) == 0 )
06351       {
06352         nlbrack = nlbrack + 1;
06353         level = nlbrack - nrbrack;
06354         strcpy ( level_name[level], wordm1 );
06355         if ( debug )
06356         {
06357           cout << "New level: " << level_name[level] << "\n";;
06358         }
06359       }
06360       else if ( strcmp ( word, "}" ) == 0 )
06361       {
06362         nrbrack = nrbrack + 1;
06363 
06364         if ( nlbrack < nrbrack )
06365         {
06366           cout << "\n";
06367           cout << "HRC_READ - Fatal error!\n";
06368           cout << "  Extraneous right bracket on line " << text_num << ".\n";
06369           cout << "  Processing field " << level_name[level] << "\n";
06370           return 1;
06371         }
06372       }
06373 //
06374 //  CONTROLPOINTS
06375 //
06376       if ( strcmp ( level_name[level], "controlpoints" ) == 0 )
06377       {
06378 
06379         if ( strcmp ( word, "{" ) == 0 )
06380         {
06381         }
06382         else if ( strcmp ( word, "}" ) == 0 )
06383         {
06384           if ( line_num < LINES_MAX )
06385           {
06386             line_dex[line_num] = -1;
06387             line_material[line_num] = 0;
06388           }
06389           line_num = line_num + 1;
06390           level = nlbrack - nrbrack;
06391         }
06392         else if ( word[0] == '[' )
06393         {
06394         }
06395         else if ( strcmp ( word, "position" ) == 0 )
06396         {
06397           count = sscanf ( next, "%f%n", &x, &width );
06398           next = next + width;
06399 
06400           count = sscanf ( next, "%f%n", &y, &width );
06401           next = next + width;
06402 
06403           count = sscanf ( next, "%f%n", &z, &width );
06404           next = next + width;
06405 
06406           temp[0] = x;
06407           temp[1] = y;
06408           temp[2] = z;
06409 
06410           if ( cor3_num < 1000 )
06411           {
06412             icor3 = rcol_find ( cor3, 3, cor3_num, temp );
06413           }
06414           else
06415           {
06416             icor3 = -1;
06417           }
06418 
06419           if ( icor3 == -1 )
06420           {
06421             icor3 = cor3_num;
06422             if ( cor3_num < COR3_MAX )
06423             {
06424               cor3[0][cor3_num] = x;
06425               cor3[1][cor3_num] = y;
06426               cor3[2][cor3_num] = z;
06427             }
06428             cor3_num = cor3_num + 1;
06429 
06430           }
06431           else
06432           {
06433             dup_num = dup_num + 1;
06434           }
06435 
06436           if ( line_num < LINES_MAX )
06437           {
06438             line_dex[line_num] = icor3;
06439             line_material[line_num] = 0;
06440           }
06441           line_num = line_num + 1;
06442         }
06443         else
06444         {
06445           bad_num = bad_num + 1;
06446           cout << "CONTROLPOINTS: Bad data " << word << "\n";
06447           return 1;
06448         }
06449 
06450       }
06451 //
06452 //  EDGES
06453 //
06454       else if ( strcmp ( level_name[level], "edges" ) == 0 )
06455       {
06456         if ( strcmp( word, "{" ) == 0 )
06457         {
06458         }
06459         else if ( strcmp ( word, "}" ) == 0 )
06460         {
06461           level = nlbrack - nrbrack;
06462         }
06463         else if ( word[0] == '[' )
06464         {
06465         }
06466         else if ( strcmp ( word, "vertices" ) == 0 )
06467         {
06468 
06469           count = sscanf ( next, "%d%n", &jval, &width );
06470           next = next + width;
06471 
06472           if ( line_num < LINES_MAX )
06473           {
06474             line_dex[line_num] = jval + cor3_num_old;
06475             line_material[line_num] = 0;
06476           }
06477           line_num = line_num + 1;
06478 
06479           count = sscanf ( next, "%d%n", &jval, &width );
06480           next = next + width;
06481 
06482           if ( line_num < LINES_MAX )
06483           {
06484             line_dex[line_num] = jval + cor3_num_old;
06485             line_material[line_num] = 0;
06486           }
06487           line_num = line_num + 1;
06488 
06489           if ( line_num < LINES_MAX )
06490           {
06491             line_dex[line_num] = -1;
06492             line_material[line_num] = -1;
06493           }
06494           line_num = line_num + 1;
06495 
06496         }
06497         else
06498         {
06499           bad_num = bad_num + 1;
06500           cout << "EDGES: Bad data " << word << "\n";
06501           return 1;
06502         }
06503 
06504       }
06505 //
06506 //  MATERIAL
06507 //
06508       else if ( strcmp ( level_name[level], "material" ) == 0 )
06509       {
06510         if ( strcmp ( word, "{" ) == 0 )
06511         {
06512           material_num = material_num + 1;
06513         }
06514         else if ( strcmp ( word, "}" ) == 0 )
06515         {
06516           level = nlbrack - nrbrack;
06517         }
06518         else if ( word[0] == '[' )
06519         {
06520         }
06521         else if ( strcmp ( word, "ambient" ) == 0 )
06522         {
06523         }
06524         else if ( strcmp ( word, "coc" ) == 0 )
06525         {
06526         }
06527         else if ( strcmp ( word, "diffuse" ) == 0 )
06528         {
06529 
06530           count = sscanf ( next, "%f%n", &r, &width );
06531           next = next + width;
06532           material_rgba[0][material_num-1] = r;
06533 
06534           count = sscanf ( next, "%f%n", &g, &width );
06535           next = next + width;
06536           material_rgba[0][material_num-1] = g;
06537 
06538           count = sscanf ( next, "%f%n", &b, &width );
06539           next = next + width;
06540           material_rgba[0][material_num-1] = b;
06541 
06542         }
06543         else if ( strcmp ( word, "exponent" ) == 0 )
06544         {
06545         }
06546         else if ( strcmp ( word, "glow" ) == 0 )
06547         {
06548         }
06549         else if ( strcmp ( word, "name" ) == 0 )
06550         {
06551           count = sscanf ( next, "%s%n", word, &width );
06552           next = next + width;
06553           strcpy ( material_name[material_num-1], word );
06554         }
06555         else if ( strcmp ( word, "reflectivity" ) == 0 )
06556         {
06557         }
06558         else if ( strcmp ( word, "refracindex" ) == 0 )
06559         {
06560         }
06561         else if ( strcmp ( word, "specular" ) == 0 )
06562         {
06563         }
06564         else if ( strcmp ( word, "transparency" ) == 0 )
06565         {
06566           count = sscanf ( next, "%f%n", &t, &width );
06567           next = next + width;
06568           material_rgba[3][material_num-1] = 1.0 - t;
06569         }
06570         else if ( strcmp ( word, "type" ) == 0 )
06571         {
06572         }
06573         else
06574         {
06575           bad_num = bad_num + 1;
06576           cout << "MATERIAL: Bad data " << word << "\n";
06577           return 1;
06578         }
06579       }
06580 //
06581 //  MESH
06582 //
06583       else if ( strcmp ( level_name[level], "mesh" ) == 0 )
06584       {
06585         if ( strcmp ( word, "{" ) == 0 )
06586         {
06587         }
06588         else if ( strcmp ( word, "}" ) == 0 )
06589         {
06590           level = nlbrack - nrbrack;
06591         }
06592         else if ( strcmp ( word, "discontinuity" ) == 0 )
06593         {
06594           break;
06595         }
06596         else if ( strcmp ( word, "edges" ) == 0 )
06597         {
06598           break;
06599         }
06600         else if ( strcmp ( word, "flag" ) == 0 )
06601         {
06602           break;
06603         }
06604         else if ( strcmp ( word, "polygons" ) == 0 )
06605         {
06606           break;
06607         }
06608         else if ( strcmp ( word, "vertices" ) == 0 )
06609         {
06610           break;
06611         }
06612         else
06613         {
06614           bad_num = bad_num + 1;
06615           cout << "MESH: Bad data " << word << "\n";
06616           return 1;
06617         }
06618 
06619       }
06620 //
06621 //  MODEL
06622 //
06623       else if ( strcmp ( level_name[level], "model" ) == 0 )
06624       {
06625         if ( strcmp ( word, "{" ) == 0 )
06626         {
06627         }
06628         else if ( strcmp ( word, "}" ) == 0 )
06629         {
06630           level = nlbrack - nrbrack;
06631         }
06632         else if ( strcmp ( word, "material" ) == 0 )
06633         {
06634           break;
06635         }
06636         else if ( strcmp ( word, "mesh" ) == 0 )
06637         {
06638           break;
06639         }
06640         else if ( strcmp ( word, "name" ) == 0 )
06641         {
06642           break;
06643         }
06644         else if ( strcmp ( word, "patch" ) == 0 )
06645         {
06646           break;
06647         }
06648         else if ( strcmp ( word, "rotation" ) == 0 )
06649         {
06650           break;
06651         }
06652         else if ( strcmp ( word, "scaling" ) == 0 )
06653         {
06654           break;
06655         }
06656         else if ( strcmp ( word, "spline" ) == 0 )
06657         {
06658           break;
06659         }
06660         else if ( strcmp ( word, "translation" ) == 0 )
06661         {
06662           break;
06663         }
06664         else
06665         {
06666           bad_num = bad_num + 1;
06667           cout << "MODEL: Bad data " << word << "\n";
06668           return 1;
06669         }
06670 
06671       }
06672 //
06673 //  NODES
06674 //
06675       else if ( strcmp ( level_name[level], "nodes" ) == 0 )
06676       {
06677         if ( strcmp ( word, "{" ) == 0 )
06678         {
06679           ivert = 0;
06680           face_order[face_num] = 0;
06681           face_num = face_num + 1;
06682         }
06683         else if ( strcmp ( word, "}" ) == 0 )
06684         {
06685           level = nlbrack - nrbrack;
06686         }
06687         else if ( word[0] == '[' )
06688         {
06689         }
06690         else if ( strcmp ( word, "normal" ) == 0 )
06691         {
06692           count = sscanf ( next, "%f%n", &x, &width );
06693           next = next + width;
06694 
06695           count = sscanf ( next, "%f%n", &y, &width );
06696           next = next + width;
06697 
06698           count = sscanf ( next, "%f%n", &z, &width );
06699           next = next + width;
06700 
06701           if ( ivert < ORDER_MAX && face_num < FACE_MAX )
06702           {
06703             vertex_normal[0][ivert-1][face_num-1] = x;
06704             vertex_normal[1][ivert-1][face_num-1] = y;
06705             vertex_normal[2][ivert-1][face_num-1] = z;
06706           }
06707 
06708         }
06709         else if ( strcmp ( word, "uvTexture" ) == 0 )
06710         {
06711           count = sscanf ( next, "%f%n", &x, &width );
06712           next = next + width;
06713 
06714           count = sscanf ( next, "%f%n", &y, &width );
06715           next = next + width;
06716 
06717           if ( ivert < ORDER_MAX && face_num < FACE_MAX )
06718           {
06719             vertex_tex_uv[0][ivert-1][face_num-1] = x;
06720             vertex_tex_uv[1][ivert-1][face_num-1] = y;
06721           }
06722         }
06723         else if ( strcmp ( word, "vertex" ) == 0 )
06724         {
06725           count = sscanf ( next, "%d%n", &jval, &width );
06726           next = next + width;
06727 
06728           if ( ivert < ORDER_MAX && face_num < FACE_MAX )
06729           {
06730             face_order[face_num-1] = face_order[face_num-1] + 1;
06731             face[ivert][face_num-1] = jval;
06732           }
06733           ivert = ivert + 1;
06734 
06735         }
06736 //
06737 //  Right now, we don't do anything with the vertexColor information.
06738 //
06739         else if ( strcmp ( word, "vertexColor" ) == 0 )
06740         {
06741           count = sscanf ( next, "%d%n", &jval, &width );
06742           next = next + width;
06743 
06744           count = sscanf ( next, "%d%n", &jval, &width );
06745           next = next + width;
06746 
06747           count = sscanf ( next, "%d%n", &jval, &width );
06748           next = next + width;
06749 
06750           count = sscanf ( next, "%d%n", &jval, &width );
06751           next = next + width;
06752         }
06753         else
06754         {
06755           bad_num = bad_num + 1;
06756           cout << "NODES: Bad data " << word << "\n";
06757           return 1;
06758         }
06759 
06760       }
06761 //
06762 //  PATCH
06763 //  I don't know what to do with this yet.
06764 //
06765       else if ( strcmp ( level_name[level], "patch" ) == 0 )
06766       {
06767         if ( strcmp ( word, "{" ) == 0 )
06768         {
06769         }
06770         else if ( strcmp ( word, "}" ) == 0 )
06771         {
06772           level = nlbrack - nrbrack;
06773         }
06774         else if ( strcmp ( word, "approx_type" ) == 0 )
06775         {
06776         }
06777         else if ( strcmp ( word, "controlpoints" ) == 0 )
06778         {
06779         }
06780         else if ( strcmp ( word, "curv_u" ) == 0 )
06781         {
06782         }
06783         else if ( strcmp ( word, "curv_v" ) == 0 )
06784         {
06785         }
06786         else if ( strcmp ( word, "recmin" ) == 0 )
06787         {
06788         }
06789         else if ( strcmp ( word, "recmax" ) == 0 )
06790         {
06791         }
06792         else if ( strcmp ( word, "recursion" ) == 0 )
06793         {
06794         }
06795         else if ( strcmp ( word, "spacial" ) == 0 )
06796         {
06797         }
06798         else if ( strcmp ( word, "taggedpoints" ) == 0 )
06799         {
06800         }
06801         else if ( strcmp ( word, "ucurve" ) == 0 )
06802         {
06803         }
06804         else if ( strcmp ( word, "ustep" ) == 0 )
06805         {
06806         }
06807         else if ( strcmp ( word, "utension" ) == 0 )
06808         {
06809         }
06810         else if ( strcmp ( word, "utype" ) == 0 )
06811         {
06812         }
06813         else if ( strcmp ( word, "vclose" ) == 0 )
06814         {
06815         }
06816         else if ( strcmp ( word, "vcurve" ) == 0 )
06817         {
06818         }
06819         else if ( strcmp ( word, "viewdep" ) == 0 )
06820         {
06821         }
06822         else if ( strcmp ( word, "vpoint" ) == 0 )
06823         {
06824         }
06825         else if ( strcmp ( word, "vstep" ) == 0 )
06826         {
06827         }
06828         else if ( strcmp ( word, "vtension" ) == 0 )
06829         {
06830         }
06831         else if ( strcmp ( word, "vtype" ) == 0 )
06832         {
06833         }
06834         else
06835         {
06836           bad_num = bad_num + 1;
06837           cout << "PATCH: Bad data " << word << "\n";
06838           return 1;
06839         }
06840       }
06841 //
06842 //  POLYGONS
06843 //
06844       else if ( strcmp ( level_name[level], "polygons" ) == 0 )
06845       {
06846         if ( strcmp ( word, "{" ) == 0 )
06847         {
06848         }
06849         else if ( strcmp ( word, "}" ) == 0 )
06850         {
06851           level = nlbrack - nrbrack;
06852         }
06853         else if ( word[0] == '[' )
06854         {
06855         }
06856         else if ( strcmp ( word, "material" ) == 0 )
06857         {
06858           count = sscanf ( next, "%d%n", &jval, &width );
06859           next = next + width;
06860 
06861           for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
06862           {
06863             vertex_material[ivert][face_num-1] = jval;
06864           }
06865 
06866         }
06867         else if ( strcmp ( word, "nodes" ) == 0 )
06868         {
06869           count = sscanf ( next, "%s%n", word2, &width );
06870           next = next + width;
06871         }
06872         else
06873         {
06874           bad_num = bad_num + 1;
06875           cout << "POLYGONS: Bad data " << word << "\n";
06876           return 1;
06877         }
06878 
06879       }
06880 //
06881 //  SPLINE
06882 //
06883       else if ( strcmp ( level_name[level], "spline" ) == 0 )
06884       {
06885         if ( strcmp ( word, "{" ) == 0 )
06886         {
06887         }
06888         else if ( strcmp ( word, "}" ) == 0 )
06889         {
06890           level = nlbrack - nrbrack;
06891         }
06892         else if ( strcmp ( word, "controlpoints" ) == 0 )
06893         {
06894           break;
06895         }
06896 //
06897 //  WHY DON'T YOU READ IN THE OBJECT NAME HERE?
06898 //
06899         else if ( strcmp ( word, "name" ) == 0 )
06900         {
06901           break;
06902         }
06903         else if ( strcmp ( word, "nbKeys" ) == 0 )
06904         {
06905           break;
06906         }
06907         else if ( strcmp ( word, "step" ) == 0 )
06908         {
06909           break;
06910         }
06911         else if ( strcmp ( word, "tension" ) == 0 )
06912         {
06913           break;
06914         }
06915         else if ( strcmp ( word, "type" ) == 0 )
06916         {
06917           break;
06918         }
06919         else
06920         {
06921           bad_num = bad_num + 1;
06922           cout << "SPLINE: Bad data " << word << "\n";
06923           return 1;
06924         }
06925 
06926       }
06927 //
06928 //  TAGGEDPOINTS
06929 //
06930       else if ( strcmp ( level_name[level], "taggedpoints" ) == 0 )
06931       {
06932         if ( strcmp ( word, "{" ) == 0 )
06933         {
06934         }
06935         else if ( strcmp ( word, "}" ) == 0 )
06936         {
06937           level = nlbrack - nrbrack;
06938         }
06939         else if ( word[0] == '[' )
06940         {
06941         }
06942         else if ( strcmp ( word, "tagged" ) == 0 )
06943         {
06944         }
06945         else
06946         {
06947           bad_num = bad_num + 1;
06948           cout << "TAGGEDPOINTS: Bad data " << word << "\n";
06949           return 1;
06950         }
06951 
06952       }
06953 //
06954 //  TEXTURE
06955 //
06956       else if ( strcmp ( level_name[level], "texture" ) == 0 )
06957       {
06958         if ( strcmp ( word, "{" ) == 0 )
06959         {
06960           texture_num = texture_num + 1;
06961         }
06962         else if ( strcmp ( word, "}" ) == 0 )
06963         {
06964           level = nlbrack - nrbrack;
06965         }
06966         else if ( word[0] == '[' )
06967         {
06968         }
06969         else if ( strcmp ( word, "ambient" ) == 0 )
06970         {
06971         }
06972         else if ( strcmp ( word, "anim" ) == 0 )
06973         {
06974         }
06975         else if ( strcmp ( word, "blending" ) == 0 )
06976         {
06977         }
06978         else if ( strcmp ( word, "diffuse" ) == 0 )
06979         {
06980         }
06981         else if ( strcmp ( word, "effect" ) == 0 )
06982         {
06983         }
06984         else if ( strcmp ( word, "glbname" ) == 0 )
06985         {
06986         }
06987         else if ( strcmp ( word, "method" ) == 0 )
06988         {
06989         }
06990         else if ( strcmp ( word, "name" ) == 0 )
06991         {
06992           count = sscanf ( next, "%s%n", word, &width );
06993           next = next + width;
06994           strcpy ( texture_name[texture_num-1], word );
06995         }
06996         else if ( strcmp ( word, "offset" ) == 0 )
06997         {
06998         }
06999         else if ( strcmp ( word, "pixelinterp" ) == 0 )
07000         {
07001         }
07002         else if ( strcmp ( word, "reflect" ) == 0 )
07003         {
07004         }
07005         else if ( strcmp ( word, "reflmap" ) == 0 )
07006         {
07007         }
07008         else if ( strcmp ( word, "repeat" ) == 0 )
07009         {
07010         }
07011         else if ( strcmp ( word, "rotation" ) == 0 )
07012         {
07013         }
07014         else if ( strcmp ( word, "roughness" ) == 0 )
07015         {
07016         }
07017         else if ( strcmp ( word, "scaling" ) == 0 )
07018         {
07019         }
07020         else if ( strcmp ( word, "specular" ) == 0 )
07021         {
07022         }
07023         else if ( strcmp ( word, "transp" ) == 0 )
07024         {
07025         }
07026         else if ( strcmp ( word, "txtsup_rot" ) == 0 )
07027         {
07028         }
07029         else if ( strcmp ( word, "txtsup_scal" ) == 0 )
07030         {
07031         }
07032         else if ( strcmp ( word, "txtsup_trans" ) == 0 )
07033         {
07034         }
07035         else
07036         {
07037           bad_num = bad_num + 1;
07038           cout << "TEXTURE: Bad data " << word << "\n";
07039           return 1;
07040         }
07041       }
07042 //
07043 //  VERTICES
07044 //
07045       else if ( strcmp ( level_name[level], "vertices" ) == 0 )
07046       {
07047         if ( strcmp ( word, "{" ) == 0 )
07048         {
07049         }
07050         else if ( strcmp ( word, "}" ) == 0 )
07051         {
07052           level = nlbrack - nrbrack;
07053         }
07054         else if ( word[0] == '[' )
07055         {
07056         }
07057         else if ( strcmp ( word, "position" ) == 0 )
07058         {
07059           count = sscanf ( next, "%f%n", &x, &width );
07060           next = next + width;
07061 
07062           count = sscanf ( next, "%f%n", &y, &width );
07063           next = next + width;
07064 
07065           count = sscanf ( next, "%f%n", &z, &width );
07066           next = next + width;
07067 
07068           if ( cor3_num < COR3_MAX )
07069           {
07070             cor3[0][cor3_num] = x;
07071             cor3[1][cor3_num] = y;
07072             cor3[2][cor3_num] = z;
07073           }
07074           cor3_num = cor3_num + 1;
07075         }
07076         else
07077         {
07078           bad_num = bad_num + 1;
07079           cout << "VERTICES: Bad data " << word << "\n";
07080           return 1;
07081         }
07082       }
07083 //
07084 //  Any other word:
07085 //
07086       else
07087       {
07088       }
07089     }
07090   }
07091 
07092 //
07093 //  End of information in file.
07094 //
07095 //  Check the "materials" defining a line.
07096 //
07097 //  If COORDINDEX is -1, so should be the MATERIALINDEX.
07098 //  If COORDINDEX is not -1, then the MATERIALINDEX shouldn"t be either.
07099 //
07100   for ( i = 0; i < line_num; i++ )
07101   {
07102     if ( line_dex[i] == -1 )
07103     {
07104       line_material[i] = -1;
07105     }
07106     else if ( line_material[i] == -1 )
07107     {
07108       line_material[i] = 0;
07109     }
07110 
07111   }
07112   return 0;
07113 }
07114 //****************************************************************************80
07115 
07116 int hrc_write ( FILE* fileout )
07117 
07118 //****************************************************************************80
07119 //
07120 //  Purpose:
07121 //
07122 //    HRC_WRITE writes graphics data to an HRC SoftImage file.
07123 //
07124 //  Example:
07125 //
07126 //    HRCH: Softimage 4D Creative Environment v3.00
07127 //
07128 //
07129 //    model
07130 //    {
07131 //      name         "cube_10x10"
07132 //      scaling      1.000 1.000 1.000
07133 //      rotation     0.000 0.000 0.000
07134 //      translation  0.000 0.000 0.000
07135 //
07136 //      mesh
07137 //      {
07138 //        flag    ( PROCESS )
07139 //        discontinuity  60.000
07140 //
07141 //        vertices   8
07142 //        {
07143 //          [0] position  -5.000  -5.000  -5.000
07144 //          [1] position  -5.000  -5.000  5.000
07145 //          [2] position  -5.000  5.000  -5.000
07146 //          [3] position  -5.000  5.000  5.000
07147 //          [4] position  5.000  -5.000  -5.000
07148 //          [5] position  5.000  -5.000  5.000
07149 //          [6] position  5.000  5.000  -5.000
07150 //          [7] position  5.000  5.000  5.000
07151 //        }
07152 //
07153 //        polygons   6
07154 //        {
07155 //          [0] nodes  4
07156 //              {
07157 //                [0] vertex  0
07158 //                    normal  -1.000  0.000  0.000
07159 //                    uvTexture  0.000  0.000
07160 //                    vertexColor 255 178 178 178
07161 //                [1] vertex  1
07162 //                    normal  -1.000  0.000  0.000
07163 //                    uvTexture  0.000  0.000
07164 //                    vertexColor 255 178 178 178
07165 //                [2] vertex  3
07166 //                    normal  -1.000  0.000  0.000
07167 //                    uvTexture  0.000  0.000
07168 //                    vertexColor 255 178 178 178
07169 //                [3] vertex  2
07170 //                    normal  -1.000  0.000  0.000
07171 //                    uvTexture  0.000  0.000
07172 //                    vertexColor 255 178 178 178
07173 //              }
07174 //              material  0
07175 //          [1] nodes  4
07176 //             {
07177 //                [0] vertex  1
07178 //                    normal  0.000  0.000  1.000
07179 //                    uvTexture  0.000  0.000
07180 //                    vertexColor 255 178 178 178
07181 //                [1] vertex  5
07182 //
07183 //    ...etc.....
07184 //
07185 //          [5] nodes  4
07186 //              {
07187 //                [0] vertex  2
07188 //                    normal  0.000  1.000  0.000
07189 //                    uvTexture  0.000  0.000
07190 //                    vertexColor 255 178 178 178
07191 //                [1] vertex  3
07192 //                    normal  0.000  1.000  0.000
07193 //                    uvTexture  0.000  0.000
07194 //                    vertexColor 255 178 178 178
07195 //                [2] vertex  7
07196 //                    normal  0.000  1.000  0.000
07197 //                    uvTexture  0.000  0.000
07198 //                    vertexColor 255 178 178 178
07199 //                [3] vertex  6
07200 //                    normal  0.000  1.000  0.000
07201 //                    uvTexture  0.000  0.000
07202 //                    vertexColor 255 178 178 178
07203 //              }
07204 //              material  0
07205 //        }
07206 //
07207 //        edges   12
07208 //        {
07209 //          [1] vertices  3  2
07210 //          [2] vertices  2  0
07211 //          [3] vertices  0  1
07212 //          [4] vertices  1  3
07213 //          [5] vertices  7  3
07214 //          [6] vertices  1  5
07215 //          [7] vertices  5  7
07216 //          [8] vertices  6  7
07217 //          [9] vertices  5  4
07218 //          [10] vertices  4  6
07219 //          [11] vertices  2  6
07220 //          [12] vertices  4  0
07221 //        }
07222 //      }
07223 //
07224 //      material [0]
07225 //      {
07226 //      name           "kazoo"
07227 //      type           PHONG
07228 //      ambient        0.0  1.0  0.0
07229 //      diffuse        1.0  0.0  0.0
07230 //      specular       0.0  0.0  1.0
07231 //      exponent      50.0
07232 //      reflectivity   0.0
07233 //      transparency   0.0
07234 //      refracIndex    1.0
07235 //      glow           0
07236 //      coc            0.0
07237 //      }
07238 //
07239 //      texture [0]
07240 //      {
07241 //      name          "/usr/users/foss/HOUSE/PICTURES/mellon"
07242 //      glbname       "t2d1"
07243 //      anim          STATIC
07244 //      method        XY
07245 //      repeat        1  1
07246 //      scaling       1.000  1.000
07247 //      offset        0.000  0.000
07248 //      pixelInterp
07249 //      effect        INTENSITY
07250 //      blending      1.000
07251 //      ambient       0.977
07252 //      diffuse       1.000
07253 //      specular      0.966
07254 //      reflect       0.000
07255 //      transp        0.000
07256 //      roughness     0.000
07257 //      reflMap       1.000
07258 //      rotation      0.000
07259 //      txtsup_rot    0.000  0.000  0.000
07260 //      txtsup_trans  0.000  0.000  0.000
07261 //      txtsup_scal   1.000  1.000  1.000
07262 //      }
07263 //    }
07264 //
07265 //  Licensing:
07266 //
07267 //    This code is distributed under the GNU LGPL license.
07268 //
07269 //  Modified:
07270 //
07271 //    25 June 1998
07272 //
07273 //  Author:
07274 //
07275 //    John Burkardt
07276 //
07277 //
07278 {
07279   int iface;
07280   int ivert;
07281   int j;
07282   int jhi;
07283   int jlo;
07284   int jrel;
07285   int k;
07286   int npts;
07287   int nseg;
07288   int text_num;
07289 
07290   nseg = 0;
07291   text_num = 0;
07292 
07293   fprintf ( fileout, "HRCH: Softimage 4D Creative Environment v3.00\n" );
07294   fprintf ( fileout, "\n" );
07295   fprintf ( fileout, "\n" );
07296   text_num = text_num + 3;
07297 
07298   fprintf ( fileout, "model\n" );
07299   fprintf ( fileout, "{\n" );
07300   fprintf ( fileout, "  name         \"%s\"\n", object_name );
07301   fprintf ( fileout, "  scaling      1.000 1.000 1.000\n" );
07302   fprintf ( fileout, "  rotation     0.000 0.000 0.000\n" );
07303   fprintf ( fileout, "  translation  0.000 0.000 0.000\n" );
07304   text_num = text_num + 6;
07305 
07306   if ( 0 < face_num )
07307   {
07308     fprintf ( fileout, "\n" );
07309     fprintf ( fileout, "  mesh\n" );
07310     fprintf ( fileout, "  {\n" );
07311     fprintf ( fileout, "    flag    ( PROCESS )\n" );
07312     fprintf ( fileout, "    discontinuity  60.000\n" );
07313     text_num = text_num + 5;
07314 //
07315 //  Point coordinates.
07316 //
07317     if ( 0 < cor3_num )
07318     {
07319       fprintf ( fileout, "\n" );
07320       fprintf ( fileout, "    vertices %d\n", cor3_num );
07321       fprintf ( fileout, "    {\n" );
07322       text_num = text_num + 3;
07323 
07324       for ( j = 0; j < cor3_num; j++ )
07325       {
07326         fprintf ( fileout, "      [%d] position %f %f %f\n", j, cor3[0][j],
07327           cor3[1][j], cor3[2][j] );
07328         text_num = text_num + 1;
07329       }
07330       fprintf ( fileout, "    }\n" );
07331       text_num = text_num + 1;
07332     }
07333 //
07334 //  Faces.
07335 //
07336     fprintf ( fileout, "\n" );
07337     fprintf ( fileout, "    polygons %d\n", face_num );
07338     fprintf ( fileout, "    {\n" );
07339     text_num = text_num + 3;
07340 
07341     for ( iface = 0; iface < face_num; iface++ )
07342     {
07343       fprintf ( fileout, "      [%d] nodes %d\n", iface, face_order[iface] );
07344       fprintf ( fileout, "      {\n" );
07345       text_num = text_num + 2;
07346 
07347       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
07348       {
07349         fprintf ( fileout, "        [%d] vertex %d\n", ivert, face[ivert][iface] );
07350         fprintf ( fileout, "            normal %f %f %f\n",
07351           vertex_normal[0][ivert][iface],
07352           vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
07353         fprintf ( fileout, "            uvTexture  %f %f\n",
07354           vertex_tex_uv[0][ivert][iface], vertex_tex_uv[1][ivert][iface] );
07355         fprintf ( fileout, "            vertexColor  255 178 178 178\n" );
07356         text_num = text_num + 4;
07357       }
07358       fprintf ( fileout, "      }\n" );
07359       fprintf ( fileout, "      material %d\n", face_material[iface] );
07360       text_num = text_num + 2;
07361     }
07362     fprintf ( fileout, "    }\n" );
07363     fprintf ( fileout, "  }\n" );
07364     text_num = text_num + 2;
07365   }
07366 //
07367 //  IndexedLineSet.
07368 //
07369   if ( 0 < line_num )
07370   {
07371     nseg = 0;
07372 
07373     jhi = -1;
07374 
07375     for ( ;; )
07376     {
07377       jlo = jhi + 1;
07378 //
07379 //  Look for the next index JLO that is not -1.
07380 //
07381       while ( jlo < line_num )
07382       {
07383         if ( line_dex[jlo] != -1 )
07384         {
07385           break;
07386         }
07387         jlo = jlo + 1;
07388       }
07389 
07390       if ( line_num <= jlo )
07391       {
07392         break;
07393       }
07394 //
07395 //  Look for the highest following index JHI that is not -1.
07396 //
07397       jhi = jlo + 1;
07398 
07399       while ( jhi < line_num )
07400       {
07401         if ( line_dex[jhi] == -1 )
07402         {
07403           break;
07404         }
07405         jhi = jhi + 1;
07406       }
07407 
07408       jhi = jhi - 1;
07409 //
07410 //  Our next line segment involves LINE_DEX indices JLO through JHI.
07411 //
07412       nseg = nseg + 1;
07413       npts = jhi + 1 - jlo;
07414 
07415       fprintf ( fileout, "\n" );
07416       fprintf ( fileout, "  spline\n" );
07417       fprintf ( fileout, "  {\n" );
07418       fprintf ( fileout, "    name     \"spl%d\"\n", nseg );
07419       fprintf ( fileout, "    type     LINEAR\n" );
07420       fprintf ( fileout, "    nbKeys   %d\n", npts );
07421       fprintf ( fileout, "    tension  0.000\n" );
07422       fprintf ( fileout, "    step     1\n" );
07423       fprintf ( fileout, "\n" );
07424       text_num = text_num + 9;
07425 
07426       fprintf ( fileout, "    controlpoints\n" );
07427       fprintf ( fileout, "    {\n" );
07428       text_num = text_num + 2;
07429 
07430       for ( j = jlo; j <= jhi; j++ )
07431       {
07432         jrel = j - jlo;
07433         k = line_dex[j];
07434         fprintf ( fileout, "      [%d] position %f %f %f\n", jrel,
07435           cor3[0][k], cor3[1][k], cor3[2][k] );
07436         text_num = text_num + 1;
07437       }
07438 
07439       fprintf ( fileout, "    }\n" );
07440       fprintf ( fileout, "  }\n" );
07441       text_num = text_num + 2;
07442     }
07443   }
07444 //
07445 //  MATERIALS
07446 //
07447   for ( i = 0; i < material_num; i++ )
07448   {
07449     fprintf ( fileout, "  material [%d]\n", i );
07450     fprintf ( fileout, "  {\n" );
07451     fprintf ( fileout, "    name           \"%s\"\n", material_name[i] );
07452     fprintf ( fileout, "    type           PHONG\n" );
07453     fprintf ( fileout, "    ambient        %f %f %f\n", material_rgba[0][i],
07454       material_rgba[1][i], material_rgba[2][i] );
07455     fprintf ( fileout, "    diffuse        %f %f %f\n", material_rgba[0][i],
07456       material_rgba[1][i], material_rgba[2][i] );
07457     fprintf ( fileout, "    specular       %f %f %f\n", material_rgba[0][i],
07458       material_rgba[1][i], material_rgba[2][i] );
07459     fprintf ( fileout, "    exponent      50.0\n" );
07460     fprintf ( fileout, "    reflectivity   0.0\n" );
07461     fprintf ( fileout, "    transparency   %f\n", 1.0 - material_rgba[3][i] );
07462     fprintf ( fileout, "    refracIndex    1.0\n" );
07463     fprintf ( fileout, "    glow           0\n" );
07464     fprintf ( fileout, "    coc            0.0\n" );
07465     fprintf ( fileout, "  }\n" );
07466 
07467     text_num = text_num + 14;
07468 
07469   }
07470 //
07471 //  TEXTURES
07472 //
07473   for ( i = 0; i < texture_num; i++ )
07474   {
07475     fprintf ( fileout, "  texture [%d]\n", i );
07476     fprintf ( fileout, "  {\n" );
07477     fprintf ( fileout, "    name           \"%s\"\n", texture_name[i] );
07478     fprintf ( fileout, "    glbname        \"t2d1\"\n" );
07479     fprintf ( fileout, "    anim           STATIC\n" );
07480     fprintf ( fileout, "    method         XY\n" );
07481     fprintf ( fileout, "    repeat         1 1\n" );
07482     fprintf ( fileout, "    scaling        1.000  1.000\n" );
07483     fprintf ( fileout, "    offset         0.000  0.000\n" );
07484     fprintf ( fileout, "    pixelInterp\n" );
07485     fprintf ( fileout, "    effect         INTENSITY\n" );
07486     fprintf ( fileout, "    blending       1.000\n" );
07487     fprintf ( fileout, "    ambient        0.977\n" );
07488     fprintf ( fileout, "    diffuse        1.000\n" );
07489     fprintf ( fileout, "    specular       0.966\n" );
07490     fprintf ( fileout, "    reflect        0.000\n" );
07491     fprintf ( fileout, "    transp         0.000\n" );
07492     fprintf ( fileout, "    roughness      0.000\n" );
07493     fprintf ( fileout, "    reflMap        1.000\n" );
07494     fprintf ( fileout, "    rotation       0.000\n" );
07495     fprintf ( fileout, "    txtsup_rot     0.000  0.000  0.000\n" );
07496     fprintf ( fileout, "    txtsup_trans   0.000  0.000  0.000\n" );
07497     fprintf ( fileout, "    txtsup_scal    1.000  1.000  1.000\n" );
07498     fprintf ( fileout, "  }\n" );
07499 
07500     text_num = text_num + 25;
07501 
07502   }
07503   fprintf ( fileout, "}\n" );
07504   text_num = text_num + 1;
07505 //
07506 //  Report.
07507 //
07508   cout << "\n";
07509   cout << "HRC_WRITE - Wrote " << text_num << " text lines.\n";
07510 
07511   return 0;
07512 }
07513 //****************************************************************************80
07514 
07515 int i4_max ( int i1, int i2 )
07516 
07517 //****************************************************************************80
07518 //
07519 //  Purpose:
07520 //
07521 //    I4_MAX returns the maximum of two I4s.
07522 //
07523 //  Licensing:
07524 //
07525 //    This code is distributed under the GNU LGPL license.
07526 //
07527 //  Modified:
07528 //
07529 //    13 October 1998
07530 //
07531 //  Author:
07532 //
07533 //    John Burkardt
07534 //
07535 //  Parameters:
07536 //
07537 //    Input, int I1, I2, are two integers to be compared.
07538 //
07539 //    Output, int I4_MAX, the larger of I1 and I2.
07540 //
07541 {
07542   if ( i2 < i1 )
07543   {
07544     return i1;
07545   }
07546   else
07547   {
07548     return i2;
07549   }
07550 
07551 }
07552 //****************************************************************************80
07553 
07554 int i4_min ( int i1, int i2 )
07555 
07556 //****************************************************************************80
07557 //
07558 //  Purpose:
07559 //
07560 //    I4_MIN returns the smaller of two I4's.
07561 //
07562 //  Licensing:
07563 //
07564 //    This code is distributed under the GNU LGPL license.
07565 //
07566 //  Modified:
07567 //
07568 //    13 October 1998
07569 //
07570 //  Author:
07571 //
07572 //    John Burkardt
07573 //
07574 //  Parameters:
07575 //
07576 //    Input, int I1, I2, two integers to be compared.
07577 //
07578 //    Output, int I4_MIN, the smaller of I1 and I2.
07579 //
07580 {
07581   if ( i1 < i2 )
07582   {
07583     return i1;
07584   }
07585   else
07586   {
07587     return i2;
07588   }
07589 
07590 }
07591 //****************************************************************************80
07592 
07593 int i4_modp ( int i, int j )
07594 
07595 //****************************************************************************80
07596 //
07597 //  Purpose:
07598 //
07599 //    I4_MODP returns the nonnegative remainder of I4 division.
07600 //
07601 //  Discussion:
07602 //
07603 //    If
07604 //      NREM = I4_MODP ( I, J )
07605 //      NMULT = ( I - NREM ) / J
07606 //    then
07607 //      I = J * NMULT + NREM
07608 //    where NREM is always nonnegative.
07609 //
07610 //    The MOD function computes a result with the same sign as the
07611 //    quantity being divided.  Thus, suppose you had an angle A,
07612 //    and you wanted to ensure that it was between 0 and 360.
07613 //    Then mod(A,360) would do, if A was positive, but if A
07614 //    was negative, your result would be between -360 and 0.
07615 //
07616 //    On the other hand, I4_MODP(A,360) is between 0 and 360, always.
07617 //
07618 //  Example:
07619 //
07620 //        I         J     MOD  I4_MODP   I4_MODP Factorization
07621 //
07622 //      107        50       7       7    107 =  2 *  50 + 7
07623 //      107       -50       7       7    107 = -2 * -50 + 7
07624 //     -107        50      -7      43   -107 = -3 *  50 + 43
07625 //     -107       -50      -7      43   -107 =  3 * -50 + 43
07626 //
07627 //  Licensing:
07628 //
07629 //    This code is distributed under the GNU LGPL license.
07630 //
07631 //  Modified:
07632 //
07633 //    26 May 1999
07634 //
07635 //  Author:
07636 //
07637 //    John Burkardt
07638 //
07639 //  Parameters:
07640 //
07641 //    Input, int I, the number to be divided.
07642 //
07643 //    Input, int J, the number that divides I.
07644 //
07645 //    Output, int I4_MODP, the nonnegative remainder when I is
07646 //    divided by J.
07647 //
07648 {
07649   int value;
07650 
07651   if ( j == 0 )
07652   {
07653     cout << "\n";
07654     cout << "I4_MODP - Fatal error!\n";
07655     cout << "  I4_MODP ( I, J ) called with J = " << j << "\n";
07656     exit ( 1 );
07657   }
07658 
07659   value = i % j;
07660 
07661   if ( value < 0 )
07662   {
07663     value = value + abs ( j );
07664   }
07665 
07666   return value;
07667 }
07668 //****************************************************************************80
07669 
07670 int i4_wrap ( int ival, int ilo, int ihi )
07671 
07672 //****************************************************************************80
07673 //
07674 //  Purpose:
07675 //
07676 //    I4_WRAP forces an I4 to lie between given limits by wrapping.
07677 //
07678 //  Example:
07679 //
07680 //    ILO = 4, IHI = 8
07681 //
07682 //    I  I4_WRAP
07683 //
07684 //    -2     8
07685 //    -1     4
07686 //     0     5
07687 //     1     6
07688 //     2     7
07689 //     3     8
07690 //     4     4
07691 //     5     5
07692 //     6     6
07693 //     7     7
07694 //     8     8
07695 //     9     4
07696 //    10     5
07697 //    11     6
07698 //    12     7
07699 //    13     8
07700 //    14     4
07701 //
07702 //  Licensing:
07703 //
07704 //    This code is distributed under the GNU LGPL license.
07705 //
07706 //  Modified:
07707 //
07708 //    19 August 2003
07709 //
07710 //  Author:
07711 //
07712 //    John Burkardt
07713 //
07714 //  Parameters:
07715 //
07716 //    Input, int IVAL, an integer value.
07717 //
07718 //    Input, int ILO, IHI, the desired bounds for the integer value.
07719 //
07720 //    Output, int I4_WRAP, a "wrapped" version of IVAL.
07721 //
07722 {
07723   int jhi;
07724   int jlo;
07725   int value;
07726   int wide;
07727 
07728   jlo = i4_min ( ilo, ihi );
07729   jhi = i4_max ( ilo, ihi );
07730 
07731   wide = jhi + 1 - jlo;
07732 
07733   if ( wide == 1 )
07734   {
07735     value = jlo;
07736   }
07737   else
07738   {
07739     value = jlo + i4_modp ( ival - jlo, wide );
07740   }
07741 
07742   return value;
07743 }
07744 //****************************************************************************80
07745 
07746 void init_program_data ( )
07747 
07748 //****************************************************************************80
07749 //
07750 //  Purpose:
07751 //
07752 //    INIT_PROGRAM_DATA initializes the internal program data.
07753 //
07754 //  Licensing:
07755 //
07756 //    This code is distributed under the GNU LGPL license.
07757 //
07758 //  Modified:
07759 //
07760 //    26 May 1999
07761 //
07762 //  Author:
07763 //
07764 //    John Burkardt
07765 //
07766 {
07767   byte_swap = false;
07768   debug = false;
07769   line_prune = 1;
07770   color_num = 0;
07771   cor3_num = 0;
07772   face_num = 0;
07773   line_num = 0;
07774 
07775   if ( debug )
07776   {
07777     cout << "\n";
07778     cout << "INIT_PROGRAM_DATA: Program data initialized.\n";
07779   }
07780 
07781   return;
07782 
07783 }
07784 //****************************************************************************80
07785 
07786 int interact ( )
07787 
07788 //****************************************************************************80
07789 //
07790 //  Purpose:
07791 //
07792 //    INTERACT carries on an interactive session with the user.
07793 //
07794 //  Licensing:
07795 //
07796 //    This code is distributed under the GNU LGPL license.
07797 //
07798 //  Modified:
07799 //
07800 //    09 May 2005
07801 //
07802 //  Author:
07803 //
07804 //    John Burkardt
07805 //
07806 {
07807   int i;
07808   int icor3;
07809   int ierror;
07810   int iface;
07811   int itemp;
07812   int ivert;
07813   int j;
07814   int jvert;
07815   int m;
07816   char *next;
07817   bool success;
07818   float temp;
07819   float x;
07820   float y;
07821   float z;
07822 
07823   strcpy ( filein_name, "NO_IN_NAME" );
07824   strcpy ( fileout_name, "NO_OUT_NAME" );
07825 //
07826 //  Say hello.
07827 //
07828   hello ( );
07829 //
07830 //  Get the next user command.
07831 //
07832   cout << "\n";
07833   cout << "Enter command (H for help)\n";
07834 
07835   while ( fgets ( input, LINE_MAX_LEN, stdin ) != NULL )
07836   {
07837 //
07838 //  Advance to the first nonspace character in INPUT.
07839 //
07840     for ( next = input; *next != '\0' && ch_is_space ( *next ); next++ )
07841     {
07842     }
07843 //
07844 //  Skip blank lines and comments.
07845 //
07846     if ( *next == '\0' )
07847     {
07848       continue;
07849     }
07850 //
07851 //  Command: << FILENAME
07852 //  Append new data to current graphics information.
07853 //
07854     if ( *next == '<' && *(next+1) == '<' )
07855     {
07856       next = next + 2;
07857       sscanf ( next, "%s", filein_name );
07858 
07859       success = data_read ( );
07860 
07861       if ( !success )
07862       {
07863         cout << "\n";
07864         cout << "INTERACT - Fatal error!\n";
07865         cout << "  Failure reported from DATA_READ.\n";
07866       }
07867     }
07868 //
07869 //  Command: < FILENAME
07870 //
07871     else if ( *next == '<' )
07872     {
07873       next = next + 1;
07874       sscanf ( next, "%s", filein_name );
07875 
07876       data_init ( );
07877 
07878       success = data_read ( );
07879 
07880       if ( !success )
07881       {
07882         cout << "\n";
07883         cout << "INTERACT - Fatal error!\n";
07884         cout << "  DATA_READ failed to read input data.\n";
07885       }
07886     }
07887 //
07888 //  Command: > FILENAME
07889 //
07890     else if ( *next == '>' )
07891     {
07892       next = next + 1;
07893       sscanf ( next, "%s", fileout_name );
07894 
07895       ierror = data_write ( );
07896 
07897       if ( ierror == ERROR )
07898       {
07899         cout << "\n";
07900         cout << "INTERACT - Fatal error!\n";
07901         cout << "  OUTPUT_DATA failed to write output data.\n";
07902       }
07903 
07904     }
07905 //
07906 //  B: Switch byte swapping option.
07907 //
07908     else if ( *next == 'B' || *next == 'b' )
07909     {
07910       if ( byte_swap )
07911       {
07912         byte_swap = false;
07913         cout << "Byte_swapping reset to FALSE.\n";
07914       }
07915       else
07916       {
07917         byte_swap = true;
07918         cout << "Byte_swapping reset to TRUE.\n";
07919       }
07920 
07921     }
07922 //
07923 //  D: Switch debug option.
07924 //
07925     else if ( *next == 'D' || *next == 'd' )
07926     {
07927       if ( debug )
07928       {
07929         debug = false;
07930         cout << "Debug reset to FALSE.\n";
07931       }
07932       else
07933       {
07934         debug = true;
07935         cout << "Debug reset to TRUE.\n";
07936       }
07937     }
07938 //
07939 //  F: Check a face.
07940 //
07941     else if ( *next == 'f' || *next == 'F' )
07942     {
07943       cout << "\n";
07944       cout << "  Enter a face index between 0 and " << face_num-1 << "\n";
07945       scanf ( "%d", &iface );
07946       face_print ( iface );
07947     }
07948 //
07949 //  H: Help
07950 //
07951     else if ( *next == 'h' || *next == 'H' )
07952     {
07953       help ( );
07954     }
07955 //
07956 //  I: Print change information.
07957 //
07958     else if ( *next == 'i' || *next == 'I')
07959     {
07960       news ( );
07961     }
07962 //
07963 //  LINES:
07964 //  Convert face information to lines.
07965 //
07966     else if ( *next == 'l' || *next == 'L')
07967     {
07968       if ( 0 < face_num )
07969       {
07970         cout << "\n";
07971         cout << "INTERACT - Note:\n";
07972         cout << "  Face information will be converted\n";
07973         cout << "  to line information.\n";
07974 
07975           face_to_line ( );
07976 
07977           if ( LINES_MAX < line_num )
07978           {
07979             cout << "\n";
07980             cout << "INTERACT - Note:\n";
07981             cout << "  Some face information was lost.\n";
07982             cout << "  The maximum number of lines is " << LINES_MAX << "\n";
07983             cout << "  but we would need at least " << line_num << ".\n";
07984 
07985             line_num = LINES_MAX;
07986 
07987           }
07988 
07989           face_num = 0;
07990       }
07991       else
07992       {
07993         cout << "\n";
07994         cout << "INTERACT - Note:\n";
07995         cout << "  There were no faces to convert.\n";
07996 
07997       }
07998 
07999     }
08000 //
08001 //  N: Recompute normal vectors.
08002 //
08003     else if ( *next == 'n' || *next == 'N' )
08004     {
08005       for ( iface = 0; iface < face_num; iface++ )
08006       {
08007         for ( i = 0; i < 3; i++ )
08008         {
08009           face_normal[i][iface] = 0.0;
08010         }
08011       }
08012 
08013       for ( iface = 0; iface < face_num; iface++ )
08014       {
08015          for ( ivert = 0; ivert < face_order[iface]; ivert++ )
08016          {
08017           for ( i = 0; i < 3; i++ )
08018           {
08019             vertex_normal[i][ivert][iface] = 0.0;
08020           }
08021         }
08022       }
08023 
08024       vertex_normal_set ( );
08025 
08026       cor3_normal_set ( );
08027 
08028       face_normal_ave ( );
08029     }
08030 //
08031 //  P: Line pruning optiont
08032 //
08033     else if ( *next == 'p' || *next == 'P' )
08034     {
08035       cout << "\n";
08036       cout << "INTERACT - SET LINE PRUNING OPTION.\n";
08037       cout << "\n";
08038       cout << "  LINE_PRUNE = 0 means no line pruning.\n";
08039       cout << "               nonzero means line pruning.\n";
08040       cout << "\n";
08041       cout << "  Current value is LINE_PRUNE = " << line_prune << ".\n";
08042       cout << "\n";
08043       cout << "  Enter new value for LINE_PRUNE.\n";
08044 
08045       if ( fgets ( input, LINE_MAX_LEN, stdin ) == NULL )
08046       {
08047         cout << "  ??? Error trying to read input.\n" ;
08048       }
08049       else
08050       {
08051         sscanf ( input, "%d", &line_prune );
08052         cout << "  New value is LINE_PRUNE = " << line_prune << ".\n";
08053       }
08054     }
08055 //
08056 //  Q: Quit
08057 //
08058     else if ( *next == 'q' || *next == 'Q' )
08059     {
08060       cout << "\n";
08061       cout << "INTERACT - Normal end of execution.\n";
08062       return 0;
08063     }
08064 //
08065 //  R: Reverse normal vectors.
08066 //
08067     else if ( *next == 'r' || *next == 'R' )
08068     {
08069       for ( icor3 = 0; icor3 < cor3_num; icor3++ )
08070       {
08071         for ( i = 0; i < 3; i++ )
08072         {
08073           cor3_normal[i][icor3] = - cor3_normal[i][icor3];
08074         }
08075       }
08076 
08077       for ( iface = 0; iface < face_num; iface++ )
08078       {
08079         for ( i = 0; i < 3; i++ )
08080         {
08081           face_normal[i][iface] = - face_normal[i][iface];
08082         }
08083       }
08084 
08085       for ( iface = 0; iface < face_num; iface++ )
08086       {
08087         for ( ivert = 0; ivert < face_order[iface]; ivert++ )
08088         {
08089           for ( i = 0; i < 3; i++ )
08090           {
08091             vertex_normal[i][ivert][iface] =
08092               - vertex_normal[i][ivert][iface];
08093           }
08094         }
08095       }
08096       cout << "\n";
08097       cout << "INTERACT - Note:\n";
08098       cout << "  Reversed node, face and vertex normals.\n";
08099     }
08100 //
08101 //  S: Select a few faces, discard the rest.
08102 //
08103     else if ( *next == 's' || *next == 'S' )
08104     {
08105       face_subset ( );
08106     }
08107 //
08108 //  T: Transform the data.
08109 //
08110     else if ( *next == 't' || *next == 'T' )
08111     {
08112       cout << "\n";
08113       cout << "For now, we only offer point scaling.\n";
08114       cout << "Enter X, Y, Z scale factors:\n";
08115 
08116       scanf ( "%f %f %f", &x, &y, &z );
08117 
08118       for ( j = 0; j < cor3_num; j++ )
08119       {
08120         cor3[0][j] = x * cor3[0][j];
08121         cor3[1][j] = y * cor3[1][j];
08122         cor3[2][j] = z * cor3[2][j];
08123       }
08124 
08125       for ( iface = 0; iface < face_num; iface++ )
08126       {
08127         for ( i = 0; i < 3; i++ )
08128         {
08129           face_normal[i][iface] = 0.0;
08130         }
08131       }
08132 
08133       for ( iface = 0; iface < face_num; iface++ )
08134       {
08135          for ( ivert = 0; ivert < face_order[iface]; ivert++ )
08136          {
08137           for ( i = 0; i < 3; i++ )
08138           {
08139             vertex_normal[i][ivert][iface] = 0.0;
08140           }
08141         }
08142       }
08143 
08144       vertex_normal_set ( );
08145 
08146       cor3_normal_set ( );
08147 
08148       face_normal_ave ( );
08149     }
08150 //
08151 //  U: Renumber faces, count objects:
08152 //
08153     else if ( *next == 'u' || *next == 'U' )
08154     {
08155     }
08156 //
08157 //  V: Convert polygons to triangles:
08158 //
08159     else if ( *next == 'v' || *next == 'V' )
08160     {
08161     }
08162 //
08163 //  W: Reverse the face node ordering.
08164 //
08165     else if ( *next == 'w' || *next == 'W' )
08166     {
08167       if ( 0 < face_num )
08168       {
08169         for ( iface = 0; iface < face_num; iface++ )
08170         {
08171           m = face_order[iface];
08172 
08173           for ( ivert = 0; ivert < m/2; ivert++ )
08174           {
08175             jvert = m - ivert - 1;
08176 
08177             itemp = face[ivert][iface];
08178             face[ivert][iface] = face[jvert][iface];
08179             face[jvert][iface] = itemp;
08180 
08181             itemp = vertex_material[ivert][iface];
08182             vertex_material[ivert][iface] = vertex_material[jvert][iface];
08183             vertex_material[jvert][iface] = itemp;
08184 
08185             for ( i = 0; i < 3; i++ )
08186             {
08187               temp = vertex_normal[i][ivert][iface];
08188               vertex_normal[i][ivert][iface] =
08189                 vertex_normal[i][jvert][iface];
08190               vertex_normal[i][jvert][iface] = temp;
08191             }
08192           }
08193         }
08194         cout << "\n";
08195         cout << "INTERACT - Note:\n";
08196         cout << "  Reversed face node ordering.\n";
08197       }
08198     }
08199 //
08200 //  Command: ???
08201 //
08202     else
08203     {
08204       cout << "\n";
08205       cout << "INTERACT: Warning!\n";
08206       cout << "  Your command was not recognized.\n";
08207     }
08208 
08209     cout << "\n";
08210     cout << "Enter command (H for help)\n";
08211 
08212   }
08213   return 0;
08214 }
08215 //****************************************************************************80
08216 
08217 int iv_read ( FILE *filein )
08218 
08219 //****************************************************************************80
08220 //
08221 //  Purpose:
08222 //
08223 //    IV_READ reads graphics information from an Inventor file.
08224 //
08225 //  Example:
08226 //
08227 //     #Inventor V2.0 ascii
08228 //
08229 //     Separator {
08230 //       Info {
08231 //         string "Inventor file generated by IVCON.
08232 //         Original data in file cube.iv."
08233 //       }
08234 //       Separator {
08235 //         LightModel {
08236 //           model PHONG
08237 //         }
08238 //         MatrixTransform { matrix
08239 //           0.9  0.0  0.0  0.0
08240 //           0.0 -0.9  0.0  0.0
08241 //           0.0  0.0 -1.5  0.0
08242 //           0.0  0.0  0.0  1.0
08243 //         }
08244 //         Material {
08245 //           ambientColor  0.2 0.2 0.2
08246 //           diffuseColor  [
08247 //             0.8 0.8 0.8,
08248 //             0.7 0.1 0.1,
08249 //             0.1 0.8 0.2,
08250 //           ]
08251 //           emissiveColor 0.0 0.0 0.0
08252 //           specularColor 0.0 0.0 0.0
08253 //           shininess     0.2
08254 //           transparency  [
08255 //             0.0, 0.5, 1.0,
08256 //           ]
08257 //         }
08258 //         Texture2 {
08259 //           filename      "fred.rgb"
08260 //           wrapS         REPEAT
08261 //           wrapT         REPEAT
08262 //           model         MODULATE
08263 //           blendColor    0.0 0.0 0.0
08264 //         }
08265 //
08266 //         MaterialBinding {
08267 //           value PER_VERTEX_INDEXED
08268 //         }
08269 //         NormalBinding {
08270 //           value PER_VERTEX_INDEXED
08271 //         }
08272 //         TextureCoordinateBinding {
08273 //           value PER_VERTEX_INDEXED
08274 //         }
08275 //
08276 //         ShapeHints {
08277 //           vertexOrdering COUNTERCLOCKWISE
08278 //           shapeType UNKNOWN_SHAPE_TYPE
08279 //           faceType CONVEX
08280 //           creaseAngle 6.28319
08281 //         }
08282 //
08283 //         Coordinate3 {
08284 //           point [
08285 //                8.59816       5.55317      -3.05561,
08286 //                8.59816       2.49756      0.000000E+00,
08287 //                ...etc...
08288 //                2.48695       2.49756      -3.05561,
08289 //           ]
08290 //         }
08291 //
08292 //         Normal {
08293 //           vector [
08294 //             0.71 0.71 0.0,
08295 //             ...etc...
08296 //             0.32 0.32 0.41,
08297 //           ]
08298 //         }
08299 //
08300 //         TextureCoordinate2 {
08301 //           point [
08302 //                0.0  1.0,
08303 //                0.1, 0.8,
08304 //                ...etc...
08305 //                0.4  0.7,
08306 //           ]
08307 //         }
08308 //
08309 //         IndexedLineSet {
08310 //           coordIndex [
08311 //              0,    1,    2,   -1,
08312 //              3,    4,    5,   -1,
08313 //              7,    8,    9,   -1,
08314 //            ...etc...
08315 //            189,  190,  191,   -1,
08316 //           ]
08317 //           materialIndex [
08318 //              0,    0,    0,   -1,
08319 //              1,    1,    1,   -1,
08320 //              2,    2,    2,   -1,
08321 //            ...etc...
08322 //             64,   64,   64,   -1,
08323 //           ]
08324 //         }
08325 //
08326 //         IndexedFaceSet {
08327 //           coordIndex [
08328 //              0,    1,    2,   -1,
08329 //              3,    4,    5,   -1,
08330 //              7,    8,    9,   -1,
08331 //            ...etc...
08332 //            189,  190,  191,   -1,
08333 //           ]
08334 //           materialIndex [
08335 //              0,    0,    0,   -1,
08336 //              1,    1,    1,   -1,
08337 //              2,    2,    2,   -1,
08338 //            ...etc...
08339 //             64,   64,   64,   -1,
08340 //           ]
08341 //           normalIndex [
08342 //              0,    0,    0,   -1,
08343 //              1,    1,    1,   -1,
08344 //              2,    2,    2,   -1,
08345 //            ...etc...
08346 //             64,   64,   64,   -1,
08347 //           ]
08348 //           textureCoordIndex [
08349 //              0,    0,    0,   -1,
08350 //              1,    1,    1,   -1,
08351 //              2,    2,    2,   -1,
08352 //            ...etc...
08353 //             64,   64,   64,   -1,
08354 //           ]
08355 //         }
08356 //
08357 //         IndexedTriangleStripSet {
08358 //           vertexProperty VertexProperty {
08359 //             vertex [ x y z,
08360 //                      ...
08361 //                      x y z ]
08362 //             normal [ x y z,
08363 //                      ...
08364 //                      x y z ]
08365 //             materialBinding OVERALL
08366 //             normalBinding PER_VERTEX_INDEXED
08367 //           }
08368 //           coordIndex [
08369 //             i, j, k, l, m, -1,
08370 //             n, o, p, q, r, s, t, u, -1,
08371 //             v, w, x, -1
08372 //                 ..., -1 ]
08373 //           normalIndex -1
08374 //         }
08375 //
08376 //       }
08377 //     }
08378 //
08379 //  Licensing:
08380 //
08381 //    This code is distributed under the GNU LGPL license.
08382 //
08383 //  Modified:
08384 //
08385 //    01 July 1999
08386 //
08387 //  Author:
08388 //
08389 //    John Burkardt
08390 //
08391 {
08392   char  c;
08393   int   count;
08394   int   i;
08395   int   icol;
08396   int   icolor;
08397   int   icface;
08398   int   inormface;
08399   int   iface_num;
08400   int   irow;
08401   int   iuv;
08402   int   ivert;
08403   int   iword;
08404   int   ix;
08405   int   ixyz;
08406   int   iy;
08407   int   iz;
08408   int   j;
08409   int   jval;
08410   int   level;
08411   char *next;
08412   int   nlbrack;
08413   int   nrbrack;
08414   int   nu;
08415   int   null_index;
08416   int   cor3_num_old;
08417   int   line_num2;
08418   int   face_num2;
08419   int   normal_num_temp;
08420   int   text_numure_temp;
08421   int   nv;
08422   int   result;
08423   float rval;
08424   int   width;
08425   char  word[LINE_MAX_LEN];
08426   char  word1[LINE_MAX_LEN];
08427   char  wordm1[LINE_MAX_LEN];
08428   float xvec[3];
08429 
08430   icface = 0;
08431   icol = -1;
08432   inormface = 0;
08433   iface_num = face_num;
08434   irow = 0;
08435   ix = 0;
08436   ixyz = 0;
08437   iy = 0;
08438   iz = 0;
08439   jval = 0;
08440   level = 0;
08441   strcpy ( level_name[0], "Top" );
08442   nlbrack = 0;
08443   nrbrack = 0;
08444   nu = 0;
08445   cor3_num_old = cor3_num;
08446   face_num2 = face_num;
08447   line_num2 = line_num;
08448   normal_num_temp = 0;
08449   text_numure_temp = 0;
08450   nv = 0;
08451   rval = 0.0;
08452   strcpy ( word, " " );
08453   strcpy ( wordm1, " " );
08454 //
08455 //  Read the next line of text from the input file.
08456 //
08457   for ( ;; )
08458   {
08459     if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
08460     {
08461       break;
08462     }
08463 
08464     text_num = text_num + 1;
08465     next = input;
08466     iword = 0;
08467 //
08468 //  Remove all commas from the line, so we can use SSCANF to read
08469 //  numeric items.
08470 //
08471     i = 0;
08472     while ( input[i] != '\0' )
08473     {
08474       if ( input[i] == ',' )
08475       {
08476         input[i] = ' ';
08477       }
08478       i++;
08479     }
08480 //
08481 //  Force brackets and braces to be buffered by spaces.
08482 //
08483     i = 0;
08484     while ( input[i] != '\0' )
08485     {
08486       i++;
08487     }
08488     null_index = i;
08489 
08490     i = 0;
08491     while ( input[i] != '\0' && i < LINE_MAX_LEN )
08492     {
08493       if ( input[i] == '[' || input[i] == ']' ||
08494            input[i] == '{' || input[i] == '}' )
08495       {
08496         result = ch_pad ( &i, &null_index, input, LINE_MAX_LEN );
08497         if ( result == ERROR )
08498         {
08499           break;
08500         }
08501       }
08502       else
08503       {
08504         i++;
08505       }
08506     }
08507 //
08508 //  Read a word from the line.
08509 //
08510     for ( ;; )
08511     {
08512       strcpy ( wordm1, word );
08513       strcpy ( word, " " );
08514 
08515       count = sscanf ( next, "%s%n", word, &width );
08516       next = next + width;
08517 
08518       if ( count <= 0 )
08519       {
08520         break;
08521       }
08522 
08523       iword = iword + 1;
08524 
08525       if ( iword == 1 )
08526       {
08527         strcpy ( word1, word );
08528       }
08529 //
08530 //  The first line of the file must be the header.
08531 //
08532       if ( text_num == 1 )
08533       {
08534         if ( !s_eqi ( word1, "#Inventor" ) )
08535         {
08536           cout << "\n";
08537           cout << "IV_READ - Fatal error!\n";
08538           cout << "  The input file has a bad header.\n";
08539           return 1;
08540         }
08541         else
08542         {
08543           comment_num = comment_num + 1;
08544         }
08545         break;
08546       }
08547 //
08548 //  A comment begins anywhere with '#'.
08549 //  Skip the rest of the line.
08550 //
08551       if ( word[1] == '#' )
08552       {
08553         comment_num = comment_num + 1;
08554         break;
08555       }
08556 //
08557 //  If the word is a curly or square bracket, count it.
08558 //  If the word is a left bracket, the previous word is the name of a node.
08559 //
08560       if ( strcmp ( word, "{" ) == 0 || strcmp ( word, "[" ) == 0 )
08561       {
08562         nlbrack = nlbrack + 1;
08563         level = nlbrack - nrbrack;
08564         strcpy ( level_name[level], wordm1 );
08565         if ( debug )
08566         {
08567           cout << "Begin level: " << wordm1 << "\n";
08568         }
08569       }
08570       else if ( strcmp ( word, "}" ) == 0 || strcmp ( word, "]" ) == 0 )
08571       {
08572         nrbrack = nrbrack + 1;
08573 
08574         if ( nlbrack < nrbrack )
08575         {
08576           cout << "\n";
08577           cout << "IV_READ - Fatal error!\n";
08578           cout << "  Extraneous right bracket on line " << text_num << ".\n";
08579           cout << "  Currently processing field " << level_name[level] << "\n";
08580           return 1;
08581         }
08582       }
08583 //
08584 //  BASECOLOR
08585 //
08586       if ( s_eqi ( level_name[level], "BASECOLOR" ) )
08587       {
08588         if ( strcmp ( word, "{" ) == 0 )
08589         {
08590         }
08591         else if ( strcmp ( word, "}" ) == 0 )
08592         {
08593           level = nlbrack - nrbrack;
08594         }
08595         else if ( s_eqi ( word, "RGB" ) )
08596         {
08597         }
08598         else
08599         {
08600           bad_num = bad_num + 1;
08601           cout << "Bad data " << word << "\n";
08602         }
08603       }
08604 //
08605 //  COORDINATE3
08606 //
08607       else if ( s_eqi ( level_name[level], "COORDINATE3" ) )
08608       {
08609         if ( strcmp ( word, "{" ) == 0 )
08610         {
08611         }
08612         else if ( strcmp ( word, "}" ) == 0 )
08613         {
08614           level = nlbrack - nrbrack;
08615         }
08616         else if ( s_eqi ( word, "POINT" ) )
08617         {
08618         }
08619         else
08620         {
08621           bad_num = bad_num + 1;
08622           cout << "COORDINATE3: Bad data " << word << "\n";
08623         }
08624       }
08625 //
08626 //  COORDINATE4
08627 //
08628       else if ( s_eqi ( level_name[level], "COORDINATE4" ) )
08629       {
08630         if ( strcmp ( word, "{" ) == 0 )
08631         {
08632         }
08633         else if ( strcmp ( word, "}" ) == 0 )
08634         {
08635           level = nlbrack - nrbrack;
08636         }
08637         else if ( s_eqi ( word, "POINT" ) )
08638         {
08639         }
08640         else
08641         {
08642           bad_num = bad_num + 1;
08643           cout << "COORDINATE4: Bad data " << word << "\n";
08644         }
08645       }
08646 //
08647 //  COORDINDEX
08648 //
08649       else if ( s_eqi ( level_name[level], "COORDINDEX" ) )
08650       {
08651         if ( strcmp ( word, "[" ) == 0 )
08652         {
08653           ivert = 0;
08654         }
08655         else if ( strcmp ( word, "]" ) == 0 )
08656         {
08657           level = nlbrack - nrbrack;
08658         }
08659 //
08660 //  (indexedlineset) COORDINDEX
08661 //
08662         else if ( s_eqi ( level_name[level-1], "INDEXEDLINESET" ) )
08663         {
08664 
08665           count = sscanf ( word, "%d%n", &jval, &width );
08666 
08667           if ( 0 < count )
08668           {
08669             if ( jval < -1 )
08670             {
08671               bad_num = bad_num + 1;
08672             }
08673             else
08674             {
08675               if ( line_num < LINES_MAX )
08676               {
08677                 if ( jval != -1 )
08678                 {
08679                   jval = jval + cor3_num_old;
08680                 }
08681                 line_dex[line_num] = jval;
08682               }
08683               line_num = line_num + 1;
08684             }
08685           }
08686           else
08687           {
08688             bad_num = bad_num + 1;
08689           }
08690         }
08691 //
08692 //  (indexedfaceset) COORDINDEX
08693 //  Warning: If the list of indices is not terminated with a final -1, then
08694 //  the last face won't get counted.
08695 //
08696         else if ( s_eqi ( level_name[level-1], "INDEXEDFACESET" ) )
08697         {
08698           count = sscanf ( word, "%d%n", &jval, &width );
08699 
08700           if ( 0 < count )
08701           {
08702             if ( jval == -1 )
08703             {
08704               ivert = 0;
08705               face_num = face_num + 1;
08706             }
08707             else
08708             {
08709               if ( ivert == 0 )
08710               {
08711                 if ( face_num < FACE_MAX )
08712                 {
08713                   face_order[face_num] = 0;
08714                 }
08715               }
08716               if ( face_num < FACE_MAX )
08717               {
08718                 face_order[face_num] = face_order[face_num] + 1;
08719                 face[ivert][face_num] = jval + cor3_num_old;
08720                 ivert = ivert + 1;
08721               }
08722             }
08723           }
08724         }
08725 //
08726 //  (indexednurbssurface) COORDINDEX
08727 //
08728         else if ( s_eqi ( level_name[level-1], "INDEXEDNURBSSURFACE" ) )
08729         {
08730         }
08731 //
08732 //  (indexedtrianglestripset) COORDINDEX
08733 //
08734 //  First three coordinate indices I1, I2, I3 define a triangle.
08735 //  Next triangle is defined by I2, I3, I4 (actually, I4, I3, I2
08736 //  to stay with same counterclockwise sense).
08737 //  Next triangle is defined by I3, I4, I5 ( do not need to reverse
08738 //  odd numbered triangles) and so on.
08739 //  List is terminated with -1.
08740 //
08741         else if ( s_eqi ( level_name[level-1], "INDEXEDTRIANGLESTRIPSET" ) )
08742         {
08743           count = sscanf ( word, "%d%n", &jval, &width );
08744 
08745           if ( 0 < count )
08746           {
08747             if ( jval == -1 )
08748             {
08749               ivert = 0;
08750             }
08751             else
08752             {
08753               ix = iy;
08754               iy = iz;
08755               iz = jval + cor3_num_old;
08756 
08757               if ( ivert == 0 )
08758               {
08759                 if ( face_num < FACE_MAX )
08760                 {
08761                   face[ivert][face_num] = jval + cor3_num_old;
08762                   face_order[face_num] = 3;
08763                 }
08764               }
08765               else if ( ivert == 1 )
08766               {
08767                 if ( face_num < FACE_MAX )
08768                 {
08769                   face[ivert][face_num] = jval + cor3_num_old;
08770                 }
08771               }
08772               else if ( ivert == 2 )
08773               {
08774                 if ( face_num < FACE_MAX )
08775                 {
08776                   face[ivert][face_num] = jval + cor3_num_old;
08777                 }
08778                 face_num = face_num + 1;
08779               }
08780               else
08781               {
08782                 if ( face_num < FACE_MAX )
08783                 {
08784                   face_order[face_num] = 3;
08785                   if ( ( ivert % 2 ) == 0 )
08786                   {
08787                     face[0][face_num] = ix;
08788                     face[1][face_num] = iy;
08789                     face[2][face_num] = iz;
08790                   }
08791                   else
08792                   {
08793                     face[0][face_num] = iz;
08794                     face[1][face_num] = iy;
08795                     face[2][face_num] = ix;
08796                   }
08797                 }
08798                 face_num = face_num + 1;
08799               }
08800               ivert = ivert + 1;
08801 //
08802 //  Very very tentative guess as to how indices into the normal
08803 //  vector array are set up...
08804 //
08805               if ( face_num < FACE_MAX && 2 < ivert )
08806               {
08807                 for ( i = 0; i < 3; i++ )
08808                 {
08809                   face_normal[i][face_num] = normal_temp[i][ix];
08810                 }
08811               }
08812             }
08813           }
08814         }
08815       }
08816 //
08817 //  INDEXEDFACESET
08818 //
08819       else if ( s_eqi ( level_name[level], "INDEXEDFACESET" ) )
08820       {
08821         if ( strcmp ( word, "{" ) == 0 )
08822         {
08823         }
08824         else if ( strcmp ( word, "}" ) == 0 )
08825         {
08826           level = nlbrack - nrbrack;
08827         }
08828         else if ( s_eqi ( word, "COORDINDEX" ) )
08829         {
08830           ivert = 0;
08831         }
08832         else if ( s_eqi ( word, "MATERIALINDEX" ) )
08833         {
08834         }
08835         else if ( s_eqi ( word, "NORMALINDEX" ) )
08836         {
08837         }
08838         else if ( s_eqi ( word, "TEXTURECOORDINDEX" ) )
08839         {
08840           if ( texture_num <= 0 )
08841           {
08842             texture_num = 1;
08843             strcpy ( texture_name[0], "Texture_0000" );
08844           }
08845         }
08846         else
08847         {
08848           bad_num = bad_num + 1;
08849           cout << "Bad data " << word << "\n";
08850         }
08851       }
08852 //
08853 //  INDEXEDLINESET
08854 //
08855       else if ( s_eqi ( level_name[level], "INDEXEDLINESET" ) )
08856       {
08857         if ( strcmp ( word, "{" ) == 0 )
08858         {
08859         }
08860         else if ( strcmp ( word, "}" ) == 0 )
08861         {
08862           level = nlbrack - nrbrack;
08863         }
08864         else if ( s_eqi ( word, "COORDINDEX" ) )
08865         {
08866         }
08867         else if ( s_eqi ( word, "MATERIALINDEX" ) )
08868         {
08869         }
08870         else
08871         {
08872           bad_num = bad_num + 1;
08873           cout << "Bad data " << word << "\n";
08874         }
08875       }
08876 //
08877 //  INDEXEDNURBSSURFACE
08878 //
08879       else if ( s_eqi ( level_name[level], "INDEXEDNURBSSURFACE" ) )
08880       {
08881         if ( strcmp ( word, "{" ) == 0 )
08882         {
08883         }
08884         else if ( strcmp ( word, "}" ) == 0 )
08885         {
08886           level = nlbrack - nrbrack;
08887         }
08888         else if ( s_eqi ( word, "NUMUCONTROLPOINTS" ) )
08889         {
08890           count = sscanf ( word, "%d%n", &jval, &width );
08891 
08892           if ( 0 < count )
08893           {
08894             nu = jval;
08895             if ( debug )
08896             {
08897               cout << "NU = " << nu << "\n";
08898             }
08899           }
08900           else
08901           {
08902             nu = 0;
08903             bad_num = bad_num + 1;
08904             cout << "Bad data " << word << "\n";
08905           }
08906         }
08907         else if ( s_eqi ( word, "NUMVCONTROLPOINTS" ) )
08908         {
08909           count = sscanf ( word, "%d%n", &jval, &width );
08910 
08911           if ( 0 < count )
08912           {
08913             nv = jval;
08914             if ( debug )
08915             {
08916               cout << "NV = " << nv << "\n";
08917             }
08918           }
08919           else
08920           {
08921             nv = 0;
08922             bad_num = bad_num + 1;
08923           }
08924         }
08925         else if ( s_eqi ( word, "COORDINDEX" ) )
08926         {
08927         }
08928         else if ( s_eqi ( word, "UKNOTVECTOR" ) )
08929         {
08930         }
08931         else if ( s_eqi ( word, "VKNOTVECTOR" ) )
08932         {
08933         }
08934         else
08935         {
08936           bad_num = bad_num + 1;
08937           cout << "Bad data " << word << "\n";
08938         }
08939       }
08940 //
08941 //  INDEXEDTRIANGLESTRIPSET
08942 //
08943       else if ( s_eqi ( level_name[level], "INDEXEDTRIANGLESTRIPSET" ) )
08944       {
08945         if ( strcmp ( word, "{" ) == 0 )
08946         {
08947         }
08948         else if ( strcmp ( word, "}" ) == 0 )
08949         {
08950           level = nlbrack - nrbrack;
08951         }
08952         else if ( s_eqi ( word, "VERTEXPROPERTY" ) )
08953         {
08954           count = sscanf ( next, "%s%n", word, &width );
08955           next = next + width;
08956         }
08957         else if ( s_eqi ( word, "COORDINDEX" ) )
08958         {
08959           ivert = 0;
08960         }
08961         else if ( s_eqi ( word, "NORMALINDEX" ) )
08962         {
08963           count = sscanf ( next, "%s%n", word, &width );
08964           next = next + width;
08965         }
08966         else
08967         {
08968           bad_num = bad_num + 1;
08969           cout << "Bad data " << word << "\n";
08970         }
08971       }
08972 //
08973 //  INFO
08974 //
08975       else if ( s_eqi ( level_name[level], "INFO" ) )
08976       {
08977         if ( strcmp ( word, "{" ) == 0 )
08978         {
08979         }
08980         else if ( strcmp ( word, "}" ) == 0 )
08981         {
08982           level = nlbrack - nrbrack;
08983         }
08984         else if ( s_eqi ( word, "STRING" ) )
08985         {
08986         }
08987         else if ( strcmp ( word, "\"" ) == 0 )
08988         {
08989         }
08990         else
08991         {
08992         }
08993       }
08994 //
08995 //  LIGHTMODEL
08996 //  Read, but ignore.
08997 //
08998       else if ( s_eqi ( level_name[level], "LIGHTMODEL" ) )
08999       {
09000         if ( strcmp ( word, "{" ) == 0 )
09001         {
09002         }
09003         else if ( strcmp ( word, "}" ) == 0 )
09004         {
09005           level = nlbrack - nrbrack;
09006         }
09007         else if ( s_eqi ( word, "model" ) )
09008         {
09009         }
09010         else
09011         {
09012         }
09013       }
09014 //
09015 //  MATERIAL
09016 //  Read, but ignore.
09017 //
09018       else if ( s_eqi ( level_name[level],"MATERIAL" ) )
09019       {
09020         if ( strcmp ( word, "{" ) == 0 )
09021         {
09022         }
09023         else if ( strcmp ( word, "}" ) == 0 )
09024         {
09025           level = nlbrack - nrbrack;
09026         }
09027         else if ( s_eqi ( word, "AMBIENTCOLOR" ) )
09028         {
09029         }
09030         else if ( s_eqi ( word, "EMISSIVECOLOR" ) )
09031         {
09032         }
09033         else if ( s_eqi ( word, "DIFFUSECOLOR" ) )
09034         {
09035         }
09036         else if ( s_eqi ( word, "SHININESS" ) )
09037         {
09038         }
09039         else if ( s_eqi ( word, "SPECULARCOLOR" ) )
09040         {
09041         }
09042         else if ( s_eqi ( word, "TRANSPARENCY" ) )
09043         {
09044         }
09045         else
09046         {
09047         }
09048       }
09049 //
09050 //  MATERIALBINDING
09051 //  Read, but ignore
09052 //
09053       else if ( s_eqi ( level_name[level], "MATERIALBINDING" ) )
09054       {
09055         if ( strcmp ( word, "{" ) == 0 )
09056         {
09057         }
09058         else if ( strcmp ( word, "}" ) == 0 )
09059         {
09060           level = nlbrack - nrbrack;
09061         }
09062         else if ( s_eqi ( word, "VALUE" ) )
09063         {
09064           count = sscanf ( next, "%s%n", material_binding, &width );
09065           next = next + width;
09066         }
09067         else
09068         {
09069           count = sscanf ( next, "%f%n", &rval, &width );
09070           next = next + width;
09071 
09072           if ( 0 < count )
09073           {
09074           }
09075           else
09076           {
09077             bad_num = bad_num + 1;
09078             cout << "Bad data " << word << "\n";
09079           }
09080         }
09081       }
09082 //
09083 //  MATERIALINDEX
09084 //
09085       else if ( s_eqi ( level_name[level], "MATERIALINDEX" ) )
09086       {
09087         if ( strcmp ( word, "[" ) == 0 )
09088         {
09089           ivert = 0;
09090         }
09091         else if ( strcmp ( word, "]" ) == 0 )
09092         {
09093           level = nlbrack - nrbrack;
09094         }
09095 //
09096 //  (indexedfaceset) MATERIALINDEX
09097 //
09098         else if ( s_eqi ( level_name[level-1], "INDEXEDFACESET" ) )
09099         {
09100           count = sscanf ( word, "%d%n", &jval, &width );
09101 
09102           if ( 0 < count )
09103           {
09104             if ( jval == -1 )
09105             {
09106               ivert = 0;
09107               face_num2 = face_num2 + 1;
09108             }
09109             else
09110             {
09111               if ( face_num2 < FACE_MAX )
09112               {
09113                 if ( jval != -1 )
09114                 {
09115                   jval = jval + cor3_num_old;
09116                 }
09117                 vertex_material[ivert][face_num2] = jval;
09118                 ivert = ivert + 1;
09119               }
09120             }
09121           }
09122           else
09123           {
09124             bad_num = bad_num + 1;
09125             cout << "Bad data " << word << "\n";
09126           }
09127         }
09128 //
09129 //  (indexedlineset) MATERIALINDEX
09130 //
09131         else if ( s_eqi ( level_name[level-1], "INDEXEDLINESET" ) )
09132         {
09133           count = sscanf ( word, "%d%n", &jval, &width );
09134 
09135           if ( 0 < count )
09136           {
09137             if ( line_num2 < LINES_MAX )
09138             {
09139               if ( jval != -1 )
09140               {
09141                 jval = jval + cor3_num_old;
09142               }
09143               line_material[line_num2] = jval;
09144               line_num2 = line_num2 + 1;
09145             }
09146           }
09147           else
09148           {
09149             bad_num = bad_num + 1;
09150             cout << "Bad data " << word << "\n";
09151           }
09152         }
09153         else
09154         {
09155           count = sscanf ( word, "%d%n", &jval, &width );
09156 
09157           if ( 0 < count )
09158           {
09159           }
09160           else
09161           {
09162             bad_num = bad_num + 1;
09163             cout << "Bad data " << word << "\n";
09164           }
09165         }
09166       }
09167 //
09168 //  MATRIXTRANSFORM.
09169 //
09170       else if ( s_eqi ( level_name[level], "MATRIXTRANSFORM" ) )
09171       {
09172         if ( strcmp ( word, "{" ) == 0 )
09173         {
09174         }
09175         else if ( strcmp ( word, "}" ) == 0 )
09176         {
09177           level = nlbrack - nrbrack;
09178         }
09179         else if ( s_eqi ( word, "MATRIX" ) )
09180         {
09181           icol = -1;
09182           irow = 0;
09183         }
09184         else
09185         {
09186           count = sscanf ( word, "%f%n", &rval, &width );
09187 
09188           if ( 0 < count )
09189           {
09190             icol = icol + 1;
09191             if ( 3 < icol )
09192             {
09193               icol = 0;
09194               irow = irow + 1;
09195               if ( 3 < irow )
09196               {
09197                 irow = 0;
09198               }
09199             }
09200 
09201             transform_matrix[irow][icol] = rval;
09202           }
09203 
09204         }
09205       }
09206 //
09207 //  NORMAL
09208 //  The field "VECTOR" may be followed by three numbers,
09209 //  (handled here),  or by a square bracket, and sets of three numbers.
09210 //
09211       else if ( s_eqi ( level_name[level], "NORMAL" ) )
09212       {
09213 //
09214 //  (vertexproperty) NORMAL
09215 //
09216         if ( s_eqi ( level_name[level-1], "VERTEXPROPERTY" ) )
09217         {
09218           if ( strcmp ( word, "[" ) == 0 )
09219           {
09220             ixyz = 0;
09221           }
09222           else if ( strcmp ( word, "]" ) == 0 )
09223           {
09224             level = nlbrack - nrbrack;
09225           }
09226           else
09227           {
09228 
09229             count = sscanf ( word, "%f%n", &rval, &width );
09230 
09231             if ( 0 < count )
09232             {
09233 
09234               if ( inormface < FACE_MAX )
09235               {
09236                 face_normal[ixyz][inormface] = rval;
09237               }
09238 
09239               ixyz = ixyz + 1;
09240               if ( 2 < ixyz )
09241               {
09242                 ixyz = 0;
09243                 inormface = inormface + 1;
09244               }
09245             }
09246           }
09247         }
09248 //
09249 //  (anythingelse) NORMAL
09250 //
09251         else
09252         {
09253           if ( strcmp ( word, "{" ) == 0 )
09254           {
09255             ixyz = 0;
09256           }
09257           else if ( strcmp ( word, "}" ) == 0 )
09258           {
09259             level = nlbrack - nrbrack;
09260           }
09261           else if ( s_eqi ( word, "VECTOR" ) )
09262           {
09263           }
09264           else
09265           {
09266             count = sscanf ( word, "%f%n", &rval, &width );
09267 
09268             if ( 0 < count )
09269             {
09270 
09271 //
09272 //  COMMENTED OUT!
09273 //
09274 //              if ( nfnorm < FACE_MAX )
09275 //              {
09276 //                normal[ixyz][nfnorm] = rval;
09277 //              }
09278 //
09279 //
09280               ixyz = ixyz + 1;
09281               if ( 2 < ixyz )
09282               {
09283                 ixyz = 0;
09284               }
09285             }
09286             else
09287             {
09288               bad_num = bad_num + 1;
09289               cout << "Bad data " << word << "\n";
09290             }
09291           }
09292         }
09293       }
09294 //
09295 //  NORMALBINDING
09296 //  Read, but ignore
09297 //
09298       else if ( s_eqi ( level_name[level], "NORMALBINDING" ) )
09299       {
09300 
09301         if ( strcmp ( word, "{" ) == 0 )
09302         {
09303         }
09304         else if ( strcmp ( word, "}" ) == 0 )
09305         {
09306           level = nlbrack - nrbrack;
09307         }
09308         else if ( s_eqi ( word, "VALUE" ) )
09309         {
09310           count = sscanf ( next, "%s%n", normal_binding, &width );
09311           next = next + width;
09312         }
09313         else
09314         {
09315           count = sscanf ( word, "%f%n", &rval, &width );
09316 
09317           if ( 0 < count )
09318           {
09319           }
09320           else
09321           {
09322             bad_num = bad_num + 1;
09323             cout << "Bad data " << word << "\n";
09324           }
09325         }
09326       }
09327 //
09328 //  NORMALINDEX
09329 //
09330       else if ( s_eqi ( level_name[level], "NORMALINDEX" ) )
09331       {
09332 //
09333 //  (indexedtrianglestripset) NORMALINDEX
09334 //
09335         if ( s_eqi ( level_name[level-1], "INDEXEDTRIANGLESTRIPSET" ) )
09336         {
09337           count = sscanf ( word, "%d%n", &jval, &width );
09338 
09339           if ( 0 < count )
09340           {
09341           }
09342           else if ( strcmp ( word, "[" ) == 0 )
09343           {
09344           }
09345           else if ( strcmp ( word, "]" ) == 0 )
09346           {
09347           }
09348         }
09349 //
09350 //  (anythingelse) NORMALINDEX
09351 //
09352         else
09353         {
09354 
09355           if ( strcmp ( word, "[" ) == 0 )
09356           {
09357             ivert = 0;
09358           }
09359           else if ( strcmp ( word, "]" ) == 0 )
09360           {
09361             level = nlbrack - nrbrack;
09362           }
09363           else
09364           {
09365             count = sscanf ( word, "%d%n", &jval, &width );
09366 
09367             if ( 0 < count )
09368             {
09369               if ( jval == -1 )
09370               {
09371                 ivert = 0;
09372                 iface_num = iface_num + 1;
09373               }
09374               else
09375               {
09376                 if ( iface_num < FACE_MAX )
09377                 {
09378                   for ( i = 0; i < 3; i++ )
09379                   {
09380                     vertex_normal[i][ivert][iface_num] = normal_temp[i][jval];
09381                   }
09382                   ivert = ivert + 1;
09383                 }
09384               }
09385             }
09386             else
09387             {
09388               bad_num = bad_num + 1;
09389               cout << "Bad data " << word << "\n";
09390             }
09391           }
09392         }
09393       }
09394 //
09395 //  (coordinate3) POINT
09396 //
09397       else if ( s_eqi ( level_name[level], "POINT" ) )
09398       {
09399         if ( s_eqi ( level_name[level-1], "COORDINATE3" ) )
09400         {
09401           if ( strcmp ( word, "[" ) == 0 )
09402           {
09403             ixyz = 0;
09404             cor3_num_old = cor3_num;
09405           }
09406           else if ( strcmp ( word, "]" ) == 0 )
09407           {
09408             level = nlbrack - nrbrack;
09409           }
09410           else
09411           {
09412             count = sscanf ( word, "%f%n", &rval, &width );
09413 
09414             if ( 0 < count )
09415             {
09416               if ( cor3_num < COR3_MAX )
09417               {
09418                 xvec[ixyz] = rval;
09419               }
09420 
09421               ixyz = ixyz + 1;
09422 
09423               if ( ixyz == 3 )
09424               {
09425                 ixyz = 0;
09426 
09427                 tmat_mxp ( transform_matrix, xvec, xvec );
09428 
09429                 cor3[0][cor3_num] = xvec[0];
09430                 cor3[1][cor3_num] = xvec[1];
09431                 cor3[2][cor3_num] = xvec[2];
09432 
09433                 cor3_num = cor3_num + 1;
09434 
09435                 continue;
09436               }
09437             }
09438             else
09439             {
09440               bad_num = bad_num + 1;
09441               break;
09442             }
09443           }
09444         }
09445 //
09446 //  (texturecoodinate2) POINT
09447 //
09448         else if ( s_eqi ( level_name[level-1], "TEXTURECOORDINATE2" ) )
09449         {
09450           if ( strcmp ( word, "[" ) == 0 )
09451           {
09452             iuv = 0;
09453             text_numure_temp = 0;
09454           }
09455           else if ( strcmp ( word, "]" ) == 0 )
09456           {
09457             level = nlbrack - nrbrack;
09458           }
09459           else
09460           {
09461 
09462             count = sscanf ( word, "%f%n", &rval, &width );
09463 
09464             if ( 0 < count )
09465             {
09466 
09467               texture_temp[iuv][text_numure_temp] = rval;
09468 
09469               iuv = iuv + 1;
09470               if ( iuv == 2 )
09471               {
09472                 iuv = 0;
09473                 text_numure_temp = text_numure_temp + 1;
09474               }
09475             }
09476             else
09477             {
09478               cout << "TextureCoordinate2 { Point [: Bad data\n";
09479               bad_num = bad_num + 1;
09480               break;
09481             }
09482           }
09483         }
09484       }
09485 //
09486 //  RGB
09487 //
09488       else if ( s_eqi ( level_name[level],"RGB" ) )
09489       {
09490 //
09491 //  (basecolor) RGB
09492 //
09493         if ( s_eqi ( level_name[level-1], "BASECOLOR" ) )
09494         {
09495           if ( strcmp ( word, "[" ) == 0 )
09496           {
09497             icolor = 0;
09498           }
09499           else if ( strcmp ( word, "]" ) == 0 )
09500           {
09501             level = nlbrack - nrbrack;
09502           }
09503           else
09504           {
09505             count = sscanf ( word, "%f%n", &rval, &width );
09506 
09507             if ( 0 < count )
09508             {
09509 
09510               rgbcolor[icolor][color_num] = rval;
09511               icolor = icolor + 1;
09512 
09513               if ( icolor == 3 )
09514               {
09515                 icolor = 0;
09516                 color_num = color_num + 1;
09517               }
09518             }
09519             else
09520             {
09521               bad_num = bad_num + 1;
09522               cout << "Bad data " << word << "\n";
09523             }
09524           }
09525         }
09526 //
09527 //  (anythingelse RGB)
09528 //
09529         else
09530         {
09531           cout << "HALSBAND DES TODES!\n";
09532 
09533           if ( strcmp ( word, "[" ) == 0 )
09534           {
09535             icolor = 0;
09536             ivert = 0;
09537           }
09538           else if ( strcmp ( word, "]" ) == 0 )
09539           {
09540             level = nlbrack - nrbrack;
09541           }
09542           else
09543           {
09544 
09545             count = sscanf ( word, "%f%n", &rval, &width );
09546 
09547             if ( 0 < count )
09548             {
09549 
09550               if ( icface < FACE_MAX )
09551               {
09552 
09553                 vertex_rgb[icolor][ivert][icface] = rval;
09554 
09555                 icolor = icolor + 1;
09556                 if ( icolor == 3 )
09557                 {
09558                   icolor = 0;
09559                   color_num = color_num + 1;
09560                   ivert = ivert + 1;
09561                   if ( ivert == face_order[icface] )
09562                   {
09563                     ivert = 0;
09564                     icface = icface + 1;
09565                   }
09566                 }
09567               }
09568             }
09569             else
09570             {
09571               bad_num = bad_num + 1;
09572               cout << "Bad data " << word << "\n";
09573             }
09574           }
09575         }
09576 
09577       }
09578 //
09579 //  SEPARATOR
09580 //
09581       else if ( s_eqi ( level_name[level], "SEPARATOR" ) )
09582       {
09583         if ( strcmp ( word, "{" ) == 0 )
09584         {
09585         }
09586         else if ( strcmp ( word, "}" ) == 0 )
09587         {
09588           level = nlbrack - nrbrack;
09589         }
09590         else
09591         {
09592         }
09593       }
09594 //
09595 //  SHAPEHINTS
09596 //  Read, but ignore.
09597 //
09598       else if ( s_eqi ( level_name[level], "SHAPEHINTS" ) )
09599       {
09600         if ( strcmp ( word, "{" ) == 0 )
09601         {
09602         }
09603         else if ( strcmp ( word, "}" ) == 0 )
09604         {
09605           level = nlbrack - nrbrack;
09606         }
09607         else if ( s_eqi ( word, "CREASEANGLE" ) )
09608         {
09609           count = sscanf ( next, "%f%n", &rval, &width );
09610           next = next + width;
09611 
09612           if ( count <= 0 )
09613           {
09614             bad_num = bad_num + 1;
09615             cout << "Bad data " << word << "\n";
09616           }
09617         }
09618         else if ( s_eqi ( word, "FACETYPE" ) )
09619         {
09620           count = sscanf ( next, "%s%n", word, &width );
09621           next = next + width;
09622         }
09623         else if ( s_eqi ( word, "SHAPETYPE" ) )
09624         {
09625           count = sscanf ( next, "%s%n", word, &width );
09626           next = next + width;
09627         }
09628         else if ( s_eqi ( word, "VERTEXORDERING" ) )
09629         {
09630           count = sscanf ( next, "%s%n", word, &width );
09631           next = next + width;
09632         }
09633         else
09634         {
09635           bad_num = bad_num + 1;
09636           cout << "Bad data " << word << "\n";
09637         }
09638       }
09639 //
09640 //  TEXTURE2
09641 //
09642       else if ( s_eqi ( level_name[level], "TEXTURE2" ) )
09643       {
09644         if ( strcmp ( word, "{" ) == 0 )
09645         {
09646         }
09647         else if ( strcmp ( word, "}" ) == 0 )
09648         {
09649           level = nlbrack - nrbrack;
09650           texture_num = texture_num + 1;
09651         }
09652         else if ( s_eqi ( word, "BLENDCOLOR" ) )
09653         {
09654         }
09655 //
09656 //  NEED TO REMOVE QUOTES SURROUNDING TEXTURE NAME.
09657 //
09658         else if ( s_eqi ( word, "FILENAME" ) )
09659         {
09660           count = sscanf ( next, "%s%n", word, &width );
09661           next = next + width;
09662 
09663           strcpy ( texture_name[texture_num], word );
09664 
09665           i = 0;
09666           j = 0;
09667           do
09668           {
09669             c = texture_name[texture_num][i];
09670             i = i + 1;
09671             if ( c != '"' )
09672             {
09673               texture_name[texture_num][j] = c;
09674               j = j + 1;
09675             }
09676           } while ( c != '\0' );
09677 
09678         }
09679         else if ( s_eqi ( word, "IMAGE" ) )
09680         {
09681         }
09682         else if ( s_eqi ( word, "MODEL" ) )
09683         {
09684           count = sscanf ( next, "%s%n", word, &width );
09685           next = next + width;
09686         }
09687         else if ( s_eqi ( word, "WRAPS" ) )
09688         {
09689           count = sscanf ( next, "%s%n", word, &width );
09690           next = next + width;
09691         }
09692         else if ( s_eqi ( word, "WRAPT" ) )
09693         {
09694           count = sscanf ( next, "%s%n", word, &width );
09695           next = next + width;
09696         }
09697         else
09698         {
09699         }
09700       }
09701 //
09702 //  TEXTURECOORDINATE2
09703 //
09704       else if ( s_eqi ( level_name[level], "TEXTURECOORDINATE2" ) )
09705       {
09706         if ( strcmp ( word, "{" ) == 0 )
09707         {
09708         }
09709         else if ( strcmp ( word, "}" ) == 0 )
09710         {
09711           level = nlbrack - nrbrack;
09712         }
09713         else if ( s_eqi ( word, "POINT" ) )
09714         {
09715         }
09716         else
09717         {
09718           bad_num = bad_num + 1;
09719           cout << "TEXTURECOORDINATE2: Bad data " << word << "\n";
09720         }
09721       }
09722 //
09723 //  TEXTURECOORDINATEBINDING
09724 //
09725       else if ( s_eqi ( level_name[level], "TEXTURECOORDINATEBINDING" ) )
09726       {
09727         if ( strcmp ( word, "{" ) == 0 )
09728         {
09729         }
09730         else if ( strcmp ( word, "}" ) == 0 )
09731         {
09732           level = nlbrack - nrbrack;
09733         }
09734         else if ( s_eqi ( word, "VALUE" ) )
09735         {
09736           count = sscanf ( next, "%s%n", texture_binding, &width );
09737           next = next + width;
09738         }
09739         else
09740         {
09741           bad_num = bad_num + 1;
09742           cout << "Bad data " << word << "\n";
09743         }
09744       }
09745 //
09746 //  TEXTURECOORDINDEX
09747 //
09748       else if ( s_eqi ( level_name[level], "TEXTURECOORDINDEX" ) )
09749       {
09750         if ( strcmp ( word, "[" ) == 0 )
09751         {
09752           ivert = 0;
09753           iface_num = 0;
09754         }
09755         else if ( strcmp ( word, "]" ) == 0 )
09756         {
09757           level = nlbrack - nrbrack;
09758         }
09759         else
09760         {
09761           count = sscanf ( word, "%d%n", &jval, &width );
09762 
09763           if ( 0 < count )
09764           {
09765             if ( jval == - 1 )
09766             {
09767               ivert = 0;
09768             }
09769             else
09770             {
09771               if ( iface_num < FACE_MAX )
09772               {
09773                 vertex_tex_uv[0][ivert][iface_num] = texture_temp[0][jval];
09774                 vertex_tex_uv[1][ivert][iface_num] = texture_temp[1][jval];
09775               }
09776 
09777               ivert = ivert + 1;
09778 
09779               if ( ivert == face_order[iface_num] )
09780               {
09781                 ivert = 0;
09782                 iface_num = iface_num + 1;
09783               }
09784             }
09785 
09786           }
09787           else
09788           {
09789             bad_num = bad_num + 1;
09790             cout << "Bad data " << word << "\n";
09791           }
09792 
09793         }
09794       }
09795 //
09796 //  UKNOTVECTOR
09797 //
09798       else if ( s_eqi ( level_name[level], "UKNOTVECTOR" ) )
09799       {
09800         if ( strcmp ( word, "[" ) == 0 )
09801         {
09802           continue;
09803         }
09804         else if ( strcmp ( word, "]" ) == 0 )
09805         {
09806           level = nlbrack - nrbrack;
09807           continue;
09808         }
09809         else
09810         {
09811           count = sscanf ( word, "%d%n", &jval, &width );
09812         }
09813       }
09814 //
09815 //  VECTOR
09816 //
09817       else if ( s_eqi ( level_name[level], "VECTOR" ) )
09818       {
09819         if ( strcmp ( word, "[" ) == 0 )
09820         {
09821         }
09822         else if ( strcmp ( word, "]" ) == 0 )
09823         {
09824           level = nlbrack - nrbrack;
09825         }
09826 //
09827 //  (normal) VECTOR
09828 //
09829         else if ( s_eqi ( level_name[level-1], "NORMAL" ) )
09830         {
09831 
09832           count = sscanf ( word, "%f%n", &rval, &width );
09833 
09834           if ( 0 < count )
09835           {
09836             if ( normal_num_temp < ORDER_MAX * FACE_MAX )
09837             {
09838               normal_temp[ixyz][normal_num_temp] = rval;
09839               ixyz = ixyz + 1;
09840               if ( ixyz == 3 )
09841               {
09842                 ixyz = 0;
09843                 normal_num_temp = normal_num_temp + 1;
09844               }
09845             }
09846           }
09847           else
09848           {
09849             bad_num = bad_num + 1;
09850             cout << "NORMAL VECTOR: bad data " << word << "\n";
09851           }
09852         }
09853       }
09854 //
09855 //  (vertexproperty) VERTEX
09856 //
09857       else if ( s_eqi ( level_name[level], "VERTEX" ) )
09858       {
09859         if ( s_eqi ( level_name[level-1], "VERTEXPROPERTY" ) )
09860         {
09861           if ( strcmp ( word, "[" ) == 0 )
09862           {
09863             ixyz = 0;
09864             cor3_num_old = cor3_num;
09865           }
09866           else if ( strcmp ( word, "]" ) == 0 )
09867           {
09868             level = nlbrack - nrbrack;
09869           }
09870           else
09871           {
09872             count = sscanf ( word, "%f%n", &rval, &width );
09873 
09874             if ( 0 < count )
09875             {
09876               if ( cor3_num < COR3_MAX )
09877               {
09878                 cor3[ixyz][cor3_num] = rval;
09879               }
09880               ixyz = ixyz + 1;
09881               if ( ixyz == 3 )
09882               {
09883                 ixyz = 0;
09884                 cor3_num = cor3_num + 1;
09885               }
09886 
09887             }
09888             else
09889             {
09890               bad_num = bad_num + 1;
09891               cout << "Bad data " << word << "\n";
09892             }
09893           }
09894         }
09895       }
09896 //
09897 //  (indexedtrianglestripset) VERTEXPROPERTY
09898 //
09899       else if ( s_eqi ( level_name[level], "VERTEXPROPERTY" ) )
09900       {
09901         if ( strcmp ( word, "{" ) == 0 )
09902         {
09903         }
09904         else if ( strcmp ( word, "}" ) == 0 )
09905         {
09906           level = nlbrack - nrbrack;
09907         }
09908         else if ( s_eqi ( word, "VERTEX" ) )
09909         {
09910         }
09911         else if ( s_eqi ( word, "NORMAL" ) )
09912         {
09913           ixyz = 0;
09914         }
09915         else if ( s_eqi ( word, "MATERIALBINDING" ) )
09916         {
09917           count = sscanf ( next, "%s%n", word, &width );
09918           next = next + width;
09919         }
09920         else if ( s_eqi ( word, "NORMALBINDING" ) )
09921         {
09922           count = sscanf ( next, "%s%n", word, &width );
09923           next = next + width;
09924         }
09925         else
09926         {
09927           bad_num = bad_num + 1;
09928           cout << "Bad data " << word << "\n";
09929         }
09930       }
09931 //
09932 //  VKNOTVECTOR
09933 //
09934       else if ( s_eqi ( level_name[level], "VKNOTVECTOR" ) )
09935       {
09936         if ( strcmp ( word, "[" ) == 0 )
09937         {
09938           continue;
09939         }
09940         else if ( strcmp ( word, "]" ) == 0 )
09941         {
09942           level = nlbrack - nrbrack;
09943           continue;
09944         }
09945         else
09946         {
09947           count = sscanf ( word, "%d%n", &jval, &width );
09948         }
09949       }
09950 //
09951 //  Any other word:
09952 //
09953       else
09954       {
09955       }
09956     }
09957   }
09958 //
09959 //  Reset the transformation matrix to the identity,
09960 //  because, presumably, we've applied it by now.
09961 //
09962   tmat_init ( transform_matrix );
09963 
09964   return 0;
09965 }
09966 //****************************************************************************80
09967 
09968 int iv_write ( FILE *fileout )
09969 
09970 //****************************************************************************80
09971 //
09972 //  Purpose:
09973 //
09974 //    IV_WRITE writes graphics information to an Inventor file.
09975 //
09976 //  Licensing:
09977 //
09978 //    This code is distributed under the GNU LGPL license.
09979 //
09980 //  Modified:
09981 //
09982 //    29 June 1999
09983 //
09984 //  Author:
09985 //
09986 //    John Burkardt
09987 //
09988 {
09989   int icor3;
09990   int iface;
09991   int itemp;
09992   int ivert;
09993   int j;
09994   int length;
09995   int text_num;
09996 
09997   text_num = 0;
09998 
09999   fprintf ( fileout, "#Inventor V2.0 ascii\n" );
10000   fprintf ( fileout, "\n" );
10001   fprintf ( fileout, "Separator {\n" );
10002   fprintf ( fileout, "  Info {\n" );
10003   fprintf ( fileout, "    string \"%s generated by IVCON.\"\n", fileout_name );
10004   fprintf ( fileout, "    string \"Original data in file %s.\"\n", filein_name );
10005   fprintf ( fileout, "  }\n" );
10006   fprintf ( fileout, "  Separator {\n" );
10007   text_num = text_num + 8;
10008 //
10009 //  LightModel:
10010 //
10011 //    BASE_COLOR ignores light sources, and uses only diffuse color
10012 //      and transparency.  Even without normal vector information,
10013 //      the object will show up.  However, you won't get shadow
10014 //      and lighting effects.
10015 //
10016 //    PHONG uses the Phong lighting model, accounting for light sources
10017 //      and surface orientation.  This is the default.  I believe
10018 //      you need accurate normal vector information in order for this
10019 //      option to produce nice pictures.
10020 //
10021 //    DEPTH ignores light sources, and calculates lighting based on
10022 //      the location of the object within the near and far planes
10023 //      of the current camera's view volume.
10024 //
10025   fprintf ( fileout, "    LightModel {\n" );
10026   fprintf ( fileout, "      model PHONG\n" );
10027   fprintf ( fileout, "    }\n" );
10028   text_num = text_num + 3;
10029 //
10030 //  Transformation matrix.
10031 //
10032   fprintf ( fileout, "    MatrixTransform { matrix\n" );
10033   fprintf ( fileout, "      %f %f %f %f\n", transform_matrix[0][0],
10034     transform_matrix[0][1], transform_matrix[0][2], transform_matrix[0][3] );
10035   fprintf ( fileout, "      %f %f %f %f\n", transform_matrix[1][0],
10036     transform_matrix[1][1], transform_matrix[1][2], transform_matrix[1][3] );
10037   fprintf ( fileout, "      %f %f %f %f\n", transform_matrix[2][0],
10038     transform_matrix[2][1], transform_matrix[2][2], transform_matrix[2][3] );
10039   fprintf ( fileout, "      %f %f %f %f\n", transform_matrix[3][0],
10040     transform_matrix[3][1], transform_matrix[3][2], transform_matrix[3][3] );
10041   fprintf ( fileout, "    }\n" );
10042   text_num = text_num + 6;
10043 //
10044 //  Material.
10045 //
10046   fprintf ( fileout, "    Material {\n" );
10047   fprintf ( fileout, "      ambientColor  0.2 0.2 0.2\n" );
10048   fprintf ( fileout, "      diffuseColor  0.8 0.8 0.8\n" );
10049   fprintf ( fileout, "      emissiveColor 0.0 0.0 0.0\n" );
10050   fprintf ( fileout, "      specularColor 0.0 0.0 0.0\n" );
10051   fprintf ( fileout, "      shininess     0.2\n" );
10052   fprintf ( fileout, "      transparency  0.0\n" );
10053   fprintf ( fileout, "    }\n" );
10054   text_num = text_num + 8;
10055 //
10056 //  MaterialBinding
10057 //
10058   fprintf ( fileout, "    MaterialBinding {\n" );
10059   fprintf ( fileout, "      value PER_VERTEX_INDEXED\n" );
10060   fprintf ( fileout, "    }\n" );
10061   text_num = text_num + 3;
10062 //
10063 //  NormalBinding
10064 //
10065 //    PER_VERTEX promises that we will write a list of normal vectors
10066 //    in a particular order, namely, the normal vectors for the vertices
10067 //    of the first face, then the second face, and so on.
10068 //
10069 //    PER_VERTEX_INDEXED promises that we will write a list of normal vectors,
10070 //    and then, as part of the IndexedFaceSet, we will give a list of
10071 //    indices referencing this normal vector list.
10072 //
10073   fprintf ( fileout, "    NormalBinding {\n" );
10074   fprintf ( fileout, "      value PER_VERTEX_INDEXED\n" );
10075   fprintf ( fileout, "    }\n" );
10076   text_num = text_num + 3;
10077 //
10078 //  Texture2.
10079 //
10080 //  FLAW: We can only handle on texture right now.
10081 //
10082   if ( 0 < texture_num )
10083   {
10084     fprintf ( fileout, "    Texture2 {\n" );
10085     fprintf ( fileout, "      filename \"%s\"\n", texture_name[0] );
10086     fprintf ( fileout, "      wrapS       REPEAT\n" );
10087     fprintf ( fileout, "      wrapT       REPEAT\n" );
10088     fprintf ( fileout, "      model       MODULATE\n" );
10089     fprintf ( fileout, "      blendColor  0.0 0.0 0.0\n" );
10090     fprintf ( fileout, "    }\n" );
10091     text_num = text_num + 7;
10092   }
10093 //
10094 //  TextureCoordinateBinding
10095 //
10096   fprintf ( fileout, "    TextureCoordinateBinding {\n" );
10097   fprintf ( fileout, "      value PER_VERTEX_INDEXED\n" );
10098   fprintf ( fileout, "    }\n" );
10099   text_num = text_num + 3;
10100 //
10101 //  ShapeHints
10102 //
10103   fprintf ( fileout, "    ShapeHints {\n" );
10104   fprintf ( fileout, "      vertexOrdering COUNTERCLOCKWISE\n" );
10105   fprintf ( fileout, "      shapeType UNKNOWN_SHAPE_TYPE\n" );
10106   fprintf ( fileout, "      faceType CONVEX\n" );
10107   fprintf ( fileout, "      creaseAngle 6.28319\n" );
10108   fprintf ( fileout, "    }\n" );
10109   text_num = text_num + 6;
10110 //
10111 //  Point coordinates.
10112 //
10113   fprintf ( fileout, "    Coordinate3 {\n" );
10114   fprintf ( fileout, "      point [\n" );
10115   text_num = text_num + 2;
10116 
10117   for ( j = 0; j < cor3_num; j++ )
10118   {
10119     fprintf ( fileout, "        %f %f %f,\n", cor3[0][j], cor3[1][j],
10120       cor3[2][j] );
10121     text_num = text_num + 1;
10122   }
10123   fprintf ( fileout, "      ]\n" );
10124   fprintf ( fileout, "    }\n" );
10125   text_num = text_num + 2;
10126 //
10127 //  Texture coordinates.
10128 //
10129   fprintf ( fileout, "    TextureCoordinate2 {\n" );
10130   fprintf ( fileout, "      point [\n" );
10131   text_num = text_num + 2;
10132 
10133   for ( iface = 0; iface < face_num; iface++ )
10134   {
10135     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
10136     {
10137       fprintf ( fileout, "        %f %f,\n", vertex_tex_uv[0][ivert][iface],
10138         vertex_tex_uv[1][ivert][iface] );
10139       text_num = text_num + 1;
10140     }
10141   }
10142   fprintf ( fileout, "      ]\n" );
10143   fprintf ( fileout, "    }\n" );
10144   text_num = text_num + 2;
10145 //
10146 //  BaseColor.
10147 //
10148   if ( 0 < color_num )
10149   {
10150     fprintf ( fileout, "    BaseColor {\n" );
10151     fprintf ( fileout, "      rgb [\n" );
10152     text_num = text_num + 2;
10153 
10154     for ( j = 0; j < color_num; j++ )
10155     {
10156       fprintf ( fileout, "        %f %f %f,\n", rgbcolor[0][j], rgbcolor[1][j],
10157         rgbcolor[2][j] );
10158       text_num = text_num + 1;
10159     }
10160 
10161     fprintf ( fileout, "      ]\n" );
10162     fprintf ( fileout, "    }\n" );
10163     text_num = text_num + 2;
10164   }
10165 //
10166 //  Normal vectors.
10167 //    Use the normal vectors associated with nodes.
10168 //
10169   if ( 0 < face_num )
10170   {
10171     fprintf ( fileout, "    Normal { \n" );
10172     fprintf ( fileout, "      vector [\n" );
10173     text_num = text_num + 2;
10174 
10175     for ( icor3 = 0; icor3 < cor3_num; icor3++ )
10176     {
10177       fprintf ( fileout, "        %f %f %f,\n",
10178         cor3_normal[0][icor3],
10179         cor3_normal[1][icor3],
10180         cor3_normal[2][icor3] );
10181       text_num = text_num + 1;
10182     }
10183 
10184     fprintf ( fileout, "      ]\n" );
10185     fprintf ( fileout, "    }\n" );
10186     text_num = text_num + 2;
10187   }
10188 //
10189 //  IndexedLineSet
10190 //
10191   if ( 0 < line_num )
10192   {
10193     fprintf ( fileout, "    IndexedLineSet {\n" );
10194 //
10195 //  IndexedLineSet coordIndex
10196 //
10197     fprintf ( fileout, "      coordIndex [\n" );
10198     text_num = text_num + 2;
10199 
10200     length = 0;
10201 
10202     for ( j = 0; j < line_num; j++ )
10203     {
10204       if ( length == 0 )
10205       {
10206         fprintf ( fileout, "       " );
10207       }
10208 
10209       fprintf ( fileout, " %d,", line_dex[j] );
10210       length = length + 1;
10211 
10212       if ( line_dex[j] == -1 || 10 <= length || j == line_num-1 )
10213       {
10214         fprintf ( fileout, "\n" );
10215         text_num = text_num + 1;
10216         length = 0;
10217       }
10218     }
10219 
10220     fprintf ( fileout, "      ]\n" );
10221     text_num = text_num + 1;
10222 //
10223 //  IndexedLineSet materialIndex.
10224 //
10225     fprintf ( fileout, "      materialIndex [\n" );
10226     text_num = text_num + 1;
10227 
10228     length = 0;
10229 
10230     for ( j = 0; j < line_num; j++ )
10231     {
10232       if ( length == 0 )
10233       {
10234         fprintf ( fileout, "       " );
10235       }
10236 
10237       fprintf ( fileout, " %d,", line_material[j] );
10238       length = length + 1;
10239 
10240       if ( line_material[j] == -1 || 10 <= length || j == line_num-1 )
10241       {
10242         fprintf ( fileout, "\n" );
10243         text_num = text_num + 1;
10244         length = 0;
10245       }
10246     }
10247 
10248     fprintf ( fileout, "      ]\n" );
10249     fprintf ( fileout, "    }\n" );
10250     text_num = text_num + 2;
10251   }
10252 //
10253 //  IndexedFaceSet.
10254 //
10255   if ( 0 < face_num )
10256   {
10257     fprintf ( fileout, "    IndexedFaceSet {\n" );
10258     fprintf ( fileout, "      coordIndex [\n" );
10259     text_num = text_num + 2;
10260 
10261     for ( iface = 0; iface < face_num; iface++ )
10262     {
10263       fprintf ( fileout, "       " );
10264 
10265       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
10266       {
10267         fprintf ( fileout, " %d,", face[ivert][iface] );
10268       }
10269       fprintf ( fileout, " -1,\n" );
10270       text_num = text_num + 1;
10271     }
10272 
10273     fprintf ( fileout, "      ]\n" );
10274     text_num = text_num + 1;
10275 //
10276 //  IndexedFaceSet normalIndex
10277 //
10278     fprintf ( fileout, "      normalIndex [\n" );
10279     text_num = text_num + 1;
10280 
10281     for ( iface = 0; iface < face_num; iface++ )
10282     {
10283       fprintf ( fileout, "       " );
10284 
10285       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
10286       {
10287         fprintf ( fileout, " %d,", face[ivert][iface] );
10288       }
10289       fprintf ( fileout, " -1,\n" );
10290       text_num = text_num + 1;
10291     }
10292     fprintf ( fileout, "      ]\n" );
10293     text_num = text_num + 1;
10294 //
10295 //  IndexedFaceSet materialIndex
10296 //
10297     fprintf ( fileout, "      materialIndex [\n" );
10298     text_num = text_num + 1;
10299 
10300     for ( iface = 0; iface < face_num; iface++ )
10301     {
10302       fprintf ( fileout, "       " );
10303 
10304       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
10305       {
10306         fprintf ( fileout, " %d,", vertex_material[ivert][iface] );
10307       }
10308       fprintf ( fileout, " -1,\n" );
10309       text_num = text_num + 1;
10310     }
10311 
10312     fprintf ( fileout, "      ]\n" );
10313     text_num = text_num + 1;
10314 //
10315 //  IndexedFaceSet textureCoordIndex
10316 //
10317     fprintf ( fileout, "      textureCoordIndex [\n" );
10318     text_num = text_num + 1;
10319 
10320     itemp = 0;
10321 
10322     for ( iface = 0; iface < face_num; iface++ )
10323     {
10324       fprintf ( fileout, "       " );
10325 
10326       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
10327       {
10328         fprintf ( fileout, " %d,", itemp );
10329         itemp = itemp + 1;
10330       }
10331       fprintf ( fileout, " -1,\n" );
10332       text_num = text_num + 1;
10333     }
10334 
10335     fprintf ( fileout, "      ]\n" );
10336 
10337     fprintf ( fileout, "    }\n" );
10338     text_num = text_num + 2;
10339   }
10340 //
10341 //  Close up the Separator nodes.
10342 //
10343   fprintf ( fileout, "  }\n" );
10344   fprintf ( fileout, "}\n" );
10345   text_num = text_num + 2;
10346 //
10347 //  Report.
10348 //
10349   cout << "\n";
10350   cout << "IV_WRITE - Wrote " << text_num << " text lines;\n";
10351 
10352   return 0;
10353 }
10354 //****************************************************************************80
10355 
10356 int i4vec_max ( int n, int *a )
10357 
10358 //****************************************************************************80
10359 //
10360 //  Purpose:
10361 //
10362 //    I4VEC_MAX returns the maximum element in an I4VEC.
10363 //
10364 //  Licensing:
10365 //
10366 //    This code is distributed under the GNU LGPL license.
10367 //
10368 //  Modified:
10369 //
10370 //    09 October 1998
10371 //
10372 //  Author:
10373 //
10374 //    John Burkardt
10375 //
10376 {
10377   int  i;
10378   int *ia;
10379   int  imax;
10380 
10381   if ( n <= 0 )
10382   {
10383     imax = 0;
10384   }
10385   else
10386   {
10387     ia = a;
10388     imax = *ia;
10389     for ( i = 1; i < n; i++ )
10390     {
10391       ia = ia + 1;
10392       if ( imax < *ia )
10393       {
10394         imax = *ia;
10395       }
10396     }
10397   }
10398   return imax;
10399 }
10400 
10401 //****************************************************************************80
10402 
10403 long int long_int_read ( FILE *filein )
10404 
10405 //****************************************************************************80
10406 //
10407 //  Purpose:
10408 //
10409 //    LONG_INT_READ reads a long int from a binary file.
10410 //
10411 //  Licensing:
10412 //
10413 //    This code is distributed under the GNU LGPL license.
10414 //
10415 //  Modified:
10416 //
10417 //    24 May 1999
10418 //
10419 //  Author:
10420 //
10421 //    John Burkardt
10422 //
10423 {
10424   union {
10425     long int yint;
10426     char ychar[4];
10427   } y;
10428 
10429   if ( byte_swap )
10430   {
10431     y.ychar[3] = fgetc ( filein );
10432     y.ychar[2] = fgetc ( filein );
10433     y.ychar[1] = fgetc ( filein );
10434     y.ychar[0] = fgetc ( filein );
10435   }
10436   else
10437   {
10438     y.ychar[0] = fgetc ( filein );
10439     y.ychar[1] = fgetc ( filein );
10440     y.ychar[2] = fgetc ( filein );
10441     y.ychar[3] = fgetc ( filein );
10442   }
10443 
10444   return y.yint;
10445 }
10446 //****************************************************************************80
10447 
10448 int long_int_write ( FILE *fileout, long int int_val )
10449 
10450 //****************************************************************************80
10451 //
10452 //  Purpose:
10453 //
10454 //    LONG_INT_WRITE writes a long int to a binary file.
10455 //
10456 //  Licensing:
10457 //
10458 //    This code is distributed under the GNU LGPL license.
10459 //
10460 //  Modified:
10461 //
10462 //    14 October 1998
10463 //
10464 //  Author:
10465 //
10466 //    John Burkardt
10467 //
10468 {
10469   union {
10470     long int yint;
10471     char ychar[4];
10472   } y;
10473 
10474   y.yint = int_val;
10475 
10476   if ( byte_swap )
10477   {
10478     fputc ( y.ychar[3], fileout );
10479     fputc ( y.ychar[2], fileout );
10480     fputc ( y.ychar[1], fileout );
10481     fputc ( y.ychar[0], fileout );
10482   }
10483   else
10484   {
10485     fputc ( y.ychar[0], fileout );
10486     fputc ( y.ychar[1], fileout );
10487     fputc ( y.ychar[2], fileout );
10488     fputc ( y.ychar[3], fileout );
10489   }
10490 
10491   return 4;
10492 }
10493 //****************************************************************************80
10494 
10495 void news ( )
10496 
10497 //****************************************************************************80
10498 //
10499 //  Purpose:
10500 //
10501 //    NEWS reports the program change history.
10502 //
10503 //  Licensing:
10504 //
10505 //    This code is distributed under the GNU LGPL license.
10506 //
10507 //  Modified:
10508 //
10509 //    05 September 2003
10510 //
10511 //  Author:
10512 //
10513 //    John Burkardt
10514 //
10515 {
10516   cout << "\n";
10517   cout << "Recent changes:\n";
10518   cout << "\n";
10519   cout << "  05 September 2003\n";
10520   cout << "    Trying to sneak OFF_READ in.\n";
10521   cout << "    Replaced all C PRINTF calls by C++ COUT <<\n";
10522   cout << "  29 August 2003\n";
10523   cout << "    Added OFF_WRITE.\n";
10524   cout << "  04 July 2000\n";
10525   cout << "    Added preliminary XGL_WRITE.\n";
10526   cout << "  26 September 1999\n";
10527   cout << "    After ASE_READ, call NODE_TO_VERTEX_MAT\n";
10528   cout << "    and VERTEX_TO_FACE_MATERIAL.\n";
10529   cout << "  27 July 1999\n";
10530   cout << "    Corrected TMAT_ROT_VECTOR.\n";
10531   cout << "  17 July 1999\n";
10532   cout << "    Added null edge and face deletion.\n";
10533   cout << "    Corrected a string problem in SMF_READ.\n";
10534   cout << "  03 July 1999\n";
10535   cout << "    Fixed a problem with BINDING variables in SMF_READ.\n";
10536   cout << "  02 July 1999\n";
10537   cout << "    Added limited texture support in 3DS/IV.\n";
10538   cout << "  26 June 1999\n";
10539   cout << "    BYU_READ added.\n";
10540   cout << "  25 June 1999\n";
10541   cout << "    BYU_WRITE added.\n";
10542   cout << "  22 June 1999\n";
10543   cout << "    TRIB_READ added.\n";
10544   cout << "  16 June 1999\n";
10545   cout << "    TRIB_WRITE Greg Hood binary triangle output routine added.\n";
10546   cout << "  10 June 1999\n";
10547   cout << "    TRIA_WRITE Greg Hood ASCII triangle output routine added.\n";
10548   cout << "  09 June 1999\n";
10549   cout << "    TEC_WRITE TECPLOT output routine added.\n";
10550   cout << "    IV_READ and IV_WRITE use TRANSFORM_MATRIX now.\n";
10551   cout << "  26 May 1999\n";
10552   cout << "    LINE_PRUNE option added for VLA_WRITE.\n";
10553   cout << "  24 May 1999\n";
10554   cout << "    Added << command to append new graphics data to old.\n";
10555   cout << "    Stuck in first draft STLB_READ/STLB_WRITE routines.\n";
10556   cout << "    STLA_WRITE and STLB_WRITE automatically decompose \n";
10557   cout << "      non-triangular faces before writing.\n";
10558   cout << "  23 May 1999\n";
10559   cout << "    Stuck in first draft WRL_WRITE routine.\n";
10560   cout << "  22 May 1999\n";
10561   cout << "    Faces converted to lines before calling VLA_WRITE.\n";
10562   cout << "    Added UCD_WRITE.\n";
10563   cout << "    Added MATERIAL/PATCH/TAGGEDPOINTS fields in HRC_READ.\n";
10564   cout << "  17 May 1999\n";
10565   cout << "    Updated SMF_WRITE, SMF_READ to match code in IVREAD.\n";
10566   cout << "    Added transformation matrix routines.\n";
10567   cout << "  16 May 1999\n";
10568   cout << "    Zik Saleeba improved DXF support to handle polygons.\n";
10569   cout << "  15 April 1999\n";
10570   cout << "    Zik Saleeba added Golgotha GMOD file format support.\n";
10571   cout << "  03 December 1998\n";
10572   cout << "    Set up simple hooks in TDS_READ_MATERIAL_SECTION.\n";
10573   cout << "  02 December 1998\n";
10574   cout << "    Set up simple hooks for texture map names.\n";
10575   cout << "  19 November 1998\n";
10576   cout << "    IV_WRITE uses PER_VERTEX normal binding.\n";
10577   cout << "  18 November 1998\n";
10578   cout << "    Added node normals.\n";
10579   cout << "    Finally added the -RN option.\n";
10580   cout << "  17 November 1998\n";
10581   cout << "    Added face node ordering reversal option.\n";
10582   cout << "  20 October 1998\n";
10583   cout << "    Added DATA_REPORT.\n";
10584   cout << "  19 October 1998\n";
10585   cout << "    SMF_READ and SMF_WRITE added.\n";
10586   cout << "  16 October 1998\n";
10587   cout << "    Fixing a bug in IV_READ that chokes on ]} and other\n";
10588   cout << "    cases where brackets aren't properly spaced.\n";
10589   cout << "  11 October 1998\n";
10590   cout << "    Added face subset selection option S.\n";
10591   cout << "  09 October 1998\n";
10592   cout << "    Reworking normal vector treatments.\n";
10593   cout << "    Synchronizing IVREAD and IVCON.\n";
10594   cout << "    POV_WRITE added.\n";
10595   cout << "  02 October 1998\n";
10596   cout << "    IVCON reproduces BOX.3DS and CONE.3DS exactly.\n";
10597   cout << "  30 September 1998\n";
10598   cout << "    IVCON compiled on the PC.\n";
10599   cout << "    Interactive BYTE_SWAP option added for binary files.\n";
10600   cout << "  25 September 1998\n";
10601   cout << "    OBJECT_NAME made available to store object name.\n";
10602   cout << "  23 September 1998\n";
10603   cout << "    3DS binary files can be written.\n";
10604   cout << "  15 September 1998\n";
10605   cout << "    3DS binary files can be read.\n";
10606   cout << "  01 September 1998\n";
10607   cout << "    COR3_RANGE, FACE_NORMAL_AVE added.\n";
10608   cout << "    Major modifications to normal vectors.\n";
10609   cout << "  24 August 1998\n";
10610   cout << "    HRC_READ added.\n";
10611   cout << "  21 August 1998\n";
10612   cout << "    TXT_WRITE improved.\n";
10613   cout << "  20 August 1998\n";
10614   cout << "    HRC_WRITE can output lines as linear splines.\n";
10615   cout << "  19 August 1998\n";
10616   cout << "    Automatic normal computation for OBJ files.\n";
10617   cout << "    Added normal vector computation.\n";
10618   cout << "    HRC_WRITE is working.\n";
10619   cout << "  18 August 1998\n";
10620   cout << "    IV_READ/IV_WRITE handle BASECOLOR RGB properly now.\n";
10621   cout << "    Improved treatment of face materials and normals.\n";
10622   cout << "  17 August 1998\n";
10623   cout << "    ORDER_MAX increased to 35.\n";
10624   cout << "    FACE_PRINT routine added.\n";
10625   cout << "    INIT_DATA routine added.\n";
10626   cout << "  14 August 1998\n";
10627   cout << "    IV_READ is working.\n";
10628   cout << "  13 August 1998\n";
10629   cout << "    ASE_WRITE is working.\n";
10630   cout << "    IV_WRITE is working.\n";
10631   cout << "  12 August 1998\n";
10632   cout << "    ASE_READ is working.\n";
10633   cout << "  10 August 1998\n";
10634   cout << "    DXF_WRITE is working.\n";
10635   cout << "    DXF_READ is working.\n";
10636   cout << "  27 July 1998\n";
10637   cout << "    Interactive mode is working.\n";
10638   cout << "    OBJ_READ is working.\n";
10639   cout << "  25 July 1998\n";
10640   cout << "    OBJ_WRITE is working.\n";
10641   cout << "  24 July 1998\n";
10642   cout << "    DATA_CHECK checks the input data.\n";
10643   cout << "    VLA_READ is working.\n";
10644   cout << "    VLA_WRITE is working.\n";
10645   cout << "  23 July 1998\n";
10646   cout << "    STL_WRITE is working.\n";
10647   cout << "  22 July 1998\n";
10648   cout << "    STL_READ is working.\n";
10649   cout << "    TXT_WRITE is working.\n";
10650 }
10651 //****************************************************************************80
10652 
10653 void node_to_vertex_material ( )
10654 
10655 //****************************************************************************80
10656 //
10657 //  Purpose:
10658 //
10659 //    NODE_TO_VERTEX_MAT extends node material definitions to vertices.
10660 //
10661 //  Discussion:
10662 //
10663 //    A NODE is a point in space.
10664 //    A VERTEX is a node as used in a particular face.
10665 //    One node may be used as a vertex in several faces, or none.
10666 //
10667 //  Licensing:
10668 //
10669 //    This code is distributed under the GNU LGPL license.
10670 //
10671 //  Modified:
10672 //
10673 //    22 May 1999
10674 //
10675 //  Author:
10676 //
10677 //    John Burkardt
10678 //
10679 {
10680   int iface;
10681   int ivert;
10682   int node;
10683 
10684   for ( iface = 0; iface < face_num; iface++ )
10685   {
10686     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
10687     {
10688       node = face[ivert][iface];
10689       vertex_material[ivert][iface] = cor3_material[node];
10690     }
10691   }
10692 
10693   return;
10694 }
10695 //****************************************************************************80
10696 
10697 int obj_read ( FILE *filein )
10698 
10699 //****************************************************************************80
10700 //
10701 //  Purpose:
10702 //
10703 //    OBJ_READ reads a Wavefront OBJ file.
10704 //
10705 //  Example:
10706 //
10707 //    #  magnolia.obj
10708 //
10709 //    mtllib ./vp.mtl
10710 //
10711 //    g
10712 //    v -3.269770 -39.572201 0.876128
10713 //    v -3.263720 -39.507999 2.160890
10714 //    ...
10715 //    v 0.000000 -9.988540 0.000000
10716 //    g stem
10717 //    s 1
10718 //    usemtl brownskn
10719 //    f 8 9 11 10
10720 //    f 12 13 15 14
10721 //    ...
10722 //    f 788 806 774
10723 //
10724 //  Licensing:
10725 //
10726 //    This code is distributed under the GNU LGPL license.
10727 //
10728 //  Modified:
10729 //
10730 //    20 October 1998
10731 //
10732 //  Author:
10733 //
10734 //    John Burkardt
10735 //
10736 {
10737   int count;
10738   int i;
10739   int ivert;
10740   char *next;
10741   char *next2;
10742   char *next3;
10743   int node;
10744   int vertex_normal_num;
10745   float r1;
10746   float r2;
10747   float r3;
10748   char token[LINE_MAX_LEN];
10749   char token2[LINE_MAX_LEN];
10750   int width;
10751 //
10752 //  Initialize.
10753 //
10754   vertex_normal_num = 0;
10755 //
10756 //  Read the next line of the file into INPUT.
10757 //
10758   while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL )
10759   {
10760     text_num = text_num + 1;
10761 //
10762 //  Advance to the first nonspace character in INPUT.
10763 //
10764     for ( next = input; *next != '\0' && ch_is_space ( *next ); next++ )
10765     {
10766     }
10767 //
10768 //  Skip blank lines and comments.
10769 //
10770     if ( *next == '\0' )
10771     {
10772       continue;
10773     }
10774 
10775     if ( *next == '#' || *next == '$' )
10776     {
10777       comment_num = comment_num + 1;
10778       continue;
10779     }
10780 //
10781 //  Extract the first word in this line.
10782 //
10783     sscanf ( next, "%s%n", token, &width );
10784 //
10785 //  Set NEXT to point to just after this token.
10786 //
10787     next = next + width;
10788 //
10789 //  BEVEL
10790 //  Bevel interpolation.
10791 //
10792     if ( s_eqi ( token, "BEVEL" ) )
10793     {
10794       continue;
10795     }
10796 //
10797 //  BMAT
10798 //  Basis matrix.
10799 //
10800     else if ( s_eqi ( token, "BMAT" ) )
10801     {
10802       continue;
10803     }
10804 //
10805 //  C_INTERP
10806 //  Color interpolation.
10807 //
10808     else if ( s_eqi ( token, "C_INTERP" ) )
10809     {
10810       continue;
10811     }
10812 //
10813 //  CON
10814 //  Connectivity between free form surfaces.
10815 //
10816     else if ( s_eqi ( token, "CON" ) )
10817     {
10818       continue;
10819     }
10820 //
10821 //  CSTYPE
10822 //  Curve or surface type.
10823 //
10824     else if ( s_eqi ( token, "CSTYPE" ) )
10825     {
10826       continue;
10827     }
10828 //
10829 //  CTECH
10830 //  Curve approximation technique.
10831 //
10832     else if ( s_eqi ( token, "CTECH" ) )
10833     {
10834       continue;
10835     }
10836 //
10837 //  CURV
10838 //  Curve.
10839 //
10840     else if ( s_eqi ( token, "CURV" ) )
10841     {
10842       continue;
10843     }
10844 //
10845 //  CURV2
10846 //  2D curve.
10847 //
10848     else if ( s_eqi ( token, "CURV2" ) )
10849     {
10850       continue;
10851     }
10852 //
10853 //  D_INTERP
10854 //  Dissolve interpolation.
10855 //
10856     else if ( s_eqi ( token, "D_INTERP" ) )
10857     {
10858       continue;
10859     }
10860 //
10861 //  DEG
10862 //  Degree.
10863 //
10864     else if ( s_eqi ( token, "DEG" ) )
10865     {
10866       continue;
10867     }
10868 //
10869 //  END
10870 //  End statement.
10871 //
10872     else if ( s_eqi ( token, "END" ) )
10873     {
10874       continue;
10875     }
10876 //
10877 //  F V1 V2 V3
10878 //    or
10879 //  F V1/VT1/VN1 V2/VT2/VN2 ...
10880 //    or
10881 //  F V1//VN1 V2//VN2 ...
10882 //
10883 //  Face.
10884 //  A face is defined by the vertices.
10885 //  Optionally, slashes may be used to include the texture vertex
10886 //  and vertex normal indices.
10887 //
10888 //  OBJ line node indices are 1 based rather than 0 based.
10889 //  So we have to decrement them before loading them into FACE.
10890 //
10891     else if ( s_eqi ( token, "F" ) )
10892     {
10893       ivert = 0;
10894       face_order[face_num] = 0;
10895 //
10896 //  Read each item in the F definition as a token, and then
10897 //  take it apart.
10898 //
10899       for ( ;; )
10900       {
10901         count = sscanf ( next, "%s%n", token2, &width );
10902         next = next + width;
10903 
10904         if ( count != 1 )
10905         {
10906           break;
10907         }
10908 
10909         count = sscanf ( token2, "%d%n", &node, &width );
10910         next2 = token2 + width;
10911 
10912         if ( count != 1 )
10913         {
10914           break;
10915         }
10916 
10917         if ( ivert < ORDER_MAX && face_num < FACE_MAX )
10918         {
10919           face[ivert][face_num] = node-1;
10920           vertex_material[ivert][face_num] = 0;
10921           face_order[face_num] = face_order[face_num] + 1;
10922         }
10923 //
10924 //  If there's a slash, skip to the next slash, and extract the
10925 //  index of the normal vector.
10926 //
10927         if ( *next2 == '/' )
10928         {
10929           for ( next3 = next2 + 1; next3 < token2 + LINE_MAX_LEN; next3++ )
10930           {
10931             if ( *next3 == '/' )
10932             {
10933               next3 = next3 + 1;
10934               count = sscanf ( next3, "%d%n", &node, &width );
10935 
10936               node = node - 1;
10937               if ( 0 <= node && node < vertex_normal_num )
10938               {
10939                 for ( i = 0; i < 3; i++ )
10940                 {
10941                   vertex_normal[i][ivert][face_num] = normal_temp[i][node];
10942                 }
10943               }
10944               break;
10945             }
10946           }
10947         }
10948         ivert = ivert + 1;
10949       }
10950       face_num = face_num + 1;
10951     }
10952 //
10953 //  G
10954 //  Group name.
10955 //
10956     else if ( s_eqi ( token, "G" ) )
10957     {
10958       continue;
10959     }
10960 //
10961 //  HOLE
10962 //  Inner trimming hole.
10963 //
10964     else if ( s_eqi ( token, "HOLE" ) )
10965     {
10966       continue;
10967     }
10968 //
10969 //  L
10970 //  I believe OBJ line node indices are 1 based rather than 0 based.
10971 //  So we have to decrement them before loading them into LINE_DEX.
10972 //
10973     else if ( s_eqi ( token, "L" ) )
10974     {
10975       for ( ;; )
10976       {
10977         count = sscanf ( next, "%d%n", &node, &width );
10978         next = next + width;
10979 
10980         if ( count != 1 )
10981         {
10982           break;
10983         }
10984 
10985         if ( line_num < LINES_MAX  )
10986         {
10987           line_dex[line_num] = node-1;
10988           line_material[line_num] = 0;
10989         }
10990         line_num = line_num + 1;
10991 
10992       }
10993 
10994       if ( line_num < LINES_MAX )
10995       {
10996         line_dex[line_num] = -1;
10997         line_material[line_num] = -1;
10998       }
10999       line_num = line_num + 1;
11000 
11001     }
11002 //
11003 //  LOD
11004 //  Level of detail.
11005 //
11006     else if ( s_eqi ( token, "LOD" ) )
11007     {
11008       continue;
11009     }
11010 //
11011 //  MG
11012 //  Merging group.
11013 //
11014     else if ( s_eqi ( token, "MG" ) )
11015     {
11016       continue;
11017     }
11018 //
11019 //  MTLLIB
11020 //  Material library.
11021 //
11022 
11023     else if ( s_eqi ( token, "MTLLIB" ) )
11024     {
11025       continue;
11026     }
11027 //
11028 //  O
11029 //  Object name.
11030 //
11031     else if ( s_eqi ( token, "O" ) )
11032     {
11033       continue;
11034     }
11035 //
11036 //  P
11037 //  Point.
11038 //
11039     else if ( s_eqi ( token, "P" ) )
11040     {
11041       continue;
11042     }
11043 //
11044 //  PARM
11045 //  Parameter values.
11046 //
11047     else if ( s_eqi ( token, "PARM" ) )
11048     {
11049       continue;
11050     }
11051 //
11052 //  S
11053 //  Smoothing group
11054 //
11055     else if ( s_eqi ( token, "S" ) )
11056     {
11057       continue;
11058     }
11059 //
11060 //  SCRV
11061 //  Special curve.
11062 //
11063     else if ( s_eqi ( token, "SCRV" ) )
11064     {
11065       continue;
11066     }
11067 //
11068 //  SHADOW_OBJ
11069 //  Shadow casting.
11070 //
11071     else if ( s_eqi ( token, "SHADOW_OBJ" ) )
11072     {
11073       continue;
11074     }
11075 //
11076 //  SP
11077 //  Special point.
11078 //
11079     else if ( s_eqi ( token, "SP" ) )
11080     {
11081       continue;
11082     }
11083 //
11084 //  STECH
11085 //  Surface approximation technique.
11086 //
11087     else if ( s_eqi ( token, "STECH" ) )
11088     {
11089       continue;
11090     }
11091 //
11092 //  STEP
11093 //  Stepsize.
11094 //
11095     else if ( s_eqi ( token, "CURV" ) )
11096     {
11097       continue;
11098     }
11099 //
11100 //  SURF
11101 //  Surface.
11102 //
11103     else if ( s_eqi ( token, "SURF" ) )
11104     {
11105       continue;
11106     }
11107 //
11108 //  TRACE_OBJ
11109 //  Ray tracing.
11110 //
11111     else if ( s_eqi ( token, "TRACE_OBJ" ) )
11112     {
11113       continue;
11114     }
11115 //
11116 //  TRIM
11117 //  Outer trimming loop.
11118 //
11119     else if ( s_eqi ( token, "TRIM" ) )
11120     {
11121       continue;
11122     }
11123 //
11124 //  USEMTL
11125 //  Material name.
11126 //
11127     else if ( s_eqi ( token, "USEMTL" ) )
11128     {
11129       continue;
11130     }
11131 //
11132 //  V X Y Z W
11133 //  Geometric vertex.
11134 //  W is optional, a weight for rational curves and surfaces.
11135 //  The default for W is 1.
11136 //
11137     else if ( s_eqi ( token, "V" ) )
11138     {
11139       sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
11140 
11141       if ( cor3_num < COR3_MAX )
11142       {
11143         cor3[0][cor3_num] = r1;
11144         cor3[1][cor3_num] = r2;
11145         cor3[2][cor3_num] = r3;
11146       }
11147 
11148       cor3_num = cor3_num + 1;
11149 
11150     }
11151 //
11152 //  VN
11153 //  Vertex normals.
11154 //
11155     else if ( s_eqi ( token, "VN" ) )
11156     {
11157       sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
11158 
11159       if ( vertex_normal_num < ORDER_MAX * FACE_MAX )
11160       {
11161         normal_temp[0][vertex_normal_num] = r1;
11162         normal_temp[1][vertex_normal_num] = r2;
11163         normal_temp[2][vertex_normal_num] = r3;
11164       }
11165 
11166       vertex_normal_num = vertex_normal_num + 1;
11167 
11168     }
11169 //
11170 //  VT
11171 //  Vertex texture.
11172 //
11173     else if ( s_eqi ( token, "VT" ) )
11174     {
11175       continue;
11176     }
11177 //
11178 //  VP
11179 //  Parameter space vertices.
11180 //
11181     else if ( s_eqi ( token, "VP" ) )
11182     {
11183       continue;
11184     }
11185 //
11186 //  Unrecognized
11187 //
11188     else
11189     {
11190       bad_num = bad_num + 1;
11191     }
11192 
11193   }
11194   return 0;
11195 }
11196 //****************************************************************************80
11197 
11198 int obj_write ( FILE *fileout )
11199 
11200 //****************************************************************************80
11201 //
11202 //  Purpose:
11203 //
11204 //    OBJ_WRITE writes a Wavefront OBJ file.
11205 //
11206 //  Example:
11207 //
11208 //    #  magnolia.obj
11209 //
11210 //    mtllib ./vp.mtl
11211 //
11212 //    g
11213 //    v -3.269770 -39.572201 0.876128
11214 //    v -3.263720 -39.507999 2.160890
11215 //    ...
11216 //    v 0.000000 -9.988540 0.000000
11217 //    g stem
11218 //    s 1
11219 //    usemtl brownskn
11220 //    f 8 9 11 10
11221 //    f 12 13 15 14
11222 //    ...
11223 //    f 788 806 774
11224 //
11225 //  Licensing:
11226 //
11227 //    This code is distributed under the GNU LGPL license.
11228 //
11229 //  Modified:
11230 //
11231 //    01 September 1998
11232 //
11233 //  Author:
11234 //
11235 //    John Burkardt
11236 //
11237 //  Parameters:
11238 //
11239 //    Input, FILE *FILEOUT, a pointer to the output file.
11240 //
11241 {
11242   int i;
11243   int iface;
11244   int indexvn;
11245   int ivert;
11246   int k;
11247   bool next;
11248   int text_num;
11249   float w;
11250 //
11251 //  Initialize.
11252 //
11253   text_num = 0;
11254   w = 1.0;
11255 
11256   fprintf ( fileout, "# %s created by IVCON.\n", fileout_name );
11257   fprintf ( fileout, "# Original data in %s.\n", filein_name );
11258   fprintf ( fileout, "\n" );
11259   fprintf ( fileout, "g %s\n", object_name );
11260   fprintf ( fileout, "\n" );
11261 
11262   text_num = text_num + 5;
11263 //
11264 //  V: vertex coordinates.
11265 //
11266   for ( i = 0; i < cor3_num; i++ )
11267   {
11268     fprintf ( fileout, "v %f %f %f %f\n",
11269       cor3[0][i], cor3[1][i], cor3[2][i], w );
11270     text_num = text_num + 1;
11271   }
11272 //
11273 //  VN: Vertex face normal vectors.
11274 //
11275   if ( 0 < face_num )
11276   {
11277     fprintf ( fileout, "\n" );
11278     text_num = text_num + 1;
11279   }
11280 
11281   for ( iface = 0; iface < face_num; iface++ )
11282   {
11283     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
11284     {
11285       fprintf ( fileout, "vn %f %f %f\n", vertex_normal[0][ivert][iface],
11286         vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
11287       text_num = text_num + 1;
11288     }
11289   }
11290 //
11291 //  F: faces.
11292 //
11293   if ( 0 < face_num )
11294   {
11295     fprintf ( fileout, "\n" );
11296     text_num = text_num + 1;
11297   }
11298 
11299   indexvn = 0;
11300 
11301   for ( iface = 0; iface < face_num; iface++ )
11302   {
11303     fprintf ( fileout, "f" );
11304     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
11305     {
11306       indexvn = indexvn + 1;
11307       fprintf ( fileout, " %d//%d", face[ivert][iface]+1, indexvn );
11308     }
11309     fprintf ( fileout, "\n" );
11310     text_num = text_num + 1;
11311   }
11312 //
11313 //  L: lines.
11314 //
11315   if ( 0 < line_num )
11316   {
11317     fprintf ( fileout, "\n" );
11318     text_num = text_num + 1;
11319   }
11320 
11321   next = true;
11322 
11323   for ( i = 0; i < line_num; i++ )
11324   {
11325     k = line_dex[i];
11326 
11327     if ( k == -1 )
11328     {
11329       fprintf ( fileout, "\n" );
11330       text_num = text_num + 1;
11331       next = true;
11332     }
11333     else
11334     {
11335       if ( next )
11336       {
11337         fprintf ( fileout, "l" );
11338         next = false;
11339       }
11340       fprintf ( fileout, " %d", k+1 );
11341     }
11342 
11343   }
11344 
11345   fprintf ( fileout, "\n" );
11346   text_num = text_num + 1;
11347 //
11348 //  Report.
11349 //
11350   cout << "\n";
11351   cout << "OBJ_WRITE - Wrote " << text_num << " text lines.\n";
11352 
11353   return 0;
11354 }
11355 //****************************************************************************80
11356 
11357 int off_read ( ifstream &file_in )
11358 
11359 //****************************************************************************80
11360 //
11361 //  Purpose:
11362 //
11363 //    OFF_READ reads a GEOMVIEW OFF file.
11364 //
11365 //  Example:
11366 //
11367 //    OFF
11368 //    8  6  12
11369 //    0.0 0.0 0.0
11370 //    0.0 0.0 1.0
11371 //    0.0 1.0 0.0
11372 //    0.0 1.0 1.0
11373 //    1.0 0.0 0.0
11374 //    1.0 0.0 1.0
11375 //    1.0 1.0 0.0
11376 //    1.0 1.0 1.0
11377 //    4  0 2 3 1
11378 //    4  4 5 7 6
11379 //    4  0 1 5 4
11380 //    4  2 6 7 3
11381 //    4  0 4 6 2
11382 //    4  1 3 7 5
11383 //
11384 //  Licensing:
11385 //
11386 //    This code is distributed under the GNU LGPL license.
11387 //
11388 //  Modified:
11389 //
11390 //    05 September 2003
11391 //
11392 //  Author:
11393 //
11394 //    John Burkardt
11395 //
11396 //  Parameters:
11397 //
11398 //    Input, ifstream &FILE_IN, a pointer to the OFF file.
11399 //
11400 //    Output, int *COR3_NUM, the number of nodes.
11401 //
11402 //    Output, int *FACE_NUM, the number of faces.
11403 {
11404   int cor3_num2;
11405   int edge_num;
11406   bool error;
11407   int face_num2;
11408   int ivec[21];
11409   int j;
11410   int last;
11411   char line[255];
11412   int noncomment_num;
11413   int order;
11414   float rvec[3];
11415   int text_num;
11416   int vert;
11417 //
11418 //  Read the optional "OFF" line, and the line with the number of nodes,
11419 //  faces and edges.
11420 //
11421   noncomment_num = 0;
11422   text_num = 0;
11423 
11424   while ( 1 )
11425   {
11426     file_in.getline ( line, sizeof ( line ) );
11427 
11428     if ( file_in.eof ( ) )
11429     {
11430       cout << "\n";
11431       cout << "OFF_READ - Fatal error!\n";
11432       cout << "  End-of-file before anything was read.\n";
11433       cout << "  Number of text lines read = " << text_num << "\n";
11434       return 1;
11435     }
11436 
11437     text_num = text_num + 1;
11438 
11439     if ( line[0] == '#' || s_len_trim ( line ) == 0 )
11440     {
11441       continue;
11442     }
11443 
11444     noncomment_num = noncomment_num + 1;
11445 
11446     if ( line[0] == 'O' &&
11447         line[1] == 'F' &&
11448         line[2] == 'F' )
11449     {
11450       if ( noncomment_num == 1 )
11451       {
11452         continue;
11453       }
11454       else
11455       {
11456         cout << "\n";
11457         cout << "OFF_READ - Fatal error!\n";
11458         cout << "  The 'OFF' tag, if used, must be the first noncomment\n";
11459         cout << "  line in the file.\n";
11460         cout << "  Number of text lines read = " << text_num << "\n";
11461         return 1;
11462       }
11463     }
11464 
11465     error = s_to_i4vec ( line, 3, ivec );
11466 
11467     if ( error )
11468     {
11469       cout << "\n";
11470       cout << "OFF_READ - Fatal error!\n";
11471       cout << "  Error from S_TO_I4VEC while trying to extract\n";
11472       cout << "  COR3_NUM FACE_NUM EDGE_NUM record.\n";
11473       cout << "  Number of text lines read = " << text_num << "\n";
11474       cout << "  Current line = \"" << line << "\"\n";
11475       return 1;
11476     }
11477 
11478     cor3_num = ivec[0];
11479     face_num = ivec[1];
11480     edge_num = ivec[2];
11481     break;
11482 
11483   }
11484 //
11485 //  Read the lines that define the vertex coordinates
11486 //
11487 //  Each line has the form "X Y Z"
11488 //
11489   cor3_num2 = 0;
11490 
11491   while ( cor3_num2 < cor3_num )
11492   {
11493     file_in.getline ( line, sizeof ( line ) );
11494 
11495     if ( file_in.eof ( ) )
11496     {
11497       cout << "\n";
11498       cout << "OFF_READ - Fatal error!\n";
11499       cout << "  End of file while reading X Y Z coordinate data.\n";
11500       cout << "  Number of text lines read = " << text_num << "\n";
11501       return 1;
11502     }
11503 
11504     text_num = text_num + 1;
11505 
11506     if ( line[0] == '#' || s_len_trim ( line ) == 0 )
11507     {
11508       continue;
11509     }
11510     noncomment_num = noncomment_num + 1;
11511 
11512     error = s_to_r4vec ( line, 3, rvec );
11513 
11514     if ( error )
11515     {
11516       cout << "\n";
11517       cout << "OFF_READ - Fatal error!\n";
11518       cout << "  Error from S_TO_R4VEC while trying to extract X Y Z data.\n";
11519       cout << "  Number of text lines read = " << text_num << "\n";
11520       return 1;
11521     }
11522 
11523     for ( j = 0; j < 3; j++ )
11524     {
11525       cor3[j][cor3_num2] = rvec[j];
11526     }
11527 
11528     cor3_num2 = cor3_num2 + 1;
11529   }
11530 //
11531 //  Read the lines that define the faces.
11532 //
11533 //  Each line has the form " n  V1  V2  V3 ... Vn"
11534 //
11535   face_num2 = 0;
11536 
11537   while ( face_num2 < face_num )
11538   {
11539     file_in.getline ( line, sizeof ( line ) );
11540 
11541     if ( file_in.eof ( ) )
11542     {
11543       cout << "\n";
11544       cout << "OFF_READ - Fatal error!\n";
11545       cout << "  End of file while reading face data.\n";
11546       cout << "  Number of text lines read = " << text_num << "\n";
11547       return 1;
11548     }
11549 
11550     text_num = text_num + 1;
11551 
11552     if ( line[0] == '#' || s_len_trim ( line ) == 0 )
11553     {
11554       continue;
11555     }
11556 
11557     noncomment_num = noncomment_num + 1;
11558 
11559     order = s_to_i4 ( line, &last, &error );
11560 
11561     if ( error )
11562     {
11563       cout << "\n";
11564       cout << "OFF_READ - Fatal error!\n";
11565       cout << "  Error from S_TO_I4 while extracting face order.\n";
11566       cout << "  Number of text lines read = " << text_num << "\n";
11567       return 1;
11568     }
11569 
11570     face_order[face_num2] = order;
11571 
11572     error = s_to_i4vec ( line, order+1, ivec );
11573 
11574     if ( error )
11575     {
11576       cout << "\n";
11577       cout << "OFF_READ - Fatal error!\n";
11578       cout << "  Error from S_TO_I4VEC while extracting face indices.\n";
11579       cout << "  Number of text lines read = " << text_num << "\n";
11580       return 1;
11581     }
11582 
11583     for ( vert = 0; vert < order; vert++ )
11584     {
11585       face[vert][face_num2] = ivec[vert+1];
11586     }
11587 
11588     face_num2 = face_num2 + 1;
11589   }
11590 
11591   cout << "\n";
11592   cout << "OFF_READ read " << text_num << " lines.\n";
11593 
11594   return 0;
11595 }
11596 //****************************************************************************80
11597 
11598 int off_write ( FILE *fileout )
11599 
11600 //****************************************************************************80
11601 //
11602 //  Purpose:
11603 //
11604 //    OFF_WRITE writes graphics information to a GEOMVIEW OFF file.
11605 //
11606 //  Example:
11607 //
11608 //    OFF
11609 //    8  6  12
11610 //    0.0 0.0 0.0
11611 //    0.0 0.0 1.0
11612 //    0.0 1.0 0.0
11613 //    0.0 1.0 1.0
11614 //    1.0 0.0 0.0
11615 //    1.0 0.0 1.0
11616 //    1.0 1.0 0.0
11617 //    1.0 1.0 1.0
11618 //    4  0 2 3 1
11619 //    4  4 5 7 6
11620 //    4  0 1 5 4
11621 //    4  2 6 7 3
11622 //    4  0 4 6 2
11623 //    4  1 3 7 5
11624 //
11625 //  Licensing:
11626 //
11627 //    This code is distributed under the GNU LGPL license.
11628 //
11629 //  Modified:
11630 //
11631 //    28 August 2003
11632 //
11633 //  Author:
11634 //
11635 //    John Burkardt
11636 //
11637 //  Parameters:
11638 //
11639 //    Input, FILE *FILEOUT, a pointer to the output file.
11640 //
11641 {
11642   int edge_num;
11643   int i;
11644   int iface;
11645   int ivert;
11646   int j;
11647   int text_num;
11648 //
11649 //  "Magic Number"
11650 //
11651   text_num = 0;
11652   fprintf ( fileout, "OFF\n" );
11653   text_num = text_num + 1;
11654 //
11655 //  Compute EDGE_NUM.
11656 //
11657   edge_num = edge_count ( );
11658 //
11659 //  Counts.
11660 //
11661   fprintf ( fileout, "%d  %d  %d\n", cor3_num, face_num, edge_num );
11662   text_num = text_num + 1;
11663 //
11664 //  Vertex coordinates.
11665 //
11666   for ( j = 0; j < cor3_num; j++ )
11667   {
11668     for ( i = 0; i < 3; i++ )
11669     {
11670       fprintf ( fileout, "%f  ", cor3[i][j] );
11671     }
11672     fprintf ( fileout, "\n" );
11673     text_num = text_num + 1;
11674   }
11675 //
11676 //  Face count, and vertex indices.
11677 //
11678   for ( iface = 0; iface < face_num; iface++ )
11679   {
11680     fprintf ( fileout, "%d  ", face_order[iface] );
11681 
11682     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
11683     {
11684       fprintf ( fileout, "%d  ",  face[ivert][iface] );
11685     }
11686     fprintf ( fileout, "\n" );
11687     text_num = text_num + 1;
11688 
11689   }
11690 //
11691 //  Report.
11692 //
11693   cout << "\n";
11694   cout << "OFF_WRITE - Wrote " << text_num
11695        << " text lines to " << fileout_name << "\n";
11696 
11697   return 0;
11698 }
11699 //****************************************************************************80
11700 
11701 int pov_write ( FILE *fileout )
11702 
11703 //****************************************************************************80
11704 //
11705 //  Purpose:
11706 //
11707 //    POV_WRITE writes graphics information to a POV file.
11708 //
11709 //  Example:
11710 //
11711 //    // cone.pov created by IVCON.
11712 //    // Original data in cone.iv
11713 //
11714 //    #version 3.0
11715 //    #include "colors.inc"
11716 //    #include "shapes.inc"
11717 //    global_settings { assumed_gamma 2.2 }
11718 //
11719 //    camera {
11720 //     right < 4/3, 0, 0>
11721 //     up < 0, 1, 0 >
11722 //     sky < 0, 1, 0 >
11723 //     angle 20
11724 //     location < 0, 0, -300 >
11725 //     look_at < 0, 0, 0>
11726 //    }
11727 //
11728 //    light_source { < 20, 50, -100 > color White }
11729 //
11730 //    background { color SkyBlue }
11731 //
11732 //    #declare RedText = texture {
11733 //      pigment { color rgb < 0.8, 0.2, 0.2> }
11734 //      finish { ambient 0.2 diffuse 0.5 }
11735 //    }
11736 //
11737 //    #declare BlueText = texture {
11738 //      pigment { color rgb < 0.2, 0.2, 0.8> }
11739 //      finish { ambient 0.2 diffuse 0.5 }
11740 //    }
11741 //    mesh {
11742 //      smooth_triangle {
11743 //        < 0.29, -0.29, 0.0>, < 0.0, 0.0, -1.0 >,
11744 //        < 38.85, 10.03, 0.0>, < 0.0, 0.0, -1.0 >,
11745 //        < 40.21, -0.29, 0.0>, <  0.0, 0.0, -1.0 >
11746 //        texture { RedText } }
11747 //        ...
11748 //      smooth_triangle {
11749 //        <  0.29, -0.29, 70.4142 >, < 0.0,  0.0, 1.0 >,
11750 //        <  8.56,  -2.51, 70.4142 >, < 0.0,  0.0, 1.0 >,
11751 //        <  8.85, -0.29, 70.4142 >, < 0.0,  0.0, 1.0 >
11752 //        texture { BlueText } }
11753 //    }
11754 //
11755 //  Licensing:
11756 //
11757 //    This code is distributed under the GNU LGPL license.
11758 //
11759 //  Modified:
11760 //
11761 //    08 October 1998
11762 //
11763 //  Author:
11764 //
11765 //    John Burkardt
11766 //
11767 {
11768   int i;
11769   int j;
11770   int jj;
11771   int jlo;
11772   int k;
11773   int text_num;
11774 
11775   text_num = 0;
11776   fprintf ( fileout,  "// %s created by IVCON.\n", fileout_name );
11777   fprintf ( fileout,  "// Original data in %s.\n", filein_name );
11778   text_num = text_num + 2;
11779 //
11780 //  Initial declarations.
11781 //
11782   fprintf ( fileout, "\n" );
11783   fprintf ( fileout, "#version 3.0\n" );
11784   fprintf ( fileout, "#include \"colors.inc\"\n" );
11785   fprintf ( fileout, "#include \"shapes.inc\"\n" );
11786   fprintf ( fileout, "global_settings { assumed_gamma 2.2 }\n" );
11787   fprintf ( fileout, "\n" );
11788   fprintf ( fileout, "camera {\n" );
11789   fprintf ( fileout, " right < 4/3, 0, 0>\n" );
11790   fprintf ( fileout, " up < 0, 1, 0 >\n" );
11791   fprintf ( fileout, " sky < 0, 1, 0 >\n" );
11792   fprintf ( fileout, " angle 20\n" );
11793   fprintf ( fileout, " location < 0, 0, -300 >\n" );
11794   fprintf ( fileout, " look_at < 0, 0, 0>\n" );
11795   fprintf ( fileout, "}\n" );
11796   fprintf ( fileout, "\n" );
11797   fprintf ( fileout, "light_source { < 20, 50, -100 > color White }\n" );
11798   fprintf ( fileout, "\n" );
11799   fprintf ( fileout, "background { color SkyBlue }\n" );
11800 
11801   text_num = text_num + 15;
11802 //
11803 //  Declare RGB textures.
11804 //
11805   fprintf ( fileout, "\n" );
11806   fprintf ( fileout, "#declare RedText = texture {\n" );
11807   fprintf ( fileout, "  pigment { color rgb < 0.8, 0.2, 0.2> }\n" );
11808   fprintf ( fileout, "  finish { ambient 0.2 diffuse 0.5 }\n" );
11809   fprintf ( fileout, "}\n" );
11810   fprintf ( fileout, "\n" );
11811   fprintf ( fileout, "#declare GreenText = texture {\n" );
11812   fprintf ( fileout, "  pigment { color rgb < 0.2, 0.8, 0.2> }\n" );
11813   fprintf ( fileout, "  finish { ambient 0.2 diffuse 0.5 }\n" );
11814   fprintf ( fileout, "}\n" );
11815   fprintf ( fileout, "\n" );
11816   fprintf ( fileout, "#declare BlueText = texture {\n" );
11817   fprintf ( fileout, "  pigment { color rgb < 0.2, 0.2, 0.8> }\n" );
11818   fprintf ( fileout, "  finish { ambient 0.2 diffuse 0.5 }\n" );
11819   fprintf ( fileout, "}\n" );
11820 //
11821 //  Write one big object.
11822 //
11823   fprintf ( fileout,  "mesh {\n" );
11824   text_num = text_num + 1;
11825 //
11826 //  Do the next face.
11827 //
11828   for ( i = 0; i < face_num; i++ )
11829   {
11830 //
11831 //  Break the face up into triangles, anchored at node 1.
11832 //
11833     for ( jlo = 0; jlo < face_order[i] - 2; jlo++ )
11834     {
11835       fprintf ( fileout, "  smooth_triangle {\n" );
11836       text_num = text_num + 1;
11837 
11838       for ( j = jlo; j < jlo + 3; j++ )
11839       {
11840         if ( j == jlo )
11841         {
11842           jj = 0;
11843         }
11844         else
11845         {
11846           jj = j;
11847         }
11848 
11849         k = face[jj][i];
11850 
11851         fprintf ( fileout, "<%f, %f, %f>, <%f, %f, %f>",
11852           cor3[0][k], cor3[1][k], cor3[2][k],
11853           vertex_normal[0][jj][i],
11854           vertex_normal[1][jj][i],
11855           vertex_normal[2][jj][i] );
11856 
11857         if ( j < jlo + 2 )
11858         {
11859           fprintf ( fileout, ",\n" );
11860         }
11861         else
11862         {
11863           fprintf ( fileout, "\n" );
11864         }
11865         text_num = text_num + 1;
11866 
11867       }
11868 
11869       if (i%6 == 1 )
11870       {
11871         fprintf ( fileout,  "texture { RedText } }\n" );
11872       }
11873       else if ( i%2 == 0 )
11874       {
11875         fprintf ( fileout,  "texture { BlueText } }\n" );
11876       }
11877       else
11878       {
11879         fprintf ( fileout,  "texture { GreenText } }\n" );
11880       }
11881       text_num = text_num + 1;
11882 
11883     }
11884 
11885   }
11886 
11887   fprintf ( fileout,  "}\n" );
11888   text_num = text_num + 1;
11889 //
11890 //  Report.
11891 //
11892   cout << "\n";
11893   cout << "POV_WRITE - Wrote " << text_num << " text lines.\n";
11894 
11895   return 0;
11896 }
11897 //****************************************************************************80
11898 
11899 int rcol_find ( float a[][COR3_MAX], int m, int n, float r[] )
11900 
11901 //****************************************************************************80
11902 //
11903 //  Purpose:
11904 //
11905 //    RCOL_FIND finds if a vector occurs in a table.
11906 //
11907 //  Discussion:
11908 //
11909 //    Explicitly forcing the second dimension to be COR3_MAX is a kludge.
11910 //    I have to figure out how to do this as pointer references.
11911 //
11912 //    Also, since the array is not sorted, this routine should not be carelessly
11913 //    called repeatedly for really big values of N, because you'll waste a
11914 //    lot of time.
11915 //
11916 //  Licensing:
11917 //
11918 //    This code is distributed under the GNU LGPL license.
11919 //
11920 //  Modified:
11921 //
11922 //    27 April 1999
11923 //
11924 //  Author:
11925 //
11926 //    John Burkardt
11927 //
11928 {
11929   int i;
11930   int icol;
11931   int j;
11932 
11933   icol = -1;
11934 
11935   for ( j = 0; j < n; j++ )
11936   {
11937     for ( i = 0; i < m; i++ )
11938     {
11939       if ( a[i][j] != r[i] )
11940       {
11941         break;
11942       }
11943       if ( i == m-1 )
11944       {
11945         return j;
11946       }
11947     }
11948   }
11949 
11950   return icol;
11951 }
11952 //****************************************************************************80
11953 
11954 float rgb_to_hue ( float r, float g, float b )
11955 
11956 //****************************************************************************80
11957 //
11958 //  Purpose:
11959 //
11960 //    RGB_TO_HUE converts (R,G,B) colors to a hue value between 0 and 1.
11961 //
11962 //  Discussion:
11963 //
11964 //    The hue computed here should be the same as the H value computed
11965 //    for HLS and HSV, except that it ranges from 0 to 1 instead of
11966 //    0 to 360.
11967 //
11968 //    A monochromatic color ( white, black, or a shade of gray) does not
11969 //    have a hue.  This routine will return a special value of H = -1
11970 //    for such cases.
11971 //
11972 //  Example:
11973 //
11974 //    Color    R    G    B     H
11975 //
11976 //    red  1.0  0.0  0.0   0.00
11977 //    yellow   1.0  1.0  0.0   0.16
11978 //    green    0.0  1.0  0.0   0.33
11979 //    cyan     0.0  1.0  1.0   0.50
11980 //    blue     0.0  0.0  1.0   0.67
11981 //    magenta  1.0  0.0  1.0   0.83
11982 //
11983 //    black    0.0  0.0  0.0  -1.00
11984 //    gray     0.5  0.5  0.5  -1.00
11985 //    white    1.0  1.0  1.0  -1.00
11986 //
11987 //  Licensing:
11988 //
11989 //    This code is distributed under the GNU LGPL license.
11990 //
11991 //  Modified:
11992 //
11993 //    22 May 1999
11994 //
11995 //  Author:
11996 //
11997 //    John Burkardt
11998 //
11999 //  Parameters:
12000 //
12001 //    Input, float R, G, B, the red, green and blue values of the color.
12002 //    These values should be between 0 and 1.
12003 //
12004 //    Output, float RGB_TO_HUE, the corresponding hue of the color, or -1.0 if
12005 //    the color is monochromatic.
12006 //
12007 {
12008   float h;
12009   float rgbmax;
12010   float rgbmin;
12011 //
12012 //  Make sure the colors are between 0 and 1.
12013 //
12014   if ( r < 0.0 )
12015   {
12016     r = 0.0;
12017   }
12018   else if ( 1.0 < r )
12019   {
12020     r = 1.0;
12021   }
12022 
12023   if ( g < 0.0 )
12024   {
12025     g = 0.0;
12026   }
12027   else if ( 1.0 < g )
12028   {
12029     g = 1.0;
12030   }
12031 
12032   if ( b < 0.0 )
12033   {
12034     b = 0.0;
12035   }
12036   else if ( 1.0 < b )
12037   {
12038     b = 1.0;
12039   }
12040 //
12041 //  Compute the minimum and maximum of R, G and B.
12042 //
12043   rgbmax = r;
12044   if ( rgbmax < g )
12045   {
12046     rgbmax = g;
12047   }
12048   if ( rgbmax < b )
12049   {
12050     rgbmax = b;
12051   }
12052 
12053   rgbmin = r;
12054   if ( g < rgbmin )
12055   {
12056     rgbmin = g;
12057   }
12058   if ( b < rgbmin )
12059   {
12060     rgbmin = b;
12061   }
12062 //
12063 //  If RGBMAX = RGBMIN, the color has no hue.
12064 //
12065   if ( rgbmax == rgbmin )
12066   {
12067     h = - 1.0;
12068   }
12069 //
12070 //  Otherwise, we need to determine the dominant color.
12071 //
12072   else
12073   {
12074     if ( r == rgbmax )
12075     {
12076       h = ( g - b ) / ( rgbmax - rgbmin );
12077     }
12078     else if ( g == rgbmax )
12079     {
12080       h = 2.0 + ( b - r ) / ( rgbmax - rgbmin );
12081     }
12082     else if ( b == rgbmax )
12083     {
12084       h = 4.0 + ( r - g ) / ( rgbmax - rgbmin );
12085     }
12086 
12087     h = h / 6.0;
12088 //
12089 //  Make sure H lies between 0 and 1.0.
12090 //
12091     if ( h < 0.0 )
12092     {
12093       h = h + 1.0;
12094     }
12095     else if ( 1.0 < h )
12096     {
12097       h = h - 1.0;
12098     }
12099 
12100   }
12101 
12102   return h;
12103 }
12104 //****************************************************************************80
12105 
12106 bool s_eqi ( char *s1, char *s2 )
12107 
12108 //****************************************************************************80
12109 //
12110 //  Purpose:
12111 //
12112 //    S_EQI reports whether two strings are equal, ignoring case.
12113 //
12114 //  Licensing:
12115 //
12116 //    This code is distributed under the GNU LGPL license.
12117 //
12118 //  Modified:
12119 //
12120 //    05 May 2003
12121 //
12122 //  Author:
12123 //
12124 //    John Burkardt
12125 //
12126 //  Parameters:
12127 //
12128 //    Input, char *S1, char *S2, pointers to two strings.
12129 //
12130 //    Output, bool S_EQI, is true if the strings are equal.
12131 //
12132 {
12133   int i;
12134   int nchar;
12135   int nchar1;
12136   int nchar2;
12137 
12138   nchar1 = strlen ( s1 );
12139   nchar2 = strlen ( s2 );
12140   nchar = i4_min ( nchar1, nchar2 );
12141 
12142 //
12143 //  The strings are not equal if they differ over their common length.
12144 //
12145   for ( i = 0; i < nchar; i++ )
12146   {
12147 
12148     if ( ch_cap ( s1[i] ) != ch_cap ( s2[i] ) )
12149     {
12150       return false;
12151     }
12152   }
12153 //
12154 //  The strings are not equal if the longer one includes nonblanks
12155 //  in the tail.
12156 //
12157   if ( nchar < nchar1 )
12158   {
12159     for ( i = nchar; i < nchar1; i++ )
12160     {
12161       if ( s1[i] != ' ' )
12162       {
12163         return false;
12164       }
12165     }
12166   }
12167   else if ( nchar < nchar2 )
12168   {
12169     for ( i = nchar; i < nchar2; i++ )
12170     {
12171       if ( s2[i] != ' ' )
12172       {
12173         return false;
12174       }
12175     }
12176   }
12177 
12178   return true;
12179 
12180 }
12181 //****************************************************************************80
12182 
12183 int s_len_trim ( char *s )
12184 
12185 //****************************************************************************80
12186 //
12187 //  Purpose:
12188 //
12189 //    S_LEN_TRIM returns the length of a string to the last nonblank.
12190 //
12191 //  Licensing:
12192 //
12193 //    This code is distributed under the GNU LGPL license.
12194 //
12195 //  Modified:
12196 //
12197 //    26 April 2003
12198 //
12199 //  Author:
12200 //
12201 //    John Burkardt
12202 //
12203 //  Parameters:
12204 //
12205 //    Input, char *S, a pointer to a string.
12206 //
12207 //    Output, int S_LEN_TRIM, the length of the string to the last nonblank.
12208 //    If S_LEN_TRIM is 0, then the string is entirely blank.
12209 //
12210 {
12211   int n;
12212   char *t;
12213 
12214   n = strlen ( s );
12215   t = s + strlen ( s ) - 1;
12216 
12217   while ( 0 < n )
12218   {
12219     if ( *t != ' ' )
12220     {
12221       return n;
12222     }
12223     t--;
12224     n--;
12225   }
12226 
12227   return n;
12228 }
12229 //****************************************************************************80
12230 
12231 int s_to_i4 ( char *s, int *last, bool *error )
12232 
12233 //****************************************************************************80
12234 //
12235 //  Purpose:
12236 //
12237 //    S_TO_I4 reads an I4 from a string.
12238 //
12239 //  Licensing:
12240 //
12241 //    This code is distributed under the GNU LGPL license.
12242 //
12243 //  Modified:
12244 //
12245 //    13 June 2003
12246 //
12247 //  Author:
12248 //
12249 //    John Burkardt
12250 //
12251 //  Parameters:
12252 //
12253 //    Input, char *S, a string to be examined.
12254 //
12255 //    Output, int *LAST, the last character of S used to make IVAL.
12256 //
12257 //    Output, bool *ERROR is TRUE if an error occurred.
12258 //
12259 //    Output, int *S_TO_I4, the integer value read from the string.
12260 //    If the string is blank, then IVAL will be returned 0.
12261 //
12262 {
12263   char c;
12264   int i;
12265   int isgn;
12266   int istate;
12267   int ival;
12268 
12269   *error = false;
12270   istate = 0;
12271   isgn = 1;
12272   i = 0;
12273   ival = 0;
12274 
12275   while ( *s )
12276   {
12277     c = s[i];
12278     i = i + 1;
12279 //
12280 //  Haven't read anything.
12281 //
12282     if ( istate == 0 )
12283     {
12284       if ( c == ' ' )
12285       {
12286       }
12287       else if ( c == '-' )
12288       {
12289         istate = 1;
12290         isgn = -1;
12291       }
12292       else if ( c == '+' )
12293       {
12294         istate = 1;
12295         isgn = + 1;
12296       }
12297       else if ( '0' <= c && c <= '9' )
12298       {
12299         istate = 2;
12300         ival = c - '0';
12301       }
12302       else
12303       {
12304         *error = true;
12305         return ival;
12306       }
12307     }
12308 //
12309 //  Have read the sign, expecting digits.
12310 //
12311     else if ( istate == 1 )
12312     {
12313       if ( c == ' ' )
12314       {
12315       }
12316       else if ( '0' <= c && c <= '9' )
12317       {
12318         istate = 2;
12319         ival = c - '0';
12320       }
12321       else
12322       {
12323         *error = true;
12324         return ival;
12325       }
12326     }
12327 //
12328 //  Have read at least one digit, expecting more.
12329 //
12330     else if ( istate == 2 )
12331     {
12332       if ( '0' <= c && c <= '9' )
12333       {
12334         ival = 10 * (ival) + c - '0';
12335       }
12336       else
12337       {
12338         ival = isgn * ival;
12339         *last = i - 1;
12340         return ival;
12341       }
12342 
12343     }
12344   }
12345 //
12346 //  If we read all the characters in the string, see if we're OK.
12347 //
12348   if ( istate == 2 )
12349   {
12350     ival = isgn * ival;
12351     *last = s_len_trim ( s );
12352   }
12353   else
12354   {
12355     *error = true;
12356     *last = 0;
12357   }
12358 
12359   return ival;
12360 }
12361 //****************************************************************************80
12362 
12363 bool s_to_i4vec ( char *s, int n, int ivec[] )
12364 
12365 //****************************************************************************80
12366 //
12367 //  Purpose:
12368 //
12369 //    S_TO_I4VEC reads an I4VEC from a string.
12370 //
12371 //  Licensing:
12372 //
12373 //    This code is distributed under the GNU LGPL license.
12374 //
12375 //  Modified:
12376 //
12377 //    19 January 2004
12378 //
12379 //  Author:
12380 //
12381 //    John Burkardt
12382 //
12383 //  Parameters:
12384 //
12385 //    Input, char *S, the string to be read.
12386 //
12387 //    Input, int N, the number of values expected.
12388 //
12389 //    Output, int IVEC[N], the values read from the string.
12390 //
12391 //    Output, bool S_TO_I4VEC, is TRUE if an error occurred.
12392 //
12393 {
12394   bool error;
12395   int i;
12396   int lchar;
12397 
12398   error = false;
12399 
12400   for ( i = 0; i < n; i++ )
12401   {
12402     ivec[i] = s_to_i4 ( s, &lchar, &error );
12403 
12404     if ( error )
12405     {
12406       cout << "\n";
12407       cout << "S_TO_I4VEC - Fatal error!\n";
12408       cout << "  S_TO_I4 returned error while reading item " << i << "\n";
12409       return error;
12410     }
12411 
12412     s = s + lchar;
12413 
12414   }
12415 
12416   return error;
12417 }
12418 //****************************************************************************80
12419 
12420 float s_to_r4 ( char *s, int *lchar, bool *error )
12421 
12422 //****************************************************************************80
12423 //
12424 //  Purpose:
12425 //
12426 //    S_TO_R4 reads an R4 from a string.
12427 //
12428 //  Discussion:
12429 //
12430 //    This routine will read as many characters as possible until it reaches
12431 //    the end of the string, or encounters a character which cannot be
12432 //    part of the real number.
12433 //
12434 //    Legal input is:
12435 //
12436 //       1 blanks,
12437 //       2 '+' or '-' sign,
12438 //       2.5 spaces
12439 //       3 integer part,
12440 //       4 decimal point,
12441 //       5 fraction part,
12442 //       6 'E' or 'e' or 'D' or 'd', exponent marker,
12443 //       7 exponent sign,
12444 //       8 exponent integer part,
12445 //       9 exponent decimal point,
12446 //      10 exponent fraction part,
12447 //      11 blanks,
12448 //      12 final comma or semicolon.
12449 //
12450 //    with most quantities optional.
12451 //
12452 //  Example:
12453 //
12454 //    S                 R
12455 //
12456 //    '1'               1.0
12457 //    '     1   '       1.0
12458 //    '1A'              1.0
12459 //    '12,34,56'        12.0
12460 //    '  34 7'          34.0
12461 //    '-1E2ABCD'        -100.0
12462 //    '-1X2ABCD'        -1.0
12463 //    ' 2E-1'           0.2
12464 //    '23.45'           23.45
12465 //    '-4.2E+2'         -420.0
12466 //    '17d2'            1700.0
12467 //    '-14e-2'         -0.14
12468 //    'e2'              100.0
12469 //    '-12.73e-9.23'   -12.73 * 10.0**(-9.23)
12470 //
12471 //  Licensing:
12472 //
12473 //    This code is distributed under the GNU LGPL license.
12474 //
12475 //  Modified:
12476 //
12477 //    07 August 2003
12478 //
12479 //  Author:
12480 //
12481 //    John Burkardt
12482 //
12483 //  Parameters:
12484 //
12485 //    Input, char *S, the string containing the
12486 //    data to be read.  Reading will begin at position 1 and
12487 //    terminate at the end of the string, or when no more
12488 //    characters can be read to form a legal real.  Blanks,
12489 //    commas, or other nonnumeric data will, in particular,
12490 //    cause the conversion to halt.
12491 //
12492 //    Output, int *LCHAR, the number of characters read from
12493 //    the string to form the number, including any terminating
12494 //    characters such as a trailing comma or blanks.
12495 //
12496 //    Output, bool *ERROR, is true if an error occurred.
12497 //
12498 //    Output, float S_TO_R4, the real value that was read from the string.
12499 //
12500 {
12501   char c;
12502   int ihave;
12503   int isgn;
12504   int iterm;
12505   int jbot;
12506   int jsgn;
12507   int jtop;
12508   int nchar;
12509   int ndig;
12510   float r;
12511   float rbot;
12512   float rexp;
12513   float rtop;
12514   char TAB = 9;
12515 
12516   nchar = s_len_trim ( s );
12517   *error = false;
12518   r = 0.0E+00;
12519   *lchar = -1;
12520   isgn = 1;
12521   rtop = 0.0E+00;
12522   rbot = 1.0E+00;
12523   jsgn = 1;
12524   jtop = 0;
12525   jbot = 1;
12526   ihave = 1;
12527   iterm = 0;
12528 
12529   for ( ; ; )
12530   {
12531     c = s[*lchar+1];
12532     *lchar = *lchar + 1;
12533 //
12534 //  Blank or TAB character.
12535 //
12536     if ( c == ' ' || c == TAB )
12537     {
12538       if ( ihave == 2 )
12539       {
12540       }
12541       else if ( ihave == 6 || ihave == 7 )
12542       {
12543         iterm = 1;
12544       }
12545       else if ( 1 < ihave )
12546       {
12547         ihave = 11;
12548       }
12549     }
12550 //
12551 //  Comma.
12552 //
12553     else if ( c == ',' || c == ';' )
12554     {
12555       if ( ihave != 1 )
12556       {
12557         iterm = 1;
12558         ihave = 12;
12559         *lchar = *lchar + 1;
12560       }
12561     }
12562 //
12563 //  Minus sign.
12564 //
12565     else if ( c == '-' )
12566     {
12567       if ( ihave == 1 )
12568       {
12569         ihave = 2;
12570         isgn = -1;
12571       }
12572       else if ( ihave == 6 )
12573       {
12574         ihave = 7;
12575         jsgn = -1;
12576       }
12577       else
12578       {
12579         iterm = 1;
12580       }
12581     }
12582 //
12583 //  Plus sign.
12584 //
12585     else if ( c == '+' )
12586     {
12587       if ( ihave == 1 )
12588       {
12589         ihave = 2;
12590       }
12591       else if ( ihave == 6 )
12592       {
12593         ihave = 7;
12594       }
12595       else
12596       {
12597         iterm = 1;
12598       }
12599     }
12600 //
12601 //  Decimal point.
12602 //
12603     else if ( c == '.' )
12604     {
12605       if ( ihave < 4 )
12606       {
12607         ihave = 4;
12608       }
12609       else if ( 6 <= ihave && ihave <= 8 )
12610       {
12611         ihave = 9;
12612       }
12613       else
12614       {
12615         iterm = 1;
12616       }
12617     }
12618 //
12619 //  Exponent marker.
12620 //
12621     else if ( ch_eqi ( c, 'E' ) || ch_eqi ( c, 'D' ) )
12622     {
12623       if ( ihave < 6 )
12624       {
12625         ihave = 6;
12626       }
12627       else
12628       {
12629         iterm = 1;
12630       }
12631     }
12632 //
12633 //  Digit.
12634 //
12635     else if ( ihave < 11 && '0' <= c && c <= '9' )
12636     {
12637       if ( ihave <= 2 )
12638       {
12639         ihave = 3;
12640       }
12641       else if ( ihave == 4 )
12642       {
12643         ihave = 5;
12644       }
12645       else if ( ihave == 6 || ihave == 7 )
12646       {
12647         ihave = 8;
12648       }
12649       else if ( ihave == 9 )
12650       {
12651         ihave = 10;
12652       }
12653 
12654       ndig = ch_to_digit ( c );
12655 
12656       if ( ihave == 3 )
12657       {
12658         rtop = 10.0E+00 * rtop + ( float ) ndig;
12659       }
12660       else if ( ihave == 5 )
12661       {
12662         rtop = 10.0E+00 * rtop + ( float ) ndig;
12663         rbot = 10.0E+00 * rbot;
12664       }
12665       else if ( ihave == 8 )
12666       {
12667         jtop = 10 * jtop + ndig;
12668       }
12669       else if ( ihave == 10 )
12670       {
12671         jtop = 10 * jtop + ndig;
12672         jbot = 10 * jbot;
12673       }
12674     }
12675 //
12676 //  Anything else is regarded as a terminator.
12677 //
12678     else
12679     {
12680       iterm = 1;
12681     }
12682 //
12683 //  If we haven't seen a terminator, and we haven't examined the
12684 //  entire string, go get the next character.
12685 //
12686     if ( iterm == 1 || nchar <= *lchar + 1 )
12687     {
12688       break;
12689     }
12690 
12691   }
12692 //
12693 //  If we haven't seen a terminator, and we have examined the
12694 //  entire string, then we're done, and LCHAR is equal to NCHAR.
12695 //
12696   if ( iterm != 1 && (*lchar) + 1 == nchar )
12697   {
12698     *lchar = nchar;
12699   }
12700 //
12701 //  Number seems to have terminated.  Have we got a legal number?
12702 //  Not if we terminated in states 1, 2, 6 or 7!
12703 //
12704   if ( ihave == 1 || ihave == 2 || ihave == 6 || ihave == 7 )
12705   {
12706     *error = true;
12707     return r;
12708   }
12709 //
12710 //  Number seems OK.  Form it.
12711 //
12712   if ( jtop == 0 )
12713   {
12714     rexp = 1.0E+00;
12715   }
12716   else
12717   {
12718     if ( jbot == 1 )
12719     {
12720       rexp = pow ( ( double ) 10.0E+00, ( double ) ( jsgn * jtop ) );
12721     }
12722     else
12723     {
12724       rexp = jsgn * jtop;
12725       rexp = rexp / jbot;
12726       rexp = pow ( ( double ) 10.0E+00, ( double ) rexp );
12727     }
12728 
12729   }
12730 
12731   r = isgn * rexp * rtop / rbot;
12732 
12733   return r;
12734 }
12735 //****************************************************************************80
12736 
12737 bool s_to_r4vec ( char *s, int n, float rvec[] )
12738 
12739 //****************************************************************************80
12740 //
12741 //  Purpose:
12742 //
12743 //    S_TO_R4VEC reads an R4VEC from a string.
12744 //
12745 //  Licensing:
12746 //
12747 //    This code is distributed under the GNU LGPL license.
12748 //
12749 //  Modified:
12750 //
12751 //    19 February 2001
12752 //
12753 //  Author:
12754 //
12755 //    John Burkardt
12756 //
12757 //  Parameters:
12758 //
12759 //    Input, character ( len = * ) S, the string to be read.
12760 //
12761 //    Input, integer N, the number of values expected.
12762 //
12763 //    Output, real RVEC[N], the values read from the string.
12764 //
12765 //    Output, bool S_TO_R4VEC, is true if an error occurred.
12766 //
12767 {
12768   bool error;
12769   int i;
12770   int lchar;
12771 
12772   error = false;
12773 
12774   for ( i = 0; i < n; i++ )
12775   {
12776     rvec[i] = s_to_r4 ( s, &lchar, &error );
12777 
12778     if ( error )
12779     {
12780       return error;
12781     }
12782 
12783     s = s + lchar;
12784 
12785   }
12786 
12787   return error;
12788 }
12789 //****************************************************************************80
12790 
12791 short int short_int_read ( FILE *filein )
12792 
12793 //****************************************************************************80
12794 //
12795 //  Purpose:
12796 //
12797 //    SHORT_INT_READ reads a short int from a binary file.
12798 //
12799 //  Licensing:
12800 //
12801 //    This code is distributed under the GNU LGPL license.
12802 //
12803 //  Modified:
12804 //
12805 //    14 October 1998
12806 //
12807 //  Author:
12808 //
12809 //    John Burkardt
12810 //
12811 {
12812   unsigned char  c1;
12813   unsigned char  c2;
12814   short int      ival;
12815 
12816   c1 = fgetc ( filein );
12817   c2 = fgetc ( filein );
12818 
12819   ival = c1 | ( c2 << 8 );
12820 
12821   return ival;
12822 }
12823 //****************************************************************************80
12824 
12825 int short_int_write ( FILE *fileout, short int short_int_val )
12826 
12827 //****************************************************************************80
12828 //
12829 //  Purpose:
12830 //
12831 //    SHORT_INT_WRITE writes a short int to a binary file.
12832 //
12833 //  Licensing:
12834 //
12835 //    This code is distributed under the GNU LGPL license.
12836 //
12837 //  Modified:
12838 //
12839 //    14 October 1998
12840 //
12841 //  Author:
12842 //
12843 //    John Burkardt
12844 //
12845 {
12846   union {
12847     short int yint;
12848     char ychar[2];
12849   } y;
12850 
12851   y.yint = short_int_val;
12852 
12853   if ( byte_swap )
12854   {
12855     fputc ( y.ychar[1], fileout );
12856     fputc ( y.ychar[0], fileout );
12857   }
12858   else
12859   {
12860     fputc ( y.ychar[0], fileout );
12861     fputc ( y.ychar[1], fileout );
12862   }
12863 
12864   return 2;
12865 }
12866 //****************************************************************************80
12867 
12868 int smf_read ( FILE *filein )
12869 
12870 //****************************************************************************80
12871 //
12872 //  Purpose:
12873 //
12874 //    SMF_READ reads an SMF file.
12875 //
12876 //  Example:
12877 //
12878 //    #SMF2.0
12879 //    #  cube_face.smf
12880 //    #  This example demonstrates how an RGB color can be assigned to
12881 //    #  each face of an object.
12882 //    #
12883 //    # First, define the geometry of the cube.
12884 //    #
12885 //    v 0.0  0.0  0.0
12886 //    v 1.0  0.0  0.0
12887 //    v 0.0  1.0  0.0
12888 //    v 1.0  1.0  0.0
12889 //    v 0.0  0.0  1.0
12890 //    v 1.0  0.0  1.0
12891 //    v 0.0  1.0  1.0
12892 //    v 1.0  1.0  1.0
12893 //    f 1 4 2
12894 //    f 1 3 4
12895 //    f 5 6 8
12896 //    f 5 8 7
12897 //    f 1 2 6
12898 //    f 1 6 5
12899 //    f 2 4 8
12900 //    f 2 8 6
12901 //    f 4 3 7
12902 //    f 4 7 8
12903 //    f 3 1 5
12904 //    f 3 5 7
12905 //    #
12906 //    #  Colors will be bound 1 per face.
12907 //    #
12908 //    bind c face
12909 //    c 1.0  0.0  0.0
12910 //    c 1.0  0.0  0.0
12911 //    c 0.0  1.0  0.0
12912 //    c 0.0  1.0  0.0
12913 //    c 0.0  0.0  1.0
12914 //    c 0.0  0.0  1.0
12915 //    c 1.0  1.0  0.0
12916 //    c 1.0  1.0  0.0
12917 //    c 0.0  1.0  1.0
12918 //    c 0.0  1.0  1.0
12919 //    c 1.0  0.0  1.0
12920 //    c 1.0  0.0  1.0
12921 //    #
12922 //    #  Normal vectors will be bound 1 per face.
12923 //    #
12924 //    bind n face
12925 //    n  0.0   0.0  -1.0
12926 //    n  0.0   0.0  -1.0
12927 //    n  0.0   0.0   1.0
12928 //    n  0.0   0.0   1.0
12929 //    n  0.0  -1.0   0.0
12930 //    n  0.0  -1.0   0.0
12931 //    n  1.0   0.0   0.0
12932 //    n  1.0   0.0   0.0
12933 //    n  0.0   1.0   0.0
12934 //    n  0.0   1.0   0.0
12935 //    n -1.0   0.0   0.0
12936 //    n -1.0   0.0   0.0
12937 //    #
12938 //    #  Texture coordinate pairs will be bound 1 per face.
12939 //    #
12940 //    bind r face
12941 //    r  0.0   0.0
12942 //    r  0.0   0.1
12943 //    r  0.0   0.2
12944 //    r  0.0   0.3
12945 //    r  0.1   0.0
12946 //    r  0.1   0.1
12947 //    r  0.1   0.2
12948 //    r  0.1   0.3
12949 //    r  0.2   0.0
12950 //    r  0.2   0.1
12951 //    r  0.2   0.2
12952 //    r  0.2   0.3
12953 //
12954 //  Licensing:
12955 //
12956 //    This code is distributed under the GNU LGPL license.
12957 //
12958 //  Modified:
12959 //
12960 //    03 July 1999
12961 //
12962 //  Author:
12963 //
12964 //    John Burkardt
12965 //
12966 {
12967   float angle;
12968   char axis;
12969   float b;
12970   char cnr[LINE_MAX_LEN];
12971   int count;
12972   float dx;
12973   float dy;
12974   int face_count;
12975   float g;
12976   int icor3_normal;
12977   int icor3_tex_uv;
12978   int iface_normal;
12979   int iface_tex_uv;
12980   int imat;
12981   int ivert;
12982   int level;
12983   char *next;
12984   int node;
12985   int node_count;
12986   float r;
12987   float r1;
12988   float r2;
12989   float r3;
12990   float rgba[4];
12991   char *string = "Dummy material";
12992   float sx;
12993   float sy;
12994   float sz;
12995   char token[LINE_MAX_LEN];
12996   char token2[LINE_MAX_LEN];
12997   char type[LINE_MAX_LEN];
12998   float u;
12999   float v;
13000   int vertex_base;
13001   int vertex_correction;
13002   int width;
13003   float x;
13004   float xvec[3];
13005   float y;
13006   float z;
13007 
13008   face_count = 0;
13009   icor3_normal = 0;
13010   icor3_tex_uv = 0;
13011   iface_normal = 0;
13012   iface_tex_uv = 0;
13013   level = 0;
13014   node_count = 0;
13015   vertex_base = 0;
13016   vertex_correction = 0;
13017 //
13018 //  Read the next line of the file into INPUT.
13019 //
13020   while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL )
13021   {
13022     text_num = text_num + 1;
13023 
13024     if ( debug )
13025     {
13026       cout << "SMF_READ: DEBUG: Reading line #" << text_num << "\n";
13027     }
13028 //
13029 //  Advance to the first nonspace character in INPUT.
13030 //
13031     for ( next = input; *next != '\0' && ch_is_space ( *next ); next++ )
13032     {
13033     }
13034 //
13035 //  Skip blank lines.
13036 //
13037 
13038     if ( *next == '\0' )
13039     {
13040       continue;
13041     }
13042 //
13043 //  Skip comment lines.
13044 //
13045     if ( *next == '#' || *next == '$' )
13046     {
13047       comment_num = comment_num + 1;
13048       continue;
13049     }
13050 //
13051 //  Extract the first word in this line.
13052 //
13053     sscanf ( next, "%s%n", token, &width );
13054 //
13055 //  Set NEXT to point to just after this token.
13056 //
13057     next = next + width;
13058 //
13059 //  BEGIN
13060 //  Reset the transformation matrix to identity.
13061 //  Node numbering starts at zero again.  (Really, this is level based)
13062 //  (Really should define a new transformation matrix, and concatenate.)
13063 //  (Also, might need to keep track of level.)
13064 //
13065     if ( s_eqi ( token, "BEGIN" ) )
13066     {
13067       level = level + 1;
13068       vertex_base = cor3_num;
13069       group_num = group_num + 1;
13070       tmat_init ( transform_matrix );
13071     }
13072 //
13073 //  BIND [c|n|r] [vertex|face]
13074 //  Specify the binding for RGB color, Normal, or Texture.
13075 //  Options are "vertex" or "face"
13076 //
13077     else if ( s_eqi ( token, "BIND" ) )
13078     {
13079       sscanf ( next, "%s%n", cnr, &width );
13080       next = next + width;
13081 
13082       if ( debug )
13083       {
13084         cout << "CNR = " << cnr << "\n";
13085       }
13086 
13087       sscanf ( next, "%s%n", type, &width );
13088       next = next + width;
13089 
13090       if ( debug )
13091       {
13092         cout << "TYPE = " << type << "\n";
13093       }
13094 
13095       if ( s_eqi ( cnr, "C" ) )
13096       {
13097         if ( s_eqi ( type, "VERTEX" ) )
13098         {
13099           strcpy ( material_binding, "PER_VERTEX" );
13100         }
13101         else if ( s_eqi ( type, "FACE" ) )
13102         {
13103           strcpy ( material_binding, "PER_FACE" );
13104         }
13105       }
13106       else if ( s_eqi ( cnr, "N" ) )
13107       {
13108         if ( s_eqi ( type, "VERTEX" ) )
13109         {
13110           strcpy ( normal_binding, "PER_VERTEX" );
13111         }
13112         else if ( s_eqi ( type, "FACE" ) )
13113         {
13114           strcpy ( normal_binding, "PER_FACE" );
13115         }
13116       }
13117       else if ( s_eqi ( cnr, "R" ) )
13118       {
13119         if ( s_eqi ( type, "VERTEX" ) )
13120         {
13121           strcpy ( texture_binding, "PER_VERTEX" );
13122         }
13123         else if ( s_eqi ( type, "FACE" ) )
13124         {
13125           strcpy ( texture_binding, "PER_FACE" );
13126         }
13127 
13128       }
13129 
13130     }
13131 //
13132 //  C <r> <g> <b>
13133 //  Specify an RGB color, with R, G, B between 0.0 and 1.0.
13134 //
13135     else if ( s_eqi ( token, "C" ) )
13136     {
13137       sscanf ( next, "%f%n", &r, &width );
13138       next = next + width;
13139 
13140       sscanf ( next, "%f%n", &g, &width );
13141       next = next + width;
13142 
13143       sscanf ( next, "%f%n", &b, &width );
13144       next = next + width;
13145 //
13146 //    Set up a temporary material (R,G,B,1.0).
13147 //    Add the material to the material database, or find the index of
13148 //      a matching material already in.
13149 //    Assign the material of the node or face to this index.
13150 //
13151       rgba[0] = r;
13152       rgba[1] = g;
13153       rgba[2] = b;
13154       rgba[3] = 1.0;
13155 
13156       if ( material_num < MATERIAL_MAX )
13157       {
13158         for ( k = 0; k < 4; k++ )
13159         {
13160           material_rgba[k][material_num] = rgba[k];
13161         }
13162 
13163         imat = material_num;
13164         material_num = material_num + 1;
13165 
13166       }
13167       else
13168       {
13169         imat = 0;
13170       }
13171 
13172       if ( s_eqi ( material_binding, "PER_FACE" ) )
13173       {
13174         face_count = face_count + 1;
13175         face_material[face_count] = imat;
13176       }
13177       else if ( s_eqi ( material_binding, "PER_VERTEX" ) )
13178       {
13179         node_count = node_count + 1;
13180         cor3_material[node_count] = imat;
13181 
13182       }
13183       else
13184       {
13185         cout << "\n";
13186         cout << "SMF_READ - Fatal error!\n";
13187         cout << "  Material binding undefined!\n";
13188         return 1;
13189 
13190       }
13191 
13192     }
13193 //
13194 //  END
13195 //  Drop down a level.
13196 //
13197     else if ( s_eqi ( token, "END" ) )
13198     {
13199       level = level - 1;
13200 
13201       if ( level < 0 )
13202       {
13203         cout << "\n";
13204         cout << "SMF_READ - Fatal error!\n";
13205         cout << "  More END statements than BEGINs!\n";
13206         return 1;
13207       }
13208     }
13209 //
13210 //  F V1 V2 V3
13211 //
13212 //  Face.
13213 //  A face is defined by the vertices.
13214 //  Node indices are 1 based rather than 0 based.
13215 //  So we have to decrement them before loading them into FACE.
13216 //  Note that vertex indices start back at 0 each time a BEGIN is entered.
13217 //  The strategy here won't handle nested BEGIN's, just one at a time.
13218 //
13219 
13220     else if ( s_eqi ( token, "F" ) )
13221     {
13222       ivert = 0;
13223       face_order[face_num] = 0;
13224 //
13225 //  Read each item in the F definition as a token, and then
13226 //  take it apart.
13227 //
13228       for ( ;; )
13229       {
13230         count = sscanf ( next, "%s%n", token2, &width );
13231         next = next + width;
13232 
13233         if ( count != 1 )
13234         {
13235           break;
13236         }
13237 
13238         count = sscanf ( token2, "%d%n", &node, &width );
13239 
13240         if ( count != 1 )
13241         {
13242           break;
13243         }
13244 
13245         if ( ivert < ORDER_MAX && face_num < FACE_MAX )
13246         {
13247           face[ivert][face_num] = node - 1 + vertex_base;
13248           vertex_material[ivert][face_num] = 0;
13249           face_order[face_num] = face_order[face_num] + 1;
13250         }
13251         ivert = ivert + 1;
13252       }
13253       face_num = face_num + 1;
13254     }
13255 //
13256 //  N <x> <y> <z>
13257 //  Specify a normal vector.
13258 //
13259     else if ( s_eqi ( token, "N" ) )
13260     {
13261       sscanf ( next, "%f%n", &x, &width );
13262       next = next + width;
13263 
13264       sscanf ( next, "%f%n", &y, &width );
13265       next = next + width;
13266 
13267       sscanf ( next, "%f%n", &z, &width );
13268       next = next + width;
13269 
13270       if ( s_eqi ( normal_binding, "PER_FACE" ) )
13271       {
13272         face_normal[0][iface_normal] = x;
13273         face_normal[1][iface_normal] = y;
13274         face_normal[2][iface_normal] = z;
13275 
13276         iface_normal = iface_normal + 1;
13277       }
13278       else if ( s_eqi ( normal_binding, "PER_VERTEX" ) )
13279       {
13280         cor3_normal[0][icor3_normal] = x;
13281         cor3_normal[1][icor3_normal] = y;
13282         cor3_normal[2][icor3_normal] = z;
13283 
13284         icor3_normal = icor3_normal + 1;
13285       }
13286       else
13287       {
13288         cout << "\n";
13289         cout << "SMF_READ - Fatal error!\n";
13290         cout << "  Normal binding undefined!\n";
13291         return 1;
13292 
13293       }
13294     }
13295 //
13296 //  R <u> <v>
13297 //  Specify a texture coordinate.
13298 //
13299     else if ( s_eqi ( token, "R" ) )
13300     {
13301       sscanf ( next, "%f%n", &u, &width );
13302       next = next + width;
13303 
13304       sscanf ( next, "%f%n", &v, &width );
13305       next = next + width;
13306 
13307       if ( s_eqi ( texture_binding, "PER_FACE" ) )
13308       {
13309         face_tex_uv[0][iface_tex_uv] = u;
13310         face_tex_uv[1][iface_tex_uv] = v;
13311 
13312         icor3_tex_uv = icor3_tex_uv + 1;
13313 
13314       }
13315       else if ( s_eqi ( texture_binding, "PER_VERTEX" ) )
13316       {
13317         cor3_tex_uv[0][icor3_tex_uv] = u;
13318         cor3_tex_uv[1][icor3_tex_uv] = v;
13319 
13320         icor3_tex_uv = icor3_tex_uv + 1;
13321       }
13322       else
13323       {
13324         cout << "\n";
13325         cout << "SMF_READ - Fatal error!\n";
13326         cout << "  Texture binding undefined!\n";
13327         return 1;
13328       }
13329 
13330     }
13331 //
13332 //  ROT [x|y|z] <theta>
13333 //
13334     else if ( s_eqi ( token, "ROT" ) )
13335     {
13336       sscanf ( next, "%c%n", &axis, &width );
13337       next = next + width;
13338 
13339       sscanf ( next, "%f%n", &angle, &width );
13340       next = next + width;
13341 
13342       tmat_rot_axis ( transform_matrix, transform_matrix, angle, axis );
13343     }
13344 //
13345 //  SCALE <sx> <sy> <sz>
13346 //
13347     else if ( s_eqi ( token, "SCALE" ) )
13348     {
13349       sscanf ( next, "%f%n", &sx, &width );
13350       next = next + width;
13351 
13352       sscanf ( next, "%f%n", &sy, &width );
13353       next = next + width;
13354 
13355       sscanf ( next, "%f%n", &sz, &width );
13356       next = next + width;
13357 
13358       tmat_scale ( transform_matrix, transform_matrix, sx, sy, sz );
13359     }
13360 //
13361 //  SET VERTEX_CORRECTION <i>
13362 //  Specify increment to add to vertex indices in file.
13363 //
13364     else if ( s_eqi ( token, "SET" ) )
13365     {
13366       sscanf ( next, "%s%n", cnr, &width );
13367       next = next + width;
13368 
13369       sscanf ( next, "%d%n", &vertex_correction, &width );
13370       next = next + width;
13371     }
13372 //
13373 //  T_SCALE <dx> <dy>
13374 //  Specify a scaling to texture coordinates.
13375 //
13376     else if ( s_eqi ( token, "T_SCALE" ) )
13377     {
13378       sscanf ( next, "%f%n", &dx, &width );
13379       next = next + width;
13380 
13381       sscanf ( next, "%f%n", &dy, &width );
13382       next = next + width;
13383     }
13384 //
13385 //  T_TRANS <dx> <dy>
13386 //  Specify a translation to texture coordinates.
13387 //
13388     else if ( s_eqi ( token, "T_TRANS" ) )
13389     {
13390       sscanf ( next, "%f%n", &dx, &width );
13391       next = next + width;
13392 
13393       sscanf ( next, "%f%n", &dy, &width );
13394       next = next + width;
13395     }
13396 //
13397 //  TEX <filename>
13398 //  Specify a filename containing the texture.
13399 //  (ANY CHANCE THIS IS RIGHT?)
13400 //  The compiler warns that STRING is not initialized.
13401 //
13402     else if ( s_eqi ( token, "TEX" ) )
13403     {
13404       sscanf ( next, "%s%n", string, &width );
13405 
13406       for ( i = 0; i < LINE_MAX_LEN; i++ )
13407       {
13408         texture_name[texture_num][i] = string[i];
13409         if ( string[i] == '\0' )
13410         {
13411           break;
13412         }
13413       }
13414 
13415       texture_num = texture_num + 1;
13416     }
13417 //
13418 //  TRANS <dx> <dy> <dz>
13419 //
13420     else if ( s_eqi ( token, "TRANS" ) )
13421     {
13422       sscanf ( next, "%f%n", &x, &width );
13423       next = next + width;
13424 
13425       sscanf ( next, "%f%n", &y, &width );
13426       next = next + width;
13427 
13428       sscanf ( next, "%f%n", &z, &width );
13429       next = next + width;
13430 
13431       tmat_trans ( transform_matrix, transform_matrix, x, y, z );
13432     }
13433 //
13434 //  V X Y Z
13435 //  Geometric vertex.
13436 //
13437     else if ( s_eqi ( token, "V" ) )
13438     {
13439       sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
13440 
13441       xvec[0] = r1;
13442       xvec[1] = r2;
13443       xvec[2] = r3;
13444 //
13445 //  Apply current transformation matrix.
13446 //  Right now, we can only handle one matrix, not a stack of
13447 //  matrices representing nested BEGIN/END's.
13448 //
13449       tmat_mxp ( transform_matrix, xvec, xvec );
13450 
13451       if ( cor3_num < COR3_MAX )
13452       {
13453         for ( i = 0; i < 3; i++ )
13454         {
13455           cor3[i][cor3_num] = xvec[i];
13456         }
13457       }
13458 
13459       cor3_num = cor3_num + 1;
13460 
13461     }
13462 //
13463 //  Unrecognized keyword.
13464 //
13465     else
13466     {
13467       bad_num = bad_num + 1;
13468 
13469       if ( bad_num <= 10 )
13470       {
13471         cout << "\n";
13472         cout << "SMF_READ: Bad data on line " << text_num << ".\n";
13473       }
13474     }
13475 
13476   }
13477 //
13478 //  Extend the material definition
13479 //  * from the face to the vertices and nodes, or
13480 //  * from the vertices to the faces and nodes.
13481 //
13482   if ( strcmp ( material_binding, "PER_FACE" ) == 0 )
13483   {
13484     face_to_vertex_material ( );
13485 
13486     vertex_to_node_material ( );
13487 
13488   }
13489   else if ( strcmp ( material_binding, "PER_VERTEX" ) == 0 )
13490   {
13491     node_to_vertex_material ( );
13492 
13493     vertex_to_face_material ( );
13494 
13495   }
13496 
13497   return 0;
13498 }
13499 //****************************************************************************80
13500 
13501 int smf_write ( FILE *fileout )
13502 
13503 //****************************************************************************80
13504 //
13505 //  Purpose:
13506 //
13507 //    SMF_WRITE writes graphics information to an SMF file.
13508 //
13509 //  Example:
13510 //
13511 //    #SMF2.0
13512 //    #  cube_face.smf
13513 //    #  This example demonstrates how an RGB color can be assigned to
13514 //    #  each face of an object.
13515 //    #
13516 //    # First, define the geometry of the cube.
13517 //    #
13518 //    v 0.0  0.0  0.0
13519 //    v 1.0  0.0  0.0
13520 //    v 0.0  1.0  0.0
13521 //    v 1.0  1.0  0.0
13522 //    v 0.0  0.0  1.0
13523 //    v 1.0  0.0  1.0
13524 //    v 0.0  1.0  1.0
13525 //    v 1.0  1.0  1.0
13526 //    f 1 4 2
13527 //    f 1 3 4
13528 //    f 5 6 8
13529 //    f 5 8 7
13530 //    f 1 2 6
13531 //    f 1 6 5
13532 //    f 2 4 8
13533 //    f 2 8 6
13534 //    f 4 3 7
13535 //    f 4 7 8
13536 //    f 3 1 5
13537 //    f 3 5 7
13538 //    #
13539 //    #  Colors will be bound 1 per face.
13540 //    #
13541 //    bind c face
13542 //    c 1.0  0.0  0.0
13543 //    c 1.0  0.0  0.0
13544 //    c 0.0  1.0  0.0
13545 //    c 0.0  1.0  0.0
13546 //    c 0.0  0.0  1.0
13547 //    c 0.0  0.0  1.0
13548 //    c 1.0  1.0  0.0
13549 //    c 1.0  1.0  0.0
13550 //    c 0.0  1.0  1.0
13551 //    c 0.0  1.0  1.0
13552 //    c 1.0  0.0  1.0
13553 //    c 1.0  0.0  1.0
13554 //    #
13555 //    #  Normal vectors will be bound 1 per face.
13556 //    #
13557 //    bind n face
13558 //    n  0.0   0.0  -1.0
13559 //    n  0.0   0.0  -1.0
13560 //    n  0.0   0.0   1.0
13561 //    n  0.0   0.0   1.0
13562 //    n  0.0  -1.0   0.0
13563 //    n  0.0  -1.0   0.0
13564 //    n  1.0   0.0   0.0
13565 //    n  1.0   0.0   0.0
13566 //    n  0.0   1.0   0.0
13567 //    n  0.0   1.0   0.0
13568 //    n -1.0   0.0   0.0
13569 //    n -1.0   0.0   0.0
13570 //    #
13571 //    #  Texture coordinate pairs will be bound 1 per face.
13572 //    #
13573 //    bind r face
13574 //    r  0.0   0.0
13575 //    r  0.0   0.1
13576 //    r  0.0   0.2
13577 //    r  0.0   0.3
13578 //    r  0.1   0.0
13579 //    r  0.1   0.1
13580 //    r  0.1   0.2
13581 //    r  0.1   0.3
13582 //    r  0.2   0.0
13583 //    r  0.2   0.1
13584 //    r  0.2   0.2
13585 //    r  0.2   0.3
13586 //
13587 //  Licensing:
13588 //
13589 //    This code is distributed under the GNU LGPL license.
13590 //
13591 //  Modified:
13592 //
13593 //    05 July 1999
13594 //
13595 //  Author:
13596 //
13597 //    John Burkardt
13598 //
13599 {
13600   int i;
13601   int icor3;
13602   int iface;
13603   int imat;
13604   int ivert;
13605   int text_num;
13606 //
13607 //  Initialize.
13608 //
13609   text_num = 0;
13610 
13611   fprintf ( fileout, "#$SMF 2.0\n" );
13612   fprintf ( fileout, "#$vertices %d\n", cor3_num );
13613   fprintf ( fileout, "#$faces %d\n", face_num );
13614   fprintf ( fileout, "#\n" );
13615   fprintf ( fileout, "# %s created by IVCON.\n", fileout_name );
13616   fprintf ( fileout, "# Original data in %s.\n", filein_name );
13617   fprintf ( fileout, "#\n" );
13618 
13619   text_num = text_num + 7;
13620 //
13621 //  V: vertex coordinates.
13622 //
13623   for ( i = 0; i < cor3_num; i++ )
13624   {
13625     fprintf ( fileout, "v %f %f %f\n",
13626       cor3[0][i], cor3[1][i], cor3[2][i] );
13627     text_num = text_num + 1;
13628   }
13629 //
13630 //  F: faces.
13631 //
13632   if ( 0 < face_num )
13633   {
13634     fprintf ( fileout, "\n" );
13635     text_num = text_num + 1;
13636   }
13637 
13638   for ( iface = 0; iface < face_num; iface++ )
13639   {
13640     fprintf ( fileout, "f" );
13641     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
13642     {
13643       fprintf ( fileout, " %d", face[ivert][iface]+1 );
13644     }
13645     fprintf ( fileout, "\n" );
13646     text_num = text_num + 1;
13647   }
13648 //
13649 //  Material binding.
13650 //
13651   fprintf ( fileout, "bind c vertex\n" );
13652   text_num = text_num + 1;
13653 //
13654 //  Material RGB values at each node.
13655 //
13656   for ( icor3 = 0; icor3 < cor3_num; icor3++ )
13657   {
13658     imat = cor3_material[icor3];
13659 
13660     fprintf ( fileout, "c %f %f %f\n", material_rgba[0][imat],
13661       material_rgba[1][imat], material_rgba[2][imat] );
13662 
13663     text_num = text_num + 1;
13664   }
13665 //
13666 //  Normal binding.
13667 //
13668   fprintf ( fileout, "bind n vertex\n" );
13669   text_num = text_num + 1;
13670 //
13671 //  Normal vector at each node.
13672 //
13673   for ( icor3 = 0; icor3 < cor3_num; icor3++ )
13674   {
13675     fprintf ( fileout, "n %f %f %f\n", cor3_normal[0][icor3],
13676       cor3_normal[1][icor3], cor3_normal[2][icor3] );
13677 
13678     text_num = text_num + 1;
13679   }
13680 
13681   if ( 0 < texture_num )
13682   {
13683 //
13684 //  Texture filename.
13685 //
13686     fprintf ( fileout, "tex %s\n", texture_name[0] );
13687     text_num = text_num + 1;
13688 //
13689 //  Texture binding.
13690 //
13691     fprintf ( fileout, "bind r vertex\n" );
13692     text_num = text_num + 1;
13693 //
13694 //  Texture coordinates at each node.
13695 //
13696     for ( icor3 = 0; icor3 < cor3_num; icor3++ )
13697     {
13698       fprintf ( fileout, "r %f %f\n", cor3_tex_uv[0][icor3],
13699         cor3_tex_uv[1][icor3] );
13700       text_num = text_num + 1;
13701     }
13702 
13703   }
13704 //
13705 //  Report.
13706 //
13707   cout << "\n";
13708   cout << "SMF_WRITE - Wrote " << text_num << " text lines.\n";
13709 
13710   return 0;
13711 }
13712 //****************************************************************************80
13713 
13714 void sort_heap_external ( int n, int *indx, int *i, int *j, int isgn )
13715 
13716 //****************************************************************************80
13717 //
13718 //  Purpose:
13719 //
13720 //    SORT_HEAP_EXTERNAL externally sorts a list of items into linear order.
13721 //
13722 //  Discussion:
13723 //
13724 //    The actual list is not passed to the routine.  Hence it may
13725 //    consist of ints, reals, numbers, names, etc.  The user,
13726 //    after each return from the routine, will be asked to compare or
13727 //    interchange two items.
13728 //
13729 //  Licensing:
13730 //
13731 //    This code is distributed under the GNU LGPL license.
13732 //
13733 //  Modified:
13734 //
13735 //    20 May 1999
13736 //
13737 //  Author:
13738 //
13739 //    Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf.
13740 //    C++ version by John Burkardt.
13741 //
13742 //  Parameters:
13743 //
13744 //    Input, int N, the length of the input list.
13745 //
13746 //    Input/output, int *INDX.
13747 //
13748 //    The user must set INDX to 0 before the first call.
13749 //
13750 //    On return,
13751 //
13752 //      if INDX is greater than 0, the user must interchange
13753 //      items I and J and recall the routine.
13754 //
13755 //      If INDX is less than 0, the user is to compare items I
13756 //      and J and return in ISGN a negative value if I is to
13757 //      precede J, and a positive value otherwise.
13758 //
13759 //      If INDX is 0, the sorting is done.
13760 //
13761 //    Output, int *I, *J.  On return with INDX positive,
13762 //    elements I and J of the user's list should be
13763 //    interchanged.  On return with INDX negative, elements I
13764 //    and J are to be compared by the user.
13765 //
13766 //    Input, int ISGN. On return with INDX negative, the
13767 //    user should compare elements I and J of the list.  If
13768 //    item I is to precede item J, set ISGN negative,
13769 //    otherwise set ISGN positive.
13770 //
13771 {
13772   static int k = 0;
13773   static int k1 = 0;
13774   static int n1 = 0;
13775 
13776   if ( *indx == 0 )
13777   {
13778 
13779     n1 = n;
13780     k = n / 2;
13781     k1 = k;
13782 
13783   }
13784   else if ( *indx < 0 )
13785   {
13786 
13787     if ( *indx == -2 )
13788     {
13789 
13790       if ( isgn < 0 )
13791       {
13792         *i = *i + 1;
13793       }
13794 
13795       *j = k1 - 1;
13796       k1 = *i + 1;
13797       *indx = - 1;
13798       return;
13799 
13800     }
13801 
13802     if ( 0 < isgn )
13803     {
13804       *indx = 2;
13805       return;
13806     }
13807 
13808     if ( k <= 1 )
13809     {
13810 
13811       if ( n1 == 1 )
13812       {
13813         *indx = 0;
13814       }
13815       else
13816       {
13817         *i = n1 - 1;
13818         n1 = n1 - 1;
13819         *j = 0;
13820         *indx = 1;
13821       }
13822 
13823       return;
13824 
13825     }
13826 
13827     k = k - 1;
13828     k1 = k;
13829 
13830   }
13831   else if ( *indx == 1 )
13832   {
13833     k1 = k;
13834   }
13835 
13836   for ( ;; )
13837   {
13838 
13839     *i = 2 * k1 - 1;
13840 
13841     if ( *i == n1 - 1 )
13842     {
13843       *j = k1 - 1;
13844       k1 = *i + 1;
13845       *indx = - 1;
13846       return;
13847     }
13848     else if ( *i <= n1 - 1 )
13849     {
13850       *j = *i + 1;
13851       *indx = - 2;
13852       return;
13853     }
13854 
13855     if ( k <= 1 )
13856     {
13857       break;
13858     }
13859 
13860     k = k - 1;
13861     k1 = k;
13862   }
13863 
13864   if ( n1 == 1 )
13865   {
13866     *indx = 0;
13867   }
13868   else
13869   {
13870     *i = n1 - 1;
13871     n1 = n1 - 1;
13872     *j = 0;
13873     *indx = 1;
13874   }
13875 
13876   return;
13877 }
13878 //****************************************************************************80
13879 
13880 int stla_read ( FILE *filein )
13881 
13882 //****************************************************************************80
13883 //
13884 //  Purpose:
13885 //
13886 //    STLA_READ reads an ASCII STL (stereolithography) file.
13887 //
13888 //  Example:
13889 //
13890 //    solid MYSOLID
13891 //      facet normal 0.4 0.4 0.2
13892 //        outerloop
13893 //          vertex  1.0 2.1 3.2
13894 //          vertex  2.1 3.7 4.5
13895 //          vertex  3.1 4.5 6.7
13896 //        endloop
13897 //      endfacet
13898 //      ...
13899 //      facet normal 0.2 0.2 0.4
13900 //        outerloop
13901 //          vertex  2.0 2.3 3.4
13902 //          vertex  3.1 3.2 6.5
13903 //          vertex  4.1 5.5 9.0
13904 //        endloop
13905 //      endfacet
13906 //    endsolid MYSOLID
13907 //
13908 //  Licensing:
13909 //
13910 //    This code is distributed under the GNU LGPL license.
13911 //
13912 //  Modified:
13913 //
13914 //    20 October 1998
13915 //
13916 //  Author:
13917 //
13918 //    John Burkardt
13919 //
13920 //  Reference:
13921 //
13922 //    3D Systems, Inc,
13923 //    Stereolithography Interface Specification,
13924 //    October 1989.
13925 //
13926 {
13927   int   count;
13928   int   i;
13929   int   icor3;
13930   int   ivert;
13931   char *next;
13932   float r1;
13933   float r2;
13934   float r3;
13935   float r4;
13936   float temp[3];
13937   char  token[LINE_MAX_LEN];
13938   int   width;
13939 //
13940 //  Read the next line of the file into INPUT.
13941 //
13942   while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL )
13943   {
13944     text_num = text_num + 1;
13945 //
13946 //  Advance to the first nonspace character in INPUT.
13947 //
13948     for ( next = input; *next != '\0' && ch_is_space ( *next ); next++ )
13949     {
13950     }
13951 //
13952 //  Skip blank lines and comments.
13953 //
13954     if ( *next == '\0' || *next == '#' || *next == '!' || *next == '$' )
13955     {
13956       continue;
13957     }
13958 //
13959 //  Extract the first word in this line.
13960 //
13961     sscanf ( next, "%s%n", token, &width );
13962 //
13963 //  Set NEXT to point to just after this token.
13964 //
13965     next = next + width;
13966 //
13967 //  FACET
13968 //
13969     if ( s_eqi ( token, "facet" ) )
13970     {
13971 //
13972 //  Get the XYZ coordinates of the normal vector to the face.
13973 //
13974       sscanf ( next, "%*s %e %e %e", &r1, &r2, &r3 );
13975 
13976       if ( face_num < FACE_MAX )
13977       {
13978         face_normal[0][face_num] = r1;
13979         face_normal[1][face_num] = r2;
13980         face_normal[2][face_num] = r3;
13981       }
13982 
13983       fgets ( input, LINE_MAX_LEN, filein );
13984       text_num = text_num + 1;
13985 
13986       ivert = 0;
13987 
13988       for ( ;; )
13989       {
13990         fgets ( input, LINE_MAX_LEN, filein );
13991         text_num = text_num + 1;
13992 
13993         count = sscanf ( input, "%*s %e %e %e", &r1, &r2, &r3 );
13994 
13995         if ( count != 3 )
13996         {
13997           break;
13998         }
13999 
14000         temp[0] = r1;
14001         temp[1] = r2;
14002         temp[2] = r3;
14003 
14004         if ( cor3_num < 1000 )
14005         {
14006           icor3 = rcol_find ( cor3, 3, cor3_num, temp );
14007         }
14008         else
14009         {
14010           icor3 = -1;
14011         }
14012 
14013         if ( icor3 == -1 )
14014         {
14015           icor3 = cor3_num;
14016 
14017           if ( cor3_num < COR3_MAX )
14018           {
14019             for ( i = 0; i < 3; i++ )
14020             {
14021               cor3[i][cor3_num] = temp[i];
14022             }
14023           }
14024           cor3_num = cor3_num + 1;
14025         }
14026         else
14027         {
14028           dup_num = dup_num + 1;
14029         }
14030 
14031         if ( ivert < ORDER_MAX && face_num < FACE_MAX )
14032         {
14033           face[ivert][face_num] = icor3;
14034           vertex_material[ivert][face_num] = 0;
14035           for ( i = 0; i < 3; i++ )
14036           {
14037             vertex_normal[i][ivert][face_num] = face_normal[i][face_num];
14038           }
14039         }
14040 
14041         ivert = ivert + 1;
14042       }
14043 
14044       fgets ( input, LINE_MAX_LEN, filein );
14045       text_num = text_num + 1;
14046 
14047       if ( face_num < FACE_MAX )
14048       {
14049         face_order[face_num] = ivert;
14050       }
14051 
14052       face_num = face_num + 1;
14053 
14054     }
14055 //
14056 //  COLOR
14057 //
14058 
14059     else if ( s_eqi ( token, "color" ) )
14060     {
14061       sscanf ( next, "%*s %f %f %f %f", &r1, &r2, &r3, &r4 );
14062     }
14063 //
14064 // SOLID
14065 //
14066     else if ( s_eqi ( token, "solid" ) )
14067     {
14068       object_num = object_num + 1;
14069     }
14070 //
14071 // ENDSOLID
14072 //
14073     else if ( s_eqi ( token, "endsolid" ) )
14074     {
14075     }
14076 //
14077 //  Unexpected or unrecognized.
14078 //
14079     else
14080     {
14081       cout << "\n";
14082       cout << "STLA_READ - Fatal error!\n";
14083       cout << "  Unrecognized first word on line.\n";
14084       return 1;
14085     }
14086 
14087   }
14088   return 0;
14089 }
14090 //****************************************************************************80
14091 
14092 int stla_write ( FILE *fileout )
14093 
14094 //****************************************************************************80
14095 //
14096 //  Purpose:
14097 //
14098 //    STLA_WRITE writes an ASCII STL (stereolithography) file.
14099 //
14100 //  Discussion:
14101 //
14102 //    The polygons in an STL file should only be triangular.  This routine
14103 //    will try to automatically decompose higher-order polygonal faces into
14104 //    suitable triangles, without actually modifying the internal graphics
14105 //    data.
14106 //
14107 //  Example:
14108 //
14109 //    solid MYSOLID
14110 //      facet normal 0.4 0.4 0.2
14111 //        outerloop
14112 //          vertex  1.0 2.1 3.2
14113 //          vertex  2.1 3.7 4.5
14114 //          vertex  3.1 4.5 6.7
14115 //        endloop
14116 //      endfacet
14117 //      ...
14118 //      facet normal 0.2 0.2 0.4
14119 //        outerloop
14120 //          vertex  2.0 2.3 3.4
14121 //          vertex  3.1 3.2 6.5
14122 //          vertex  4.1 5.5 9.0
14123 //        endloop
14124 //      endfacet
14125 //    endsolid
14126 //
14127 //  Licensing:
14128 //
14129 //    This code is distributed under the GNU LGPL license.
14130 //
14131 //  Modified:
14132 //
14133 //    01 September 1998
14134 //
14135 //  Author:
14136 //
14137 //    John Burkardt
14138 //
14139 //  Reference:
14140 //
14141 //    3D Systems, Inc,
14142 //    Stereolithography Interface Specification,
14143 //    October 1989.
14144 //
14145 {
14146   int icor3;
14147   int iface;
14148   int jvert;
14149   int face_num2;
14150   int text_num;
14151 //
14152 //  Initialize.
14153 //
14154   text_num = 0;
14155   face_num2 = 0;
14156 
14157   fprintf ( fileout, "solid MYSOLID created by IVCON, original data in %s\n",
14158     filein_name );
14159 
14160   text_num = text_num + 1;
14161 
14162   for ( iface = 0; iface < face_num; iface++ )
14163   {
14164     for ( jvert = 2; jvert < face_order[iface]; jvert++ )
14165     {
14166       face_num2 = face_num2 + 1;
14167 
14168       fprintf ( fileout, "  facet normal %f %f %f\n",
14169         face_normal[0][iface], face_normal[1][iface], face_normal[2][iface] );
14170 
14171       fprintf ( fileout, "    outer loop\n" );
14172 
14173       icor3 = face[0][iface];
14174       fprintf ( fileout, "      vertex %f %f %f\n",
14175         cor3[0][icor3], cor3[1][icor3], cor3[2][icor3] );
14176 
14177       icor3 = face[jvert-1][iface];
14178       fprintf ( fileout, "      vertex %f %f %f\n",
14179         cor3[0][icor3], cor3[1][icor3], cor3[2][icor3] );
14180 
14181       icor3 = face[jvert][iface];
14182       fprintf ( fileout, "      vertex %f %f %f\n",
14183         cor3[0][icor3], cor3[1][icor3], cor3[2][icor3] );
14184 
14185       fprintf ( fileout, "    endloop\n" );
14186       fprintf ( fileout, "  endfacet\n" );
14187       text_num = text_num + 7;
14188     }
14189   }
14190 
14191   fprintf ( fileout, "endsolid MYSOLID\n" );
14192   text_num = text_num + 1;
14193 //
14194 //  Report.
14195 //
14196   cout << "\n";
14197   cout << "STLA_WRITE - Wrote " << text_num << " text lines.\n";
14198 
14199   if ( face_num != face_num2 )
14200   {
14201     cout << "  Number of faces in original data was " << face_num << ".\n";
14202     cout << "  Number of triangular faces in decomposed data is "
14203          << face_num2 << ".\n";
14204   }
14205 
14206   return 0;
14207 }
14208 //****************************************************************************80
14209 
14210 int stlb_read ( FILE *filein )
14211 
14212 //****************************************************************************80
14213 //
14214 //  Purpose:
14215 //
14216 //    STLB_READ reads a binary STL (stereolithography) file.
14217 //
14218 //  Example:
14219 //
14220 //    80 byte string = header containing nothing in particular
14221 //
14222 //    4 byte int = number of faces
14223 //
14224 //    For each face:
14225 //
14226 //      3 4-byte floats = components of normal vector to face;
14227 //      3 4-byte floats = coordinates of first node;
14228 //      3 4-byte floats = coordinates of second node;
14229 //      3 4-byte floats = coordinates of third and final node;
14230 //        2-byte int = attribute, whose value is 0.
14231 //
14232 //  Licensing:
14233 //
14234 //    This code is distributed under the GNU LGPL license.
14235 //
14236 //  Modified:
14237 //
14238 //    24 May 1999
14239 //
14240 //  Author:
14241 //
14242 //    John Burkardt
14243 //
14244 //  Reference:
14245 //
14246 //    3D Systems, Inc,
14247 //    Stereolithography Interface Specification,
14248 //    October 1989.
14249 //
14250 {
14251   short int attribute = 0;
14252   char c;
14253   float cvec[3];
14254   int icor3;
14255   int i;
14256   int iface;
14257   int ivert;
14258 //
14259 //  80 byte Header.
14260 //
14261   for ( i = 0; i < 80; i++ )
14262   {
14263     c = ch_read ( filein );
14264     if ( debug )
14265     {
14266       cout << c << "\n";
14267     }
14268     bytes_num = bytes_num + 1;
14269  }
14270 //
14271 //  Number of faces.
14272 //
14273   face_num = long_int_read ( filein );
14274   bytes_num = bytes_num + 4;
14275 //
14276 //  For each (triangular) face,
14277 //    components of normal vector,
14278 //    coordinates of three vertices,
14279 //    2 byte "attribute".
14280 //
14281   for ( iface = 0; iface < face_num; iface++ )
14282   {
14283     face_order[iface] = 3;
14284     face_material[iface] = 0;
14285 
14286     for ( i = 0; i < 3; i++ )
14287     {
14288       face_normal[i][iface] = float_read ( filein );
14289       bytes_num = bytes_num + 4;
14290     }
14291 
14292     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
14293     {
14294       for ( i = 0; i < 3; i++ )
14295       {
14296         cvec[i] = float_read ( filein );
14297         bytes_num = bytes_num + 4;
14298       }
14299 
14300       if ( cor3_num < 1000 )
14301       {
14302         icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
14303       }
14304       else
14305       {
14306         icor3 = -1;
14307       }
14308 
14309       if ( icor3 == -1 )
14310       {
14311         icor3 = cor3_num;
14312         if ( cor3_num < COR3_MAX )
14313         {
14314           cor3[0][cor3_num] = cvec[0];
14315           cor3[1][cor3_num] = cvec[1];
14316           cor3[2][cor3_num] = cvec[2];
14317         }
14318         cor3_num = cor3_num + 1;
14319       }
14320       else
14321       {
14322         dup_num = dup_num + 1;
14323       }
14324 
14325       face[ivert][iface] = icor3;
14326 
14327     }
14328     attribute = short_int_read ( filein );
14329     if ( debug )
14330     {
14331       cout << "ATTRIBUTE = " << attribute << "\n";
14332     }
14333     bytes_num = bytes_num + 2;
14334   }
14335 
14336   return 0;
14337 }
14338 //****************************************************************************80
14339 
14340 int stlb_write ( FILE *fileout )
14341 
14342 //****************************************************************************80
14343 //
14344 //  Purpose:
14345 //
14346 //    STLB_WRITE writes a binary STL (stereolithography) file.
14347 //
14348 //  Discussion:
14349 //
14350 //    The polygons in an STL file should only be triangular.  This routine
14351 //    will try to automatically decompose higher-order polygonal faces into
14352 //    suitable triangles, without actually modifying the internal graphics
14353 //    data.
14354 //
14355 //  Example:
14356 //
14357 //    80 byte string = header containing nothing in particular
14358 //
14359 //    4 byte int = number of faces
14360 //
14361 //    For each face:
14362 //
14363 //      3 4-byte floats = components of normal vector to face;
14364 //      3 4-byte floats = coordinates of first node;
14365 //      3 4-byte floats = coordinates of second node;
14366 //      3 4-byte floats = coordinates of third and final node;
14367 //        2-byte int = attribute, whose value is 0.
14368 //
14369 //  Licensing:
14370 //
14371 //    This code is distributed under the GNU LGPL license.
14372 //
14373 //  Modified:
14374 //
14375 //    24 May 1999
14376 //
14377 //  Author:
14378 //
14379 //    John Burkardt
14380 //
14381 //  Reference:
14382 //
14383 //    3D Systems, Inc,
14384 //    Stereolithography Interface Specification,
14385 //    October 1989.
14386 //
14387 {
14388   short int attribute = 0;
14389   char c;
14390   int i;
14391   int icor3;
14392   int iface;
14393   int jvert;
14394   int face_num2;
14395 //
14396 //  Write the 80 byte header.
14397 //
14398   for ( i = 0; i < 80; i++ )
14399   {
14400     c = ' ';
14401     bytes_num = bytes_num + ch_write ( fileout, c );
14402   }
14403 //
14404 //  Number of faces.
14405 //
14406   face_num2 = 0;
14407   for ( iface = 0; iface < face_num; iface++ )
14408   {
14409     face_num2 = face_num2 + face_order[iface] - 2;
14410   }
14411 
14412   bytes_num = bytes_num + long_int_write ( fileout, face_num2 );
14413 //
14414 //  For each (triangular) face,
14415 //    components of normal vector,
14416 //    coordinates of three vertices,
14417 //    2 byte "attribute".
14418 //
14419   for ( iface = 0; iface < face_num; iface++ )
14420   {
14421     for ( jvert = 2; jvert < face_order[iface]; jvert++ )
14422     {
14423       for ( i = 0; i < 3; i++ )
14424       {
14425         bytes_num = bytes_num + float_write ( fileout, face_normal[i][iface] );
14426       }
14427 
14428       icor3 = face[0][iface];
14429       for ( i = 0; i < 3; i++ )
14430       {
14431         bytes_num = bytes_num + float_write ( fileout, cor3[i][icor3] );
14432       }
14433 
14434       icor3 = face[jvert-1][iface];
14435       for ( i = 0; i < 3; i++ )
14436       {
14437         bytes_num = bytes_num + float_write ( fileout, cor3[i][icor3] );
14438       }
14439 
14440       icor3 = face[jvert][iface];
14441       for ( i = 0; i < 3; i++ )
14442       {
14443         bytes_num = bytes_num + float_write ( fileout, cor3[i][icor3] );
14444       }
14445 
14446       bytes_num = bytes_num + short_int_write ( fileout, attribute );
14447 
14448     }
14449 
14450   }
14451 //
14452 //  Report.
14453 //
14454   cout << "\n";
14455   cout << "STLB_WRITE - Wrote " << bytes_num << " bytes.\n";
14456 
14457   if ( face_num != face_num2 )
14458   {
14459     cout << "  Number of faces in original data was " << face_num << ".\n";
14460     cout << "  Number of triangular faces in decomposed data is "
14461          << face_num2 << ".\n";
14462   }
14463 
14464   return 0;
14465 }
14466 //****************************************************************************80
14467 
14468 void tds_pre_process ( )
14469 
14470 //****************************************************************************80
14471 //
14472 //  Purpose:
14473 //
14474 //    TDS_PRE_PROCESS divides the monolithic object into acceptably small pieces.
14475 //
14476 //  Discussion:
14477 //
14478 //    The 3DS binary format allows an unsigned short int for the number of
14479 //    points, and number of faces in an object.  This limits such quantities
14480 //    to 65535.  We have at least one interesting object with more faces
14481 //    than that.  So we need to tag faces and nodes somehow.
14482 //
14483 //  Licensing:
14484 //
14485 //    This code is distributed under the GNU LGPL license.
14486 //
14487 //  Modified:
14488 //
14489 //    14 October 1998
14490 //
14491 //  Author:
14492 //
14493 //    John Burkardt
14494 //
14495 {
14496 //
14497 //  COMMENTED OUT
14498 //
14499 //  static unsigned short int BIG = 60000;
14500 //
14501 
14502   return;
14503 }
14504 //****************************************************************************80
14505 
14506 int tds_read ( FILE *filein )
14507 
14508 //****************************************************************************80
14509 //
14510 //  Purpose:
14511 //
14512 //    TDS_READ reads a 3D Studio MAX binary 3DS file.
14513 //
14514 //  Licensing:
14515 //
14516 //    This code is distributed under the GNU LGPL license.
14517 //
14518 //  Modified:
14519 //
14520 //    20 October 1998
14521 //
14522 //  Author:
14523 //
14524 //    John Burkardt
14525 //
14526 {
14527   unsigned long int chunk_begin;
14528   unsigned long int   chunk_end;
14529   unsigned long int   chunk_length;
14530   unsigned long int   chunk_length2;
14531   unsigned long int   position;
14532   unsigned short int  temp_int;
14533   int                 version;
14534   int                 views_read;
14535 //
14536 //  Initialize.
14537 //
14538   views_read = 0;
14539 
14540   temp_int = tds_read_u_short_int ( filein );
14541 
14542   if ( temp_int == 0x4d4d )
14543   {
14544     if ( debug )
14545     {
14546       cout << "TDS_READ: DEBUG: Read magic number "
14547            << hex << temp_int << "\n";
14548     }
14549 //
14550 //  Move to 28 bytes from the beginning of the file.
14551 //
14552     position = 28;
14553     fseek ( filein, ( long ) position, SEEK_SET );
14554     version = fgetc ( filein );
14555 
14556     if ( version < 3 )
14557     {
14558       cout << "\n";
14559       cout << "TDS_READ - Fatal error!\n";
14560       cout << "  This routine can only read 3DS version 3 or later.\n";
14561       cout << "  The input file is version " << version << ".\n";
14562       return 1;
14563     }
14564 
14565     if ( debug )
14566     {
14567       cout << "TDS_READ: DEBUG: Version number is " << version << ".\n";
14568     }
14569 //
14570 //  Move to 2 bytes from the beginning of the file.
14571 //  Set CURRENT_POINTER to the first byte of the chunk.
14572 //  Set CHUNK_LENGTH to the number of bytes in the chunk.
14573 //
14574     chunk_begin = 0;
14575     position = 2;
14576     fseek ( filein, ( long ) position, SEEK_SET );
14577 
14578     chunk_length = tds_read_u_long_int ( filein );
14579     position = 6;
14580 
14581     chunk_end = chunk_begin + chunk_length;
14582 
14583     if ( debug )
14584     {
14585       cout << "\n";
14586       cout << "TDS_READ:\n";
14587       cout << "  Chunk begin  = " << chunk_begin << "\n";
14588       cout << "  Chunk length = " << chunk_length << "\n";
14589       cout << "  Chunk end    = " << chunk_end << "\n";
14590     }
14591 
14592     while ( position + 2 < chunk_end )
14593     {
14594       temp_int = tds_read_u_short_int ( filein );
14595       position = position + 2;
14596 
14597       if ( debug )
14598       {
14599         cout << "TDS_READ: Short int = " << hex << temp_int << "\n";
14600         cout << "  position = " << position << "\n";
14601       }
14602 
14603       if ( temp_int == 0x0002 )
14604       {
14605         if ( debug )
14606         {
14607           cout << "TDS_READ: Read_Initial_Section:\n";
14608         }
14609         chunk_length2 = tds_read_u_long_int ( filein );
14610         position = position + 4;
14611         position = position - 6 + chunk_length2;
14612         fseek ( filein, ( long ) position, SEEK_SET );
14613       }
14614       else if ( temp_int == 0x3d3d )
14615       {
14616         if ( debug )
14617         {
14618           cout << "TDS_READ: Read_Edit_Section:\n";
14619         }
14620         position = position - 2;
14621         position = position + tds_read_edit_section ( filein, &views_read );
14622       }
14623       else if ( temp_int == 0xb000 )
14624       {
14625         if ( debug )
14626         {
14627           cout << "TDS_READ: Read_Keyframe_Section:\n";
14628         }
14629 
14630         position = position - 2;
14631         position = position + tds_read_keyframe_section ( filein, &views_read );
14632       }
14633       else
14634       {
14635         cout << "\n";
14636         cout << "TDS_READ - Fatal error!\n";
14637         cout << "  Unexpected input, position = " << position << "\n";
14638         cout << "  TEMP_INT = " << hex << temp_int << "\n";
14639         return 1;
14640       }
14641     }
14642     position = chunk_begin + chunk_length;
14643     fseek ( filein, ( long ) position, SEEK_SET );
14644   }
14645   else
14646   {
14647     cout << "\n";
14648     cout << "TDS_READ - Fatal error!\n";
14649     cout << "  Could not find the main section tag.\n";
14650     return 1;
14651   }
14652 
14653   return 0;
14654 }
14655 //****************************************************************************80
14656 
14657 unsigned long tds_read_ambient_section ( FILE *filein )
14658 
14659 //****************************************************************************80
14660 //
14661 //  Purpose:
14662 //
14663 //    TDS_READ_AMBIENT_SECTION ???
14664 //
14665 //  Licensing:
14666 //
14667 //    This code is distributed under the GNU LGPL license.
14668 //
14669 {
14670   unsigned long int current_pointer;
14671   bool end_found = false;
14672   int i;
14673   long int pointer;
14674   float rgb_val[3];
14675   unsigned short int temp_int;
14676   unsigned long int temp_pointer;
14677   unsigned long int teller;
14678   unsigned char true_c_val[3];
14679 
14680   current_pointer = ftell ( filein ) - 2;
14681   temp_pointer = tds_read_u_long_int ( filein );
14682   teller = 6;
14683 
14684   while ( !end_found )
14685   {
14686     temp_int = tds_read_u_short_int ( filein );
14687     teller = teller + 2;
14688 
14689     switch ( temp_int )
14690     {
14691       case 0x0010:
14692         if ( debug )
14693         {
14694           cout << "     COLOR_F color definition section tag of "
14695             << hex << temp_int << "\n";
14696         }
14697         for ( i = 0; i < 3; i++ )
14698         {
14699           rgb_val[i] = float_read ( filein );
14700         }
14701         if ( debug )
14702         {
14703           cout << "RGB_VAL = "
14704             << setw(10) << rgb_val[0] << "  "
14705             << setw(10) << rgb_val[1] << "  "
14706             << setw(10) << rgb_val[2] << "\n";
14707         }
14708         teller = teller + 3 * sizeof ( float );
14709         break;
14710       case 0x0011:
14711         if ( debug )
14712         {
14713           cout << "     COLOR_24 24 bit color definition section tag of "
14714             << hex << temp_int << "\n";;
14715         }
14716 
14717         for ( i = 0; i < 3; i++ )
14718         {
14719           true_c_val[i] = fgetc ( filein );
14720         }
14721         if ( debug )
14722         {
14723           cout << "TRUE_C_VAL = "
14724             << setw(6) << true_c_val[0] << "  "
14725             << setw(6) << true_c_val[1] << "  "
14726             << setw(6) << true_c_val[2] << "\n";
14727         }
14728         teller = teller + 3;
14729         break;
14730       default:
14731         break;
14732     }
14733 
14734     if ( temp_pointer <= teller )
14735     {
14736       end_found = true;
14737     }
14738 
14739   }
14740 
14741   pointer = ( long ) ( current_pointer + temp_pointer );
14742   fseek ( filein, pointer, SEEK_SET );
14743 
14744   return ( temp_pointer );
14745 }
14746 //****************************************************************************80
14747 
14748 unsigned long tds_read_background_section ( FILE *filein )
14749 
14750 //****************************************************************************80
14751 //
14752 //  Purpose:
14753 //
14754 //    TDS_READ_BACKGROUND_SECTION ???
14755 //
14756 //  Licensing:
14757 //
14758 //    This code is distributed under the GNU LGPL license.
14759 //
14760 {
14761   unsigned long int   current_pointer;
14762   bool end_found = false;
14763   int i;
14764   long int pointer;
14765   float rgb_val[3];
14766   unsigned short int temp_int;
14767   unsigned long int temp_pointer;
14768   unsigned long int teller;
14769   unsigned char true_c_val[3];
14770 
14771   current_pointer = ftell ( filein ) - 2;
14772   temp_pointer = tds_read_u_long_int ( filein );
14773   teller = 6;
14774 
14775   while ( !end_found )
14776   {
14777     temp_int = tds_read_u_short_int ( filein );
14778     teller = teller + 2;
14779 
14780     switch ( temp_int )
14781     {
14782       case 0x0010:
14783         if ( debug )
14784         {
14785           cout << "   COLOR_F RGB color definition section tag of "
14786             << hex << temp_int << "\n";
14787         }
14788         for ( i = 0; i < 3; i++ )
14789         {
14790           rgb_val[i] = float_read ( filein );
14791         }
14792         if ( debug )
14793         {
14794           cout << "RGB_VAL = "
14795                << setw(10) << rgb_val[0] << "  "
14796                << setw(10) << rgb_val[1] << "  "
14797                << setw(10) << rgb_val[2] << "\n";
14798         }
14799         teller = teller + 3 * sizeof ( float );
14800         break;
14801       case 0x0011:
14802         if ( debug )
14803         {
14804           cout << "   COLOR_24 24 bit color definition section tag of "
14805             << hex << temp_int << "\n";
14806         }
14807 
14808         for ( i = 0; i < 3; i++ )
14809         {
14810           true_c_val[i] = fgetc ( filein );
14811         }
14812         if ( debug )
14813         {
14814           cout << "TRUE_C_VAL = "
14815                << setw(6) << true_c_val[0] << "  "
14816                << setw(6) << true_c_val[1] << "  "
14817                << setw(6) << true_c_val[2] << "\n";
14818         }
14819         teller = teller + 3;
14820         break;
14821       default:
14822         break;
14823     }
14824 
14825     if ( temp_pointer <= teller )
14826     {
14827       end_found = true;
14828     }
14829 
14830   }
14831 
14832   pointer = ( long ) ( current_pointer + temp_pointer );
14833   fseek ( filein, pointer, SEEK_SET );
14834 
14835   return ( temp_pointer );
14836 }
14837 //****************************************************************************80
14838 
14839 unsigned long tds_read_boolean ( unsigned char *boolean, FILE *filein )
14840 
14841 //****************************************************************************80
14842 //
14843 //  Purpose:
14844 //
14845 //    TDS_READ_BOOLEAN ???
14846 //
14847 //  Licensing:
14848 //
14849 //    This code is distributed under the GNU LGPL license.
14850 //
14851 {
14852   unsigned long current_pointer;
14853   long int pointer;
14854   unsigned long temp_pointer;
14855 
14856   current_pointer = ftell ( filein ) - 2;
14857   temp_pointer = tds_read_u_long_int ( filein );
14858 
14859   *boolean = fgetc ( filein );
14860 
14861   pointer = ( long ) ( current_pointer + temp_pointer );
14862   fseek ( filein, pointer, SEEK_SET );
14863 
14864   return ( temp_pointer );
14865 }
14866 //****************************************************************************80
14867 
14868 unsigned long tds_read_camera_section ( FILE *filein )
14869 
14870 //****************************************************************************80
14871 //
14872 //  Purpose:
14873 //
14874 //    TDS_READ_CAMERA_SECTION ???
14875 //
14876 //  Licensing:
14877 //
14878 //    This code is distributed under the GNU LGPL license.
14879 //
14880 {
14881   float               camera_eye[3];
14882   float               camera_focus[3];
14883   unsigned long int   current_pointer;
14884   float               lens;
14885   long int            pointer;
14886   float               rotation;
14887   unsigned long int   temp_pointer;
14888   unsigned short int  u_short_int_val;
14889 
14890   current_pointer = ftell ( filein ) - 2;
14891   temp_pointer = tds_read_u_long_int ( filein );
14892 
14893   camera_eye[0] = float_read ( filein );
14894   camera_eye[1] = float_read ( filein );
14895   camera_eye[2] = float_read ( filein );
14896 
14897   camera_focus[0] = float_read ( filein );
14898   camera_focus[1] = float_read ( filein );
14899   camera_focus[2] = float_read ( filein );
14900 
14901   rotation = float_read ( filein );
14902   lens = float_read ( filein );
14903 
14904   if ( debug )
14905   {
14906     cout << " Found camera viewpoint at XYZ = "
14907       << setw(10) << camera_eye[0] << "  "
14908       << setw(10) << camera_eye[1] << "  "
14909       << setw(10) << camera_eye[2] << "\n";
14910     cout << "     Found camera focus coordinates at XYZ = "
14911       << setw(10) << camera_focus[0] << "  "
14912       << setw(10) << camera_focus[1] << "  "
14913       << setw(10) << camera_focus[2] << "\n";
14914     cout << "     Rotation of camera is:  " << rotation << "\n";
14915     cout << "     Lens in used camera is: " << lens << " mm.\n";
14916   }
14917 
14918   if ( 0 < ( temp_pointer-38 ) )
14919   {
14920     if ( debug )
14921     {
14922       cout << "          Found extra camera sections.\n";
14923     }
14924 
14925     u_short_int_val = tds_read_u_short_int ( filein );
14926 
14927     if ( u_short_int_val == 0x4710 )
14928     {
14929       if ( debug )
14930       {
14931         cout << "          CAM_SEE_CONE.\n";
14932       }
14933       tds_read_unknown_section ( filein );
14934     }
14935 
14936     u_short_int_val = tds_read_u_short_int ( filein );
14937 
14938     if ( u_short_int_val == 0x4720 )
14939     {
14940       if ( debug )
14941       {
14942         cout << "          CAM_RANGES.\n";
14943       }
14944       tds_read_unknown_section ( filein );
14945     }
14946 
14947   }
14948 
14949   pointer = ( long ) ( current_pointer + temp_pointer );
14950   fseek ( filein, pointer, SEEK_SET );
14951 
14952   return ( temp_pointer );
14953 }
14954 //****************************************************************************80
14955 
14956 unsigned long tds_read_edit_section ( FILE *filein, int *views_read )
14957 
14958 //****************************************************************************80
14959 //
14960 //  Purpose:
14961 //
14962 //    TDS_READ_EDIT_SECTION ???
14963 //
14964 //  Licensing:
14965 //
14966 //    This code is distributed under the GNU LGPL license.
14967 //
14968 //  Modified:
14969 //
14970 //    18 September 1998
14971 //
14972 {
14973   unsigned long int   chunk_length;
14974   unsigned long int   current_pointer;
14975   bool end_found = false;
14976   long int            pointer;
14977   unsigned long int   teller;
14978   unsigned short int  temp_int;
14979 
14980   current_pointer = ftell ( filein ) - 2;
14981   chunk_length = tds_read_u_long_int ( filein );
14982   teller = 6;
14983 
14984   while ( !end_found )
14985   {
14986     temp_int = tds_read_u_short_int ( filein );
14987     teller = teller + 2;
14988 
14989     if ( debug )
14990     {
14991       cout << "    TDS_READ_EDIT_SECTION processing tag "
14992            << hex << temp_int << "\n";
14993     }
14994 
14995     switch ( temp_int )
14996     {
14997       case 0x1100:
14998         if ( debug )
14999         {
15000           cout << "    BIT_MAP section tag of "
15001                << hex << temp_int << "\n";
15002         }
15003         teller = teller + tds_read_unknown_section ( filein );
15004         break;
15005       case 0x1201:
15006         if ( debug )
15007         {
15008           cout << "    USE_SOLID_BGND section tag of "
15009                << hex << temp_int << "\n";
15010         }
15011         teller = teller + tds_read_unknown_section ( filein );
15012         break;
15013       case 0x1300:
15014         if ( debug )
15015         {
15016           cout << "    V_GRADIENT section tag of "
15017                << hex << temp_int << "\n";
15018         }
15019         teller = teller + tds_read_unknown_section ( filein );
15020         break;
15021       case 0x1400:
15022         teller = teller + tds_read_unknown_section ( filein );
15023         break;
15024       case 0x1420:
15025         teller = teller + tds_read_unknown_section ( filein );
15026         break;
15027       case 0x1450:
15028         teller = teller + tds_read_unknown_section ( filein );
15029         break;
15030       case 0x1500:
15031         teller = teller + tds_read_unknown_section ( filein );
15032         break;
15033       case 0x2200:
15034         teller = teller + tds_read_unknown_section ( filein );
15035         break;
15036       case 0x2201:
15037         teller = teller + tds_read_unknown_section ( filein );
15038         break;
15039       case 0x2210:
15040         teller = teller + tds_read_unknown_section ( filein );
15041         break;
15042       case 0x2300:
15043         teller = teller + tds_read_unknown_section ( filein );
15044         break;
15045       case 0x2302:
15046         teller = teller + tds_read_unknown_section ( filein );
15047         break;
15048       case 0x3000:
15049         teller = teller + tds_read_unknown_section ( filein );
15050         break;
15051       case 0x2100:
15052         if ( debug )
15053         {
15054           cout << "    AMBIENT_LIGHT section tag of "
15055                << hex << temp_int << "\n";
15056         }
15057         teller = teller + tds_read_ambient_section ( filein );
15058         break;
15059       case 0x1200:
15060         if ( debug )
15061         {
15062           cout << "    SOLID_BGND section tag of "
15063                << hex << temp_int << "\n";
15064         }
15065         teller = teller + tds_read_background_section ( filein );
15066         break;
15067       case 0x0100:
15068         if ( debug )
15069         {
15070           cout << "    MASTER_SCALE section tag of "
15071                << hex << temp_int << "\n";
15072         }
15073         teller = teller + tds_read_unknown_section ( filein );
15074         break;
15075       case 0x3d3e:
15076         if ( debug )
15077         {
15078           cout << "    MESH_VERSION section tag of "
15079                << hex << temp_int << "\n";
15080         }
15081         teller = teller + tds_read_unknown_section ( filein );
15082         break;
15083       case 0xafff:
15084         if ( debug )
15085         {
15086           cout << "    MAT_ENTRY section tag of "
15087                << hex << temp_int << "\n";
15088         }
15089         teller = teller + tds_read_material_section ( filein );
15090         break;
15091       case 0x4000:
15092         if ( debug )
15093         {
15094           cout << "    NAMED_OBJECT section tag of "
15095                << hex << temp_int << "\n";
15096         }
15097         teller = teller + tds_read_object_section ( filein );
15098         break;
15099       case 0x7001:
15100         if ( debug )
15101         {
15102           cout << "    VIEWPORT_LAYOUT section tag of "
15103                << hex << temp_int << "\n";
15104         }
15105         teller = teller + tds_read_view_section ( filein, views_read );
15106         break;
15107       case 0x7012:
15108         if ( debug )
15109         {
15110           cout << "    VIEWPORT_DATA_3 section tag of "
15111                << hex << temp_int << "\n";
15112         }
15113         teller = teller + tds_read_unknown_section ( filein );
15114         break;
15115       case 0x7011:
15116         if ( debug )
15117         {
15118           cout << "    VIEWPORT_DATA section tag of "
15119                << hex << temp_int << "\n";
15120         }
15121         teller = teller + tds_read_unknown_section ( filein );
15122         break;
15123       case 0x7020:
15124         if ( debug )
15125         {
15126           cout << "    VIEWPORT_SIZE section tag of "
15127                << hex << temp_int << "\n";
15128         }
15129         teller = teller + tds_read_unknown_section ( filein );
15130         break;
15131       default:
15132         if ( debug )
15133         {
15134           cout << "    Junk.\n";
15135         }
15136         break;
15137     }
15138 
15139     if ( chunk_length <= teller )
15140     {
15141       end_found = true;
15142     }
15143 
15144   }
15145 
15146   pointer = ( long ) ( current_pointer + chunk_length );
15147 
15148   fseek ( filein, pointer, SEEK_SET );
15149 
15150   return ( chunk_length );
15151 }
15152 //****************************************************************************80
15153 
15154 unsigned long tds_read_keyframe_section ( FILE *filein, int *views_read )
15155 
15156 //****************************************************************************80
15157 //
15158 //  Purpose:
15159 //
15160 //    TDS_READ_KEYFRAME_SECTION ???
15161 //
15162 //  Licensing:
15163 //
15164 //    This code is distributed under the GNU LGPL license.
15165 //
15166 {
15167   unsigned long int   current_pointer;
15168   bool end_found = false;
15169   long int            pointer;
15170   unsigned short int  temp_int;
15171   unsigned long int   temp_pointer;
15172   unsigned long int   teller;
15173 
15174   current_pointer = ftell ( filein ) - 2;
15175   temp_pointer = tds_read_u_long_int ( filein );
15176   teller = 6;
15177 
15178   while ( !end_found )
15179   {
15180     temp_int = tds_read_u_short_int ( filein );
15181     teller = teller + 2;
15182 
15183     switch ( temp_int )
15184     {
15185       case 0x7001:
15186         if ( debug )
15187         {
15188           cout << "    VIEWPORT_LAYOUT main definition section tag of "
15189                << hex << temp_int << "\n";
15190         }
15191         teller = teller + tds_read_view_section ( filein, views_read );
15192         break;
15193       case 0xb008:
15194         if ( debug )
15195         {
15196           cout << "    KFSEG frames section tag of "
15197                << hex << temp_int << "\n";
15198         }
15199         teller = teller + tds_read_unknown_section ( filein );
15200         break;
15201       case 0xb002:
15202         if ( debug )
15203         {
15204           cout << "    OBJECT_NODE_TAG object description section tag of "
15205                << hex << temp_int << "\n";
15206         }
15207         teller = teller + tds_read_keyframe_objdes_section ( filein );
15208         break;
15209       case 0xb009:
15210         if ( debug )
15211         {
15212           cout << "    KFCURTIME section tag of "
15213                << hex << temp_int << "\n";
15214         }
15215         teller = teller + tds_read_unknown_section ( filein );
15216         break;
15217       case 0xb00a:
15218         if ( debug )
15219         {
15220           cout << "    KFHDR section tag of "
15221                << hex << temp_int << "\n";
15222         }
15223         teller = teller + tds_read_unknown_section ( filein );
15224         break;
15225       default:
15226         break;
15227     }
15228 
15229     if ( temp_pointer <= teller )
15230     {
15231       end_found = true;
15232     }
15233 
15234   }
15235 
15236   pointer = ( long ) ( current_pointer + temp_pointer );
15237   fseek ( filein, pointer, SEEK_SET );
15238 
15239   return ( temp_pointer );
15240 }
15241 //****************************************************************************80
15242 
15243 unsigned long tds_read_keyframe_objdes_section ( FILE *filein )
15244 
15245 //****************************************************************************80
15246 //
15247 //  Purpose:
15248 //
15249 //    TDS_READ_KEYFRAME_OBJDES_SECTION ???
15250 //
15251 //  Licensing:
15252 //
15253 //    This code is distributed under the GNU LGPL license.
15254 //
15255 //  Modified:
15256 //
15257 //    21 September 1998
15258 //
15259 {
15260   unsigned long int   chunk_size;
15261   unsigned long int   current_pointer;
15262   bool end_found = false;
15263   long int            pointer;
15264   unsigned short int  temp_int;
15265   unsigned long int   temp_pointer;
15266   unsigned long int   teller;
15267   unsigned long int   u_long_int_val;
15268   unsigned short int  u_short_int_val;
15269 
15270   current_pointer = ftell ( filein ) - 2;
15271   temp_pointer = tds_read_u_long_int ( filein );
15272   teller = 6;
15273 
15274   while ( !end_found )
15275   {
15276     temp_int = tds_read_u_short_int ( filein );
15277     teller = teller + 2;
15278 
15279     switch ( temp_int )
15280     {
15281       case 0xb011:
15282         if ( debug )
15283         {
15284           cout << "      INSTANCE_NAME section tag of "
15285                << hex << temp_int << "\n";
15286         }
15287         teller = teller + tds_read_unknown_section ( filein );
15288         break;
15289       case 0xb010:
15290         if ( debug )
15291         {
15292           cout << "      NODE_HDR section tag of "
15293                << hex << temp_int << "\n";
15294         }
15295         teller = teller + tds_read_unknown_section ( filein );
15296         break;
15297       case 0xb020:
15298         if ( debug )
15299         {
15300           cout << "      POS_TRACK_TAG section tag of "
15301                << hex << temp_int << "\n";
15302         }
15303         chunk_size = tds_read_u_long_int ( filein );
15304         if ( debug )
15305         {
15306           cout << "      chunk_size = " << chunk_size << "\n";
15307         }
15308         u_short_int_val = tds_read_u_short_int ( filein );
15309         u_short_int_val = tds_read_u_short_int ( filein );
15310         u_short_int_val = tds_read_u_short_int ( filein );
15311         u_short_int_val = tds_read_u_short_int ( filein );
15312         u_short_int_val = tds_read_u_short_int ( filein );
15313         u_short_int_val = tds_read_u_short_int ( filein );
15314         u_short_int_val = tds_read_u_short_int ( filein );
15315         u_short_int_val = tds_read_u_short_int ( filein );
15316         u_long_int_val = tds_read_u_long_int ( filein );
15317         if ( debug )
15318         {
15319           cout << "u_short_int_val = " << u_short_int_val << "\n";
15320           cout << "u_long_int_val = " << u_long_int_val << "\n";
15321         }
15322         origin[0] = float_read ( filein );
15323         origin[1] = float_read ( filein );
15324         origin[2] = float_read ( filein );
15325         teller = teller + 32;
15326         break;
15327       case 0xb013:
15328         if ( debug )
15329         {
15330           cout << "      PIVOT section tag of "
15331                << hex << temp_int << "\n";
15332         }
15333         chunk_size = tds_read_u_long_int ( filein );
15334         pivot[0] = float_read ( filein );
15335         pivot[1] = float_read ( filein );
15336         pivot[2] = float_read ( filein );
15337         teller = teller + 12;
15338         break;
15339       case 0xb014:
15340         if ( debug )
15341         {
15342           cout << "      BOUNDBOX section tag of "
15343                << hex << temp_int << "\n";
15344         }
15345         teller = teller + tds_read_unknown_section ( filein );
15346         break;
15347       case 0xb015:
15348         if ( debug )
15349         {
15350           cout << "      MORPH_SMOOTH section tag of "
15351                << hex << temp_int << "\n";
15352         }
15353         teller = teller + tds_read_unknown_section ( filein );
15354         break;
15355       case 0xb021:
15356         if ( debug )
15357         {
15358           cout << "      ROT_TRACK_TAG section tag of "
15359                << hex << temp_int << "\n";
15360         }
15361         teller = teller + tds_read_unknown_section ( filein );
15362         break;
15363       case 0xb022:
15364         if ( debug )
15365         {
15366           cout << "      SCL_TRACK_TAG section tag of "
15367                << hex << temp_int << "\n";
15368         }
15369         teller = teller + tds_read_unknown_section ( filein );
15370         break;
15371       case 0xb030:
15372         if ( debug )
15373         {
15374           cout << "      NODE_ID section tag of "
15375                << hex << temp_int << "\n";
15376         }
15377         teller = teller + tds_read_unknown_section ( filein );
15378         break;
15379       default:
15380         break;
15381     }
15382 
15383     if ( temp_pointer <= teller )
15384     {
15385       end_found = true;
15386     }
15387 
15388   }
15389 
15390   pointer = ( long ) ( current_pointer+temp_pointer );
15391   fseek ( filein, pointer, SEEK_SET );
15392 
15393   return ( temp_pointer );
15394 }
15395 //****************************************************************************80
15396 
15397 unsigned long tds_read_light_section ( FILE *filein )
15398 
15399 //****************************************************************************80
15400 //
15401 //  Purpose:
15402 //
15403 //    TDS_READ_LIGHT_SECTION ???
15404 //
15405 //  Licensing:
15406 //
15407 //    This code is distributed under the GNU LGPL license.
15408 //
15409 {
15410   unsigned char boolean;
15411   unsigned long int current_pointer;
15412   bool end_found = false;
15413   int i;
15414   float light_coors[3];
15415   long int pointer;
15416   float rgb_val[3];
15417   unsigned long int teller;
15418   unsigned short int temp_int;
15419   unsigned long int temp_pointer;
15420   unsigned char true_c_val[3];
15421 
15422   current_pointer = ftell ( filein ) - 2;
15423   temp_pointer = tds_read_u_long_int ( filein );
15424   teller = 6;
15425 
15426   light_coors[0] = float_read ( filein );
15427   light_coors[1] = float_read ( filein );
15428   light_coors[2] = float_read ( filein );
15429 
15430   teller = teller + 3 * 4;
15431 
15432   if ( debug )
15433   {
15434     cout << "     Found light at coordinates XYZ = "
15435       << setw(10) << light_coors[0] << "  "
15436       << setw(10) << light_coors[1] << "  "
15437       << setw(10) << light_coors[2] << "\n";
15438   }
15439 
15440   while ( !end_found )
15441   {
15442     temp_int = tds_read_u_short_int ( filein );
15443     teller = teller + 2;
15444 
15445     switch ( temp_int )
15446     {
15447       case 0x0010:
15448         if ( debug )
15449         {
15450           cout << "      COLOR_F RGB color definition section tag of "
15451                << hex << temp_int << "\n";
15452         }
15453         for ( i = 0; i < 3; i++ )
15454         {
15455           rgb_val[i] = float_read ( filein );
15456         }
15457         if ( debug )
15458         {
15459           cout << "      RGB_VAL value set to "
15460             << setw(10) << rgb_val[0] << "  "
15461             << setw(10) << rgb_val[1] << "  "
15462             << setw(10) << rgb_val[2] << "\n";
15463         }
15464         teller = teller + 3 * sizeof ( float );
15465         break;
15466       case 0x0011:
15467         if ( debug )
15468         {
15469           cout << "      COLOR_24 24 bit color definition section tag of "
15470                << hex << temp_int << "\n";
15471         }
15472 
15473         for ( i = 0; i < 3; i++ )
15474         {
15475           true_c_val[i] = fgetc ( filein );
15476         }
15477         if ( debug )
15478         {
15479           cout << "      TRUE_C_VAL value set to "
15480             << setw(6) << true_c_val[0] << "  "
15481             << setw(6) << true_c_val[1] << "  "
15482             << setw(6) << true_c_val[2] << "\n";
15483         }
15484         teller = teller + 3;
15485         break;
15486       case 0x4620:
15487         if ( debug )
15488         {
15489           cout << "      DL_OFF section: "
15490                << hex << temp_int << "\n";
15491         }
15492         teller = teller + tds_read_boolean ( &boolean, filein );
15493         if ( debug )
15494         {
15495           if ( boolean == 1 )
15496           {
15497             cout << "      Light is on.\n";
15498           }
15499           else
15500           {
15501             cout << "      Light is off.\n";
15502           }
15503         }
15504         break;
15505       case 0x4610:
15506         if ( debug  )
15507         {
15508           cout << "      DL_SPOTLIGHT section tag of "
15509                << hex << temp_int << "\n";
15510         }
15511         teller = teller + tds_read_spot_section ( filein );
15512         break;
15513       case 0x465a:
15514         if ( debug  )
15515         {
15516           cout << "      DL_OUTER_RANGE section tag of "
15517                << hex << temp_int << "\n";
15518         }
15519         teller = teller + tds_read_unknown_section ( filein );
15520         break;
15521       default:
15522         break;
15523     }
15524 
15525     if ( temp_pointer <= teller )
15526     {
15527       end_found = true;
15528     }
15529 
15530   }
15531 
15532   pointer = ( long ) ( current_pointer + temp_pointer );
15533   fseek ( filein, pointer, SEEK_SET );
15534 
15535   return ( temp_pointer );
15536 }
15537 //****************************************************************************80
15538 
15539 unsigned long int tds_read_u_long_int ( FILE *filein )
15540 
15541 //****************************************************************************80
15542 //
15543 //  Purpose:
15544 //
15545 //    TDS_READ_U_LONG_INT ???
15546 //
15547 //  Licensing:
15548 //
15549 //    This code is distributed under the GNU LGPL license.
15550 //
15551 //  Modified:
15552 //
15553 //    01 October 1998
15554 //
15555 //  Author:
15556 //
15557 //    John Burkardt
15558 //
15559 {
15560   union {
15561     unsigned long int yint;
15562     char ychar[4];
15563   } y;
15564 
15565   if ( byte_swap )
15566   {
15567     y.ychar[3] = fgetc ( filein );
15568     y.ychar[2] = fgetc ( filein );
15569     y.ychar[1] = fgetc ( filein );
15570     y.ychar[0] = fgetc ( filein );
15571   }
15572   else
15573   {
15574     y.ychar[0] = fgetc ( filein );
15575     y.ychar[1] = fgetc ( filein );
15576     y.ychar[2] = fgetc ( filein );
15577     y.ychar[3] = fgetc ( filein );
15578   }
15579 
15580   return y.yint;
15581 }
15582 //****************************************************************************80
15583 
15584 int tds_read_long_name ( FILE *filein )
15585 
15586 //****************************************************************************80
15587 //
15588 //  Purpose:
15589 //
15590 //    TDS_READ_LONG_NAME ???
15591 //
15592 //  Licensing:
15593 //
15594 //    This code is distributed under the GNU LGPL license.
15595 //
15596 {
15597   unsigned char  letter;
15598   unsigned int   teller;
15599 
15600   teller = 0;
15601   letter = fgetc ( filein );
15602 //
15603 //  Could be a dummy object.
15604 //
15605   if ( letter == 0 )
15606   {
15607     strcpy ( temp_name, "Default_name" );
15608     return -1;
15609   }
15610 
15611   temp_name[teller] = letter;
15612   teller = teller + 1;
15613 
15614   do
15615   {
15616     letter = fgetc ( filein );
15617     temp_name[teller] = letter;
15618     teller = teller + 1;
15619   } while ( letter != 0 );
15620 
15621   temp_name[teller-1] = 0;
15622 
15623   if ( debug )
15624   {
15625     cout << "      TDS_READ_LONG_NAME found name: " << temp_name << ".\n";
15626   }
15627 
15628   return teller;
15629 }
15630 //****************************************************************************80
15631 
15632 unsigned long tds_read_matdef_section ( FILE *filein )
15633 
15634 //****************************************************************************80
15635 //
15636 //  Purpose:
15637 //
15638 //    TDS_READ_MATDEF_SECTION ???
15639 //
15640 //  Licensing:
15641 //
15642 //    This code is distributed under the GNU LGPL license.
15643 //
15644 {
15645   unsigned long int  current_pointer;
15646   long int           pointer;
15647   int                teller;
15648   unsigned long int  temp_pointer;
15649 
15650   current_pointer = ftell ( filein ) - 2;
15651   temp_pointer = tds_read_u_long_int ( filein );
15652 
15653   teller = tds_read_long_name ( filein );
15654 
15655   if ( teller == -1 )
15656   {
15657     if ( debug )
15658     {
15659       cout << "      No material name found.\n";
15660     }
15661   }
15662   else
15663   {
15664     strcpy ( mat_name, temp_name );
15665     if ( debug )
15666     {
15667       cout << "      Material name " << mat_name << ".\n";
15668     }
15669   }
15670 
15671   pointer = ( long ) ( current_pointer + temp_pointer );
15672   fseek ( filein, pointer, SEEK_SET );
15673 
15674   return ( temp_pointer );
15675 }
15676 //****************************************************************************80
15677 
15678 unsigned long tds_read_material_section ( FILE *filein )
15679 
15680 //****************************************************************************80
15681 //
15682 //  Purpose:
15683 //
15684 //    TDS_READ_MATERIAL_SECTION ???
15685 //
15686 //  Licensing:
15687 //
15688 //    This code is distributed under the GNU LGPL license.
15689 //
15690 {
15691   unsigned long int   current_pointer;
15692   bool end_found = false;
15693   long int            pointer;
15694   unsigned short int  temp_int;
15695   unsigned long int   temp_pointer;
15696   unsigned long int   teller;
15697 
15698   current_pointer = ftell ( filein ) - 2;
15699 
15700   temp_pointer = tds_read_u_long_int ( filein );
15701   teller = 6;
15702 
15703   while ( !end_found )
15704   {
15705     temp_int = tds_read_u_short_int ( filein );
15706     teller = teller + 2;
15707 
15708     switch ( temp_int )
15709     {
15710       case 0xa000:
15711         if ( debug )
15712         {
15713           cout << "     MAT_NAME definition section tag of "
15714                << hex << temp_int << "\n";
15715         }
15716         teller = teller + tds_read_matdef_section ( filein );
15717         break;
15718       case 0xa010:
15719         if ( debug )
15720         {
15721           cout << "     MAT_AMBIENT definition section tag of "
15722                << hex << temp_int << "\n";
15723         }
15724         teller = teller + tds_read_unknown_section ( filein );
15725         break;
15726       case 0xa020:
15727         if ( debug )
15728         {
15729           cout << "     MAT_DIFFUSE definition section tag of "
15730                << hex << temp_int << "\n";
15731         }
15732         teller = teller + tds_read_unknown_section ( filein );
15733         break;
15734       case 0xa030:
15735         if ( debug )
15736         {
15737           cout << "     MAT_SPECULAR definition section tag of "
15738                << hex << temp_int << "\n";
15739         }
15740         teller = teller + tds_read_unknown_section ( filein );
15741         break;
15742       case 0xa040:
15743         if ( debug )
15744         {
15745           cout << "     MAT_SHININESS definition section tag of "
15746                << hex << temp_int << "\n";
15747         }
15748         teller = teller + tds_read_unknown_section ( filein );
15749         break;
15750       case 0xa041:
15751         if ( debug )
15752         {
15753           cout << "     MAT_SHIN2PCT definition section tag of "
15754                << hex << temp_int << "\n";
15755         }
15756         teller = teller + tds_read_unknown_section ( filein );
15757         break;
15758       case 0xa042:
15759         if ( debug )
15760         {
15761           cout << "     MAT_SHIN3PCT definition section tag of "
15762                << hex << temp_int << "\n";
15763         }
15764         teller = teller + tds_read_unknown_section ( filein );
15765         break;
15766       case 0xa050:
15767         if ( debug )
15768         {
15769           cout << "     MAT_TRANSPARENCY definition section tag of "
15770                << hex << temp_int << "\n";
15771         }
15772         teller = teller + tds_read_unknown_section ( filein );
15773         break;
15774       case 0xa052:
15775         if ( debug )
15776         {
15777          cout << "     MAT_XPFALL definition section tag of "
15778                << hex << temp_int << "\n";
15779         }
15780         teller = teller + tds_read_unknown_section ( filein );
15781         break;
15782       case 0xa053:
15783         if ( debug )
15784         {
15785           cout << "     MAT_REFBLUR definition section tag of "
15786                << hex << temp_int << "\n";
15787         }
15788         teller = teller + tds_read_unknown_section ( filein );
15789         break;
15790       case 0xa080:
15791         if ( debug )
15792         {
15793           cout << "     MAT_SELF_ILLUM definition section tag of "
15794                << hex << temp_int << "\n";
15795         }
15796         teller = teller + tds_read_unknown_section ( filein );
15797         break;
15798       case 0xa081:
15799         if ( debug )
15800         {
15801           cout << "     MAT_TWO_SIDE definition section tag of "
15802                << hex << temp_int << "\n";
15803         }
15804         teller = teller + tds_read_unknown_section ( filein );
15805         break;
15806       case 0xa082:
15807         if ( debug )
15808         {
15809           cout << "     MAT_DECAL definition section tag of "
15810                << hex << temp_int << "\n";
15811         }
15812         teller = teller + tds_read_unknown_section ( filein );
15813         break;
15814       case 0xa083:
15815         if ( debug )
15816         {
15817           cout << "     MAT_ADDITIVE definition section tag of "
15818                << hex << temp_int << "\n";
15819         }
15820         teller = teller + tds_read_unknown_section ( filein );
15821         break;
15822       case 0xa084:
15823         if ( debug )
15824         {
15825           cout << "     MAT_SELF_ILPCT definition section tag of "
15826                << hex << temp_int << "\n";
15827         }
15828         teller = teller + tds_read_unknown_section ( filein );
15829         break;
15830       case 0xa085:
15831         if ( debug )
15832         {
15833           cout << "     MAT_WIRE definition section tag of "
15834                << hex << temp_int << "\n";
15835         }
15836         teller = teller + tds_read_unknown_section ( filein );
15837         break;
15838       case 0xa086:
15839         if ( debug )
15840         {
15841           cout << "     MAT_SUPERSMP definition section tag of "
15842                << hex << temp_int << "\n";
15843         }
15844         teller = teller + tds_read_unknown_section ( filein );
15845         break;
15846       case 0xa087:
15847         if ( debug )
15848         {
15849           cout << "     MAT_WIRESIZE definition section tag of "
15850                << hex << temp_int << "\n";
15851         }
15852         teller = teller + tds_read_unknown_section ( filein );
15853         break;
15854       case 0xa088:
15855         if ( debug )
15856         {
15857           cout << "     MAT_FACEMAP definition section tag of "
15858                << hex << temp_int << "\n";
15859         }
15860         teller = teller + tds_read_unknown_section ( filein );
15861         break;
15862       case 0xa08a:
15863         if ( debug )
15864         {
15865           cout << "     MAT_XPFALLIN definition section tag of "
15866                << hex << temp_int << "\n";
15867         }
15868         teller = teller + tds_read_unknown_section ( filein );
15869         break;
15870       case 0xa08c:
15871         if ( debug )
15872         {
15873           cout << "     MAT_PHONGSOFT definition section tag of "
15874                << hex << temp_int << "\n";
15875         }
15876         teller = teller + tds_read_unknown_section ( filein );
15877         break;
15878       case 0xa08e:
15879         if ( debug )
15880         {
15881           cout << "     MAT_WIREABS definition section tag of "
15882                << hex << temp_int << "\n";
15883         }
15884         teller = teller + tds_read_unknown_section ( filein );
15885         break;
15886       case 0xa100:
15887         if ( debug )
15888         {
15889           cout << "     MAT_SHADING definition section tag of "
15890                << hex << temp_int << "\n";
15891         }
15892         teller = teller + tds_read_unknown_section ( filein );
15893         break;
15894       case 0xa200:
15895         if ( debug )
15896         {
15897           cout << "     MAT_TEXMAP definition section tag of "
15898                << hex << temp_int << "\n";
15899         }
15900         teller = teller + tds_read_texmap_section ( filein );
15901 //
15902 //        teller = teller + tds_read_unknown_section ( filein );
15903 //
15904         break;
15905       case 0xa204:
15906         if ( debug )
15907         {
15908           cout << "     MAT_SPECMAP definition section tag of "
15909                << hex << temp_int << "\n";
15910         }
15911         teller = teller + tds_read_unknown_section ( filein );
15912         break;
15913       case 0xa210:
15914         if ( debug )
15915         {
15916           cout << "     MAT_OPACMAP definition section tag of "
15917                << hex << temp_int << "\n";
15918         }
15919         teller = teller + tds_read_unknown_section ( filein );
15920         break;
15921       case 0xa220:
15922         if ( debug )
15923         {
15924           cout << "     MAT_REFLMAP definition section tag of "
15925                << hex << temp_int << "\n";
15926         }
15927         teller = teller + tds_read_unknown_section ( filein );
15928         break;
15929       case 0xa230:
15930         if ( debug )
15931         {
15932           cout << "     MAT_BUMPMAP definition section tag of "
15933                << hex << temp_int << "\n";
15934         }
15935         teller = teller + tds_read_unknown_section ( filein );
15936         break;
15937       case 0xa353:
15938         if ( debug )
15939         {
15940           cout << "     MAT_MAP_TEXBLUR definition section tag of "
15941                << hex << temp_int << "\n";
15942         }
15943         teller = teller + tds_read_unknown_section ( filein );
15944         break;
15945       default:
15946         if ( debug )
15947         {
15948           cout << "  Junk section tag of "
15949                << hex << temp_int << "\n";
15950         }
15951         break;
15952     }
15953 
15954     if ( temp_pointer <= teller )
15955     {
15956       end_found = true;
15957     }
15958 
15959   }
15960   pointer = ( long ) ( current_pointer + temp_pointer );
15961 
15962   fseek ( filein, pointer, SEEK_SET );
15963 
15964   return ( temp_pointer );
15965 }
15966 //****************************************************************************80
15967 
15968 int tds_read_name ( FILE *filein )
15969 
15970 //****************************************************************************80
15971 //
15972 //  Purpose:
15973 //
15974 //    TDS_READ_NAME ???
15975 //
15976 //  Licensing:
15977 //
15978 //    This code is distributed under the GNU LGPL license.
15979 //
15980 {
15981   unsigned char  letter;
15982   unsigned int   teller;
15983 
15984   teller = 0;
15985   letter = fgetc ( filein );
15986 //
15987 //  Could be a dummy object.
15988 //
15989 
15990   if ( letter == 0 )
15991   {
15992     strcpy ( temp_name, "Default name" );
15993     return (-1);
15994   }
15995 
15996   temp_name[teller] = letter;
15997   teller = teller + 1;
15998 
15999   do
16000   {
16001     letter = fgetc ( filein );
16002     temp_name[teller] = letter;
16003     teller = teller + 1;
16004   } while ( ( letter != 0 ) && ( teller < 12 ) );
16005 
16006   temp_name[teller-1] = 0;
16007 
16008   if ( debug )
16009   {
16010     cout << "      TDS_READ_NAME found name: " << temp_name << ".\n";
16011   }
16012 
16013   return 0;
16014 }
16015 //****************************************************************************80
16016 
16017 unsigned long tds_read_obj_section ( FILE *filein )
16018 
16019 //****************************************************************************80
16020 //
16021 //  Purpose:
16022 //
16023 //    TDS_READ_OBJ_SECTION ???
16024 //
16025 //  Discussion:
16026 //
16027 //    Thanks to John F Flanagan for some suggested corrections.
16028 //
16029 //  Licensing:
16030 //
16031 //    This code is distributed under the GNU LGPL license.
16032 //
16033 //  Modified:
16034 //
16035 //    30 June 2001
16036 //
16037 {
16038   unsigned short int b;
16039   unsigned long int chunk_size;
16040   unsigned short int color_index;
16041   unsigned long int current_pointer;
16042   bool end_found = false;
16043   unsigned short int  g;
16044   int                 i;
16045   int                 j;
16046   int                 cor3_num_base;
16047   int                 cor3_num_inc;
16048   int                 face_num_inc;
16049   long int            pointer;
16050   unsigned short int  r;
16051   unsigned short int  temp_int;
16052   unsigned long int   temp_pointer;
16053   unsigned long int   temp_pointer2;
16054   unsigned long int   teller;
16055 
16056   current_pointer = ftell ( filein ) - 2;
16057   temp_pointer = tds_read_u_long_int ( filein );
16058   teller = 6;
16059   cor3_num_base = cor3_num;
16060 
16061   while ( !end_found )
16062   {
16063     temp_int = tds_read_u_short_int ( filein );
16064     teller = teller + 2;
16065 
16066     switch ( temp_int )
16067     {
16068       case 0x4000:
16069         if ( debug )
16070         {
16071           cout << "        NAMED_OBJECT section tag of "
16072                << hex << temp_int << "\n";
16073         }
16074         teller = teller + tds_read_unknown_section ( filein );
16075         break;
16076 
16077       case 0x4100:
16078         if ( debug )
16079         {
16080           cout << "        N_TRI_OBJECT section tag of "
16081                << hex << temp_int << "\n";
16082         }
16083         teller = teller + tds_read_unknown_section ( filein );
16084         break;
16085 
16086       case 0x4110:
16087 
16088         if ( debug )
16089         {
16090           cout << "        POINT_ARRAY section tag of "
16091                << hex << temp_int << "\n";
16092         }
16093 
16094         current_pointer = ftell ( filein ) - 2;
16095         temp_pointer2 = tds_read_u_long_int ( filein );
16096         cor3_num_inc =  ( int ) tds_read_u_short_int ( filein );
16097 
16098         for ( i = cor3_num; i < cor3_num + cor3_num_inc; i++ )
16099         {
16100           cor3[0][i] = float_read ( filein );
16101           cor3[1][i] = float_read ( filein );
16102           cor3[2][i] = float_read ( filein );
16103         }
16104 
16105         cor3_num = cor3_num + cor3_num_inc;
16106         teller = teller + temp_pointer2;
16107         break;
16108 
16109       case 0x4111:
16110         if ( debug )
16111         {
16112           cout << "        POINT_FLAG_ARRAY faces (2) section tag of "
16113                << hex << temp_int << "\n";
16114         }
16115         teller = teller + tds_read_unknown_section ( filein );
16116         break;
16117 
16118       case 0x4120:
16119 
16120         if ( debug )
16121         {
16122           cout << "        FACE_ARRAY section tag of "
16123                << hex << temp_int << "\n";
16124         }
16125 
16126         temp_pointer2 = tds_read_u_long_int ( filein );
16127         face_num_inc = ( int ) tds_read_u_short_int ( filein );
16128 
16129         for ( i = face_num; i < face_num + face_num_inc; i++ )
16130         {
16131           face[0][i] = tds_read_u_short_int ( filein ) + cor3_num_base;
16132           face[1][i] = tds_read_u_short_int ( filein ) + cor3_num_base;
16133           face[2][i] = tds_read_u_short_int ( filein ) + cor3_num_base;
16134           face_order[i] = 3;
16135           face_flags[i] = tds_read_u_short_int ( filein );
16136 //
16137 //  Color is given per face, and as 24 bit RGB data packed in one word.
16138 //  Extract RGB from the word, and assign R / 255 to each vertex.
16139 //
16140 //  Just a guess, JVB, 30 June 2001.
16141 //
16142           temp_int = face_flags[i] & 0x000F;
16143           r = ( temp_int & 0x0004 ) >> 2;
16144           g = ( temp_int & 0x0002 ) >> 1;
16145           b = ( temp_int & 0x0001 );
16146 
16147           for ( j = 0; j < 3; j++ )
16148           {
16149             vertex_rgb[0][j][i] = ( float ) r / 255.0;
16150             vertex_rgb[1][j][i] = ( float ) g / 255.0;
16151             vertex_rgb[2][j][i] = ( float ) b / 255.0;
16152           }
16153 
16154         }
16155 
16156         temp_int = tds_read_u_short_int ( filein );
16157         if ( temp_int == 0x4150 )
16158         {
16159           for ( i = face_num; i < face_num + face_num_inc; i++ )
16160           {
16161             face_smooth[i] = ( int ) tds_read_u_long_int ( filein )
16162               + cor3_num_base;
16163           }
16164         }
16165         face_num = face_num + face_num_inc;
16166         teller = ftell ( filein );
16167         break;
16168 
16169       case 0x4130:
16170         if ( debug )
16171         {
16172           cout << "        MSH_MAT_GROUP section tag of "
16173                << hex << temp_int << "\n";
16174         }
16175         teller = teller + tds_read_unknown_section ( filein );
16176         break;
16177 
16178       case 0x4140:
16179         if ( debug )
16180         {
16181           cout << "        TEX_VERTS section tag of "
16182                << hex << temp_int << "\n";
16183         }
16184         teller = teller + tds_read_tex_verts_section ( filein );
16185         break;
16186 
16187       case 0x4150:
16188         if ( debug )
16189         {
16190           cout << "        SMOOTH_GROUP section tag of "
16191                << hex << temp_int << "\n";
16192         }
16193         teller = teller + tds_read_unknown_section ( filein );
16194         break;
16195 
16196       case 0x4160:
16197 
16198         if ( debug )
16199         {
16200           cout << "        MESH_MATRIX section tag of "
16201                << hex << temp_int << "\n";
16202         }
16203 
16204         tds_read_u_long_int ( filein );
16205 
16206         for ( j = 0; j < 4; j++ )
16207         {
16208           for ( i = 0; i < 3; i++ )
16209           {
16210             transform_matrix[j][i] = float_read ( filein );
16211           }
16212         }
16213         transform_matrix[0][3] = 0.0;
16214         transform_matrix[1][3] = 0.0;
16215         transform_matrix[2][3] = 0.0;
16216         transform_matrix[3][3] = 0.0;
16217 
16218         teller = teller + 12 * sizeof ( float );
16219         break;
16220 
16221       case 0x4165:
16222 
16223         if ( debug )
16224         {
16225           cout << "        MESH_COLOR section tag of "
16226                << hex << temp_int << "\n";
16227         }
16228 
16229         chunk_size = tds_read_u_long_int ( filein );
16230 
16231         if ( chunk_size == 7 )
16232         {
16233           color_index = fgetc ( filein );
16234           teller = teller + 5;
16235         }
16236         else
16237         {
16238           color_index = tds_read_u_short_int ( filein );
16239           teller = teller + 6;
16240         }
16241         if ( debug )
16242         {
16243           cout << "        Color index set to " << color_index << "\n";
16244         }
16245         break;
16246 
16247       case 0x4170:
16248         if ( debug )
16249         {
16250           cout << "        MESH_TEXTURE_INFO section tag of "
16251                << hex << temp_int << "\n";
16252         }
16253         teller = teller + tds_read_unknown_section ( filein );
16254         break;
16255 
16256       default:
16257         if ( debug )
16258         {
16259           cout << "        JUNK section tag of "
16260                << hex << temp_int << "\n";
16261         }
16262         break;
16263     }
16264 
16265     if (  temp_pointer <= teller )
16266     {
16267       end_found = true;
16268     }
16269 
16270   }
16271 
16272   pointer = ( long int ) ( current_pointer + temp_pointer );
16273   fseek ( filein, pointer, SEEK_SET );
16274 
16275   return ( temp_pointer );
16276 }
16277 //****************************************************************************80
16278 
16279 unsigned long tds_read_object_section ( FILE *filein )
16280 
16281 //****************************************************************************80
16282 //
16283 //  Purpose:
16284 //
16285 //    TDS_READ_OBJECT_SECTION ???
16286 //
16287 //  Licensing:
16288 //
16289 //    This code is distributed under the GNU LGPL license.
16290 //
16291 {
16292   bool end_found = false;
16293   unsigned long int   current_pointer;
16294   int                 int_val;
16295   long int            pointer;
16296   unsigned short int  temp_int;
16297   unsigned long int   temp_pointer;
16298   unsigned long int   teller;
16299 
16300   current_pointer = ftell ( filein ) - 2;
16301   temp_pointer = tds_read_u_long_int ( filein );
16302   teller = 6;
16303 //
16304 //  Why don't you read and save the name here?
16305 //
16306   int_val = tds_read_name ( filein );
16307 
16308   if ( int_val == -1 )
16309   {
16310     if ( debug )
16311     {
16312       cout << "      Dummy Object found\n";
16313     }
16314   }
16315   else
16316   {
16317     strcpy ( object_name, temp_name );
16318   }
16319 
16320   while ( !end_found )
16321   {
16322     temp_int = tds_read_u_short_int ( filein );
16323     teller = teller + 2;
16324 
16325     switch ( temp_int )
16326     {
16327       case 0x4700:
16328         if ( debug )
16329         {
16330           cout << "      N_CAMERA section tag of "
16331                << hex << temp_int << "\n";
16332         }
16333         teller = teller + tds_read_camera_section ( filein );
16334         break;
16335       case 0x4600:
16336         if ( debug )
16337         {
16338           cout << "      N_DIRECT_LIGHT section tag of "
16339                << hex << temp_int << "\n";
16340         }
16341         teller = teller + tds_read_light_section ( filein );
16342         break;
16343       case 0x4100:
16344         if ( debug )
16345         {
16346           cout << "      OBJ_TRIMESH section tag of "
16347                << hex << temp_int << "\n";
16348         }
16349         teller = teller + tds_read_obj_section ( filein );
16350         break;
16351       case 0x4010:
16352         if ( debug )
16353         {
16354           cout << "      OBJ_HIDDEN section tag of "
16355                << hex << temp_int << "\n";
16356         }
16357         teller = teller + tds_read_unknown_section ( filein );
16358         break;
16359       case 0x4012:
16360         if ( debug )
16361         {
16362           cout << "      OBJ_DOESNT_CAST section tag of "
16363                << hex << temp_int << "\n";
16364         }
16365         teller = teller + tds_read_unknown_section ( filein );
16366         break;
16367       default:
16368         break;
16369     }
16370 
16371     if ( temp_pointer <= teller )
16372     {
16373       end_found = true;
16374     }
16375 
16376   }
16377 
16378   pointer = ( long ) ( current_pointer + temp_pointer );
16379 
16380   fseek ( filein, pointer, SEEK_SET );
16381 
16382   return ( temp_pointer );
16383 }
16384 //****************************************************************************80
16385 
16386 unsigned long int tds_read_tex_verts_section ( FILE *filein )
16387 
16388 //****************************************************************************80
16389 //
16390 //  Purpose:
16391 //
16392 //    TDS_READ_TEX_VERTS_SECTION reads the texture vertex data.
16393 //
16394 //  Discussion:
16395 //
16396 //    The texture vertex data seems to be associated with nodes.  This routine
16397 //    distributes that data to vertices (nodes as they make up a particular
16398 //    face).
16399 //
16400 //  Licensing:
16401 //
16402 //    This code is distributed under the GNU LGPL license.
16403 //
16404 //  Modified:
16405 //
16406 //    02 July 1999
16407 //
16408 //  Author:
16409 //
16410 //    John Burkardt
16411 //
16412 {
16413   unsigned long int  current_pointer;
16414   int                icor3;
16415   long int           pointer;
16416   unsigned long int  temp_pointer;
16417   unsigned short int n2;
16418 
16419   current_pointer = ftell ( filein ) - 2;
16420   temp_pointer = tds_read_u_long_int ( filein );
16421 
16422   pointer = ( long int ) ( current_pointer + temp_pointer );
16423 
16424   n2 = tds_read_u_short_int ( filein );
16425 
16426   for ( icor3 = 0; icor3 < n2; icor3++ )
16427   {
16428     cor3_tex_uv[0][icor3] = float_read ( filein );
16429     cor3_tex_uv[1][icor3] = float_read ( filein );
16430   }
16431 
16432   fseek ( filein, pointer, SEEK_SET );
16433 
16434   return ( temp_pointer );
16435 }
16436 //****************************************************************************80
16437 
16438 unsigned long tds_read_texmap_section ( FILE *filein )
16439 
16440 //****************************************************************************80
16441 //
16442 //  Purpose:
16443 //
16444 //    TDS_READ_TEXMAP_SECTION tries to get the TEXMAP name from the TEXMAP section.
16445 //
16446 //  Discussion:
16447 //
16448 //    The code has room for lots of textures.  In this routine, we behave as
16449 //    though there were only one, and we stick its name in the first name slot.
16450 //
16451 //  Licensing:
16452 //
16453 //    This code is distributed under the GNU LGPL license.
16454 //
16455 //  Modified:
16456 //
16457 //    30 June 1999
16458 //
16459 //  Author:
16460 //
16461 //    John Burkardt
16462 //
16463 {
16464   unsigned long int current_pointer;
16465   long int           pointer;
16466   int                teller;
16467   unsigned long int  temp_pointer;
16468 
16469   texture_num = texture_num + 1;
16470 
16471   current_pointer = ftell ( filein ) - 2;
16472   temp_pointer = tds_read_u_long_int ( filein );
16473 
16474   tds_read_u_short_int ( filein );
16475   tds_read_u_short_int ( filein );
16476   tds_read_u_short_int ( filein );
16477   tds_read_u_short_int ( filein );
16478 //
16479 //  This next short int should equal A300.
16480 //
16481   tds_read_u_short_int ( filein );
16482   tds_read_u_long_int ( filein );
16483 //
16484 //  Now read the TEXMAP file name.
16485 //
16486   teller = tds_read_long_name ( filein );
16487 
16488   if ( teller == -1 )
16489   {
16490     if ( debug )
16491     {
16492       cout << "      No TEXMAP name found.\n";
16493     }
16494   }
16495   else
16496   {
16497     strcpy ( texture_name[0], temp_name );
16498     if ( debug )
16499     {
16500       cout << "      TEXMAP name " << texture_name[0] << ".\n";
16501     }
16502   }
16503 
16504   pointer = ( long ) ( current_pointer + temp_pointer );
16505   fseek ( filein, pointer, SEEK_SET );
16506 
16507   return ( temp_pointer );
16508 }
16509 //****************************************************************************80
16510 
16511 unsigned short int tds_read_u_short_int ( FILE *filein )
16512 
16513 //****************************************************************************80
16514 //
16515 //  Purpose:
16516 //
16517 //    TDS_READ_U_SHORT_INT ???
16518 //
16519 //  Licensing:
16520 //
16521 //    This code is distributed under the GNU LGPL license.
16522 //
16523 {
16524   unsigned char  c1;
16525   unsigned char  c2;
16526   short int      ival;
16527 
16528   c1 = fgetc ( filein );
16529   c2 = fgetc ( filein );
16530 
16531   ival = c1 | ( c2 << 8 );
16532 
16533   return ival;
16534 }
16535 //****************************************************************************80
16536 
16537 unsigned long tds_read_spot_section ( FILE *filein )
16538 
16539 //****************************************************************************80
16540 //
16541 //  Purpose:
16542 //
16543 //    TDS_READ_SPOT_SECTION ???
16544 //
16545 //  Licensing:
16546 //
16547 //    This code is distributed under the GNU LGPL license.
16548 //
16549 {
16550   unsigned long int current_pointer;
16551   float              falloff;
16552   float              hotspot;
16553   long int           pointer;
16554   float              target[4];
16555   unsigned long int  temp_pointer;
16556 
16557   current_pointer = ftell ( filein ) - 2;
16558   temp_pointer = tds_read_u_long_int ( filein );
16559 
16560   target[0] = float_read ( filein );
16561   target[1] = float_read ( filein );
16562   target[2] = float_read ( filein );
16563   hotspot = float_read ( filein );
16564   falloff = float_read ( filein );
16565 
16566   if ( debug )
16567   {
16568     cout << "      The target of the spot is XYZ = "
16569       << setw(10) << target[0] << "  "
16570       << setw(10) << target[1] << "  "
16571       << setw(10) << target[2] << "\n";
16572     cout << "      The hotspot of this light is " << hotspot << ".\n";
16573     cout << "      The falloff of this light is " << falloff << ".\n";
16574   }
16575 
16576   pointer = ( long ) ( current_pointer + temp_pointer );
16577 
16578   fseek ( filein, pointer, SEEK_SET );
16579 
16580   return ( temp_pointer );
16581 }
16582 //****************************************************************************80
16583 
16584 unsigned long int tds_read_unknown_section ( FILE *filein )
16585 
16586 //****************************************************************************80
16587 //
16588 //  Purpose:
16589 //
16590 //    TDS_READ_UNKNOWN_SECTION ???
16591 //
16592 //  Licensing:
16593 //
16594 //    This code is distributed under the GNU LGPL license.
16595 //
16596 {
16597   unsigned long int current_pointer;
16598   long int           pointer;
16599   unsigned long int  temp_pointer;
16600 
16601   current_pointer = ftell ( filein ) - 2;
16602   temp_pointer = tds_read_u_long_int ( filein );
16603 
16604   pointer = ( long int ) ( current_pointer + temp_pointer );
16605 
16606   fseek ( filein, pointer, SEEK_SET );
16607 
16608   return ( temp_pointer );
16609 }
16610 //****************************************************************************80
16611 
16612 unsigned long tds_read_view_section ( FILE *filein, int *views_read )
16613 
16614 //****************************************************************************80
16615 //
16616 //  Purpose:
16617 //
16618 //    TDS_READ_VIEW_SECTION ???
16619 //
16620 //  Licensing:
16621 //
16622 //    This code is distributed under the GNU LGPL license.
16623 //
16624 {
16625   unsigned long int current_pointer;
16626   bool end_found = false;
16627   long int            pointer;
16628   unsigned short int  temp_int;
16629   unsigned long int   temp_pointer;
16630   unsigned long int   teller;
16631 
16632   current_pointer = ftell ( filein ) - 2;
16633   temp_pointer = tds_read_u_long_int ( filein );
16634   teller = 6;
16635 
16636   while ( !end_found )
16637   {
16638     temp_int = tds_read_u_short_int ( filein );
16639     teller = teller + 2;
16640 
16641     switch ( temp_int )
16642     {
16643       case 0x7012:
16644         if ( debug )
16645         {
16646           cout << "     VIEWPORT_DATA_3 section tag of "
16647                << hex << temp_int << "\n";
16648         }
16649         teller = teller + tds_read_vp_section ( filein, views_read );
16650         break;
16651       case 0x7011:
16652         if ( debug )
16653         {
16654           cout << "     VIEWPORT_DATA section tag of "
16655                << hex << temp_int << "\n";
16656         }
16657         teller = teller + tds_read_unknown_section ( filein );
16658         break;
16659       case 0x7020:
16660         if ( debug )
16661         {
16662           cout << "     VIEWPORT_SIZE section tag of "
16663                << hex << temp_int << "\n";
16664         }
16665         teller = teller + tds_read_vp_section ( filein, views_read );
16666         break;
16667       default:
16668         break;
16669     }
16670 
16671     if ( temp_pointer <= teller )
16672     {
16673       end_found = true;
16674     }
16675 
16676     if ( 3 < *views_read )
16677     {
16678       end_found = true;
16679     }
16680   }
16681 
16682   pointer = ( long int ) ( current_pointer + temp_pointer );
16683 
16684   fseek ( filein, pointer, SEEK_SET );
16685 
16686   return ( temp_pointer );
16687 }
16688 //****************************************************************************80
16689 
16690 unsigned long tds_read_vp_section ( FILE *filein, int *views_read )
16691 
16692 //****************************************************************************80
16693 //
16694 //  Purpose:
16695 //
16696 //    TDS_READ_VP_SECTION ???
16697 //
16698 //  Licensing:
16699 //
16700 //    This code is distributed under the GNU LGPL license.
16701 //
16702 {
16703   unsigned int       attribs;
16704   unsigned long int  current_pointer;
16705   int                i;
16706   int                int_val;
16707   long int           pointer;
16708   unsigned int       port;
16709   unsigned long int  temp_pointer;
16710   char              *viewports[11] = {
16711                       "Bogus",
16712                       "Top",
16713                       "Bottom",
16714                       "Left",
16715                       "Right",
16716                       "Front",
16717                       "Back",
16718                       "User",
16719                       "Camera",
16720                       "Light",
16721                       "Disabled"
16722                      };
16723 
16724   *views_read = *views_read + 1;
16725 
16726   current_pointer = ftell ( filein ) - 2;
16727   temp_pointer = tds_read_u_long_int ( filein );
16728 
16729   attribs = tds_read_u_short_int ( filein );
16730 
16731   if ( attribs == 3 )
16732   {
16733     if ( debug )
16734     {
16735       cout << "<Snap> active in viewport.\n";
16736     }
16737   }
16738 
16739   if ( attribs == 5 )
16740   {
16741     if ( debug )
16742     {
16743       cout << "<Grid> active in viewport.\n";
16744     }
16745   }
16746 //
16747 //  Read 5 INTS to get to the viewport information.
16748 //
16749   for ( i = 1; i < 6; i++ )
16750   {
16751     tds_read_u_short_int ( filein );
16752   }
16753 
16754   port = tds_read_u_short_int ( filein );
16755 //
16756 //  Find camera section.
16757 //
16758   if ( ( port == 0xffff ) || ( port == 0 ) )
16759   {
16760     for ( i = 0; i < 12; i++ )
16761     {
16762       tds_read_u_short_int ( filein );
16763     }
16764 
16765     int_val = tds_read_name (filein );
16766 
16767     if ( int_val == -1 )
16768     {
16769       if ( debug )
16770       {
16771         cout << "      No Camera name found\n";;
16772       }
16773     }
16774 
16775     port = 0x0008;
16776   }
16777 
16778   if ( debug )
16779   {
16780     cout << "Reading [" << viewports[port]
16781          << "] information with tag: " << port << "\n";
16782   }
16783 
16784   pointer = ( long int ) ( current_pointer + temp_pointer );
16785 
16786   fseek ( filein, pointer, SEEK_SET );
16787 
16788   return ( temp_pointer );
16789 }
16790 //****************************************************************************80
16791 
16792 int tds_write ( FILE *fileout )
16793 
16794 //****************************************************************************80
16795 //
16796 //  Purpose:
16797 //
16798 //    TDS_WRITE writes graphics information to a 3D Studio Max 3DS file.
16799 //
16800 //  Licensing:
16801 //
16802 //    This code is distributed under the GNU LGPL license.
16803 //
16804 //  Modified:
16805 //
16806 //    14 October 1998
16807 //
16808 //  Author:
16809 //
16810 //    John Burkardt
16811 //
16812 //
16813 {
16814   float               float_val;
16815   int                 i;
16816   int                 icor3;
16817   int                 iface;
16818   int                 j;
16819   long int            l0002;
16820   long int            l0100;
16821   long int            l3d3d;
16822   long int            l3d3e;
16823   long int            l4000;
16824   long int            l4100;
16825   long int            l4110;
16826   long int            l4120;
16827   long int            l4150;
16828   long int            l4160;
16829   long int            l4d4d;
16830   long int            lb000;
16831   long int            lb002;
16832   long int            lb00a;
16833   long int            lb008;
16834   long int            lb009;
16835   long int            lb010;
16836   long int            lb013;
16837   long int            lb020;
16838   long int            lb021;
16839   long int            lb022;
16840   long int            lb030;
16841   long int            long_int_val;
16842   int                 name_length;
16843   short int           short_int_val;
16844   unsigned short int  u_short_int_val;
16845 
16846   bytes_num = 0;
16847   name_length = strlen ( object_name );
16848 
16849   l0002 = 10;
16850 
16851   l4150 = 2 + 4 + face_num * 4;
16852   l4120 = 2 + 4 + 2 + 4 * face_num * 2 + l4150;
16853   l4160 = 2 + 4 + 4 * 12;
16854   l4110 = 2 + 4 + 2 + cor3_num * 3 * 4;
16855   l4100 = 2 + 4 + l4110 + l4160 + l4120;
16856   l4000 = 2 + 4 + ( name_length + 1 ) + l4100;
16857   l0100 = 2 + 4 + 4;
16858   l3d3e = 2 + 4 + 4;
16859   l3d3d = 2 + 4 + l3d3e + l0100 + l4000;
16860 
16861   lb022 = 2 + 4 + 32;
16862   lb021 = 2 + 4 + 9 * 4;
16863   lb020 = 2 + 4 + 8 * 4;
16864   lb013 = 2 + 4 + 6 * 2;
16865   lb010 = 2 + 4 + ( name_length + 1 ) + 3 * 2;
16866   lb030 = 2 + 4 + 2;
16867   lb002 = 2 + 4 + lb030 + lb010 + lb013 + lb020 + lb021 + lb022;
16868   lb009 = 2 + 4 + 4;
16869   lb008 = 2 + 4 + 2 * 4;
16870   lb00a = 2 + 4 + 2 + 9 + 2 * 2;
16871   lb000 = 2 + 4 + lb00a + lb008 + lb009 + lb002;
16872 
16873   l4d4d = 2 + 4 + l0002 + l3d3d + lb000;
16874 //
16875 //  M3DMAGIC begin.
16876 //    tag, size.
16877 //
16878   short_int_val = ( short ) 0x4d4d;
16879   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16880   bytes_num = bytes_num + long_int_write ( fileout, l4d4d );
16881 //
16882 //  M3D_VERSION begin.
16883 //    tag, size, version.
16884 //
16885   short_int_val = ( short ) 0x0002;
16886   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16887   bytes_num = bytes_num + long_int_write ( fileout, l0002 );
16888   long_int_val = 3;
16889   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
16890 //
16891 //  M3D_VERSION end.
16892 //  MDATA begin.
16893 //    tag, size.
16894 //
16895   short_int_val = ( short ) 0x3d3d;
16896   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16897   bytes_num = bytes_num + long_int_write ( fileout, l3d3d );
16898 //
16899 //  MESH_VERSION begin.
16900 //    tag, size, version.
16901 //
16902   short_int_val = ( short ) 0x3d3e;
16903   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16904   bytes_num = bytes_num + long_int_write ( fileout, l3d3e );
16905   long_int_val = 3;
16906   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
16907 //
16908 //  MESH_VERSION end.
16909 //  MASTER_SCALE begin.
16910 //    tag, size, scale.
16911 //
16912   short_int_val = ( short ) 0x0100;
16913   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16914   bytes_num = bytes_num + long_int_write ( fileout, l0100 );
16915   float_val = 1.0;
16916   bytes_num = bytes_num + float_write ( fileout, float_val );
16917 //
16918 //  MASTER_SCALE end.
16919 //  NAMED_OBJECT begin.
16920 //    tag, size, name.
16921 //
16922   short_int_val = ( short ) 0x4000;
16923   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16924   bytes_num = bytes_num + long_int_write ( fileout, l4000 );
16925   bytes_num = bytes_num + tds_write_string ( fileout, object_name );
16926 //
16927 //  N_TRI_OBJECT begin.
16928 //    tag, size.
16929 //
16930   short_int_val = ( short ) 0x4100;
16931   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16932   bytes_num = bytes_num + long_int_write ( fileout, l4100 );
16933 //
16934 //  POINT_ARRAY begin.
16935 //    tag, size, number of points, coordinates of points.
16936 //  Warning! number of points could exceed a short!
16937 //
16938   short_int_val = ( short ) 0x4110;
16939   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16940   bytes_num = bytes_num + long_int_write ( fileout, l4110 );
16941 
16942   u_short_int_val = ( unsigned short ) cor3_num;
16943   bytes_num = bytes_num + tds_write_u_short_int ( fileout, u_short_int_val );
16944 
16945   for ( icor3 = 0; icor3 < cor3_num; icor3++ )
16946   {
16947     for ( j = 0; j < 3; j++ )
16948     {
16949       bytes_num = bytes_num + float_write ( fileout, cor3[j][icor3] );
16950     }
16951   }
16952 //
16953 //  POINT_ARRAY end.
16954 //  MESH_MATRIX begin.
16955 //    tag, size, 4 by 3 matrix.
16956 //
16957   short_int_val = ( short ) 0x4160;
16958   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16959   bytes_num = bytes_num + long_int_write ( fileout, l4160 );
16960 
16961   for ( i = 0; i < 4; i++ )
16962   {
16963     for ( j = 0; j < 3; j++ )
16964     {
16965       float_val = transform_matrix[i][j];
16966       bytes_num = bytes_num + float_write ( fileout, float_val );
16967     }
16968   }
16969 //
16970 //  MESH_MATRIX end.
16971 //  FACE_ARRAY begin.
16972 //    tag, size, number of faces, nodes per face.
16973 //  Warning: number of faces could exceed a short!
16974 //
16975   short_int_val = ( short ) 0x4120;
16976   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16977   bytes_num = bytes_num + long_int_write ( fileout, l4120 );
16978 
16979   u_short_int_val = ( unsigned short ) face_num;
16980   bytes_num = bytes_num + tds_write_u_short_int ( fileout, u_short_int_val );
16981 
16982   for ( iface = 0; iface < face_num; iface++ )
16983   {
16984     for ( j = 0; j < 3; j++ )
16985     {
16986       short_int_val = face[j][iface];
16987       bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16988     }
16989     short_int_val = face_flags[iface];
16990     bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16991   }
16992 //
16993 //  SMOOTH_GROUP begin.
16994 //    tag, size, group for each face.
16995 //
16996   short_int_val = ( short ) 0x4150;
16997   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16998   bytes_num = bytes_num + long_int_write ( fileout, l4150 );
16999 
17000   for ( iface = 0; iface < face_num; iface++ )
17001   {
17002     long_int_val = face_smooth[iface];
17003     bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17004   }
17005 //
17006 //  SMOOTH_GROUP end.
17007 //  FACE_ARRAY end.
17008 //  N_TRI_OBJECT end.
17009 //  NAMED_OBJECT end.
17010 //  MDATA end.
17011 //  KFDATA begin.
17012 //
17013   short_int_val = ( short ) 0xb000;
17014   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17015   bytes_num = bytes_num + long_int_write ( fileout, lb000 );
17016 //
17017 //  KFHDR begin.
17018 //    tag, size, revision, filename, animlen.
17019 //
17020   short_int_val = ( short ) 0xb00a;
17021   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17022   bytes_num = bytes_num + long_int_write ( fileout, lb00a );
17023   short_int_val = 5;
17024   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17025   bytes_num = bytes_num + tds_write_string ( fileout, "MAXSCENE" );
17026   short_int_val = 100;
17027   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17028   short_int_val = 0;
17029   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17030 //
17031 //  KFHDR end.
17032 //  KFSEG begin.
17033 //    tag, size, start, end.
17034 //
17035   short_int_val = ( short ) 0xb008;
17036   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17037   bytes_num = bytes_num + long_int_write ( fileout, lb008 );
17038   long_int_val = 0;
17039   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17040   long_int_val = 100;
17041   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17042 //
17043 //  KFSEG end.
17044 //  KFCURTIME begin.
17045 //    tag, size, current_frame.
17046 //
17047   short_int_val = ( short ) 0xb009;
17048   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17049   bytes_num = bytes_num + long_int_write ( fileout, lb009 );
17050   long_int_val = 0;
17051   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17052 //
17053 //  KFCURTIME end.
17054 //  OBJECT_NODE_TAG begin.
17055 //    tag, size.
17056 //
17057   short_int_val = ( short ) 0xb002;
17058   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17059   bytes_num = bytes_num + long_int_write ( fileout, lb002 );
17060 //
17061 //  NODE_ID begin.
17062 //    tag, size, id.
17063 //
17064   short_int_val = ( short ) 0xb030;
17065   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17066   bytes_num = bytes_num + long_int_write ( fileout, lb030 );
17067   short_int_val = 0;
17068   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17069 //
17070 //  NODE_ID end.
17071 //  NODE_HDR begin.
17072 //    tag, size, object_name, flag1, flag2, hierarchy.
17073 //
17074   short_int_val = ( short ) 0xb010;
17075   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17076   bytes_num = bytes_num + long_int_write ( fileout, lb010 );
17077   bytes_num = bytes_num + tds_write_string ( fileout, object_name );
17078   short_int_val = 16384;
17079   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17080   short_int_val = 0;
17081   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17082   short_int_val = -1;
17083   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17084 //
17085 //  NODE_HDR end.
17086 //  PIVOT begin.
17087 //    tag, size, pivot_x, pivot_y, pivot_z.
17088 //
17089   short_int_val = ( short ) 0xb013;
17090   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17091   bytes_num = bytes_num + long_int_write ( fileout, lb013 );
17092   for ( i = 0; i < 3; i++ )
17093   {
17094     float_val = pivot[i];
17095     bytes_num = bytes_num + float_write ( fileout, float_val );
17096   }
17097 //
17098 //  PIVOT end.
17099 //  POS_TRACK_TAG begin.
17100 //    tag, size, flag, i1, i2, i3, i4, i5, i6, frame, l1, pos_x, pos_y, pos_z.
17101 //
17102   short_int_val = ( short ) 0xb020;
17103   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17104   bytes_num = bytes_num + long_int_write ( fileout, lb020 );
17105   short_int_val = 0;
17106   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17107   short_int_val = 0;
17108   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17109   short_int_val = 0;
17110   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17111   short_int_val = 0;
17112   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17113   short_int_val = 0;
17114   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17115   short_int_val = 1;
17116   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17117   short_int_val = 0;
17118   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17119   short_int_val = 0;
17120   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17121   long_int_val = 0;
17122   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17123   for ( i = 0; i < 3; i++ )
17124   {
17125     float_val = origin[i];
17126     bytes_num = bytes_num + float_write ( fileout, float_val );
17127   }
17128 //
17129 //  POS_TRACK_TAG end.
17130 //  ROT_TRACK_TAG begin.
17131 //    tag, size, i1, i2, i3, i4, i5, i6, i7, i8, l1, rad, axis_x, axis_y, axis_z.
17132 //
17133   short_int_val = ( short ) 0xb021;
17134   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17135   bytes_num = bytes_num + long_int_write ( fileout, lb021 );
17136   short_int_val = 0;
17137   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17138   short_int_val = 0;
17139   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17140   short_int_val = 0;
17141   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17142   short_int_val = 0;
17143   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17144   short_int_val = 0;
17145   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17146   short_int_val = 1;
17147   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17148   short_int_val = 0;
17149   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17150   short_int_val = 0;
17151   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17152   long_int_val = 0;
17153   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17154   float_val = 0.0;
17155   bytes_num = bytes_num + float_write ( fileout, float_val );
17156   bytes_num = bytes_num + float_write ( fileout, float_val );
17157   bytes_num = bytes_num + float_write ( fileout, float_val );
17158   bytes_num = bytes_num + float_write ( fileout, float_val );
17159 //
17160 //  ROT_TRACK_TAG end.
17161 //  SCL_TRACK_TAG begin.
17162 //    tag, size, i1, i2, i3, i4, i5, i6, i7, i8, l1, scale_x, scale_y, scale_z.
17163 //
17164   short_int_val = ( short ) 0xb022;
17165   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17166   bytes_num = bytes_num + long_int_write ( fileout, lb022 );
17167   short_int_val = 0;
17168   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17169   short_int_val = 0;
17170   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17171   short_int_val = 0;
17172   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17173   short_int_val = 0;
17174   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17175   short_int_val = 0;
17176   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17177   short_int_val = 1;
17178   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17179   short_int_val = 0;
17180   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17181   short_int_val = 0;
17182   bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17183   long_int_val = 0;
17184   bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17185   float_val = 1.0;
17186   bytes_num = bytes_num + float_write ( fileout, float_val );
17187   bytes_num = bytes_num + float_write ( fileout, float_val );
17188   bytes_num = bytes_num + float_write ( fileout, float_val );
17189 //
17190 //  SCL_TRACK_TAG end.
17191 //  OBJECT_NODE_TAG end.
17192 //  KFDATA end.
17193 //  M3DMAGIC end.
17194 //
17195 
17196 //
17197 //  Report.
17198 //
17199   cout << "\n";
17200   cout << "TDS_WRITE wrote " << bytes_num << " bytes.\n";
17201 
17202   return 0;
17203 }
17204 //****************************************************************************80
17205 
17206 int tds_write_string ( FILE *fileout, char *string )
17207 
17208 //****************************************************************************80
17209 //
17210 //  Purpose:
17211 //
17212 //    TDS_WRITE_STRING ???
17213 //
17214 //  Licensing:
17215 //
17216 //    This code is distributed under the GNU LGPL license.
17217 //
17218 //  Modified:
17219 //
17220 //    23 September 1998
17221 //
17222 //  Author:
17223 //
17224 //    John Burkardt
17225 //
17226 {
17227   char *c;
17228   int   nchar;
17229 
17230   nchar = 0;
17231 
17232   for ( c = string; nchar < 12; c++ )
17233   {
17234     fputc ( *c, fileout );
17235     nchar = nchar + 1;
17236 
17237     if  ( *c == 0 )
17238     {
17239       return nchar;
17240     }
17241 
17242   }
17243 
17244   return nchar;
17245 }
17246 //****************************************************************************80
17247 
17248 int tds_write_u_short_int ( FILE *fileout, unsigned short int short_int_val )
17249 
17250 //****************************************************************************80
17251 //
17252 //  Purpose:
17253 //
17254 //    TDS_WRITE_U_SHORT_INT ???
17255 //
17256 //  Licensing:
17257 //
17258 //    This code is distributed under the GNU LGPL license.
17259 //
17260 //  Modified:
17261 //
17262 //    14 October 1998
17263 //
17264 //  Author:
17265 //
17266 //    John Burkardt
17267 //
17268 {
17269   union {
17270     unsigned short int yint;
17271     char ychar[2];
17272   } y;
17273 
17274   y.yint = short_int_val;
17275 
17276   if ( byte_swap )
17277   {
17278     fputc ( y.ychar[1], fileout );
17279     fputc ( y.ychar[0], fileout );
17280   }
17281   else
17282   {
17283     fputc ( y.ychar[0], fileout );
17284     fputc ( y.ychar[1], fileout );
17285   }
17286 
17287   return 2;
17288 }
17289 //****************************************************************************80
17290 
17291 int tec_write ( FILE *fileout )
17292 
17293 //****************************************************************************80
17294 //
17295 //  Purpose:
17296 //
17297 //    TEC_WRITE writes graphics information to a TECPLOT file.
17298 //
17299 //  Discussion:
17300 //
17301 //    The file format used is appropriate for 3D finite element surface
17302 //    zone data.  Polygons are decomposed into triangles where necessary.
17303 //
17304 //  Example:
17305 //
17306 //    TITLE = "cube.tec created by IVCON."
17307 //    VARIABLES = "X", "Y", "Z", "R", "G", "B"
17308 //    ZONE T="TRIANGLES", N=8, E=12, F=FEPOINT, ET=TRIANGLE
17309 //    0.0 0.0 0.0 0.0 0.0 0.0
17310 //    1.0 0.0 0.0 1.0 0.0 0.0
17311 //    1.0 1.0 0.0 1.0 1.0 0.0
17312 //    0.0 1.0 0.0 0.0 1.0 0.0
17313 //    0.0 0.0 1.0 0.0 0.0 1.0
17314 //    1.0 0.0 1.0 1.0 0.0 1.0
17315 //    1.0 1.0 1.0 1.0 1.0 1.0
17316 //    0.0 1.0 1.0 0.0 1.0 1.0
17317 //    1 4 2
17318 //    2 4 3
17319 //    1 5 8
17320 //    1 2 5
17321 //    2 6 5
17322 //    2 3 6
17323 //    3 7 6
17324 //    3 4 7
17325 //    4 8 7
17326 //    4 1 8
17327 //    5 6 8
17328 //    6 7 8
17329 //
17330 //  Licensing:
17331 //
17332 //    This code is distributed under the GNU LGPL license.
17333 //
17334 //  Modified:
17335 //
17336 //    09 June 1999
17337 //
17338 //  Author:
17339 //
17340 //    John Burkardt
17341 //
17342 {
17343   float b;
17344   int face2[3];
17345   float g;
17346   int icor3;
17347   int iface;
17348   int imat;
17349   int j;
17350   int face_num2;
17351   int text_num;
17352   float r;
17353 //
17354 //  Determine the number of triangular faces.
17355 //
17356   face_num2 = 0;
17357   for ( iface = 0; iface < face_num; iface++ )
17358   {
17359     for ( j = 0; j < face_order[iface] - 2; j++ )
17360     {
17361       face_num2 = face_num2 + 1;
17362     }
17363   }
17364 
17365   text_num = 0;
17366 
17367   fprintf ( fileout, "TITLE = \"%s created by IVCON.\"\n", fileout_name );
17368   fprintf ( fileout, "VARIABLES = \"X\", \"Y\", \"Z\", \"R\", \"G\", \"B\"\n" );
17369   fprintf ( fileout,
17370     "ZONE T=\"TRIANGLES\", N=%d, E=%d, F=FEPOINT, ET=TRIANGLE\n",
17371     cor3_num, face_num2 );
17372 
17373   text_num = text_num + 3;
17374 //
17375 //  Write out X, Y, Z, R, G, B per node.
17376 //
17377   for ( icor3 = 0; icor3 < cor3_num; icor3++ )
17378   {
17379     imat = cor3_material[icor3];
17380     r = material_rgba[0][imat];
17381     g = material_rgba[1][imat];
17382     b = material_rgba[2][imat];
17383     fprintf ( fileout, "%f %f %f %f %f %f\n", cor3[0][icor3], cor3[1][icor3],
17384       cor3[2][icor3], r, g, b );
17385     text_num = text_num + 1;
17386   }
17387 //
17388 //  Do the next face.
17389 //
17390   for ( iface = 0; iface < face_num; iface++ )
17391   {
17392 //
17393 //  Break the face up into triangles, anchored at node 1.
17394 //
17395     for ( j = 0; j < face_order[iface] - 2; j++ )
17396     {
17397       face2[0] = face[  0][iface] + 1;
17398       face2[1] = face[j+1][iface] + 1;
17399       face2[2] = face[j+2][iface] + 1;
17400 
17401       fprintf ( fileout, "%d %d %d\n", face2[0], face2[1], face2[2] );
17402       text_num = text_num + 1;
17403 
17404     }
17405 
17406   }
17407 //
17408 //  Report.
17409 //
17410   cout << "\n";
17411   cout << "TEC_WRITE - Wrote " << text_num << " text lines.\n";
17412 
17413   return 0;
17414 }
17415 //****************************************************************************80
17416 
17417 void tmat_init ( float a[4][4] )
17418 
17419 //****************************************************************************80
17420 //
17421 //  Purpose:
17422 //
17423 //    TMAT_INIT initializes the geometric transformation matrix.
17424 //
17425 //  Discussion:
17426 //
17427 //    The geometric transformation matrix can be thought of as a 4 by 4
17428 //    matrix "A" having components:
17429 //
17430 //      r11 r12 r13 t1
17431 //      r21 r22 r23 t2
17432 //      r31 r32 r33 t3
17433 //        0   0   0  1
17434 //
17435 //    This matrix encodes the rotations, scalings and translations that
17436 //    are applied to graphical objects.
17437 //
17438 //    A point P = (x,y,z) is rewritten in "homogeneous coordinates" as
17439 //    PH = (x,y,z,1).  Then to apply the transformations encoded in A to
17440 //    the point P, we simply compute A * PH.
17441 //
17442 //    Individual transformations, such as a scaling, can be represented
17443 //    by simple versions of the transformation matrix.  If the matrix
17444 //    A represents the current set of transformations, and we wish to
17445 //    apply a new transformation B, { the original points are
17446 //    transformed twice:  B * ( A * PH ).  The new transformation B can
17447 //    be combined with the original one A, to give a single matrix C that
17448 //    encodes both transformations: C = B * A.
17449 //
17450 //  Licensing:
17451 //
17452 //    This code is distributed under the GNU LGPL license.
17453 //
17454 //  Modified:
17455 //
17456 //    19 October 1998
17457 //
17458 //  Author:
17459 //
17460 //    John Burkardt
17461 //
17462 //  Reference:
17463 //
17464 //    Foley, van Dam, Feiner, Hughes,
17465 //    Computer Graphics, Principles and Practice,
17466 //    Addison Wesley, Second Edition, 1990.
17467 //
17468 //  Parameters:
17469 //
17470 //    Input, float A[4][4], the geometric transformation matrix.
17471 //
17472 {
17473   int i;
17474   int j;
17475 
17476   for ( i = 0; i < 4; i++ )
17477   {
17478     for ( j = 0; j < 4; j++ )
17479     {
17480       if ( i == j )
17481       {
17482         a[i][j] = 1.0;
17483       }
17484       else
17485       {
17486         a[i][j] = 0.0;
17487       }
17488     }
17489   }
17490   return;
17491 }
17492 //****************************************************************************80
17493 
17494 void tmat_mxm ( float a[4][4], float b[4][4], float c[4][4] )
17495 
17496 //****************************************************************************80
17497 //
17498 //  Purpose:
17499 //
17500 //    TMAT_MXM multiplies two geometric transformation matrices.
17501 //
17502 //  Discussion:
17503 //
17504 //    The product is accumulated in a temporary array, and { assigned
17505 //    to the result.  Therefore, it is legal for any two, or all three,
17506 //    of the arguments to share memory.
17507 //
17508 //  Licensing:
17509 //
17510 //    This code is distributed under the GNU LGPL license.
17511 //
17512 //  Modified:
17513 //
17514 //    19 October 1998
17515 //
17516 //  Author:
17517 //
17518 //    John Burkardt
17519 //
17520 //  Reference:
17521 //
17522 //    Foley, van Dam, Feiner, Hughes,
17523 //    Computer Graphics, Principles and Practice,
17524 //    Addison Wesley, Second Edition, 1990.
17525 //
17526 //  Parameters:
17527 //
17528 //    Input, float A[4][4], the first geometric transformation matrix.
17529 //
17530 //    Input, float B[4][4], the second geometric transformation matrix.
17531 //
17532 //    Output, float C[4][4], the product A * B.
17533 //
17534 {
17535   float d[4][4];
17536   int i;
17537   int j;
17538   int k;
17539 
17540   for ( i = 0; i < 4; i++ )
17541   {
17542     for ( k = 0; k < 4; k++ )
17543     {
17544       d[i][k] = 0.0;
17545       for ( j = 0; j < 4; j++ )
17546       {
17547         d[i][k] = d[i][k] + a[i][j] * b[j][k];
17548       }
17549     }
17550   }
17551 
17552   for ( i = 0; i < 4; i++ )
17553   {
17554     for ( j = 0; j < 4; j++ )
17555     {
17556       c[i][j] = d[i][j];
17557     }
17558   }
17559   return;
17560 }
17561 //****************************************************************************80
17562 
17563 void tmat_mxp ( float a[4][4], float x[4], float y[4] )
17564 
17565 //****************************************************************************80
17566 //
17567 //  Purpose:
17568 //
17569 //    TMAT_MXP multiplies a geometric transformation matrix times a point.
17570 //
17571 //  Licensing:
17572 //
17573 //    This code is distributed under the GNU LGPL license.
17574 //
17575 //  Modified:
17576 //
17577 //    19 October 1998
17578 //
17579 //  Author:
17580 //
17581 //    John Burkardt
17582 //
17583 //  Reference:
17584 //
17585 //    Foley, van Dam, Feiner, Hughes,
17586 //    Computer Graphics, Principles and Practice,
17587 //    Addison Wesley, Second Edition, 1990.
17588 //
17589 //  Parameters:
17590 //
17591 //    Input, float A[4][4], the geometric transformation matrix.
17592 //
17593 //    Input, float X[4], the point to be multiplied.  The fourth component
17594 //    of X is implicitly assigned the value of 1.
17595 //
17596 //    Output, float Y[4], the result of A*X.  The product is accumulated in
17597 //    a temporary vector, and { assigned to the result.  Therefore, it
17598 //    is legal for X and Y to share memory.
17599 //
17600 {
17601   int i;
17602   int j;
17603   float z[4];
17604 
17605   for ( i = 0; i < 3; i++ )
17606   {
17607     z[i] = a[i][3];
17608     for ( j = 0; j < 3; j++ )
17609     {
17610       z[i] = z[i] + a[i][j] * x[j];
17611     }
17612   }
17613 
17614   for ( i = 0; i < 3; i++ )
17615   {
17616     y[i] = z[i];
17617   }
17618   return;
17619 }
17620 //****************************************************************************80
17621 
17622 void tmat_mxp2 ( float a[4][4], float x[][3], float y[][3], int n )
17623 
17624 //****************************************************************************80
17625 //
17626 //  Purpose:
17627 //
17628 //    TMAT_MXP2 multiplies a geometric transformation matrix times N points.
17629 //
17630 //  Licensing:
17631 //
17632 //    This code is distributed under the GNU LGPL license.
17633 //
17634 //  Modified:
17635 //
17636 //    20 October 1998
17637 //
17638 //  Author:
17639 //
17640 //    John Burkardt
17641 //
17642 //  Reference:
17643 //
17644 //    Foley, van Dam, Feiner, Hughes,
17645 //    Computer Graphics, Principles and Practice,
17646 //    Addison Wesley, Second Edition, 1990.
17647 //
17648 //  Parameters:
17649 //
17650 //    Input, float A[4][4], the geometric transformation matrix.
17651 //
17652 //    Input, float X[N][3], the points to be multiplied.
17653 //
17654 //    Output, float Y[N][3], the transformed points.  Each product is
17655 //    accumulated in a temporary vector, and { assigned to the
17656 //    result.  Therefore, it is legal for X and Y to share memory.
17657 //
17658 //
17659 {
17660   int i;
17661   int j;
17662   int k;
17663   float z[4];
17664 
17665   for ( k = 0; k < n; k++ )
17666   {
17667     for ( i = 0; i < 3; i++ )
17668     {
17669       z[i] = a[i][3];
17670       for ( j = 0; j < 3; j++ )
17671       {
17672         z[i] = z[i] + a[i][j] * x[k][j];
17673       }
17674     }
17675 
17676     for ( i = 0; i < 3; i++ )
17677     {
17678       y[k][i] = z[i];
17679     }
17680 
17681   }
17682   return;
17683 }
17684 //****************************************************************************80
17685 
17686 void tmat_mxv ( float a[4][4], float x[4], float y[4] )
17687 
17688 //****************************************************************************80
17689 //
17690 //  Purpose:
17691 //
17692 //    TMAT_MXV multiplies a geometric transformation matrix times a vector.
17693 //
17694 //  Licensing:
17695 //
17696 //    This code is distributed under the GNU LGPL license.
17697 //
17698 //  Modified:
17699 //
17700 //    12 August 1999
17701 //
17702 //  Author:
17703 //
17704 //    John Burkardt
17705 //
17706 //  Reference:
17707 //
17708 //    Foley, van Dam, Feiner, Hughes,
17709 //    Computer Graphics, Principles and Practice,
17710 //    Addison Wesley, Second Edition, 1990.
17711 //
17712 //  Parameters:
17713 //
17714 //    Input, float A[4][4], the geometric transformation matrix.
17715 //
17716 //    Input, float X[3], the vector to be multiplied.  The fourth component
17717 //    of X is implicitly assigned the value of 1.
17718 //
17719 //    Output, float Y[3], the result of A*X.  The product is accumulated in
17720 //    a temporary vector, and assigned to the result.  Therefore, it
17721 //    is legal for X and Y to share memory.
17722 //
17723 {
17724   int i;
17725   int j;
17726   float z[4];
17727 
17728   for ( i = 0; i < 3; i++ )
17729   {
17730     z[i] = 0.0;
17731     for ( j = 0; j < 3; j++ )
17732     {
17733       z[i] = z[i] + a[i][j] * x[j];
17734     }
17735     z[i] = z[i] + a[i][3];
17736   }
17737 
17738   for ( i = 0; i < 3; i++ )
17739   {
17740     y[i] = z[i];
17741   }
17742   return;
17743 }
17744 //****************************************************************************80
17745 
17746 void tmat_rot_axis ( float a[4][4], float b[4][4], float angle,
17747   char axis )
17748 
17749 //****************************************************************************80
17750 //
17751 //  Purpose:
17752 //
17753 //    TMAT_ROT_AXIS applies an axis rotation to the geometric transformation matrix.
17754 //
17755 //  Licensing:
17756 //
17757 //    This code is distributed under the GNU LGPL license.
17758 //
17759 //  Modified:
17760 //
17761 //    19 April 1999
17762 //
17763 //  Author:
17764 //
17765 //    John Burkardt
17766 //
17767 //  Reference:
17768 //
17769 //    Foley, van Dam, Feiner, Hughes,
17770 //    Computer Graphics, Principles and Practice,
17771 //    Addison Wesley, Second Edition, 1990.
17772 //
17773 //  Parameters:
17774 //
17775 //    Input, float A[4][4], the current geometric transformation matrix.
17776 //
17777 //    Output, float B[4][4], the modified geometric transformation matrix.
17778 //    A and B may share the same memory.
17779 //
17780 //    Input, float ANGLE, the angle, in degrees, of the rotation.
17781 //
17782 //    Input, character AXIS, is 'X', 'Y' or 'Z', specifying the coordinate
17783 //    axis about which the rotation occurs.
17784 //
17785 {
17786   float c[4][4];
17787   float d[4][4];
17788   int i;
17789   int j;
17790   float theta;
17791 
17792   theta = angle * DEG_TO_RAD;
17793 
17794   tmat_init ( c );
17795 
17796   if ( axis == 'X' || axis == 'x' )
17797   {
17798     c[1][1] =   cos ( theta );
17799     c[1][2] = - sin ( theta );
17800     c[2][1] =   sin ( theta );
17801     c[2][2] =   cos ( theta );
17802   }
17803   else if ( axis == 'Y' || axis == 'y' )
17804   {
17805     c[0][0] =   cos ( theta );
17806     c[0][2] =   sin ( theta );
17807     c[2][0] = - sin ( theta );
17808     c[2][2] =   cos ( theta );
17809   }
17810   else if ( axis == 'Z' || axis == 'z' )
17811   {
17812     c[0][0] =   cos ( theta );
17813     c[0][1] = - sin ( theta );
17814     c[1][0] =   sin ( theta );
17815     c[1][1] =   cos ( theta );
17816   }
17817   else
17818   {
17819     cout << "\n";
17820     cout << "TMAT_ROT_AXIS - Fatal error!\n";
17821     cout << "  Illegal rotation axis: " << axis << ".\n";
17822     cout << "  Legal choices are 'X', 'Y', or 'Z'.\n";
17823     return;
17824   }
17825 
17826   tmat_mxm ( c, a, d );
17827 
17828   for ( i = 0; i < 4; i++ )
17829   {
17830     for ( j = 0; j < 4; j++ )
17831     {
17832       b[i][j] = d[i][j];
17833     }
17834   }
17835   return;
17836 }
17837 //****************************************************************************80
17838 
17839 void tmat_rot_vector ( float a[4][4], float b[4][4], float angle,
17840   float v1, float v2, float v3 )
17841 
17842 //****************************************************************************80
17843 //
17844 //  Purpose:
17845 //
17846 //    TMAT_ROT_VECTOR applies a rotation about a vector to the geometric transformation matrix.
17847 //
17848 //  Licensing:
17849 //
17850 //    This code is distributed under the GNU LGPL license.
17851 //
17852 //  Modified:
17853 //
17854 //    27 July 1999
17855 //
17856 //  Author:
17857 //
17858 //    John Burkardt
17859 //
17860 //  Reference:
17861 //
17862 //    Foley, van Dam, Feiner, Hughes,
17863 //    Computer Graphics, Principles and Practice,
17864 //    Addison Wesley, Second Edition, 1990.
17865 //
17866 //  Parameters:
17867 //
17868 //    Input, float A[4][4], the current geometric transformation matrix.
17869 //
17870 //    Output, float B[4][4], the modified geometric transformation matrix.
17871 //    A and B may share the same memory.
17872 //
17873 //    Input, float ANGLE, the angle, in degrees, of the rotation.
17874 //
17875 //    Input, float V1, V2, V3, the X, Y and Z coordinates of a (nonzero)
17876 //    point defining a vector from the origin.  The rotation will occur
17877 //    about this axis.
17878 //
17879 {
17880   float c[4][4];
17881   float ca;
17882   float d[4][4];
17883   int i;
17884   int j;
17885   float sa;
17886   float theta;
17887 
17888   if ( v1 * v1 + v2 * v2 + v3 * v3 == 0.0 )
17889   {
17890     return;
17891   }
17892 
17893   theta = angle * DEG_TO_RAD;
17894 
17895   tmat_init ( c );
17896 
17897   ca = cos ( theta );
17898   sa = sin ( theta );
17899 
17900   c[0][0] =                v1 * v1 + ca * ( 1.0 - v1 * v1 );
17901   c[0][1] = ( 1.0 - ca ) * v1 * v2 - sa * v3;
17902   c[0][2] = ( 1.0 - ca ) * v1 * v3 + sa * v2;
17903 
17904   c[1][0] = ( 1.0 - ca ) * v2 * v1 + sa * v3;
17905   c[1][1] =                v2 * v2 + ca * ( 1.0 - v2 * v2 );
17906   c[1][2] = ( 1.0 - ca ) * v2 * v3 - sa * v1;
17907 
17908   c[2][0] = ( 1.0 - ca ) * v3 * v1 - sa * v2;
17909   c[2][1] = ( 1.0 - ca ) * v3 * v2 + sa * v1;
17910   c[2][2] =                v3 * v3 + ca * ( 1.0 - v3 * v3 );
17911 
17912   tmat_mxm ( c, a, d );
17913 
17914   for ( i = 0; i < 4; i++ )
17915   {
17916     for ( j = 0; j < 4; j++ )
17917     {
17918       b[i][j] = d[i][j];
17919     }
17920   }
17921   return;
17922 }
17923 //****************************************************************************80
17924 
17925 void tmat_scale ( float a[4][4], float b[4][4], float sx, float sy,
17926   float sz )
17927 
17928 //****************************************************************************80
17929 //
17930 //  Purpose:
17931 //
17932 //    TMAT_SCALE applies a scaling to the geometric transformation matrix.
17933 //
17934 //  Licensing:
17935 //
17936 //    This code is distributed under the GNU LGPL license.
17937 //
17938 //  Modified:
17939 //
17940 //    19 October 1998
17941 //
17942 //  Author:
17943 //
17944 //    John Burkardt
17945 //
17946 //  Reference:
17947 //
17948 //    Foley, van Dam, Feiner, Hughes,
17949 //    Computer Graphics, Principles and Practice,
17950 //    Addison Wesley, Second Edition, 1990.
17951 //
17952 //  Parameters:
17953 //
17954 //    Input, float A[4][4], the current geometric transformation matrix.
17955 //
17956 //    Output, float B[4][4], the modified geometric transformation matrix.
17957 //    A and B may share the same memory.
17958 //
17959 //    Input, float SX, SY, SZ, the scalings to be applied to the X, Y and
17960 //    Z coordinates.
17961 //
17962 {
17963   float c[4][4];
17964   float d[4][4];
17965   int i;
17966   int j;
17967 
17968   tmat_init ( c );
17969 
17970   c[0][0] = sx;
17971   c[1][1] = sy;
17972   c[2][2] = sz;
17973 
17974   tmat_mxm ( c, a, d );
17975 
17976   for ( i = 0; i < 4; i++ )
17977   {
17978     for ( j = 0; j < 4; j++ )
17979     {
17980       b[i][j] = d[i][j];
17981     }
17982   }
17983   return;
17984 }
17985 //****************************************************************************80
17986 
17987 void tmat_shear ( float a[4][4], float b[4][4], char *axis, float s )
17988 
17989 //****************************************************************************80
17990 //
17991 //  Purpose:
17992 //
17993 //    TMAT_SHEAR applies a shear to the geometric transformation matrix.
17994 //
17995 //  Licensing:
17996 //
17997 //    This code is distributed under the GNU LGPL license.
17998 //
17999 //  Modified:
18000 //
18001 //    19 October 1998
18002 //
18003 //  Author:
18004 //
18005 //    John Burkardt
18006 //
18007 //  Reference:
18008 //
18009 //    Foley, van Dam, Feiner, Hughes,
18010 //    Computer Graphics, Principles and Practice,
18011 //    Addison Wesley, Second Edition, 1990.
18012 //
18013 //  Parameters:
18014 //
18015 //    Input, float A[4][4], the current geometric transformation matrix.
18016 //
18017 //    Output, float B[4][4], the modified geometric transformation matrix.
18018 //    A and B may share the same memory.
18019 //
18020 //    Input, character*3 AXIS, is 'XY', 'XZ', 'YX', 'YZ', 'ZX' or 'ZY',
18021 //    specifying the shear equation:
18022 //
18023 //      XY:  x' = x + s * y;
18024 //      XZ:  x' = x + s * z;
18025 //      YX:  y' = y + s * x;
18026 //      YZ:  y' = y + s * z;
18027 //      ZX:  z' = z + s * x;
18028 //      ZY:  z' = z + s * y.
18029 //
18030 //    Input, float S, the shear coefficient.
18031 //
18032 {
18033   float c[4][4];
18034   float d[4][4];
18035   int i;
18036   int j;
18037 
18038   tmat_init ( c );
18039 
18040   if ( strcmp ( axis, "XY" ) == 0 || strcmp ( axis, "xy" ) == 0 )
18041   {
18042     c[0][1] = s;
18043   }
18044   else if ( strcmp ( axis, "XZ" ) == 0 || strcmp ( axis, "xz" ) == 0 )
18045   {
18046     c[0][2] = s;
18047   }
18048   else if ( strcmp ( axis, "YX" ) == 0 || strcmp ( axis, "yx" ) == 0 )
18049   {
18050     c[1][0] = s;
18051   }
18052   else if ( strcmp ( axis, "YZ" ) == 0 || strcmp ( axis, "yz" ) == 0 )
18053   {
18054     c[1][2] = s;
18055   }
18056   else if ( strcmp ( axis, "ZX" ) == 0 || strcmp ( axis, "zx" ) == 0 )
18057   {
18058     c[2][0] = s;
18059   }
18060   else if ( strcmp ( axis, "ZY" ) == 0 || strcmp ( axis, "zy" ) == 0 )
18061   {
18062     c[2][1] = s;
18063   }
18064   else
18065   {
18066     cout << "\n";
18067     cout << "TMAT_SHEAR - Fatal error!\n";
18068     cout << "  Illegal shear axis: " << axis << ".\n";
18069     cout << "  Legal choices are XY, XZ, YX, YZ, ZX, or ZY.\n";
18070     return;
18071   }
18072 
18073   tmat_mxm ( c, a, d );
18074 
18075   for ( i = 0; i < 4; i++ )
18076   {
18077     for ( j = 0; j < 4; j++ )
18078     {
18079       b[i][j] = d[i][j];
18080     }
18081   }
18082   return;
18083 }
18084 //****************************************************************************80
18085 
18086 void tmat_trans ( float a[4][4], float b[4][4], float x, float y,
18087   float z )
18088 
18089 //****************************************************************************80
18090 //
18091 //  Purpose:
18092 //
18093 //    TMAT_TRANS applies a translation to the geometric transformation matrix.
18094 //
18095 //  Licensing:
18096 //
18097 //    This code is distributed under the GNU LGPL license.
18098 //
18099 //  Modified:
18100 //
18101 //    19 October 1998
18102 //
18103 //  Author:
18104 //
18105 //    John Burkardt
18106 //
18107 //  Reference:
18108 //
18109 //    Foley, van Dam, Feiner, Hughes,
18110 //    Computer Graphics, Principles and Practice,
18111 //    Addison Wesley, Second Edition, 1990.
18112 //
18113 //  Parameters:
18114 //
18115 //    Input, float A[4][4], the current geometric transformation matrix.
18116 //
18117 //    Output, float B[4][4], the modified transformation matrix.
18118 //    A and B may share the same memory.
18119 //
18120 //    Input, float X, Y, Z, the translation.  This may be thought of as the
18121 //    point that the origin moves to under the translation.
18122 //
18123 {
18124   int i;
18125   int j;
18126 
18127   for ( i = 0; i < 4; i++ )
18128   {
18129     for ( j = 0; j < 4; j++ )
18130     {
18131       b[i][j] = a[i][j];
18132     }
18133   }
18134   b[0][3] = b[0][3] + x;
18135   b[1][3] = b[1][3] + y;
18136   b[2][3] = b[2][3] + z;
18137 
18138   return;
18139 }
18140 //****************************************************************************80
18141 
18142 int tria_read ( FILE *filein )
18143 
18144 //****************************************************************************80
18145 //
18146 //  Purpose:
18147 //
18148 //    TRIA_READ reads an ASCII triangle file.
18149 //
18150 //  Example:
18151 //
18152 //    12                    <-- Number of triangles
18153 //
18154 //                          (x,y,z) and (nx,ny,nz) of normal vector at:
18155 //
18156 //    0.0 0.0 0.0 0.3 0.3 0.3   node 1 of triangle 1.
18157 //    1.0 0.0 0.0 0.3 0.1 0.3   node 2 of triangle 1,
18158 //    0.0 1.0 0.0 0.3 0.1 0.3   node 3 of triangle 1,
18159 //    1.0 0.5 0.0 0.3 0.1 0.3   node 1 of triangle 2,
18160 //    ...
18161 //    0.0 0.5 0.5 0.3 0.1 0.3   node 3 of triangle 12.
18162 //
18163 //  Licensing:
18164 //
18165 //    This code is distributed under the GNU LGPL license.
18166 //
18167 //  Modified:
18168 //
18169 //    22 June 1999
18170 //
18171 //  Author:
18172 //
18173 //    John Burkardt
18174 //
18175 {
18176   float cvec[3];
18177   int icor3;
18178   int iface;
18179   int iface_hi;
18180   int iface_lo;
18181   int ivert;
18182   int face_num2;
18183   float r1;
18184   float r2;
18185   float r3;
18186   float r4;
18187   float r5;
18188   float r6;
18189 //
18190 //  Get the number of triangles.
18191 //
18192   fgets ( input, LINE_MAX_LEN, filein );
18193   text_num = text_num + 1;
18194   sscanf ( input, "%d", &face_num2 );
18195 //
18196 //  For each triangle:
18197 //
18198   iface_lo = face_num;
18199   iface_hi = face_num + face_num2;
18200 
18201   for ( iface = iface_lo; iface < iface_hi; iface++ )
18202   {
18203     if ( iface < FACE_MAX )
18204     {
18205       face_order[iface] = 3;
18206       face_material[iface] = 0;
18207     }
18208 //
18209 //  For each face:
18210 //
18211     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
18212     {
18213       fgets ( input, LINE_MAX_LEN, filein );
18214       text_num = text_num + 1;
18215       sscanf ( input, "%e %e %e %e %e %e", &r1, &r2, &r3, &r4, &r5, &r6 );
18216 
18217       cvec[0] = r1;
18218       cvec[1] = r2;
18219       cvec[2] = r3;
18220 
18221       if ( cor3_num < 1000 )
18222       {
18223         icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
18224       }
18225       else
18226       {
18227         icor3 = -1;
18228       }
18229 
18230       if ( icor3 == -1 )
18231       {
18232         icor3 = cor3_num;
18233         if ( cor3_num < COR3_MAX )
18234         {
18235           cor3[0][cor3_num] = cvec[0];
18236           cor3[1][cor3_num] = cvec[1];
18237           cor3[2][cor3_num] = cvec[2];
18238         }
18239         cor3_num = cor3_num + 1;
18240       }
18241       else
18242       {
18243         dup_num = dup_num + 1;
18244       }
18245 
18246       if ( iface < FACE_MAX )
18247       {
18248         face[ivert][iface] = icor3;
18249         vertex_material[ivert][iface] = 0;
18250         vertex_normal[0][ivert][iface] = r4;
18251         vertex_normal[1][ivert][iface] = r5;
18252         vertex_normal[2][ivert][iface] = r6;
18253       }
18254 
18255     }
18256   }
18257   face_num = face_num + face_num2;
18258 
18259   return 0;
18260 }
18261 //****************************************************************************80
18262 
18263 int tria_write ( FILE *fileout )
18264 
18265 //****************************************************************************80
18266 //
18267 //  Purpose:
18268 //
18269 //    TRIA_WRITE writes the graphics data to an ASCII "triangle" file.
18270 //
18271 //  Discussion:
18272 //
18273 //    This is just a private format that Greg Hood requested from me.
18274 //
18275 //  Example:
18276 //
18277 //    12                    <-- Number of triangles
18278 //
18279 //                          (x,y,z) and (nx,ny,nz) of normal vector at:
18280 //
18281 //    0.0 0.0 0.0 0.3 0.3 0.3   node 1 of triangle 1.
18282 //    1.0 0.0 0.0 0.3 0.1 0.3   node 2 of triangle 1,
18283 //    0.0 1.0 0.0 0.3 0.1 0.3   node 3 of triangle 1,
18284 //    1.0 0.5 0.0 0.3 0.1 0.3   node 1 of triangle 2,
18285 //    ...
18286 //    0.0 0.5 0.5 0.3 0.1 0.3   node 3 of triangle 12.
18287 //
18288 //  Licensing:
18289 //
18290 //    This code is distributed under the GNU LGPL license.
18291 //
18292 //  Modified:
18293 //
18294 //    10 June 1999
18295 //
18296 //  Author:
18297 //
18298 //    John Burkardt
18299 //
18300 {
18301   int face2[3];
18302   int icor3;
18303   int iface;
18304   int jlo;
18305   int k;
18306   int face_num2;
18307   int text_num;
18308   float nx;
18309   float ny;
18310   float nz;
18311   float x;
18312   float y;
18313   float z;
18314 
18315   text_num = 0;
18316 //
18317 //  Determine the number of triangular faces.
18318 //
18319   face_num2 = 0;
18320   for ( iface = 0; iface < face_num; iface++ )
18321   {
18322     for ( jlo = 0; jlo < face_order[iface] - 2; jlo++ )
18323     {
18324       face_num2 = face_num2 + 1;
18325     }
18326   }
18327 
18328   fprintf ( fileout,  "%d\n", face_num2 );
18329   text_num = text_num + 1;
18330 //
18331 //  Do the next face.
18332 //
18333   for ( iface = 0; iface < face_num; iface++ )
18334   {
18335 //
18336 //  Break the face up into triangles, anchored at node 1.
18337 //
18338     for ( jlo = 0; jlo < face_order[iface] - 2; jlo++ )
18339     {
18340       face2[0] = face[    0][iface];
18341       face2[1] = face[jlo+1][iface];
18342       face2[2] = face[jlo+2][iface];
18343 
18344       for ( k = 0; k < 3; k++ )
18345       {
18346         icor3 = face2[k];
18347 
18348         x = cor3[0][icor3];
18349         y = cor3[1][icor3];
18350         z = cor3[2][icor3];
18351 
18352         nx = cor3_normal[0][icor3];
18353         ny = cor3_normal[1][icor3];
18354         nz = cor3_normal[2][icor3];
18355 
18356         fprintf ( fileout,  "%f %f %f %f %f %f\n", x, y, z, nx, ny, nz );
18357 
18358         text_num = text_num + 1;
18359 
18360       }
18361 
18362     }
18363 
18364   }
18365 //
18366 //  Report.
18367 //
18368   cout << "\n";
18369   cout << "TRIA_WRITE - Wrote " << text_num << " text lines.\n";
18370 
18371   return 0;
18372 }
18373 //****************************************************************************80
18374 
18375 int trib_read ( FILE *filein )
18376 
18377 //****************************************************************************80
18378 //
18379 //  Purpose:
18380 //
18381 //    TRIB_READ reads a binary triangle file.
18382 //
18383 //  Example:
18384 //
18385 //    4 byte int = number of triangles
18386 //
18387 //    For each triangular face:
18388 //
18389 //      3 4-byte floats = coordinates of first node;
18390 //      3 4-byte floats = components of normal vector at first node;
18391 //      3 4-byte floats = coordinates of second node;
18392 //      3 4-byte floats = components of normal vector at second node;
18393 //      3 4-byte floats = coordinates of third node;
18394 //      3 4-byte floats = components of normal vector at third node.
18395 //
18396 //  Licensing:
18397 //
18398 //    This code is distributed under the GNU LGPL license.
18399 //
18400 //  Modified:
18401 //
18402 //    22 June 1999
18403 //
18404 //  Author:
18405 //
18406 //    John Burkardt
18407 //
18408 {
18409   float cvec[3];
18410   int icor3;
18411   int i;
18412   int iface;
18413   int iface_hi;
18414   int iface_lo;
18415   int ivert;
18416   int face_num2;
18417 //
18418 //  Read the number of triangles in the file.
18419 //
18420   face_num2 = long_int_read ( filein );
18421   bytes_num = bytes_num + 4;
18422 //
18423 //  For each (triangular) face,
18424 //    read the coordinates and normal vectors of three vertices,
18425 //
18426   iface_lo = face_num;
18427   iface_hi = face_num + face_num2;
18428 
18429   for ( iface = iface_lo; iface < iface_hi; iface++ )
18430   {
18431     if ( iface < FACE_MAX )
18432     {
18433       face_order[iface] = 3;
18434       face_material[iface] = 0;
18435     }
18436 
18437     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
18438     {
18439       for ( i = 0; i < 3; i++ )
18440       {
18441         cvec[i] = float_read ( filein );
18442         bytes_num = bytes_num + 4;
18443       }
18444 
18445       if ( cor3_num < 1000 )
18446       {
18447         icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
18448       }
18449       else
18450       {
18451         icor3 = -1;
18452       }
18453 
18454       if ( icor3 == -1 )
18455       {
18456         icor3 = cor3_num;
18457         if ( cor3_num < COR3_MAX )
18458         {
18459           cor3[0][cor3_num] = cvec[0];
18460           cor3[1][cor3_num] = cvec[1];
18461           cor3[2][cor3_num] = cvec[2];
18462         }
18463         cor3_num = cor3_num + 1;
18464       }
18465       else
18466       {
18467         dup_num = dup_num + 1;
18468       }
18469 
18470       if ( iface < FACE_MAX )
18471       {
18472         face[ivert][iface] = icor3;
18473         vertex_material[ivert][iface] = 0;
18474 
18475         for ( i = 0; i < 3; i++ )
18476         {
18477           vertex_normal[i][ivert][iface] = float_read ( filein );
18478           bytes_num = bytes_num + 4;
18479         }
18480 
18481       }
18482 
18483     }
18484   }
18485 
18486   face_num = face_num + face_num2;
18487 
18488   return 0;
18489 }
18490 //****************************************************************************80
18491 
18492 int trib_write ( FILE *fileout )
18493 
18494 //****************************************************************************80
18495 //
18496 //  Purpose:
18497 //
18498 //    TRIB_WRITE writes the graphics data to a binary "triangle" file.
18499 //
18500 //  Discussion:
18501 //
18502 //    This is just a private format that Greg Hood requested from me.
18503 //
18504 //  Example:
18505 //
18506 //    12   Number of triangles
18507 //    0.0  x at node 1, triangle 1,
18508 //    0.0  y at node 1, triangle 1,
18509 //    0.0  z at node 1, triangle 1,
18510 //    0.3  nx at node 1, triangle 1,
18511 //    0.3  ny at node 1, triangle 1,
18512 //    0.3  nz at node 1, triangle 1.
18513 //    1.0  x at node 2, triangle 1,
18514 //    ...
18515 //    0.7  nz at node 3, triangle 1.
18516 //    1.2  x at node 1, triangle 2,
18517 //    ...
18518 //    0.3  nz at node 3, triangle 2.
18519 //    9.3  x at node 1, triangle 3,
18520 //    ...
18521 //    0.3  nz at node 3, triangle 12.
18522 //
18523 //  Licensing:
18524 //
18525 //    This code is distributed under the GNU LGPL license.
18526 //
18527 //  Modified:
18528 //
18529 //    16 June 1999
18530 //
18531 //  Author:
18532 //
18533 //    John Burkardt
18534 //
18535 {
18536   int face2[3];
18537   int icor3;
18538   int iface;
18539   int jlo;
18540   int k;
18541   int face_num2;
18542   float nx;
18543   float ny;
18544   float nz;
18545   float x;
18546   float y;
18547   float z;
18548 
18549   bytes_num = 0;
18550 //
18551 //  Determine the number of triangular faces.
18552 //
18553   face_num2 = 0;
18554   for ( iface = 0; iface < face_num; iface++ )
18555   {
18556     for ( jlo = 0; jlo < face_order[iface] - 2; jlo++ )
18557     {
18558       face_num2 = face_num2 + 1;
18559     }
18560   }
18561 
18562   bytes_num = bytes_num + long_int_write ( fileout, face_num2 );
18563 //
18564 //  Do the next face.
18565 //
18566   for ( iface = 0; iface < face_num; iface++ )
18567   {
18568 //
18569 //  Break the face up into triangles, anchored at node 1.
18570 //
18571     for ( jlo = 0; jlo < face_order[iface] - 2; jlo ++ )
18572     {
18573       face2[0] = face[    0][iface];
18574       face2[1] = face[jlo+1][iface];
18575       face2[2] = face[jlo+2][iface];
18576 
18577       for ( k = 0; k < 3; k++ )
18578       {
18579         icor3 = face2[k];
18580 
18581         x = cor3[0][icor3];
18582         y = cor3[1][icor3];
18583         z = cor3[2][icor3];
18584 
18585         nx = cor3_normal[0][icor3];
18586         ny = cor3_normal[1][icor3];
18587         nz = cor3_normal[2][icor3];
18588 
18589         bytes_num = bytes_num + float_write ( fileout, x );
18590         bytes_num = bytes_num + float_write ( fileout, y );
18591         bytes_num = bytes_num + float_write ( fileout, z );
18592         bytes_num = bytes_num + float_write ( fileout, nx );
18593         bytes_num = bytes_num + float_write ( fileout, ny );
18594         bytes_num = bytes_num + float_write ( fileout, nz );
18595 
18596       }
18597 
18598     }
18599 
18600   }
18601 //
18602 //  Report.
18603 //
18604   cout << "\n";
18605   cout << "TRIB_WRITE - Wrote " << bytes_num << " bytes.\n";
18606 
18607   return 0;
18608 }
18609 //****************************************************************************80
18610 
18611 int txt_write ( FILE *fileout )
18612 
18613 //****************************************************************************80
18614 //
18615 //  Purpose:
18616 //
18617 //    TXT_WRITE writes the graphics data to a text file.
18618 //
18619 //  Licensing:
18620 //
18621 //    This code is distributed under the GNU LGPL license.
18622 //
18623 //  Modified:
18624 //
18625 //    25 June 1998
18626 //
18627 //  Author:
18628 //
18629 //    John Burkardt
18630 //
18631 {
18632   int i;
18633   int iface;
18634   int iline;
18635   int imat;
18636   int ivert;
18637   int nitem;
18638   int text_num;
18639 
18640   text_num = 0;
18641 
18642   fprintf ( fileout, "%s created by IVCON.\n", fileout_name );
18643   fprintf ( fileout, "Original data in %s.\n", filein_name );
18644   fprintf ( fileout, "Object name is %s.\n", object_name );
18645   fprintf ( fileout, "Object origin at %f %f %f.\n", origin[0], origin[1],
18646     origin[2] );
18647   fprintf ( fileout, "Object pivot at %f %f %f.\n", pivot[0], pivot[1],
18648     pivot[2] );
18649   text_num = text_num + 5;
18650 //
18651 //  TRANSFORMATION MATRIX.
18652 //
18653   fprintf ( fileout, "\n" );
18654   fprintf ( fileout, "Transformation matrix:\n" );
18655   fprintf ( fileout, "\n" );
18656   text_num = text_num + 3;
18657 
18658   for ( i = 0; i < 4; i++ )
18659   {
18660     fprintf ( fileout, "  %f %f %f %f\n", transform_matrix[i][0],
18661       transform_matrix[i][1], transform_matrix[i][2], transform_matrix[i][3] );
18662       text_num = text_num + 1;
18663   }
18664 //
18665 //  NODES.
18666 //
18667   fprintf ( fileout, "\n" );
18668   fprintf ( fileout, "  %d nodes.\n", cor3_num );
18669   text_num = text_num + 2;
18670 
18671   if ( 0 < cor3_num )
18672   {
18673     fprintf ( fileout, "\n" );
18674     fprintf ( fileout, "  Node coordinate data:\n" );
18675     fprintf ( fileout, "\n" );
18676     text_num = text_num + 3;
18677 
18678     for ( i = 0; i < cor3_num; i++ )
18679     {
18680       fprintf ( fileout, " %d %f %f %f\n ", i, cor3[0][i], cor3[1][i],
18681         cor3[2][i] );
18682       text_num = text_num + 1;
18683     }
18684 
18685     fprintf ( fileout, "\n" );
18686     fprintf ( fileout, "  Node normal vectors:\n" );
18687     fprintf ( fileout, "\n" );
18688     text_num = text_num + 3;
18689 
18690     for ( i = 0; i < cor3_num; i++ )
18691     {
18692       fprintf ( fileout, " %d %f %f %f\n ", i, cor3_normal[0][i],
18693         cor3_normal[1][i], cor3_normal[2][i] );
18694       text_num = text_num + 1;
18695     }
18696 
18697     fprintf ( fileout, "\n" );
18698     fprintf ( fileout, "  Node materials:\n" );
18699     fprintf ( fileout, "\n" );
18700     text_num = text_num + 3;
18701 
18702     for ( i = 0; i < cor3_num; i++ )
18703     {
18704       fprintf ( fileout, " %d %d\n ", i, cor3_material[i] );
18705       text_num = text_num + 1;
18706     }
18707 
18708     if ( 0 < texture_num )
18709     {
18710       fprintf ( fileout, "\n" );
18711       fprintf ( fileout, "  Node texture coordinates:\n" );
18712       fprintf ( fileout, "\n" );
18713       text_num = text_num + 3;
18714 
18715       for ( i = 0; i < cor3_num; i++ )
18716       {
18717         fprintf ( fileout, " %d %f %f\n ", i, cor3_tex_uv[0][i],
18718           cor3_tex_uv[1][i] );
18719         text_num = text_num + 1;
18720       }
18721     }
18722   }
18723 //
18724 //  LINES.
18725 //
18726   fprintf ( fileout, "\n" );
18727   fprintf ( fileout, "  %d line data items.\n", line_num );
18728   text_num = text_num + 2;
18729 
18730   if ( 0 < line_num )
18731   {
18732     fprintf ( fileout, "\n" );
18733     fprintf ( fileout, "  Line index data:\n" );
18734     fprintf ( fileout, "\n" );
18735     text_num = text_num + 3;
18736 
18737     nitem = 0;
18738 
18739     for ( iline = 0; iline < line_num; iline++ )
18740     {
18741       fprintf ( fileout, " %d", line_dex[iline] );
18742       nitem = nitem + 1;
18743 
18744       if ( iline == line_num - 1 || line_dex[iline] == -1 || 10 <=  nitem )
18745       {
18746         nitem = 0;
18747         fprintf ( fileout, "\n" );
18748         text_num = text_num + 1;
18749       }
18750 
18751     }
18752 
18753     fprintf ( fileout, "\n" );
18754     fprintf ( fileout, "  Line materials:\n" );
18755     fprintf ( fileout, "\n" );
18756     text_num = text_num + 3;
18757 
18758     nitem = 0;
18759 
18760     for ( iline = 0; iline < line_num; iline++ )
18761     {
18762 
18763       fprintf ( fileout, " %d", line_material[iline] );
18764       nitem = nitem + 1;
18765 
18766       if ( iline == line_num - 1
18767         || line_material[iline] == -1 || 10 <= nitem )
18768       {
18769         nitem = 0;
18770         fprintf ( fileout, "\n" );
18771         text_num = text_num + 1;
18772       }
18773     }
18774 
18775   }
18776 //
18777 //  COLOR DATA
18778 //
18779   fprintf ( fileout, "\n" );
18780   fprintf ( fileout, "  %d colors.\n", color_num );
18781   text_num = text_num + 2;
18782 //
18783 //  FACES.
18784 //
18785   fprintf ( fileout, "\n" );
18786   fprintf ( fileout, "  %d faces.\n", face_num );
18787   text_num = text_num + 2;
18788 
18789   if ( 0 < face_num )
18790   {
18791 
18792     fprintf ( fileout, "\n" );
18793     fprintf ( fileout, "  Face, Material, Number of vertices, Smoothing, Flags:\n" );
18794     fprintf ( fileout, "\n" );
18795     text_num = text_num + 3;
18796 
18797     for ( iface = 0; iface < face_num; iface++ )
18798     {
18799       fprintf ( fileout, " %d %d %d %d %d\n", iface, face_material[iface],
18800         face_order[iface], face_smooth[iface], face_flags[iface] );
18801       text_num = text_num + 1;
18802     }
18803 
18804     fprintf ( fileout, "\n" );
18805     fprintf ( fileout, "  Face, Vertices\n" );
18806     fprintf ( fileout, "\n" );
18807     text_num = text_num + 3;
18808 
18809     for ( iface = 0; iface < face_num; iface++ )
18810     {
18811       fprintf ( fileout, "%d   ", iface );
18812       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
18813       {
18814         fprintf ( fileout, " %d", face[ivert][iface] );
18815       }
18816 
18817       fprintf ( fileout, "\n" );
18818       text_num = text_num + 1;
18819     }
18820 
18821     fprintf ( fileout, "\n" );
18822     fprintf ( fileout, "  Face normal vectors:\n" );
18823     fprintf ( fileout, "\n" );
18824     text_num = text_num + 3;
18825 
18826     for ( iface = 0; iface < face_num; iface++ )
18827     {
18828       fprintf ( fileout, " %d %f %f %f\n", iface, face_normal[0][iface],
18829         face_normal[1][iface], face_normal[2][iface] );
18830       text_num = text_num + 1;
18831     }
18832 
18833     if ( 0 < texture_num )
18834     {
18835       fprintf ( fileout, "\n" );
18836       fprintf ( fileout, "  Face texture coordinates:\n" );
18837       fprintf ( fileout, "\n" );
18838       text_num = text_num + 3;
18839 
18840       for ( iface = 0; iface < face_num; iface++ )
18841       {
18842         fprintf ( fileout, " %d %f %f\n", iface, face_tex_uv[0][iface],
18843           face_tex_uv[1][iface] );
18844         text_num = text_num + 1;
18845       }
18846     }
18847   }
18848 //
18849 //  VERTICES.
18850 //
18851   if ( 0 < face_num )
18852   {
18853     fprintf ( fileout, "\n" );
18854     fprintf ( fileout, "Vertex normal vectors:\n" );
18855     text_num = text_num + 2;
18856 
18857     for ( iface = 0; iface < face_num; iface++ )
18858     {
18859       fprintf ( fileout, "\n" );
18860       text_num = text_num + 1;
18861       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
18862       {
18863         fprintf ( fileout, " %d %d %f %f %f\n", iface, ivert,
18864           vertex_normal[0][ivert][iface], vertex_normal[1][ivert][iface],
18865           vertex_normal[2][ivert][iface] );
18866         text_num = text_num + 1;
18867       }
18868     }
18869 
18870     fprintf ( fileout, "\n" );
18871     fprintf ( fileout, "Vertex materials:\n" );
18872     fprintf ( fileout, "\n" );
18873     text_num = text_num + 3;
18874 
18875     for ( iface = 0; iface < face_num; iface++ )
18876     {
18877       fprintf ( fileout, "%d", iface );
18878       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
18879       {
18880         fprintf ( fileout, " %d", vertex_material[ivert][iface] );
18881       }
18882       fprintf ( fileout, "\n" );
18883       text_num = text_num + 1;
18884     }
18885 
18886     if ( 0 < texture_num )
18887     {
18888       fprintf ( fileout, "\n" );
18889       fprintf ( fileout, "Vertex UV texture coordinates:\n" );
18890       fprintf ( fileout, "\n" );
18891       text_num = text_num + 3;
18892 
18893       for ( iface = 0; iface < face_num; iface++ )
18894       {
18895         for ( ivert = 0; ivert < face_order[iface]; ivert++ )
18896         {
18897           fprintf ( fileout, "%d %d %f %f\n", iface, ivert,
18898             vertex_tex_uv[0][ivert][iface], vertex_tex_uv[1][ivert][iface] );
18899           text_num = text_num + 1;
18900         }
18901       }
18902     }
18903   }
18904 //
18905 //  MATERIALS.
18906 //
18907   fprintf ( fileout, "\n" );
18908   fprintf ( fileout, "%d materials.\n", material_num );
18909   fprintf ( fileout, "\n" );
18910   fprintf ( fileout, "Index      Name   R G B A\n" );
18911   fprintf ( fileout, "\n" );
18912 
18913   text_num = text_num + 5;
18914 
18915   for ( imat = 0; imat < material_num; imat++ )
18916   {
18917     fprintf ( fileout, "%d %s %f %f %f %f\n", imat, material_name[imat],
18918       material_rgba[0][imat], material_rgba[1][imat], material_rgba[2][imat],
18919       material_rgba[3][imat] );
18920     text_num = text_num + 1;
18921   }
18922 //
18923 //  TEXTURES.
18924 //
18925   fprintf ( fileout, "\n" );
18926   fprintf ( fileout, "%d textures.\n", texture_num );
18927   text_num = text_num + 2;
18928 
18929   if ( 0 < texture_num )
18930   {
18931     fprintf ( fileout, "\n" );
18932     fprintf ( fileout, "Index  Name\n" );
18933     fprintf ( fileout, "\n" );
18934     for ( i = 0; i < texture_num; i++ )
18935     {
18936       fprintf ( fileout, "%d %s\n", i, texture_name[i] );
18937     }
18938     text_num = text_num + 3;
18939   }
18940 //
18941 //  Report.
18942 //
18943   cout << "\n";
18944   cout << "TXT_WRITE - Wrote " << text_num << " text lines.\n";
18945 
18946   return 0;
18947 }
18948 //****************************************************************************80
18949 
18950 int ucd_write ( FILE *fileout )
18951 
18952 //****************************************************************************80
18953 //
18954 //  Purpose:
18955 //
18956 //    UCD_WRITE writes graphics data to an AVS UCD file.
18957 //
18958 //  Example:
18959 //
18960 //    #  cube.ucd created by IVREAD.
18961 //    #
18962 //    #  Material RGB to hue map:
18963 //    #
18964 //    #  material    R    G  B   Alpha     Hue
18965 //    #
18966 //    #    0   0.94  0.70  0.15  1.000   0.116
18967 //    #    1   0.24  0.70  0.85  1.000   0.541
18968 //    #    2   0.24  0.00  0.85  1.000   0.666
18969 //    #
18970 //    #  The node data is
18971 //    #    node # / material # / RGBA / Hue
18972 //    #
18973 //    8  6  6  0  0
18974 //    0  0.0  0.0  0.0
18975 //    1  1.0  0.0  0.0
18976 //    2  1.0  1.0  0.0
18977 //    3  0.0  1.0  0.0
18978 //    4  0.0  0.0  1.0
18979 //    5  1.0  0.0  1.0
18980 //    6  1.0  1.0  1.0
18981 //    7  0.0  1.0  1.0
18982 //    0  0  quad  0  1  2  3
18983 //    1  0  quad  0  4  5  1
18984 //    2  0  quad  1  5  6  2
18985 //    3  0  quad  2  6  7  3
18986 //    4  0  quad  3  7  4  0
18987 //    5  0  quad  4  7  6  5
18988 //    3  1 4 1
18989 //    material, 0...2
18990 //    RGBA, 0-1/0-1/0-1/0-1
18991 //    Hue, 0-1
18992 //    0  0  0.94  0.70  0.15  1.0  0.116
18993 //    1  0  0.94  0.70  0.15  1.0  0.116
18994 //    2  0  0.94  0.70  0.15  1.0  0.116
18995 //    3  0  0.94  0.70  0.15  1.0  0.116
18996 //    4  1  0.24  0.70  0.85  1.0  0.541
18997 //    5  1  0.24  0.70  0.85  1.0  0.541
18998 //    6  2  0.24  0.24  0.85  0.0  0.666
18999 //    7  2  0.24  0.24  0.85  0.0  0.666
19000 //
19001 //  Licensing:
19002 //
19003 //    This code is distributed under the GNU LGPL license.
19004 //
19005 //  Modified:
19006 //
19007 //    22 May 1999
19008 //
19009 //  Author:
19010 //
19011 //    John Burkardt
19012 //
19013 //
19014 {
19015   float a;
19016   float b;
19017   float g;
19018   float h;
19019   int i;
19020   int imat;
19021   int j;
19022   int text_num;
19023   float r;
19024 
19025   text_num = 0;
19026 
19027   fprintf ( fileout, "#  %s created by IVREAD.\n", fileout_name );
19028   fprintf ( fileout, "#\n" );
19029   fprintf ( fileout, "#  Material RGB to Hue map:\n" );
19030   fprintf ( fileout, "#\n" );
19031   fprintf ( fileout, "#  material    R    G      B     Alpha  Hue\n" );
19032   fprintf ( fileout, "#\n" );
19033 
19034   text_num = text_num + 6;
19035 
19036   for ( j = 0; j < material_num; j++ )
19037   {
19038     r = material_rgba[0][j];
19039     g = material_rgba[1][j];
19040     b = material_rgba[2][j];
19041     a = material_rgba[3][j];
19042     h = rgb_to_hue ( r, g, b );
19043     fprintf ( fileout, "#  %d %f %f %f %f %f\n", j, r, g, b, a, h );
19044     text_num = text_num + 1;
19045   }
19046 
19047   fprintf ( fileout, "#\n" );
19048   fprintf ( fileout, "#  The node data is\n" );
19049   fprintf ( fileout, "#    node # / material # / RGBA / Hue\n" );
19050   fprintf ( fileout, "#\n" );
19051   text_num = text_num + 4;
19052 
19053   fprintf ( fileout, "%d %d 6 0 0\n", cor3_num, face_num );
19054   text_num = text_num + 1;
19055 
19056   for ( j = 0; j < cor3_num; j++ )
19057   {
19058     fprintf ( fileout, "%d %f %f %f\n", j, cor3[0][j], cor3[1][j],
19059       cor3[2][j] );
19060     text_num = text_num + 1;
19061   }
19062 //
19063 //  NOTE:
19064 //  UCD only accepts triangles and quadrilaterals, not higher order
19065 //  polygons.  We would need to break polygons up to proceed.
19066 //
19067   for ( j = 0; j < face_num; j++ )
19068   {
19069     fprintf ( fileout, "%d %d", j, face_material[j] );
19070 
19071     if ( face_order[j] == 3 )
19072     {
19073       fprintf ( fileout, " tri" );
19074     }
19075     else if ( face_order[j] == 4 )
19076     {
19077       fprintf ( fileout, " quad" );
19078     }
19079     else
19080     {
19081       fprintf ( fileout, " ???" );
19082     }
19083 
19084     for ( i = 0; i < face_order[j]; i++ )
19085     {
19086       fprintf ( fileout, "%d", face[i][j] );
19087     }
19088     fprintf ( fileout, "\n" );
19089     text_num = text_num + 1;
19090 
19091   }
19092 
19093   fprintf ( fileout, "3  1  4  1\n" );
19094   fprintf ( fileout, "material, 0...%d\n", material_num - 1 );
19095   fprintf ( fileout, "RGBA, 0-1/0-1/0-1/0-1\n" );
19096   fprintf ( fileout, "Hue, 0-1\n" );
19097   text_num = text_num + 4;
19098 
19099   for ( j = 0; j < cor3_num; j++ )
19100   {
19101     imat = cor3_material[j];
19102     r = material_rgba[0][imat];
19103     g = material_rgba[1][imat];
19104     b = material_rgba[2][imat];
19105     a = material_rgba[3][imat];
19106     h = rgb_to_hue ( r, g, b );
19107 
19108     fprintf ( fileout, "%d %d %f %f %f %f %f\n", j, imat, r, g, b, a, h );
19109     text_num = text_num + 1;
19110   }
19111 //
19112 //  Report.
19113 //
19114   cout << "\n";
19115   cout << "UCD_WRITE - Wrote " << text_num << " text lines.\n";
19116 
19117   return 0;
19118 }
19119 //****************************************************************************80
19120 
19121 void vertex_normal_set ( )
19122 
19123 //****************************************************************************80
19124 //
19125 //  Purpose:
19126 //
19127 //    VERTEX_NORMAL_SET recomputes the face vertex normal vectors.
19128 //
19129 //  Licensing:
19130 //
19131 //    This code is distributed under the GNU LGPL license.
19132 //
19133 //  Modified:
19134 //
19135 //    12 October 1998
19136 //
19137 //  Author:
19138 //
19139 //    John Burkardt
19140 //
19141 {
19142   int i;
19143   int i0;
19144   int i1;
19145   int i2;
19146   int iface;
19147   int ivert;
19148   int jp1;
19149   int jp2;
19150   int nfix;
19151   float norm;
19152   float temp;
19153   float x0;
19154   float x1;
19155   float x2;
19156   float xc;
19157   float y0;
19158   float y1;
19159   float y2;
19160   float yc;
19161   float z0;
19162   float z1;
19163   float z2;
19164   float zc;
19165 
19166   if ( face_num <= 0 )
19167   {
19168     return;
19169   }
19170 
19171   nfix = 0;
19172 //
19173 //  Consider each face.
19174 //
19175   for ( iface = 0; iface < face_num; iface++ )
19176   {
19177     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
19178     {
19179       norm = 0.0;
19180       for ( i = 0; i < 3; i++ )
19181       {
19182         temp = vertex_normal[i][ivert][iface];
19183         norm = norm + temp * temp;
19184       }
19185       norm = ( float ) sqrt ( norm );
19186 
19187       if ( norm == 0.0 )
19188       {
19189         nfix = nfix + 1;
19190 
19191         i0 = face[ivert][iface];
19192         x0 = cor3[0][i0];
19193         y0 = cor3[1][i0];
19194         z0 = cor3[2][i0];
19195 
19196         jp1 = ivert + 1;
19197         if ( face_order[iface] <= jp1 )
19198         {
19199           jp1 = jp1 - face_order[iface];
19200         }
19201         i1 = face[jp1][iface];
19202         x1 = cor3[0][i1];
19203         y1 = cor3[1][i1];
19204         z1 = cor3[2][i1];
19205 
19206         jp2 = ivert + 2;
19207         if ( face_order[iface] <= jp2 )
19208         {
19209           jp2 = jp2 - face_order[iface];
19210         }
19211         i2 = face[jp2][iface];
19212         x2 = cor3[0][i2];
19213         y2 = cor3[1][i2];
19214         z2 = cor3[2][i2];
19215 
19216         xc = ( y1 - y0 ) * ( z2 - z0 ) - ( z1 - z0 ) * ( y2 - y0 );
19217         yc = ( z1 - z0 ) * ( x2 - x0 ) - ( x1 - x0 ) * ( z2 - z0 );
19218         zc = ( x1 - x0 ) * ( y2 - y0 ) - ( y1 - y0 ) * ( x2 - x0 );
19219 
19220         norm = ( float ) sqrt ( xc * xc + yc * yc + zc * zc );
19221 
19222         if ( norm == 0.0 )
19223         {
19224           xc = ( float ) 1.0 / sqrt ( 3.0 );
19225           yc = ( float ) 1.0 / sqrt ( 3.0 );
19226           zc = ( float ) 1.0 / sqrt ( 3.0 );
19227         }
19228         else
19229         {
19230           xc = xc / norm;
19231           yc = yc / norm;
19232           zc = zc / norm;
19233         }
19234 
19235         vertex_normal[0][ivert][iface] = xc;
19236         vertex_normal[1][ivert][iface] = yc;
19237         vertex_normal[2][ivert][iface] = zc;
19238 
19239       }
19240     }
19241   }
19242 
19243   if ( 0 < nfix )
19244   {
19245     cout << "\n";
19246     cout << "VERTEX_NORMAL_SET: Recomputed " << nfix
19247          << " face vertex normals.\n";
19248   }
19249 
19250   return;
19251 }
19252 //****************************************************************************80
19253 
19254 void vertex_to_face_material ( )
19255 
19256 //****************************************************************************80
19257 //
19258 //  Purpose:
19259 //
19260 //    VERTEX_TO_FACE_MATERIAL extends vertex material definitions to faces.
19261 //
19262 //  Discussion:
19263 //
19264 //    Assuming material indices are defined for all the vertices, this
19265 //    routine assigns to each face the material associated with its
19266 //    first vertex.
19267 //
19268 //  Licensing:
19269 //
19270 //    This code is distributed under the GNU LGPL license.
19271 //
19272 //  Modified:
19273 //
19274 //    22 May 1999
19275 //
19276 //  Author:
19277 //
19278 //    John Burkardt
19279 //
19280 {
19281   int iface;
19282   int ivert;
19283 
19284   ivert = 0;
19285   for ( iface = 0; iface < face_num; iface++ )
19286   {
19287     face_material[iface] = vertex_material[ivert][iface];
19288   }
19289 
19290   return;
19291 }
19292 //****************************************************************************80
19293 
19294 void vertex_to_node_material ( )
19295 
19296 //****************************************************************************80
19297 //
19298 //  Purpose:
19299 //
19300 //    VERTEX_TO_NODE_MATERIAL extends vertex material definitions to nodes.
19301 //
19302 //  Discussion:
19303 //
19304 //    A NODE is a point in space.
19305 //    A VERTEX is a node as used in a particular face.
19306 //    One node may be used as a vertex in several faces, or none.
19307 //    This routine simply runs through all the vertices, and assigns
19308 //    the material of the vertex to the corresponding node.  If a
19309 //    node appears as a vertex several times, then the node will
19310 //    end up having the material of the vertex that occurs "last".
19311 //
19312 //  Licensing:
19313 //
19314 //    This code is distributed under the GNU LGPL license.
19315 //
19316 //  Modified:
19317 //
19318 //    22 May 1999
19319 //
19320 //  Author:
19321 //
19322 //    John Burkardt
19323 //
19324 {
19325   int iface;
19326   int ivert;
19327   int node;
19328 
19329   for ( iface = 0; iface < face_num; iface++ )
19330   {
19331     for ( ivert = 0; ivert < face_order[iface]; ivert++ )
19332     {
19333       node = face[ivert][iface];
19334       cor3_material[node] = vertex_material[ivert][iface];
19335     }
19336   }
19337 
19338   return;
19339 }
19340 
19341 //****************************************************************************80
19342 
19343 int vla_read ( FILE *filein )
19344 
19345 //****************************************************************************80
19346 //
19347 //  Purpose:
19348 //
19349 //    VLA_READ reads a VLA file.
19350 //
19351 //  Example:
19352 //
19353 //     set comment cube.vla created by IVREAD
19354 //     set comment Original data in cube.iv.
19355 //     set comment
19356 //     set intensity EXPLICIT
19357 //     set parametric NON_PARAMETRIC
19358 //     set filecontent LINES
19359 //     set filetype NEW
19360 //     set depthcue 0
19361 //     set defaultdraw stellar
19362 //     set coordsys RIGHT
19363 //     set author IVREAD
19364 //     set site Buhl Planetarium
19365 //     set library_id UNKNOWN
19366 //     P   8.59816       5.55317      -3.05561       1.00000
19367 //     L   8.59816       2.49756      0.000000E+00   1.00000
19368 //     L   8.59816       2.49756      -3.05561       1.00000
19369 //     L   8.59816       5.55317      -3.05561       1.00000
19370 //     P   8.59816       5.55317      0.000000E+00   1.00000
19371 //     ...etc...
19372 //     L   2.48695       2.49756      -3.05561       1.00000
19373 //
19374 //  Licensing:
19375 //
19376 //    This code is distributed under the GNU LGPL license.
19377 //
19378 //  Modified:
19379 //
19380 //    23 May 1999
19381 //
19382 //  Author:
19383 //
19384 //    John Burkardt
19385 //
19386 {
19387   int i;
19388   int   icor3;
19389   int   dup_num;
19390   char *next;
19391   int   text_num;
19392   float r1;
19393   float r2;
19394   float r3;
19395   float temp[3];
19396   char  token[LINE_MAX_LEN];
19397   int   width;
19398 //
19399 //  Initialize.
19400 //
19401   dup_num = 0;
19402   text_num = 0;
19403 //
19404 //  Read the next line of the file into INPUT.
19405 //
19406   while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL )
19407   {
19408     text_num = text_num + 1;
19409 //
19410 //  Advance to the first nonspace character in INPUT.
19411 //
19412     for ( next = input; *next != '\0' && ch_is_space ( *next ); next++ )
19413     {
19414     }
19415 //
19416 //  Skip blank lines and comments.
19417 //
19418     if ( *next == '\0' || *next == ';' )
19419     {
19420       continue;
19421     }
19422 //
19423 //  Extract the first word in this line.
19424 //
19425     sscanf ( next, "%s%n", token, &width );
19426 //
19427 //  Set NEXT to point to just after this token.
19428 //
19429     next = next + width;
19430 //
19431 //  SET (ignore)
19432 //
19433     if ( s_eqi ( token, "set" ) )
19434     {
19435     }
19436 //
19437 //  P (begin a line)
19438 //  L (continue a line)
19439 //
19440     else if ( s_eqi ( token, "P" ) || s_eqi ( token, "L" ) )
19441     {
19442       if ( s_eqi ( token, "P" ) )
19443       {
19444         if ( 0 < line_num )
19445         {
19446           if ( line_num < LINES_MAX )
19447           {
19448             line_dex[line_num] = -1;
19449             line_material[line_num] = -1;
19450             line_num = line_num + 1;
19451           }
19452         }
19453       }
19454 
19455       sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
19456 
19457       temp[0] = r1;
19458       temp[1] = r2;
19459       temp[2] = r3;
19460 
19461       if ( cor3_num < 1000 )
19462       {
19463         icor3 = rcol_find ( cor3, 3, cor3_num, temp );
19464       }
19465       else
19466       {
19467         icor3 = -1;
19468       }
19469 
19470       if ( icor3 == -1 )
19471       {
19472         icor3 = cor3_num;
19473 
19474         if ( cor3_num < COR3_MAX )
19475         {
19476           for ( i = 0; i < 3; i++ )
19477           {
19478             cor3[i][cor3_num] = temp[i];
19479           }
19480         }
19481         cor3_num = cor3_num + 1;
19482       }
19483       else
19484       {
19485         dup_num = dup_num + 1;
19486       }
19487 
19488       if ( line_num < LINES_MAX )
19489       {
19490         line_dex[line_num] = icor3;
19491         line_material[line_num] = 0;
19492         line_num = line_num + 1;
19493       }
19494     }
19495 //
19496 //  Unexpected or unrecognized.
19497 //
19498     else
19499     {
19500       cout << "\n";
19501       cout << "VLA_READ - Fatal error!\n";
19502       cout << "  Unrecognized first word on line.\n";
19503       return 1;
19504     }
19505 
19506   }
19507 
19508   if ( 0 < line_num )
19509   {
19510     if ( line_num < LINES_MAX )
19511     {
19512       line_dex[line_num] = -1;
19513       line_material[line_num] = -1;
19514       line_num = line_num + 1;
19515     }
19516   }
19517 
19518   return 0;
19519 }
19520 //****************************************************************************80
19521 
19522 int vla_write ( FILE *fileout )
19523 
19524 //****************************************************************************80
19525 //
19526 //  Purpose:
19527 //
19528 //    VLA_WRITE writes internal graphics information to a VLA file.
19529 //
19530 //  Discussion:
19531 //
19532 //    Comments begin with a semicolon in column 1.
19533 //    The X, Y, Z coordinates of points begin with a "P" to
19534 //    denote the beginning of a line, and "L" to denote the
19535 //    continuation of a line.  The fourth entry is intensity, which
19536 //    should be between 0.0 and 1.0.
19537 //
19538 //  Example:
19539 //
19540 //     set comment cube.vla created by IVREAD
19541 //     set comment Original data in cube.iv.
19542 //     set comment
19543 //     set intensity EXPLICIT
19544 //     set parametric NON_PARAMETRIC
19545 //     set filecontent LINES
19546 //     set filetype NEW
19547 //     set depthcue 0
19548 //     set defaultdraw stellar
19549 //     set coordsys RIGHT
19550 //     set author IVREAD
19551 //     set site Buhl Planetarium
19552 //     set library_id UNKNOWN
19553 //     P   8.59816       5.55317      -3.05561       1.00000
19554 //     L   8.59816       2.49756      0.000000E+00   1.00000
19555 //     L   8.59816       2.49756      -3.05561       1.00000
19556 //     L   8.59816       5.55317      -3.05561       1.00000
19557 //     P   8.59816       5.55317      0.000000E+00   1.00000
19558 //     ...etc...
19559 //     L   2.48695       2.49756      -3.05561       1.00000
19560 //
19561 //  Licensing:
19562 //
19563 //    This code is distributed under the GNU LGPL license.
19564 //
19565 //  Modified:
19566 //
19567 //    22 May 1999
19568 //
19569 //  Author:
19570 //
19571 //    John Burkardt
19572 //
19573 {
19574   char  c;
19575   int   iline;
19576   float intense = 1.0;
19577   int   k;
19578   int   text_num;
19579 //
19580 //  Initialize.
19581 //
19582   text_num = 0;
19583 
19584   fprintf ( fileout, "set comment %s created by IVCON.\n", fileout_name );
19585   fprintf ( fileout, "set comment Original data in %s.\n", filein_name );
19586   fprintf ( fileout, "set comment\n" );
19587   fprintf ( fileout, "set intensity EXPLICIT\n" );
19588   fprintf ( fileout, "set parametric NON_PARAMETRIC\n" );
19589   fprintf ( fileout, "set filecontent LINES\n" );
19590   fprintf ( fileout, "set filetype NEW\n" );
19591   fprintf ( fileout, "set depthcue 0\n" );
19592   fprintf ( fileout, "set defaultdraw stellar\n" );
19593   fprintf ( fileout, "set coordsys RIGHT\n" );
19594   fprintf ( fileout, "set author IVCON\n" );
19595   fprintf ( fileout, "set site Buhl Planetarium\n" );
19596   fprintf ( fileout, "set library_id UNKNOWN\n" );
19597 
19598   text_num = text_num + 13;
19599 
19600   c = 'P';
19601 
19602   for ( iline = 0; iline < line_num; iline++ )
19603   {
19604 
19605     k = line_dex[iline];
19606 
19607     if ( k == -1 )
19608     {
19609       c = 'P';
19610     }
19611     else
19612     {
19613       fprintf ( fileout, "%c %f %f %f %f\n",
19614         c, cor3[0][k], cor3[1][k], cor3[2][k], intense );
19615 
19616       text_num = text_num + 1;
19617 
19618       c = 'L';
19619     }
19620   }
19621 //
19622 //  Report.
19623 //
19624   cout << "\n";
19625   cout << "VLA_WRITE - Wrote " << text_num << " text lines.\n";
19626 
19627   return 0;
19628 }
19629 //****************************************************************************80
19630 
19631 int wrl_write ( FILE *fileout )
19632 
19633 //****************************************************************************80
19634 //
19635 //  Purpose:
19636 //
19637 //    WRL_WRITE writes graphics data to a WRL file.
19638 //
19639 //  Example:
19640 //
19641 //    #VRML V2.0 utf8
19642 //
19643 //    WorldInfo {
19644 //      title "cube.iv."
19645 //      string "WRL file generated by IVREAD.
19646 //    }
19647 //
19648 //    Group {
19649 //      children [
19650 //
19651 //        Shape {
19652 //
19653 //          appearance Appearance {
19654 //            material Material {
19655 //              diffuseColor   0.0 0.0 0.0
19656 //              emissiveColor  0.0 0.0 0.0
19657 //              shininess      1.0
19658 //            }
19659 //          } #end of appearance
19660 //
19661 //          geometry IndexedLineSet {
19662 //
19663 //            coord Coordinate {
19664 //              point [
19665 //                8.59816       5.55317      -3.05561
19666 //                8.59816       2.49756      0.000000E+00
19667 //                ...etc...
19668 //                2.48695       2.49756      -3.05561
19669 //              ]
19670 //            }
19671 //
19672 //            coordIndex [
19673 //                0     1     2    -1     3     4     5     6     7     8    -
19674 //                9    10    -1    11    12    -1    13    14    15    -1    1
19675 //              ...etc...
19676 //              191    -1
19677 //            ]
19678 //
19679 //            colorPerVertex TRUE
19680 //
19681 //            colorIndex [
19682 //                0     0     0    -1     2     3     1     1     4     7    -
19683 //               10     9    -1     7     7    -1     3     2     2    -1    1
19684 //              ...etc...
19685 //              180    -1
19686 //            ]
19687 //
19688 //          }  #end of geometry
19689 //
19690 //        }  #end of Shape
19691 //
19692 //      ]  #end of children
19693 //
19694 //    }  #end of Group
19695 //
19696 //  Licensing:
19697 //
19698 //    This code is distributed under the GNU LGPL license.
19699 //
19700 //  Modified:
19701 //
19702 //    23 May 1999
19703 //
19704 //  Author:
19705 //
19706 //    John Burkardt
19707 //
19708 {
19709   int icor3;
19710   int iface;
19711   int itemp;
19712   int ivert;
19713   int j;
19714   int length;
19715   int ndx;
19716 
19717   text_num = 0;
19718 
19719   fprintf ( fileout, "#VRML V2.0 utf8\n" );
19720   fprintf ( fileout, "\n" );
19721   fprintf ( fileout, "  WorldInfo {\n" );
19722   fprintf ( fileout, "    title \"%s\"\n", fileout_name );
19723   fprintf ( fileout, "    info \"WRL file generated by IVREAD.\"\n" );
19724   fprintf ( fileout, "    info \"Original data in %s\"\n", filein_name );
19725   fprintf ( fileout, "  }\n" );
19726   fprintf ( fileout, "\n" );
19727   fprintf ( fileout, "  Group {\n" );
19728   fprintf ( fileout, "    children [\n" );
19729   fprintf ( fileout, "      Shape {\n" );
19730   fprintf ( fileout, "        appearance Appearance {\n" );
19731   fprintf ( fileout, "          material Material {\n" );
19732   fprintf ( fileout, "            diffuseColor   0.0 0.0 0.0\n" );
19733   fprintf ( fileout, "            emissiveColor  0.0 0.0 0.0\n" );
19734   fprintf ( fileout, "            shininess      1.0\n" );
19735   fprintf ( fileout, "          }\n" );
19736   fprintf ( fileout, "        }\n" );
19737 
19738   text_num = text_num + 18;
19739 //
19740 //  IndexedLineSet
19741 //
19742   if ( 0 < line_num )
19743   {
19744     fprintf ( fileout, "        geometry IndexedLineSet {\n" );
19745 //
19746 //  IndexedLineSet coord
19747 //
19748     fprintf ( fileout, "          coord Coordinate {\n" );
19749     fprintf ( fileout, "            point [\n" );
19750 
19751     text_num = text_num + 3;
19752 
19753     for ( icor3 = 0; icor3 < cor3_num; icor3++ )
19754     {
19755       fprintf ( fileout, "              %f %f %f\n", cor3[0][icor3],
19756         cor3[1][icor3], cor3[2][icor3] );
19757       text_num = text_num + 1;
19758     }
19759 
19760     fprintf ( fileout, "            ]\n" );
19761     fprintf ( fileout, "          }\n" );
19762     text_num = text_num + 2;
19763 //
19764 //  IndexedLineSet coordIndex.
19765 //
19766     fprintf ( fileout, "          coordIndex [\n" );
19767 
19768     text_num = text_num + 1;
19769 
19770     length = 0;
19771     for ( j = 0; j < line_num; j++ )
19772     {
19773       fprintf ( fileout, "%d ", line_dex[j] );
19774       length = length + 1;
19775       if ( line_dex[j] == -1 || 10 <= length || j == line_num - 1 )
19776       {
19777         fprintf ( fileout, "\n" );
19778         text_num = text_num + 1;
19779         length = 0;
19780       }
19781     }
19782 
19783     fprintf ( fileout, "          ]\n" );
19784     text_num = text_num + 1;
19785 //
19786 //  Colors. (materials)
19787 //
19788     fprintf ( fileout, "          color Color {\n" );
19789     fprintf ( fileout, "            color [\n" );
19790     text_num = text_num + 2;
19791 
19792     for ( j = 0; j < material_num; j++ )
19793     {
19794       fprintf ( fileout, "              %f %f %f\n", material_rgba[0][j],
19795         material_rgba[1][j], material_rgba[2][j] );
19796       text_num = text_num + 1;
19797     }
19798 
19799     fprintf ( fileout, "            ]\n" );
19800     fprintf ( fileout, "          }\n" );
19801     fprintf ( fileout, "          colorPerVertex TRUE\n" );
19802 //
19803 //  IndexedLineset colorIndex
19804 //
19805     fprintf ( fileout, "          colorIndex [\n" );
19806 
19807     text_num = text_num + 4;
19808 
19809     length = 0;
19810     for ( j = 0; j < line_num; j++ )
19811     {
19812       fprintf ( fileout, "%d ", line_material[j] );
19813       length = length + 1;
19814       if ( line_dex[j] == -1 || 10 <= length || j == line_num - 1 )
19815       {
19816         fprintf ( fileout, "\n" );
19817         text_num = text_num + 1;
19818         length = 0;
19819       }
19820     }
19821 
19822     fprintf ( fileout, "          ]\n" );
19823     fprintf ( fileout, "        }\n" );
19824     text_num = text_num + 2;
19825 
19826   }
19827 //
19828 //  End of IndexedLineSet
19829 //
19830 //  IndexedFaceSet
19831 //
19832   if ( 0 < face_num )
19833   {
19834 
19835     fprintf ( fileout, "        geometry IndexedFaceSet {\n" );
19836 //
19837 //  IndexedFaceSet coord
19838 //
19839     fprintf ( fileout, "          coord Coordinate {\n" );
19840     fprintf ( fileout, "            point [\n" );
19841 
19842     text_num = text_num + 3;
19843 
19844     for ( icor3 = 0; icor3 < cor3_num; icor3++ )
19845     {
19846       fprintf ( fileout, "              %f %f %f\n", cor3[0][icor3],
19847         cor3[1][icor3], cor3[2][icor3] );
19848 
19849       text_num = text_num + 1;
19850     }
19851 
19852     fprintf ( fileout, "            ]\n" );
19853     fprintf ( fileout, "          }\n" );
19854 //
19855 //  IndexedFaceSet coordIndex.
19856 //
19857     fprintf ( fileout, "          coordIndex [\n" );
19858 
19859     text_num = text_num + 3;
19860 
19861     length = 0;
19862 
19863     for ( iface = 0; iface < face_num; iface++ )
19864     {
19865       for ( ivert = 0; ivert <= face_order[iface]; ivert++ )
19866       {
19867         if ( ivert <= face_order[iface] )
19868         {
19869           itemp = face[ivert][iface];
19870         }
19871         else
19872         {
19873           itemp = 0;
19874         }
19875 
19876         fprintf ( fileout, "%d ", itemp );
19877         length = length + 1;
19878 
19879         if ( itemp == -1 || 10 <= length ||
19880           ( iface == face_num - 1 && ivert == face_order[iface]  ) )
19881         {
19882           fprintf ( fileout, "\n" );
19883           text_num = text_num + 1;
19884           length = 0;
19885         }
19886 
19887       }
19888 
19889     }
19890 
19891     fprintf ( fileout, "          ]\n" );
19892     text_num = text_num + 1;
19893 //
19894 //  IndexedFaceset colorIndex
19895 //
19896     fprintf ( fileout, "          colorIndex [\n" );
19897     text_num = text_num + 1;
19898 
19899     length = 0;
19900     ndx = 0;
19901 
19902     for ( iface = 0; iface < face_num; iface++ )
19903     {
19904       for ( ivert = 0; ivert <= face_order[iface]; ivert++ )
19905       {
19906 
19907         if ( ivert <= face_order[iface] )
19908         {
19909           itemp = vertex_material[ivert][iface];
19910           ndx = ndx + 1;
19911         }
19912         else
19913         {
19914           itemp = 0;
19915         }
19916 
19917         fprintf ( fileout, "%d ", itemp );
19918         length = length + 1;
19919 
19920         if ( itemp == -1 || 10 <= length ||
19921           ( iface == face_num - 1 && ivert == face_order[iface] )  )
19922         {
19923 
19924           fprintf ( fileout, "\n" );
19925           text_num = text_num + 1;
19926           length = 0;
19927 
19928         }
19929 
19930       }
19931 
19932     }
19933 
19934     fprintf ( fileout, "          ]\n" );
19935     fprintf ( fileout, "        }\n" );
19936     text_num = text_num + 2;
19937 
19938   }
19939 //
19940 //  End of IndexedFaceSet
19941 //
19942 //  End of:
19943 //    Shape
19944 //  children
19945 //    Group
19946 //
19947   fprintf ( fileout, "      }\n" );
19948   fprintf ( fileout, "    ]\n" );
19949   fprintf ( fileout, "  }\n" );
19950 
19951   text_num = text_num + 3;
19952 //
19953 //  Report.
19954 //
19955   cout << "\n";
19956   cout << "WRL_WRITE - Wrote " << text_num << " text lines.\n";
19957 
19958   return 0;
19959 }
19960 //****************************************************************************80
19961 
19962 int xgl_write ( FILE *fileout )
19963 
19964 //****************************************************************************80
19965 //
19966 //  Purpose:
19967 //
19968 //    XGL_WRITE writes an XGL file.
19969 //
19970 //  Discussion:
19971 //
19972 //    Two corrections to the routine were pointed out by
19973 //    Mike Phillips, msphil AT widowmaker.com, on 17 September 2001,
19974 //    and are gratefully acknowledged.
19975 //
19976 //  Example:
19977 //
19978 //    <WORLD>
19979 //
19980 //      <BACKGROUND>
19981 //        <BACKCOLOR> 0.1, 0.1, 0.1 </BACKCOLOR>
19982 //      </BACKGROUND>
19983 //
19984 //      <LIGHTING>
19985 //        <AMBIENT> 0.2, 0.1, 0.1 </AMBIENT>
19986 //        <DIRECTIONALLIGHT>
19987 //          <DIFFUSE> 0.1, 0.2, 0.1 </DIFFUSE>
19988 //          <DIRECTION> 0, 0, 100 </DIRECTION>
19989 //          <SPECULAR> 0.1, 0.1, 0.2 </SPECULAR>
19990 //        </DIRECTIONALLIGHT>
19991 //      </LIGHTING>
19992 //
19993 //      <MESH ID = "0">
19994 //
19995 //        <P ID="0"> -0.5, -0.5, 1 </P>
19996 //        <P ID="1"> 0.5, -0.5, 1 </P>
19997 //        <P ID="2"> 0.5, 0.5, 1 </P>
19998 //        <P ID="3"> -0.5, 0.5, 1 </P>
19999 //        <P ID="4"> 0.5, -0.5, 0 </P>
20000 //        <P ID="5"> -0.5, -0.5, 0 </P>
20001 //        <P ID="6"> -0.5, 0.5, 0 </P>
20002 //        <P ID="7"> 0.5, 0.5, 0 </P>
20003 //
20004 //        <N ID="0"> -0.408248, -0.408248, 0.816497 </N>
20005 //        <N ID="1"> 0.666667, -0.666667, 0.333333 </N>
20006 //        <N ID="2"> 0.408248, 0.408248, 0.816497 </N>
20007 //        <N ID="3"> -0.666667, 0.666667, 0.333333 </N>
20008 //        <N ID="4"> 0.408248, -0.408248, -0.816497 </N>
20009 //        <N ID="5"> -0.666667, -0.666667, -0.333333 </N>
20010 //        <N ID="6"> -0.408248, 0.408248, -0.816497 </N>
20011 //        <N ID="7"> 0.666667, 0.666667, -0.333333 </N>
20012 //
20013 //        <MAT ID="0">
20014 //          <ALPHA> 0.9 </ALPHA>
20015 //          <AMB> 0.1, 0.1, 0.1 </AMB>
20016 //          <DIFF> 0.2, 0.1, 0.1 </DIFF>
20017 //          <EMISS> 0.1, 0.2, 0.1 </EMISS>
20018 //          <SHINE> 0.8 </SHINE>
20019 //          <SPEC> 0.1, 0.1, 0.2 </SPEC>
20020 //        </MAT>
20021 //
20022 //        <F>
20023 //          <MATREF> 0 </MATREF>
20024 //          <FV1><PREF> 0 </PREF><NREF> 0 </NREF></FV1>
20025 //          <FV2><PREF> 1 </PREF><NREF> 1 </NREF></FV2>
20026 //          <FV3><PREF> 2 </PREF><NREF> 2 </NREF></FV3>
20027 //        </F>
20028 //        <F>
20029 //          <MATREF> 0 </MATREF>
20030 //          <FV1><PREF> 0 </PREF><NREF> 0 </NREF></FV1>
20031 //          <FV2><PREF> 2 </PREF><NREF> 2 </NREF></FV2>
20032 //          <FV3><PREF> 3 </PREF><NREF> 3 </NREF></FV3>
20033 //        </F>
20034 //        <F>
20035 //          <MATREF> 0 </MATREF>
20036 //          <FV1><PREF> 4 </PREF><NREF> 4 </NREF></FV1>
20037 //          <FV2><PREF> 5 </PREF><NREF> 5 </NREF></FV2>
20038 //          <FV3><PREF> 6 </PREF><NREF> 6 </NREF></FV3>
20039 //        </F>
20040 //        <F>
20041 //          <MATREF> 0 </MATREF>
20042 //          <FV1><PREF> 4 </PREF><NREF> 4 </NREF></FV1>
20043 //          <FV2><PREF> 6 </PREF><NREF> 6 </NREF></FV2>
20044 //          <FV3><PREF> 7 </PREF><NREF> 7 </NREF></FV3>
20045 //        </F>
20046 //        <F>
20047 //          <MATREF> 0 </MATREF>
20048 //          <FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
20049 //          <FV2><PREF> 0 </PREF><NREF> 0 </NREF></FV2>
20050 //          <FV3><PREF> 3 </PREF><NREF> 3 </NREF></FV3>
20051 //        </F>
20052 //        <F>
20053 //          <MATREF> 0 </MATREF>
20054 //          <FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
20055 //          <FV2><PREF> 3 </PREF><NREF> 3 </NREF></FV2>
20056 //          <FV3><PREF> 6 </PREF><NREF> 6 </NREF></FV3>
20057 //        </F>
20058 //        <F>
20059 //          <MATREF> 0 </MATREF>
20060 //          <FV1><PREF> 1 </PREF><NREF> 1 </NREF></FV1>
20061 //          <FV2><PREF> 4 </PREF><NREF> 4 </NREF></FV2>
20062 //          <FV3><PREF> 7 </PREF><NREF> 7 </NREF></FV3>
20063 //        </F>
20064 //        <F>
20065 //          <MATREF> 0 </MATREF>
20066 //          <FV1><PREF> 1 </PREF><NREF> 1 </NREF></FV1>
20067 //          <FV2><PREF> 7 </PREF><NREF> 7 </NREF></FV2>
20068 //          <FV3><PREF> 2 </PREF><NREF> 2 </NREF></FV3>
20069 //        </F>
20070 //        <F>
20071 //          <MATREF> 0 </MATREF>
20072 //          <FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
20073 //          <FV2><PREF> 4 </PREF><NREF> 4 </NREF></FV2>
20074 //          <FV3><PREF> 1 </PREF><NREF> 1 </NREF></FV3>
20075 //        </F>
20076 //        <F>
20077 //          <MATREF> 0 </MATREF>
20078 //          <FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
20079 //          <FV2><PREF> 1 </PREF><NREF> 1 </NREF></FV2>
20080 //          <FV3><PREF> 0 </PREF><NREF> 0 </NREF></FV3>
20081 //        </F>
20082 //        <F>
20083 //          <MATREF> 0 </MATREF>
20084 //          <FV1><PREF> 3 </PREF><NREF> 3 </NREF></FV1>
20085 //          <FV2><PREF> 2 </PREF><NREF> 2 </NREF></FV2>
20086 //          <FV3><PREF> 7 </PREF><NREF> 7 </NREF></FV3>
20087 //        </F>
20088 //        <F>
20089 //          <MATREF> 0 </MATREF>
20090 //          <FV1><PREF> 3 </PREF><NREF> 3 </NREF></FV1>
20091 //          <FV2><PREF> 7 </PREF><NREF> 7 </NREF></FV2>
20092 //          <FV3><PREF> 6 </PREF><NREF> 6 </NREF></FV3>
20093 //        </F>
20094 //      </MESH>
20095 //
20096 //      <OBJECT>
20097 //        <TRANSFORM>
20098 //          <FORWARD> 0, 0, 0 </FORWARD>
20099 //          <POSITION> 0, 0, 0 </POSITION>
20100 //          <SCALE> 1, 1, 1 </SCALE>
20101 //          <UP> 1, 1, 1 </UP>
20102 //        </TRANSFORM>
20103 //        <MESHREF> 0 </MESHREF>
20104 //      </OBJECT>
20105 //
20106 //    </WORLD>
20107 //
20108 //  Licensing:
20109 //
20110 //    This code is distributed under the GNU LGPL license.
20111 //
20112 //  Modified:
20113 //
20114 //    17 September 2001
20115 //
20116 //  Author:
20117 //
20118 //    John Burkardt
20119 //
20120 //  Reference:
20121 //
20122 //    XGL specification at http://www.xglspec.org/
20123 //
20124 {
20125   int iface;
20126   int ivert;
20127   int j;
20128   float light_ambient_rgb[3];
20129   float light_diffuse_rgb[3];
20130   float light_direction[3];
20131   float light_specular_rgb[3];
20132   int material;
20133   float material_alpha;
20134   float material_amb_rgb[3];
20135   float material_diff_rgb[3];
20136   float material_emiss_rgb[3];
20137   float material_shine;
20138   float material_spec_rgb[3];
20139   int mesh;
20140   int mesh_num = 1;
20141   int object;
20142   float transform_forward[3];
20143   float transform_position[3];
20144   float transform_scale[3];
20145   float transform_up[3];
20146 //
20147 //  Make up some placeholder values for now.
20148 //
20149   light_ambient_rgb[0] = 0.2;
20150   light_ambient_rgb[1] = 0.1;
20151   light_ambient_rgb[2] = 0.1;
20152 
20153   light_diffuse_rgb[0] = 0.1;
20154   light_diffuse_rgb[1] = 0.2;
20155   light_diffuse_rgb[2] = 0.1;
20156 
20157   light_direction[0] =   0.0;
20158   light_direction[1] =   0.0;
20159   light_direction[2] = 100.0;
20160 
20161   light_specular_rgb[0] = 0.1;
20162   light_specular_rgb[1] = 0.1;
20163   light_specular_rgb[2] = 0.2;
20164 
20165   material_alpha = 0.9;
20166 
20167   material_amb_rgb[0] = 0.1;
20168   material_amb_rgb[1] = 0.1;
20169   material_amb_rgb[2] = 0.1;
20170 
20171   material_diff_rgb[0] = 0.2;
20172   material_diff_rgb[1] = 0.1;
20173   material_diff_rgb[2] = 0.1;
20174 
20175   material_emiss_rgb[0] = 0.1;
20176   material_emiss_rgb[1] = 0.2;
20177   material_emiss_rgb[2] = 0.1;
20178 
20179   material_shine = 0.8;
20180 
20181   material_spec_rgb[0] = 0.1;
20182   material_spec_rgb[1] = 0.1;
20183   material_spec_rgb[2] = 0.2;
20184 
20185   transform_forward[0] = 0.0;
20186   transform_forward[1] = 0.0;
20187   transform_forward[2] = 0.0;
20188 
20189   transform_position[0] = 0.0;
20190   transform_position[1] = 0.0;
20191   transform_position[2] = 0.0;
20192 
20193   transform_scale[0] = 1.0;
20194   transform_scale[1] = 1.0;
20195   transform_scale[2] = 1.0;
20196 
20197   transform_up[0] = 1.0;
20198   transform_up[1] = 1.0;
20199   transform_up[2] = 1.0;
20200 
20201   object_num = 1;
20202 
20203   text_num = 0;
20204 
20205   fprintf ( fileout, "<WORLD>\n" );
20206   fprintf ( fileout, "\n" );
20207 
20208   text_num = text_num + 2;
20209 
20210   fprintf ( fileout, "  <BACKGROUND>\n" );
20211   fprintf ( fileout, "    <BACKCOLOR> %f, %f, %f </BACKCOLOR>\n",
20212     background_rgb[0], background_rgb[1], background_rgb[2] );
20213   fprintf ( fileout, "  </BACKGROUND>\n" );
20214   fprintf ( fileout, "\n" );
20215   fprintf ( fileout, "  <LIGHTING>\n" );
20216   fprintf ( fileout, "    <AMBIENT> %f, %f, %f </AMBIENT>\n",
20217     light_ambient_rgb[0], light_ambient_rgb[1], light_ambient_rgb[2] );
20218   fprintf ( fileout, "    <DIRECTIONALLIGHT>\n" );
20219   fprintf ( fileout, "      <DIFFUSE> %f, %f, %f </DIFFUSE>\n",
20220     light_diffuse_rgb[0], light_diffuse_rgb[1], light_diffuse_rgb[2] );
20221   fprintf ( fileout, "      <DIRECTION> %f, %f, %f </DIRECTION>\n",
20222     light_direction[0], light_direction[1], light_direction[2] );
20223   fprintf ( fileout, "      <SPECULAR> %f, %f, %f </SPECULAR>\n",
20224     light_specular_rgb[0], light_specular_rgb[1], light_specular_rgb[2] );
20225   fprintf ( fileout, "    </DIRECTIONALLIGHT>\n" );
20226   fprintf ( fileout, "  </LIGHTING>\n" );
20227 
20228   text_num = text_num + 12;
20229 
20230   for ( mesh = 0; mesh < mesh_num; mesh++ )
20231   {
20232     fprintf ( fileout, "\n" );
20233     fprintf ( fileout, "  <MESH ID = \"%d\">\n", mesh );
20234     fprintf ( fileout, "\n" );
20235     text_num = text_num + 3;
20236 
20237     for ( j = 0; j < cor3_num; j++ )
20238     {
20239       fprintf ( fileout, "    <P ID=\"%d\"> %f, %f, %f </P>\n", j,
20240         cor3[0][j], cor3[1][j], cor3[2][j] );
20241       text_num = text_num + 1;
20242     }
20243 
20244     fprintf ( fileout, "\n" );
20245     text_num = text_num + 1;
20246     for ( j = 0; j < cor3_num; j++ )
20247     {
20248       fprintf ( fileout, "    <N ID=\"%d\"> %f, %f, %f </N>\n", j,
20249         cor3_normal[0][j], cor3_normal[1][j], cor3_normal[2][j] );
20250       text_num = text_num + 1;
20251     }
20252 
20253     for ( material = 0; material < material_num; material++ )
20254     {
20255       fprintf ( fileout, "\n" );
20256       fprintf ( fileout, "    <MAT ID=\"%d\">\n", material );
20257       fprintf ( fileout, "      <ALPHA> %f </ALPHA>\n", material_alpha );
20258       fprintf ( fileout, "      <AMB> %f, %f, %f </AMB>\n",
20259         material_amb_rgb[0], material_amb_rgb[1], material_amb_rgb[2] );
20260       fprintf ( fileout, "      <DIFF> %f, %f, %f </DIFF>\n",
20261         material_diff_rgb[0], material_diff_rgb[1], material_diff_rgb[2] );
20262       fprintf ( fileout, "      <EMISS> %f, %f, %f </EMISS>\n",
20263         material_emiss_rgb[0], material_emiss_rgb[1], material_emiss_rgb[2] );
20264       fprintf ( fileout, "      <SHINE> %f </SHINE>\n", material_shine );
20265       fprintf ( fileout, "      <SPEC> %f, %f, %f </SPEC>\n",
20266         material_spec_rgb[0], material_spec_rgb[1], material_spec_rgb[2] );
20267       fprintf ( fileout, "    </MAT>\n" );
20268       text_num = text_num + 9;
20269     }
20270 
20271     fprintf ( fileout, "\n" );
20272     text_num = text_num + 1;
20273 
20274     for ( iface = 0; iface < face_num; iface++ )
20275     {
20276       fprintf ( fileout, "    <F>\n" );
20277       fprintf ( fileout, "      <MATREF> %d </MATREF>\n", face_material[iface] );
20278       text_num = text_num + 2;
20279       for ( ivert = 0; ivert < face_order[iface]; ivert++ )
20280       {
20281         fprintf ( fileout,
20282           "      <FV%d><PREF> %d </PREF><NREF> %d </NREF></FV%d>\n",
20283           ivert+1, face[ivert][iface], face[ivert][iface], ivert+1 );
20284         text_num = text_num + 1;
20285       }
20286       fprintf ( fileout, "    </F>\n" );
20287       text_num = text_num + 1;
20288     }
20289 
20290     fprintf ( fileout, "  </MESH>\n" );
20291     text_num = text_num + 1;
20292 
20293   }
20294 
20295   fprintf ( fileout, "\n" );
20296   text_num = text_num + 1;
20297 
20298   for ( object = 0; object < object_num; object++ )
20299   {
20300     fprintf ( fileout, "  <OBJECT>\n" );
20301     fprintf ( fileout, "    <TRANSFORM>\n" );
20302     fprintf ( fileout, "      <FORWARD> %f, %f, %f </FORWARD>\n",
20303       transform_forward[0], transform_forward[1], transform_forward[2] );
20304     fprintf ( fileout, "      <POSITION> %f, %f, %f </POSITION>\n",
20305       transform_position[0], transform_position[1], transform_position[2] );
20306     fprintf ( fileout, "'      <SCALE> %f, %f, %f </SCALE>\n",
20307       transform_scale[0], transform_scale[1], transform_scale[2] );
20308     fprintf ( fileout, "      <UP> %f, %f, %f </UP>\n",
20309       transform_up[0], transform_up[1], transform_up[2] );
20310     fprintf ( fileout, "    </TRANSFORM>\n" );
20311     mesh = 0;
20312     fprintf ( fileout, "    <MESHREF> %d </MESHREF>\n", mesh );
20313     fprintf ( fileout, "  </OBJECT>\n" );
20314     text_num = text_num + 9;
20315   }
20316 
20317   fprintf ( fileout, "\n" );
20318   fprintf ( fileout, "</WORLD>\n" );
20319   text_num = text_num + 2;
20320 
20321 //
20322 //  Report.
20323 //
20324   cout << "\n";
20325   cout << "XGL_WRITE - Wrote " << text_num << " text lines.\n";
20326 
20327   return 0;
20328 }


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