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 //