ivcon.cpp
Go to the documentation of this file.
1 //
2 // Purpose:
3 //
4 // IVCON converts various 3D graphics files.
5 //
6 // Acknowledgements:
7 //
8 // Coding, comments, and advice were supplied by a number of collaborators.
9 //
10 // Jean-Cristophe Hoelt (hoeltj AT tcd.ie) pointed out that the program was
11 // not compiling under GNU C++, and I made the necessary corrections.
12 //
13 // John F Flanagan made some corrections to the 3D Studio Max routines.
14 //
15 // Zik Saleeba (zik AT zikzak.net) enhanced the DXF routines, and added the
16 // Golgotha GMOD routines.
17 //
18 // Thanks to Susan M. Fisher, University of North Carolina,
19 // Department of Computer Science, for pointing out a coding error
20 // in FACE_NULL_DELETE that was overwriting all the data!
21 //
22 // Licensing:
23 //
24 // This code is distributed under the GNU LGPL license.
25 //
26 // Modified:
27 //
28 // 19 January 2004
29 //
30 // Author:
31 //
32 // John Burkardt
33 //
34 # include <cstdlib>
35 # include <cmath>
36 # include <cstdio>
37 # include <iostream>
38 # include <iomanip>
39 # include <fstream>
40 # include <cstring>
41 
42 using namespace std;
43 
44 # define ERROR 1
45 # define G1_SECTION_MODEL_QUADS 18
46 # define G1_SECTION_MODEL_TEXTURE_NAMES 19
47 # define G1_SECTION_MODEL_VERT_ANIMATION 20
48 # define GMOD_MAX_SECTIONS 32
49 # define GMOD_UNUSED_VERTEX 65535
50 # define PI 3.141592653589793238462643
51 
52 # define DEG_TO_RAD ( PI / 180.0 )
53 # define RAD_TO_DEG ( 180.0 / PI )
54 
55 //****************************************************************************80
56 //
57 // GLOBAL DATA
58 //
59 //****************************************************************************80
60 //
61 // BACKGROUND_RGB[3], the background color.
62 //
63 // BYTE_SWAP, byte swapping option.
64 //
65 // COR3[3][COR3_MAX], the coordinates of nodes.
66 //
67 // COR3_MATERIAL[COR3_MAX], the index of the material of each node.
68 //
69 // COR3_MAX, the maximum number of points.
70 //
71 // COR3_NORMAL[3][COR3_MAX], normal vectors associated with nodes.
72 //
73 // COR3_NUM, the number of points.
74 //
75 // COR3_RGB[3][COR3_MAX], RGB colors associated with nodes.
76 //
77 // COR3_TEX_UV[2][COR3_MAX], texture coordinates associated with nodes.
78 //
79 // FACE[ORDER_MAX][FACE_MAX] contains the index of the I-th node making up face J.
80 //
81 // FACE_AREA(FACE_MAX), the area of each face.
82 //
83 // FACE_MATERIAL[FACE_MAX]; the material of each face.
84 //
85 // FACE_MAX, the maximum number of faces.
86 //
87 // FACE_NORMAL[3][FACE_MAX], the face normal vectors.
88 //
89 // FACE_NUM, the number of faces.
90 //
91 // FACE_ORDER[FACE_MAX], the number of vertices per face.
92 //
93 // FACE_TEX_UV[2][FACE_MAX], texture coordinates associated with faces.
94 //
95 // LINE_DEX[LINES_MAX], node indices, denoting polylines, each terminated by -1.
96 //
97 // LINE_MATERIAL[LINES_MAX], index into RGBCOLOR for line color.
98 //
99 // LINES_MAX, the maximum number of line definition items.
100 //
101 // LINE_NUM, the number of line definition items.
102 //
103 // LINE_PRUNE, pruning option ( 0 = no pruning, nonzero = pruning).
104 //
105 // MATERIAL_MAX, the maximum number of materials.
106 //
107 // MATERIAL_NUM, the number of materials.
108 //
109 // ORDER_MAX, the maximum number of vertices per face.
110 //
111 // TEXTURE_MAX, the maximum number of textures.
112 //
113 // TEXTURE_NAME[TEXTURE_MAX][LINE_MAX_LEN], ...
114 //
115 // TEXTURE_NUM, the number of textures.
116 //
117 // TRANSFORM_MATRIX[4][4], the current transformation matrix.
118 //
119 // VERTEX_MATERIAL[ORDER_MAX][FACE_MAX]; the material of vertices of faces.
120 //
121 // VERTEX_NORMAL[3][ORDER_MAX][FACE_MAX], normals at vertices of faces.
122 //
123 // VERTEX_RGB[3][ORDER_MAX][FACE_MAX], colors of vertices of faces.
124 //
125 // VERTEX_TEX_UV[2][ORDER_MAX][FACE_MAX], texture coordinates of vertices of faces.
126 //
127 
128 # define COLOR_MAX 1000
129 # define COR3_MAX 200000
130 # define FACE_MAX 200000
131 # define LINE_MAX_LEN 256
132 # define LEVEL_MAX 10
133 # define LINES_MAX 100000
134 # define MATERIAL_MAX 100
135 # define ORDER_MAX 10
136 # define TEXTURE_MAX 100
137 
139 float background_rgb[3];
145 
146 float cor3[3][COR3_MAX];
151 
152 bool debug;
153 
155 
166 
167 char filein_name[81];
168 char fileout_name[81];
169 
171 
172 int i;
174 int k;
176 
181 
183 
188 
189 char mat_name[81];
191 
192 char normal_binding[80];
194 
195 char object_name[81];
197 
198 float origin[3];
199 float pivot[3];
200 float rgbcolor[3][COLOR_MAX];
201 char temp_name[81];
202 
204 
209 
210 float transform_matrix[4][4];
211 
216 
217 //****************************************************************************80
218 //
219 // FUNCTION PROTOTYPES
220 //
221 //****************************************************************************80
222 
223 int main ( int argc, char *argv[] );
224 int ase_read ( FILE *filein );
225 int ase_write ( FILE *fileout );
226 int byu_read ( FILE *filein );
227 int byu_write ( FILE *fileout );
228 char ch_cap ( char c );
229 bool ch_eqi ( char c1, char c2 );
230 int ch_index_last ( char* string, char c );
231 bool ch_is_space ( char c );
232 int ch_pad ( int *char_index, int *null_index, char *s, int max_string );
233 char ch_read ( FILE *filein );
234 int ch_to_digit ( char c );
235 int ch_write ( FILE *fileout, char c );
236 int command_line ( char **argv );
237 void cor3_normal_set ( );
238 void cor3_range ( );
239 void data_check ( );
240 void data_init ( );
241 bool data_read ( );
242 void data_report ( );
243 int data_write ( );
244 int dxf_read ( FILE *filein );
245 int dxf_write ( FILE *fileout );
246 int edge_count ( );
247 void edge_null_delete ( );
248 void face_area_set ( );
249 void face_normal_ave ( );
250 void face_null_delete ( );
251 int face_print ( int iface );
252 void face_reverse_order ( );
253 int face_subset ( );
254 void face_to_line ( );
255 void face_to_vertex_material ( );
256 char *file_ext ( char *file_name );
257 float float_read ( FILE *filein );
258 float float_reverse_bytes ( float x );
259 int float_write ( FILE *fileout, float float_val );
260 bool gmod_arch_check ( );
261 int gmod_read ( FILE *filein );
262 float gmod_read_float ( FILE *filein );
263 unsigned short gmod_read_w16 ( FILE *filein );
264 unsigned long gmod_read_w32 ( FILE *filein );
265 int gmod_write ( FILE *fileout );
266 void gmod_write_float ( float Val, FILE *fileout );
267 void gmod_write_w16 ( unsigned short Val, FILE *fileout );
268 void gmod_write_w32 ( unsigned long Val, FILE *fileout );
269 void hello ( );
270 void help ( );
271 int hrc_read ( FILE *filein );
272 int hrc_write ( FILE *fileout );
273 int i4_max ( int i1, int i2 );
274 int i4_min ( int i1, int i2 );
275 int i4_modp ( int i, int j );
276 int i4_wrap ( int ival, int ilo, int ihi );
277 void init_program_data ( );
278 int interact ( );
279 int iv_read ( FILE *filein );
280 int iv_write ( FILE *fileout );
281 int i4vec_max ( int n, int *a );
282 long int long_int_read ( FILE *filein );
283 int long_int_write ( FILE *fileout, long int int_val );
284 void news ( );
285 void node_to_vertex_material ( );
286 int obj_read ( FILE *filein );
287 int obj_write ( FILE *fileout );
288 int off_read ( ifstream &file_in );
289 int off_write ( FILE *fileout );
290 int pov_write ( FILE *fileout );
291 int rcol_find ( float a[][COR3_MAX], int m, int n, float r[] );
292 float rgb_to_hue ( float r, float g, float b );
293 bool s_eqi ( char* string1, char* string2 );
294 int s_len_trim ( char *s );
295 int s_to_i4 ( char *s, int *last, bool *error );
296 bool s_to_i4vec ( char *s, int n, int ivec[] );
297 float s_to_r4 ( char *s, int *lchar, bool *error );
298 bool s_to_r4vec ( char *s, int n, float rvec[] );
299 short int short_int_read ( FILE *filein );
300 int short_int_write ( FILE *fileout, short int int_val );
301 int smf_read ( FILE *filein );
302 int smf_write ( FILE *fileout );
303 void sort_heap_external ( int n, int *indx, int *i, int *j, int isgn );
304 int stla_read ( FILE *filein );
305 int stla_write ( FILE *fileout );
306 int stlb_read ( FILE *filein );
307 int stlb_write ( FILE *fileout );
308 void tds_pre_process ( );
309 int tds_read ( FILE *filein );
310 unsigned long int tds_read_ambient_section ( FILE *filein );
311 unsigned long int tds_read_background_section ( FILE *filein );
312 unsigned long int tds_read_boolean ( unsigned char *boolean, FILE *filein );
313 unsigned long int tds_read_camera_section ( FILE *filein );
314 unsigned long int tds_read_edit_section ( FILE *filein, int *views_read );
315 unsigned long int tds_read_keyframe_section ( FILE *filein, int *views_read );
316 unsigned long int tds_read_keyframe_objdes_section ( FILE *filein );
317 unsigned long int tds_read_light_section ( FILE *filein );
318 unsigned long int tds_read_u_long_int ( FILE *filein );
319 int tds_read_long_name ( FILE *filein );
320 unsigned long int tds_read_matdef_section ( FILE *filein );
321 unsigned long int tds_read_material_section ( FILE *filein );
322 int tds_read_name ( FILE *filein );
323 unsigned long int tds_read_obj_section ( FILE *filein );
324 unsigned long int tds_read_object_section ( FILE *filein );
325 unsigned long int tds_read_tex_verts_section ( FILE *filein );
326 unsigned long int tds_read_texmap_section ( FILE *filein );
327 unsigned short int tds_read_u_short_int ( FILE *filein );
328 unsigned long int tds_read_spot_section ( FILE *filein );
329 unsigned long int tds_read_unknown_section ( FILE *filein );
330 unsigned long int tds_read_view_section ( FILE *filein, int *views_read );
331 unsigned long int tds_read_vp_section ( FILE *filein, int *views_read );
332 int tds_write ( FILE *fileout );
333 int tds_write_string ( FILE *fileout, char *string );
334 int tds_write_u_short_int ( FILE *fileout, unsigned short int int_val );
335 int tec_write ( FILE *fileout );
336 void tmat_init ( float a[4][4] );
337 void tmat_mxm ( float a[4][4], float b[4][4], float c[4][4] );
338 void tmat_mxp ( float a[4][4], float x[4], float y[4] );
339 void tmat_mxp2 ( float a[4][4], float x[][3], float y[][3], int n );
340 void tmat_mxv ( float a[4][4], float x[4], float y[4] );
341 void tmat_rot_axis ( float a[4][4], float b[4][4], float angle, char axis );
342 void tmat_rot_vector ( float a[4][4], float b[4][4], float angle,
343  float v1, float v2, float v3 );
344 void tmat_scale ( float a[4][4], float b[4][4], float sx, float sy, float sz );
345 void tmat_shear ( float a[4][4], float b[4][4], char *axis, float s );
346 void tmat_trans ( float a[4][4], float b[4][4], float x, float y, float z );
347 int tria_read ( FILE *filein );
348 int tria_write ( FILE *fileout );
349 int trib_read ( FILE *filein );
350 int trib_write ( FILE *fileout );
351 int txt_write ( FILE *fileout );
352 int ucd_write ( FILE *fileout );
353 void vertex_normal_set ( );
354 void vertex_to_face_material ( );
355 void vertex_to_node_material ( );
356 int vla_read ( FILE *filein );
357 int vla_write ( FILE *fileout );
358 int wrl_write ( FILE *filout );
359 int xgl_write ( FILE *fileout );
360 
361 //****************************************************************************80
362 
363 int main ( int argc, char *argv[] )
364 
365 //****************************************************************************80
366 //
367 // Purpose:
368 //
369 // MAIN is the main program for IVCON.
370 //
371 // Licensing:
372 //
373 // This code is distributed under the GNU LGPL license.
374 //
375 // Modified:
376 //
377 // 05 September 2002
378 //
379 // Author:
380 //
381 // John Burkardt
382 //
383 {
384  int result;
385 
386  cout << "\n";
387  cout << "IVCON:\n";
388  cout << " C++ version\n";
389  cout << " Read, interpret, and write out graphics information\n";
390  cout << " in a variety of formats.\n";
391  cout << "\n";
392  cout << " Compiled on " << __DATE__ << " at " << __TIME__ << "\n";
393 //
394 // Initialize the program data.
395 //
396  init_program_data ( );
397 //
398 // If there are at least two command line arguments, call COMMAND_LINE.
399 // Otherwise call INTERACT and get information from the user.
400 //
401  if ( 2 <= argc )
402  {
403  result = command_line ( argv );
404  }
405  else
406  {
407  result = interact ( );
408  }
409 
410  return result;
411 }
412 //****************************************************************************80
413 
414 int ase_read ( FILE *filein )
415 
416 //****************************************************************************80
417 //
418 // Purpose:
419 //
420 // ASE_READ reads an AutoCAD ASE file.
421 //
422 // Licensing:
423 //
424 // This code is distributed under the GNU LGPL license.
425 //
426 // Modified:
427 //
428 // 22 May 1999
429 //
430 // Author:
431 //
432 // John Burkardt
433 //
434 {
435  float bval;
436  int count;
437  float gval;
438  int i;
439  int iface;
440  int ivert;
441  int iword;
442  int level;
443  char *next;
444  int nlbrack;
445  int nrbrack;
446  int cor3_num_old;
447  int face_num_old;
448  float rval;
449  float temp;
450  int width;
451  char word[LINE_MAX_LEN];
452  char word1[LINE_MAX_LEN];
453  char word2[LINE_MAX_LEN];
454  char wordm1[LINE_MAX_LEN];
455  float x;
456  float y;
457  float z;
458 
459  level = 0;
460  strcpy ( level_name[0], "Top" );
461  cor3_num_old = cor3_num;
462  face_num_old = face_num;
463  nlbrack = 0;
464  nrbrack = 0;
465 
466  strcpy ( word, " " );
467  strcpy ( wordm1, " " );
468 //
469 // Read a line of text from the file.
470 //
471  for ( ;; )
472  {
473  if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
474  {
475  break;
476  }
477 
478  text_num = text_num + 1;
479  next = input;
480  iword = 0;
481 //
482 // Read the next word from the line.
483 //
484  for ( ;; )
485  {
486 
487  strcpy ( wordm1, word );
488  strcpy ( word, " " );
489 
490  count = sscanf ( next, "%s%n", word, &width );
491  next = next + width;
492 
493  if ( count <= 0 )
494  {
495  break;
496  }
497 
498  iword = iword + 1;
499 
500  if ( iword == 1 )
501  {
502  strcpy ( word1, word );
503  }
504 //
505 // In case the new word is a bracket, update the bracket count.
506 //
507  if ( strcmp ( word, "{" ) == 0 )
508  {
509  nlbrack = nlbrack + 1;
510  level = nlbrack - nrbrack;
511  strcpy ( level_name[level], wordm1 );
512  }
513  else if ( strcmp ( word, "}" ) == 0 )
514  {
515  nrbrack = nrbrack + 1;
516 
517  if ( nlbrack < nrbrack )
518  {
519  cout << "\n";
520  cout << "ASE_READ - Fatal error!\n";
521  cout << " Extraneous right bracket on line " << text_num << "\n";
522  cout << " Currently processing field:\n";
523  cout << level_name[level] << "\n";;
524  return 1;
525  }
526 
527  }
528 //
529 // *3DSMAX_ASCIIEXPORT 200
530 //
531  if ( strcmp ( word1, "*3DSMAX_ASCIIEXPORT" ) == 0 )
532  {
533  break;
534  }
535 //
536 // *COMMENT
537 //
538  else if ( strcmp ( word1, "*COMMENT" ) == 0 )
539  {
540  break;
541  }
542 //
543 // *GEOMOBJECT
544 //
545  else if ( strcmp ( level_name[level], "*GEOMOBJECT" ) == 0 )
546  {
547  if ( strcmp ( word, "{" ) == 0 )
548  {
549  continue;
550  }
551  else if ( strcmp ( word, "}" ) == 0 )
552  {
553  level = nlbrack - nrbrack;
554  continue;
555  }
556 //
557 // Why don't you read and save this name?
558 //
559  else if ( strcmp ( word, "*NODE_NAME" ) == 0 )
560  {
561  break;
562  }
563  else if ( strcmp ( word, "*NODE_TM" ) == 0 )
564  {
565  continue;
566  }
567  else if ( strcmp ( word, "*MESH" ) == 0 )
568  {
569  continue;
570  }
571  else if ( strcmp ( word, "*PROP_CASTSHADOW" ) == 0 )
572  {
573  break;
574  }
575  else if ( strcmp ( word, "*PROP_MOTIONBLUR" ) == 0 )
576  {
577  break;
578  }
579  else if ( strcmp ( word, "*PROP_RECVSHADOW" ) == 0 )
580  {
581  break;
582  }
583  else
584  {
585  bad_num = bad_num + 1;
586  cout << "\n";
587  cout << "ASE_READ - Error!\n";
588  cout << " Bad data in GEOMOBJECT, line " << text_num << "\n";
589  break;
590  }
591  }
592 //
593 // *MESH
594 //
595  else if ( strcmp ( level_name[level], "*MESH" ) == 0 )
596  {
597  if ( strcmp ( word, "{" ) == 0 )
598  {
599  continue;
600  }
601  else if ( strcmp ( word, "}" ) == 0 )
602  {
603  level = nlbrack - nrbrack;
604  continue;
605  }
606  else if ( strcmp ( word, "*MESH_CFACELIST" ) == 0 )
607  {
608  continue;
609  }
610  else if ( strcmp ( word, "*MESH_CVERTLIST" ) == 0 )
611  {
612  continue;
613  }
614  else if ( strcmp ( word, "*MESH_FACE_LIST" ) == 0 )
615  {
616  continue;
617  }
618  else if ( strcmp ( word, "*MESH_NORMALS" ) == 0 )
619  {
620  continue;
621  }
622  else if ( strcmp ( word, "*MESH_NUMCVERTEX" ) == 0 )
623  {
624  break;
625  }
626  else if ( strcmp ( word, "*MESH_NUMCVFACES" ) == 0 )
627  {
628  break;
629  }
630  else if ( strcmp ( word, "*MESH_NUMFACES" ) == 0 )
631  {
632  break;
633  }
634  else if ( strcmp ( word, "*MESH_NUMTVERTEX" ) == 0 )
635  {
636  break;
637  }
638  else if ( strcmp ( word, "*MESH_NUMTVFACES" ) == 0 )
639  {
640  break;
641  }
642  else if ( strcmp ( word, "*MESH_NUMVERTEX" ) == 0 )
643  {
644  break;
645  }
646  else if ( strcmp ( word, "*MESH_TFACELIST" ) == 0 )
647  {
648  continue;
649  }
650  else if ( strcmp ( word, "*MESH_TVERTLIST" ) == 0 )
651  {
652  continue;
653  }
654  else if ( strcmp ( word, "*MESH_VERTEX_LIST" ) == 0 )
655  {
656  continue;
657  }
658  else if ( strcmp ( word, "*TIMEVALUE" ) == 0 )
659  {
660  break;
661  }
662  else
663  {
664  bad_num = bad_num + 1;
665  cout << "Bad data in MESH, line " << text_num << "\n";
666  break;
667  }
668  }
669 //
670 // *MESH_CFACELIST
671 //
672  else if ( strcmp ( level_name[level], "*MESH_CFACELIST" ) == 0 )
673  {
674  if ( strcmp ( word, "{" ) == 0 )
675  {
676  continue;
677  }
678  else if ( strcmp ( word, "}" ) == 0 )
679  {
680  level = nlbrack - nrbrack;
681  continue;
682  }
683  else if ( strcmp ( word, "*MESH_CFACE" ) == 0 )
684  {
685  break;
686  }
687  else
688  {
689  bad_num = bad_num + 1;
690  cout << "Bad data in MESH_CFACE, line " << text_num << "\n";
691  break;
692  }
693  }
694 //
695 // *MESH_CVERTLIST
696 //
697 // Mesh vertex indices must be incremented by COR3_NUM_OLD before being stored
698 // in the internal array.
699 //
700  else if ( strcmp ( level_name[level], "*MESH_CVERTLIST" ) == 0 )
701  {
702  if ( strcmp ( word, "{" ) == 0 )
703  {
704  continue;
705  }
706  else if ( strcmp ( word, "}" ) == 0 )
707  {
708  level = nlbrack - nrbrack;
709  continue;
710  }
711  else if ( strcmp ( word, "*MESH_VERTCOL" ) == 0 )
712  {
713  count = sscanf ( next, "%d%n", &i, &width );
714  next = next + width;
715 
716  i = i + cor3_num_old;
717 
718  count = sscanf ( next, "%f%n", &rval, &width );
719  next = next + width;
720 
721  count = sscanf ( next, "%f%n", &gval, &width );
722  next = next + width;
723 
724  count = sscanf ( next, "%f%n", &bval, &width );
725  next = next + width;
726 
727  if ( material_num < MATERIAL_MAX )
728  {
729  material_rgba[0][material_num] = rval;
730  material_rgba[1][material_num] = gval;
731  material_rgba[2][material_num] = bval;
732  material_rgba[3][material_num] = 1.0;
733  }
734 
737  }
738  else
739  {
740  bad_num = bad_num + 1;
741  cout << "\n";
742  cout << "ASE_READ - Warning!\n";
743  cout << " Bad data in MESH_CVERTLIST, line " << text_num << "\n";
744  break;
745  }
746 
747  }
748 //
749 // *MESH_FACE_LIST
750 // This coding assumes a face is always triangular or quadrilateral.
751 //
752  else if ( strcmp ( level_name[level], "*MESH_FACE_LIST" ) == 0 )
753  {
754  if ( strcmp ( word, "{" ) == 0 )
755  {
756  continue;
757  }
758  else if ( strcmp ( word, "}" ) == 0 )
759  {
760  level = nlbrack - nrbrack;
761  continue;
762  }
763  else if ( strcmp ( word, "*MESH_FACE" ) == 0 )
764  {
765  if ( face_num < FACE_MAX )
766  {
767 
768  face_material[face_num] = 0;
769  face_order[face_num] = 0;
770 
771  count = sscanf ( next, "%d%n", &i, &width );
772  next = next + width;
773 
774  count = sscanf ( next, "%s%n", word2, &width );
775  next = next + width;
776  count = sscanf ( next, "%s%n", word2, &width );
777  next = next + width;
778 
779  count = sscanf ( next, "%d%n", &i, &width );
780  next = next + width;
781  face[0][face_num] = i + cor3_num_old;
783 
784  count = sscanf ( next, "%s%n", word2, &width );
785  next = next + width;
786 
787  count = sscanf ( next, "%d%n", &i, &width );
788  next = next + width;
789  face[1][face_num] = i + cor3_num_old;
791 
792  count = sscanf ( next, "%s%n", word2, &width );
793  next = next + width;
794 
795  count = sscanf ( next, "%d%n", &i, &width );
796  next = next + width;
797  face[2][face_num] = i + cor3_num_old;
799 
800  count = sscanf ( next, "%s%n", word2, &width );
801  next = next + width;
802 
803  if ( strcmp ( word2, "D:" ) == 0 )
804  {
805  count = sscanf ( next, "%d%n", &i, &width );
806  next = next + width;
807  face[3][face_num] = i + cor3_num_old;
809  }
810  }
811 
812  face_num = face_num + 1;
813 
814  break;
815 
816  }
817  else
818  {
819  bad_num = bad_num + 1;
820  cout << "Bad data in MESH_FACE_LIST, line " << text_num << "\n";
821  break;
822  }
823  }
824 //
825 // *MESH_NORMALS
826 //
827  else if ( strcmp ( level_name[level], "*MESH_NORMALS" ) == 0 )
828  {
829  if ( strcmp ( word, "{" ) == 0 )
830  {
831  continue;
832  }
833  else if ( strcmp ( word, "}" ) == 0 )
834  {
835  level = nlbrack - nrbrack;
836  continue;
837  }
838  else if ( strcmp ( word, "*MESH_FACENORMAL" ) == 0 )
839  {
840  count = sscanf ( next, "%d%n", &iface, &width );
841  next = next + width;
842 
843  count = sscanf ( next, "%f%n", &x, &width );
844  next = next + width;
845 
846  count = sscanf ( next, "%f%n", &y, &width );
847  next = next + width;
848 
849  count = sscanf ( next, "%f%n", &z, &width );
850  next = next + width;
851 
852  iface = iface + face_num_old;
853  ivert = 0;
854 
855  face_normal[0][iface] = x;
856  face_normal[1][iface] = y;
857  face_normal[2][iface] = z;
858 
859  break;
860 
861  }
862  else if ( strcmp ( word, "*MESH_VERTEXNORMAL" ) == 0 )
863  {
864  count = sscanf ( next, "%d%n", &i, &width );
865  next = next + width;
866 
867  count = sscanf ( next, "%f%n", &x, &width );
868  next = next + width;
869 
870  count = sscanf ( next, "%f%n", &y, &width );
871  next = next + width;
872 
873  count = sscanf ( next, "%f%n", &z, &width );
874  next = next + width;
875 
876  vertex_normal[0][ivert][iface] = x;
877  vertex_normal[1][ivert][iface] = y;
878  vertex_normal[2][ivert][iface] = z;
879  ivert = ivert + 1;
880 
881  break;
882  }
883  else
884  {
885  bad_num = bad_num + 1;
886  cout << "Bad data in MESH_NORMALS, line " << text_num << "\n";
887  break;
888  }
889  }
890 //
891 // *MESH_TFACELIST
892 //
893  else if ( strcmp ( level_name[level], "*MESH_TFACELIST" ) == 0 )
894  {
895  if ( strcmp ( word, "{" ) == 0 )
896  {
897  continue;
898  }
899  else if ( strcmp ( word, "}" ) == 0 )
900  {
901  level = nlbrack - nrbrack;
902  continue;
903  }
904  else if ( strcmp ( word1, "*MESH_TFACE" ) == 0 )
905  {
906  break;
907  }
908  else
909  {
910  bad_num = bad_num + 1;
911  cout << "Bad data in MESH_TFACE_LIST, line " << text_num << "\n";
912  break;
913  }
914  }
915 //
916 // *MESH_TVERTLIST
917 //
918  else if ( strcmp ( level_name[level], "*MESH_TVERTLIST" ) == 0 )
919  {
920  if ( strcmp ( word, "{" ) == 0 )
921  {
922  continue;
923  }
924  else if ( strcmp ( word, "}" ) == 0 )
925  {
926  level = nlbrack - nrbrack;
927  continue;
928  }
929  else if ( strcmp ( word1, "*MESH_TVERT" ) == 0 )
930  {
931  break;
932  }
933  else
934  {
935  bad_num = bad_num + 1;
936  cout << "Bad data in MESH_TVERTLIST, line " << text_num << "\n";
937  break;
938  }
939  }
940 //
941 // *MESH_VERTEX_LIST
942 //
943  else if ( strcmp ( level_name[level], "*MESH_VERTEX_LIST" ) == 0 )
944  {
945  if ( strcmp ( word, "{" ) == 0 )
946  {
947  cor3_num_old = cor3_num;
948  continue;
949  }
950  else if ( strcmp ( word, "}" ) == 0 )
951  {
952  level = nlbrack - nrbrack;
953  continue;
954  }
955  else if ( strcmp ( word1, "*MESH_VERTEX" ) == 0 )
956  {
957 
958  count = sscanf ( next, "%d%n", &i, &width );
959  next = next + width;
960 
961  count = sscanf ( next, "%f%n", &x, &width );
962  next = next + width;
963 
964  count = sscanf ( next, "%f%n", &y, &width );
965  next = next + width;
966 
967  count = sscanf ( next, "%f%n", &z, &width );
968  next = next + width;
969 
970  i = i + cor3_num_old;
971  if ( cor3_num < i + 1 )
972  {
973  cor3_num = i + 1;
974  }
975 
976  if ( i < COR3_MAX )
977  {
978  cor3[0][i] =
979  transform_matrix[0][0] * x
980  + transform_matrix[0][1] * y
981  + transform_matrix[0][2] * z
982  + transform_matrix[0][3];
983 
984  cor3[1][i] =
985  transform_matrix[1][0] * x
986  + transform_matrix[1][1] * y
987  + transform_matrix[1][2] * z
988  + transform_matrix[1][3];
989 
990  cor3[2][i] =
991  transform_matrix[2][0] * x
992  + transform_matrix[2][1] * y
993  + transform_matrix[2][2] * z
994  + transform_matrix[2][3];
995  }
996 
997  break;
998  }
999  else
1000  {
1001  bad_num = bad_num + 1;
1002  cout << "Bad data in MESH_VERTEX_LIST, line " << text_num << "\n";
1003  break;
1004  }
1005  }
1006 //
1007 // *NODE_TM
1008 //
1009 // Each node should start out with a default transformation matrix.
1010 //
1011  else if ( strcmp ( level_name[level], "*NODE_TM" ) == 0 )
1012  {
1013  if ( strcmp ( word, "{" ) == 0 )
1014  {
1016 
1017  continue;
1018  }
1019  else if ( strcmp ( word, "}" ) == 0 )
1020  {
1021  level = nlbrack - nrbrack;
1022  continue;
1023  }
1024  else if ( strcmp ( word, "*INHERIT_POS" ) == 0 )
1025  {
1026  break;
1027  }
1028  else if ( strcmp ( word, "*INHERIT_ROT" ) == 0 )
1029  {
1030  break;
1031  }
1032  else if ( strcmp ( word, "*INHERIT_SCL" ) == 0 )
1033  {
1034  break;
1035  }
1036  else if ( strcmp ( word, "*NODE_NAME" ) == 0 )
1037  {
1038  break;
1039  }
1040  else if ( strcmp ( word, "*TM_POS" ) == 0 )
1041  {
1042  break;
1043  }
1044  else if ( strcmp ( word, "*TM_ROTANGLE" ) == 0 )
1045  {
1046  break;
1047  }
1048  else if ( strcmp ( word, "*TM_ROTAXIS" ) == 0 )
1049  {
1050  break;
1051  }
1052  else if ( strcmp ( word, "*TM_ROW0" ) == 0 )
1053  {
1054  count = sscanf ( next, "%f%n", &temp, &width );
1055  next = next + width;
1056  transform_matrix[0][0] = temp;
1057 
1058  count = sscanf ( next, "%f%n", &temp, &width );
1059  next = next + width;
1060  transform_matrix[1][0] = temp;
1061 
1062  count = sscanf ( next, "%f%n", &temp, &width );
1063  next = next + width;
1064  transform_matrix[2][0] = temp;
1065 
1066  break;
1067  }
1068  else if ( strcmp ( word, "*TM_ROW1" ) == 0 )
1069  {
1070  count = sscanf ( next, "%f%n", &temp, &width );
1071  next = next + width;
1072  transform_matrix[0][1] = temp;
1073 
1074  count = sscanf ( next, "%f%n", &temp, &width );
1075  next = next + width;
1076  transform_matrix[1][1] = temp;
1077 
1078  count = sscanf ( next, "%f%n", &temp, &width );
1079  next = next + width;
1080  transform_matrix[2][1] = temp;
1081 
1082  break;
1083  }
1084  else if ( strcmp ( word, "*TM_ROW2" ) == 0 )
1085  {
1086  count = sscanf ( next, "%f%n", &temp, &width );
1087  next = next + width;
1088  transform_matrix[0][2] = temp;
1089 
1090  count = sscanf ( next, "%f%n", &temp, &width );
1091  next = next + width;
1092  transform_matrix[1][2] = temp;
1093 
1094  count = sscanf ( next, "%f%n", &temp, &width );
1095  next = next + width;
1096  transform_matrix[2][2] = temp;
1097 
1098  break;
1099  }
1100  else if ( strcmp ( word, "*TM_ROW3" ) == 0 )
1101  {
1102  count = sscanf ( next, "%f%n", &temp, &width );
1103  next = next + width;
1104  transform_matrix[0][3] = temp;
1105 
1106  count = sscanf ( next, "%f%n", &temp, &width );
1107  next = next + width;
1108  transform_matrix[1][3] = temp;
1109 
1110  count = sscanf ( next, "%f%n", &temp, &width );
1111  next = next + width;
1112  transform_matrix[2][3] = temp;
1113 
1114  break;
1115  }
1116  else if ( strcmp ( word, "*TM_SCALE" ) == 0 )
1117  {
1118  break;
1119  }
1120  else if ( strcmp ( word, "*TM_SCALEAXIS" ) == 0 )
1121  {
1122  break;
1123  }
1124  else if ( strcmp ( word, "*TM_SCALEAXISANG" ) == 0 )
1125  {
1126  break;
1127  }
1128  else
1129  {
1130  bad_num = bad_num + 1;
1131  cout << "Bad data in NODE_TM, line " << text_num << "\n";
1132  break;
1133  }
1134  }
1135 //
1136 // *SCENE
1137 //
1138  else if ( strcmp ( level_name[level], "*SCENE" ) == 0 )
1139  {
1140  if ( strcmp ( word, "{" ) == 0 )
1141  {
1142  continue;
1143  }
1144  else if ( strcmp ( word, "}" ) == 0 )
1145  {
1146  level = nlbrack - nrbrack;
1147  continue;
1148  }
1149  else if ( strcmp ( word, "*SCENE_AMBIENT_STATIC" ) == 0 )
1150  {
1151  break;
1152  }
1153  else if ( strcmp ( word, "*SCENE_BACKGROUND_STATIC" ) == 0 )
1154  {
1155  break;
1156  }
1157  else if ( strcmp ( word, "*SCENE_FILENAME" ) == 0 )
1158  {
1159  break;
1160  }
1161  else if ( strcmp ( word, "*SCENE_FIRSTFRAME" ) == 0 )
1162  {
1163  break;
1164  }
1165  else if ( strcmp ( word, "*SCENE_FRAMESPEED" ) == 0 )
1166  {
1167  break;
1168  }
1169  else if ( strcmp ( word, "*SCENE_LASTFRAME" ) == 0 )
1170  {
1171  break;
1172  }
1173  else if ( strcmp ( word, "*SCENE_TICKSPERFRAME" ) == 0 )
1174  {
1175  break;
1176  }
1177  else
1178  {
1179  bad_num = bad_num + 1;
1180  cout << "Bad data in SCENE, line " << text_num << "\n";
1181  break;
1182  }
1183  }
1184  }
1185 //
1186 // End of loop reading words from the line.
1187 //
1188  }
1189 //
1190 // End of loop reading lines from input file.
1191 //
1192 
1193  return 0;
1194 }
1195 //****************************************************************************80
1196 
1197 int ase_write ( FILE *fileout )
1198 
1199 //****************************************************************************80
1200 //
1201 // Purpose:
1202 //
1203 // ASE_WRITE writes graphics information to an AutoCAD ASE file.
1204 //
1205 // Licensing:
1206 //
1207 // This code is distributed under the GNU LGPL license.
1208 //
1209 // Modified:
1210 //
1211 // 30 September 1998
1212 //
1213 // Author:
1214 //
1215 // John Burkardt
1216 //
1217 // Parameters:
1218 //
1219 // Input, FILE *fileout, the output file.
1220 //
1221 {
1222  int i1;
1223  int i2;
1224  int i3;
1225  int i4;
1226  int iface;
1227  int ivert;
1228  int j;
1229  int text_num;
1230 
1231  text_num = 0;
1232 //
1233 // Write the header.
1234 //
1235  fprintf ( fileout, "*3DSMAX_ASCIIEXPORT 200\n" );
1236  fprintf ( fileout, "*COMMENT \"%s, created by IVCON.\"\n", fileout_name );
1237  fprintf ( fileout, "*COMMENT \"Original data in %s\"\n", filein_name );
1238 
1239  text_num = text_num + 3;
1240 //
1241 // Write the scene block.
1242 //
1243  fprintf ( fileout, "*SCENE {\n" );
1244  fprintf ( fileout, " *SCENE_FILENAME \"\"\n" );
1245  fprintf ( fileout, " *SCENE_FIRSTFRAME 0\n" );
1246  fprintf ( fileout, " *SCENE_LASTFRAME 100\n" );
1247  fprintf ( fileout, " *SCENE_FRAMESPEED 30\n" );
1248  fprintf ( fileout, " *SCENE_TICKSPERFRAME 160\n" );
1249  fprintf ( fileout, " *SCENE_BACKGROUND_STATIC 0.0000 0.0000 0.0000\n" );
1250  fprintf ( fileout, " *SCENE_AMBIENT_STATIC 0.0431 0.0431 0.0431\n" );
1251  fprintf ( fileout, "}\n" );
1252 
1253  text_num = text_num + 9;
1254 //
1255 // Begin the big geometry block.
1256 //
1257  fprintf ( fileout, "*GEOMOBJECT {\n" );
1258  fprintf ( fileout, " *NODE_NAME \"%s\"\n", object_name );
1259 
1260  text_num = text_num + 2;
1261 //
1262 // Sub block NODE_TM:
1263 //
1264  fprintf ( fileout, " *NODE_TM {\n" );
1265  fprintf ( fileout, " *NODE_NAME \"Object01\"\n" );
1266  fprintf ( fileout, " *INHERIT_POS 0 0 0\n" );
1267  fprintf ( fileout, " *INHERIT_ROT 0 0 0\n" );
1268  fprintf ( fileout, " *INHERIT_SCL 0 0 0\n" );
1269  fprintf ( fileout, " *TM_ROW0 1.0000 0.0000 0.0000\n" );
1270  fprintf ( fileout, " *TM_ROW1 0.0000 1.0000 0.0000\n" );
1271  fprintf ( fileout, " *TM_ROW2 0.0000 0.0000 1.0000\n" );
1272  fprintf ( fileout, " *TM_ROW3 0.0000 0.0000 0.0000\n" );
1273  fprintf ( fileout, " *TM_POS 0.0000 0.0000 0.0000\n" );
1274  fprintf ( fileout, " *TM_ROTAXIS 0.0000 0.0000 0.0000\n" );
1275  fprintf ( fileout, " *TM_ROTANGLE 0.0000\n" );
1276  fprintf ( fileout, " *TM_SCALE 1.0000 1.0000 1.0000\n" );
1277  fprintf ( fileout, " *TM_SCALEAXIS 0.0000 0.0000 0.0000\n" );
1278  fprintf ( fileout, " *TM_SCALEAXISANG 0.0000\n" );
1279  fprintf ( fileout, " }\n" );
1280 
1281  text_num = text_num + 16;
1282 //
1283 // Sub block MESH:
1284 // Items
1285 //
1286  fprintf ( fileout, " *MESH {\n" );
1287  fprintf ( fileout, " *TIMEVALUE 0\n" );
1288  fprintf ( fileout, " *MESH_NUMVERTEX %d\n", cor3_num );
1289  fprintf ( fileout, " *MESH_NUMFACES %d\n", face_num );
1290 
1291  text_num = text_num + 4;
1292 //
1293 // Sub sub block MESH_VERTEX_LIST
1294 //
1295  fprintf ( fileout, " *MESH_VERTEX_LIST {\n" );
1296  text_num = text_num + 1;
1297 
1298  for ( j = 0; j < cor3_num; j++ )
1299  {
1300  fprintf ( fileout, " *MESH_VERTEX %d %f %f %f\n", j, cor3[0][j],
1301  cor3[1][j], cor3[2][j] );
1302  text_num = text_num + 1;
1303  }
1304 
1305  fprintf ( fileout, " }\n" );
1306  text_num = text_num + 1;
1307 //
1308 // Sub sub block MESH_FACE_LIST
1309 // Items MESH_FACE
1310 //
1311  fprintf ( fileout, " *MESH_FACE_LIST {\n" );
1312  text_num = text_num + 1;
1313 
1314  for ( iface = 0; iface < face_num; iface++ )
1315  {
1316  i1 = face[0][iface];
1317  i2 = face[1][iface];
1318  i3 = face[2][iface];
1319 
1320  if ( face_order[iface] == 3 )
1321  {
1322  fprintf ( fileout, " *MESH_FACE %d: A: %d B: %d C: %d", iface, i1, i2, i3 );
1323  fprintf ( fileout, " AB: 1 BC: 1 CA: 1 *MESH_SMOOTHING *MESH_MTLID 1\n" );
1324  text_num = text_num + 1;
1325  }
1326  else if ( face_order[iface] == 4 )
1327  {
1328  i4 = face[3][iface];
1329  fprintf ( fileout, " *MESH_FACE %d: A: %d B: %d C: %d D: %d", iface, i1, i2, i3, i4 );
1330  fprintf ( fileout, " AB: 1 BC: 1 CD: 1 DA: 1 *MESH_SMOOTHING *MESH_MTLID 1\n" );
1331  text_num = text_num + 1;
1332  }
1333  }
1334 
1335  fprintf ( fileout, " }\n" );
1336  text_num = text_num + 1;
1337 //
1338 // Item MESH_NUMTVERTEX.
1339 //
1340  fprintf ( fileout, " *MESH_NUMTVERTEX 0\n" );
1341  text_num = text_num + 1;
1342 //
1343 // Item NUMCVERTEX.
1344 //
1345  fprintf ( fileout, " *MESH_NUMCVERTEX 0\n" );
1346  text_num = text_num + 1;
1347 //
1348 // Sub block MESH_NORMALS
1349 // Items MESH_FACENORMAL, MESH_VERTEXNORMAL (repeated)
1350 //
1351  fprintf ( fileout, " *MESH_NORMALS {\n" );
1352  text_num = text_num + 1;
1353 
1354  for ( iface = 0; iface < face_num; iface++ )
1355  {
1356  fprintf ( fileout, " *MESH_FACENORMAL %d %f %f %f\n",
1357  iface, face_normal[0][iface], face_normal[1][iface], face_normal[2][iface] );
1358  text_num = text_num + 1;
1359 
1360  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
1361  {
1362  fprintf ( fileout, " *MESH_VERTEXNORMAL %d %f %f %f\n",
1363  face[ivert][iface], vertex_normal[0][ivert][iface],
1364  vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
1365  text_num = text_num + 1;
1366  }
1367  }
1368 
1369  fprintf ( fileout, " }\n" );
1370  text_num = text_num + 1;
1371 //
1372 // Close the MESH object.
1373 //
1374  fprintf ( fileout, " }\n" );
1375 //
1376 // A few closing parameters.
1377 //
1378  fprintf ( fileout, " *PROP_MOTIONBLUR 0\n" );
1379  fprintf ( fileout, " *PROP_CASTSHADOW 1\n" );
1380  fprintf ( fileout, " *PROP_RECVSHADOW 1\n" );
1381 //
1382 // Close the GEOM object.
1383 //
1384  fprintf ( fileout, "}\n" );
1385 
1386  text_num = text_num + 5;
1387 //
1388 // Report.
1389 //
1390  cout << "\n";
1391  cout << "ASE_WRITE - Wrote " << text_num << " text lines;\n";
1392 
1393  return 0;
1394 }
1395 //****************************************************************************80
1396 
1397 int byu_read ( FILE *filein )
1398 
1399 //****************************************************************************80
1400 //
1401 // Purpose:
1402 //
1403 // BYU_READ reads graphics data from a Movie.BYU surface geometry file.
1404 //
1405 // Discussion:
1406 //
1407 // A Movie.BYU surface geometry file contains 4 groups of data.
1408 //
1409 // The first group of data is a single line, containing 4 integers,
1410 // each one left justified in 8 columns. The integers are:
1411 //
1412 // PART_NUM, VERTEX_NUM, POLY_NUM, EDGE_NUM,
1413 //
1414 // that is, the number of parts or objects, the number of vertices or nodes,
1415 // the number of polygons or faces, and the number of edges.
1416 //
1417 // The second group of data is a single line, containing 2 integers,
1418 // each one left justified in 8 columnes. The integers are:
1419 //
1420 // POLY1, POLY2,
1421 //
1422 // the starting and ending polygon numbers. Presumably, this means
1423 // that the polygons are labeled POLY1, POLY1+1, ..., POLY2, comprising
1424 // a total of POLY_NUM polygons.
1425 //
1426 // The third group is the X, Y and Z coordinates of all the vertices.
1427 // These may be written using a FORTRAN format of 6E12.5, which
1428 // crams two sets of (X,Y,Z) data onto each line, with each real value
1429 // written in an exponential format with 5 places after the decimal.
1430 // However, it is generally possible to write the XYZ coordinate data
1431 // for each vertex on a separate line.
1432 //
1433 // The fourth group defines the polygons in terms of the vertex indices.
1434 // For each polygon, the vertices that make up the polygon are listed in
1435 // counterclockwise order. The last vertex listed is given with a negative
1436 // sign to indicate the end of the list. All the vertices for all the
1437 // polygons are listed one after the other, using a format that puts
1438 // up to 10 left-justified integers on a line, with each integer occupying
1439 // 8 spaces.
1440 //
1441 // This code will certainly read a BYU file created by BYU_WRITE, but
1442 // it will not handle more general files. In particular, an object
1443 // can have several parts, the coordinate data can be grouped so
1444 // that there are 2 sets of (x,y,z) data per line, and so on.
1445 //
1446 // Example:
1447 //
1448 // 1 8 6 24
1449 // 1 6
1450 // 0.00000E+00 0.00000E+00 0.00000E+00
1451 // 1.00000E+00 0.00000E+00 0.00000E+00
1452 // 1.00000E+00 2.00000E+00 0.00000E+00
1453 // 0.00000E+00 2.00000E+00 0.00000E+00
1454 // 0.00000E+00 0.00000E+00 1.00000E+00
1455 // 1.00000E+00 0.00000E+00 1.00000E+00
1456 // 1.00000E+00 2.00000E+00 1.00000E+00
1457 // 0.00000E+00 2.00000E+00 1.00000E+00
1458 // 4 3 2 -1
1459 // 5 6 7 -8
1460 // 1 5 8 -4
1461 // 4 8 7 -3
1462 // 3 7 6 -2
1463 // 2 6 5 -1
1464 //
1465 // Licensing:
1466 //
1467 // This code is distributed under the GNU LGPL license.
1468 //
1469 // Modified:
1470 //
1471 // 24 May 2001
1472 //
1473 // Author:
1474 //
1475 // John Burkardt
1476 //
1477 //
1478 {
1479  int cor3_num_new;
1480  int count;
1481  int edge_num;
1482  int face_num_new;
1483  int iface;
1484  int ival;
1485  int ivert;
1486  int j;
1487  char *next;
1488  int part_num;
1489  int poly1;
1490  int poly2;
1491  int text_num;
1492  int width;
1493  float x;
1494  float y;
1495  float z;
1496 
1497  text_num = 0;
1498 
1499  if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
1500  {
1501  return 1;
1502  }
1503  text_num = text_num + 1;
1504 
1505  sscanf ( input, "%d %d %d %d", &part_num, &cor3_num_new, &face_num_new,
1506  &edge_num );
1507 
1508  if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
1509  {
1510  return 1;
1511  }
1512  text_num = text_num + 1;
1513 
1514  sscanf ( input, "%d %d", &poly1, &poly2 );
1515 
1516  for ( j = cor3_num; j < cor3_num + cor3_num_new; j++ )
1517  {
1518  if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
1519  {
1520  return 1;
1521  }
1522  text_num = text_num + 1;
1523 
1524  sscanf ( input, "%f %f %f", &x, &y, &z );
1525  cor3[0][j] = x;
1526  cor3[1][j] = y;
1527  cor3[2][j] = z;
1528  }
1529 
1530  for ( iface = face_num; iface < face_num + face_num_new; iface++ )
1531  {
1532  if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
1533  {
1534  return 1;
1535  }
1536  text_num = text_num + 1;
1537 
1538  next = input;
1539  ivert = 0;
1540 
1541  for (;;)
1542  {
1543  count = sscanf ( next, "%d%n", &ival, &width );
1544  next = next + width;
1545 
1546  if ( count <= 0 )
1547  {
1548  return 1;
1549  }
1550 
1551  if ( 0 < ival )
1552  {
1553  face[ivert][iface] = ival - 1 + cor3_num;
1554  }
1555  else
1556  {
1557  face[ivert][iface] = - ival - 1 - cor3_num;
1558  break;
1559  }
1560 
1561  ivert = ivert + 1;
1562 
1563  }
1564  face_order[iface] = ivert + 1;
1565  }
1566 
1567  cor3_num = cor3_num + cor3_num_new;
1568  face_num = face_num + face_num_new;
1569 //
1570 // Report.
1571 //
1572  cout << "\n";
1573  cout << "BYU_READ - Read " << text_num << " text lines.\n";
1574 
1575  return 0;
1576 }
1577 //****************************************************************************80
1578 
1579 int byu_write ( FILE *fileout )
1580 
1581 //****************************************************************************80
1582 //
1583 // Purpose:
1584 //
1585 // BYU_WRITE writes out the graphics data as a Movie.BYU surface geometry file.
1586 //
1587 // Discussion:
1588 //
1589 // A Movie.BYU surface geometry file contains 4 groups of data.
1590 //
1591 // The first group of data is a single line, containing 4 integers,
1592 // each one left justified in 8 columns. The integers are:
1593 //
1594 // PART_NUM, VERTEX_NUM, POLY_NUM, EDGE_NUM,
1595 //
1596 // that is, the number of parts or objects, the number of vertices or nodes,
1597 // the number of polygons or faces, and the number of edges.
1598 //
1599 // The second group of data is a single line, containing 2 integers,
1600 // each one left justified in 8 columnes. The integers are:
1601 //
1602 // POLY1, POLY2,
1603 //
1604 // the starting and ending polygon numbers. Presumably, this means
1605 // that the polygons are labeled POLY1, POLY1+1, ..., POLY2, comprising
1606 // a total of POLY_NUM polygons.
1607 //
1608 // The third group is the X, Y and Z coordinates of all the vertices.
1609 // These may be written using a FORTRAN format of 6E12.5, which
1610 // crams two sets of (X,Y,Z) data onto each line, with each real value
1611 // written in an exponential format with 5 places after the decimal.
1612 // However, it is generally possible to write the XYZ coordinate data
1613 // for each vertex on a separate line.
1614 //
1615 // The fourth group defines the polygons in terms of the vertex indices.
1616 // For each polygon, the vertices that make up the polygon are listed in
1617 // counterclockwise order. The last vertex listed is given with a negative
1618 // sign to indicate the end of the list. All the vertices for all the
1619 // polygons are listed one after the other, using a format that puts
1620 // up to 10 left-justified integers on a line, with each integer occupying
1621 // 8 spaces.
1622 //
1623 // Example:
1624 //
1625 // 1 8 6 24
1626 // 1 6
1627 // 0.00000E+00 0.00000E+00 0.00000E+00
1628 // 1.00000E+00 0.00000E+00 0.00000E+00
1629 // 1.00000E+00 2.00000E+00 0.00000E+00
1630 // 0.00000E+00 2.00000E+00 0.00000E+00
1631 // 0.00000E+00 0.00000E+00 1.00000E+00
1632 // 1.00000E+00 0.00000E+00 1.00000E+00
1633 // 1.00000E+00 2.00000E+00 1.00000E+00
1634 // 0.00000E+00 2.00000E+00 1.00000E+00
1635 // 4 3 2 -1
1636 // 5 6 7 -8
1637 // 1 5 8 -4
1638 // 4 8 7 -3
1639 // 3 7 6 -2
1640 // 2 6 5 -1
1641 //
1642 // Licensing:
1643 //
1644 // This code is distributed under the GNU LGPL license.
1645 //
1646 // Modified:
1647 //
1648 // 24 May 2001
1649 //
1650 // Author:
1651 //
1652 // John Burkardt
1653 //
1654 {
1655  int edge_num;
1656  int iface;
1657  int ivert;
1658  int j;
1659  int jp;
1660  int part_num;
1661  int text_num;
1662 
1663  text_num = 0;
1664 
1665  edge_num = 0;
1666  for ( iface = 0; iface < face_num; iface++ )
1667  {
1668  edge_num = edge_num + face_order[iface];
1669  }
1670 
1671  part_num = 1;
1672 
1673  fprintf ( fileout, "%d %d %d %d\n", part_num, cor3_num, face_num, edge_num );
1674  text_num = text_num + 1;
1675 
1676  fprintf ( fileout, "1 %d\n", face_num );
1677  text_num = text_num + 1;
1678 
1679  for ( j = 0; j < cor3_num; j++ )
1680  {
1681  fprintf ( fileout, "%f %f %f\n", cor3[0][j], cor3[1][j], cor3[2][j] );
1682  text_num = text_num + 1;
1683  }
1684 
1685  for ( iface = 0; iface < face_num; iface++ )
1686  {
1687  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
1688  {
1689  jp = face[ivert][iface] + 1;
1690  if ( ivert == face_order[iface] - 1 )
1691  {
1692  jp = - jp;
1693  }
1694  fprintf ( fileout, "%d ", jp );
1695  }
1696  fprintf ( fileout, "\n" );
1697  text_num = text_num + 1;
1698  }
1699 //
1700 // Report.
1701 //
1702  cout << "\n";
1703  cout << "BYU_WRITE - Wrote " << text_num << " text lines.\n";
1704 
1705  return 0;
1706 }
1707 //****************************************************************************80
1708 
1709 char ch_cap ( char c )
1710 
1711 //****************************************************************************80
1712 //
1713 // Purpose:
1714 //
1715 // CH_CAP capitalizes a single character.
1716 //
1717 // Discussion:
1718 //
1719 // This routine should be equivalent to the library "toupper" function.
1720 //
1721 // Licensing:
1722 //
1723 // This code is distributed under the GNU LGPL license.
1724 //
1725 // Modified:
1726 //
1727 // 19 July 1998
1728 //
1729 // Author:
1730 //
1731 // John Burkardt
1732 //
1733 // Parameters:
1734 //
1735 // Input, char C, the character to capitalize.
1736 //
1737 // Output, char CH_CAP, the capitalized character.
1738 //
1739 {
1740  if ( 97 <= c && c <= 122 )
1741  {
1742  c = c - 32;
1743  }
1744 
1745  return c;
1746 }
1747 //****************************************************************************80
1748 
1749 bool ch_eqi ( char c1, char c2 )
1750 
1751 //****************************************************************************80
1752 //
1753 // Purpose:
1754 //
1755 // CH_EQI is true if two characters are equal, disregarding case.
1756 //
1757 // Licensing:
1758 //
1759 // This code is distributed under the GNU LGPL license.
1760 //
1761 // Modified:
1762 //
1763 // 13 June 2003
1764 //
1765 // Author:
1766 //
1767 // John Burkardt
1768 //
1769 // Parameters:
1770 //
1771 // Input, char C1, char C2, the characters to compare.
1772 //
1773 // Output, bool CH_EQI, is true if the two characters are equal,
1774 // disregarding case.
1775 //
1776 {
1777  if ( 97 <= c1 && c1 <= 122 )
1778  {
1779  c1 = c1 - 32;
1780  }
1781  if ( 97 <= c2 && c2 <= 122 )
1782  {
1783  c2 = c2 - 32;
1784  }
1785 
1786  return ( c1 == c2 );
1787 }
1788 //****************************************************************************80
1789 
1790 int ch_index_last ( char *s, char c )
1791 
1792 //****************************************************************************80
1793 //
1794 // Purpose:
1795 //
1796 // CH_INDEX_LAST finds the last occurrence of a character in a string.
1797 //
1798 // Licensing:
1799 //
1800 // This code is distributed under the GNU LGPL license.
1801 //
1802 // Modified:
1803 //
1804 // 16 October 1998
1805 //
1806 // Author:
1807 //
1808 // John Burkardt
1809 //
1810 // Parameters:
1811 //
1812 // Input, char *S, a pointer to a string to be searched.
1813 //
1814 // Input, char C, the character to be searched for in s.
1815 //
1816 // Output, int CH_INDEX_LAST, the index in s of the last occurrence
1817 // of C, or -1 if c does not occur in s.
1818 //
1819 {
1820  int i;
1821  int j;
1822  int nchar;
1823 
1824  j = -1;
1825 
1826  nchar = strlen ( s );
1827 
1828  for ( i = 0; i < nchar; i++ )
1829  {
1830  if ( s[i] == c )
1831  {
1832  j = i;
1833  }
1834  }
1835 
1836  return j;
1837 
1838 }
1839 //****************************************************************************80
1840 
1841 bool ch_is_space ( char c )
1842 
1843 //****************************************************************************80
1844 //
1845 // Purpose:
1846 //
1847 // CH_IS_SPACE is TRUE if a character represents "white space".
1848 //
1849 // Discussion:
1850 //
1851 // A white space character is a space, a form feed, a newline, a carriage
1852 // return, a horizontal tab, or a vertical tab.
1853 //
1854 // Licensing:
1855 //
1856 // This code is distributed under the GNU LGPL license.
1857 //
1858 // Modified:
1859 //
1860 // 02 October 2004
1861 //
1862 // Author:
1863 //
1864 // John Burkardt
1865 //
1866 // Parameters:
1867 //
1868 // Input, char C, the character to be analyzed.
1869 //
1870 // Output, bool CH_IS_SPACE, is TRUE if C is a whitespace character.
1871 //
1872 {
1873  if ( c == ' ' )
1874  {
1875  return true;
1876  }
1877  else if ( c == '\f' )
1878  {
1879  return true;
1880  }
1881  else if ( c == '\n' )
1882  {
1883  return true;
1884  }
1885  else if ( c == '\r' )
1886  {
1887  return true;
1888  }
1889  else if ( c == '\t' )
1890  {
1891  return true;
1892  }
1893  else if ( c == '\v' )
1894  {
1895  return true;
1896  }
1897  else
1898  {
1899  return false;
1900  }
1901 }
1902 //****************************************************************************80
1903 
1904 int ch_pad ( int *char_index, int *null_index, char *s, int max_string )
1905 
1906 //****************************************************************************80
1907 //
1908 // Purpose:
1909 //
1910 // CH_PAD "pads" a character in a string with a blank on either side.
1911 //
1912 // Licensing:
1913 //
1914 // This code is distributed under the GNU LGPL license.
1915 //
1916 // Modified:
1917 //
1918 // 16 October 1998
1919 //
1920 // Author:
1921 //
1922 // John Burkardt
1923 //
1924 // Parameters:
1925 //
1926 // Input/output, int *CHAR_INDEX, the position of the character to be
1927 // padded. On output, this is increased by 1.
1928 //
1929 // Input/output, int *NULL_INDEX, the position of the terminating NULL in
1930 // the string. On output, this is increased by 2.
1931 //
1932 // Input/output, char S[MAX_STRING], the string to be manipulated.
1933 //
1934 // Input, int MAX_STRING, the maximum number of characters that can be stored
1935 // in s.
1936 //
1937 // Output, int CH_PAD, is 0 if the operation worked, and 1 otherwise.
1938 //
1939 {
1940  int i;
1941 
1942  if ( *char_index < 0 ||
1943  *null_index <= *char_index ||
1944  max_string - 1 < *char_index )
1945  {
1946  return 1;
1947  }
1948 
1949  if ( max_string - 1 < (*null_index) + 2 )
1950  {
1951  return 1;
1952  }
1953 
1954  for ( i = *null_index + 2; *char_index + 2 < i; i-- )
1955  {
1956  s[i] = s[i-2];
1957  }
1958  s[*char_index+2] = ' ';
1959  s[*char_index+1] = s[*char_index];
1960  s[*char_index] = ' ';
1961 
1962  *char_index = *char_index + 1;
1963  *null_index = *null_index + 2;
1964 
1965  return 0;
1966 }
1967 //****************************************************************************80
1968 
1969 char ch_read ( FILE *filein )
1970 
1971 //****************************************************************************80
1972 //
1973 // Purpose:
1974 //
1975 // CH_READ reads one character from a binary file.
1976 //
1977 // Licensing:
1978 //
1979 // This code is distributed under the GNU LGPL license.
1980 //
1981 // Modified:
1982 //
1983 // 24 May 1999
1984 //
1985 // Author:
1986 //
1987 // John Burkardt
1988 //
1989 {
1990  char c;
1991 
1992  c = ( char ) fgetc ( filein );
1993 
1994  return c;
1995 }
1996 //****************************************************************************80
1997 
1998 int ch_to_digit ( char c )
1999 
2000 //****************************************************************************80
2001 //
2002 // Purpose:
2003 //
2004 // CH_TO_DIGIT returns the integer value of a base 10 digit.
2005 //
2006 // Example:
2007 //
2008 // C DIGIT
2009 // --- -----
2010 // '0' 0
2011 // '1' 1
2012 // ... ...
2013 // '9' 9
2014 // ' ' 0
2015 // 'X' -1
2016 //
2017 // Licensing:
2018 //
2019 // This code is distributed under the GNU LGPL license.
2020 //
2021 // Modified:
2022 //
2023 // 13 June 2003
2024 //
2025 // Author:
2026 //
2027 // John Burkardt
2028 //
2029 // Parameters:
2030 //
2031 // Input, char C, the decimal digit, '0' through '9' or blank are legal.
2032 //
2033 // Output, int CH_TO_DIGIT, the corresponding integer value. If C was
2034 // 'illegal', then DIGIT is -1.
2035 //
2036 {
2037  int digit;
2038 
2039  if ( '0' <= c && c <= '9' )
2040  {
2041  digit = c - '0';
2042  }
2043  else if ( c == ' ' )
2044  {
2045  digit = 0;
2046  }
2047  else
2048  {
2049  digit = -1;
2050  }
2051 
2052  return digit;
2053 }
2054 //****************************************************************************80
2055 
2056 int ch_write ( FILE *fileout, char c )
2057 
2058 //****************************************************************************80
2059 //
2060 // Purpose:
2061 //
2062 // CH_WRITE writes one character to a binary file.
2063 //
2064 // Licensing:
2065 //
2066 // This code is distributed under the GNU LGPL license.
2067 //
2068 // Modified:
2069 //
2070 // 24 May 1999
2071 //
2072 // Author:
2073 //
2074 // John Burkardt
2075 //
2076 {
2077  fputc ( c, fileout );
2078 
2079  return 1;
2080 }
2081 //****************************************************************************80
2082 
2083 int command_line ( char **argv )
2084 
2085 //****************************************************************************80
2086 //
2087 // Purpose:
2088 //
2089 // COMMAND_LINE carries out a command-line session of file conversion.
2090 //
2091 // Discussion:
2092 //
2093 // This routine is invoked when the user command is something like
2094 //
2095 // ivcon filein_name fileout_name
2096 //
2097 // or
2098 //
2099 // ivcon -rn filein_name fileout_name
2100 //
2101 // where "-rn" signals the "reverse normals" option, or
2102 //
2103 // ivcon -rf filein_name fileout_name
2104 //
2105 // where "-rf" signals the "reverse faces" option.
2106 //
2107 // Licensing:
2108 //
2109 // This code is distributed under the GNU LGPL license.
2110 //
2111 // Modified:
2112 //
2113 // 28 June 1999
2114 //
2115 // Author:
2116 //
2117 // John Burkardt
2118 //
2119 {
2120  int i;
2121  int iarg;
2122  int icor3;
2123  int ierror;
2124  int iface;
2125  int ivert;
2126  bool reverse_faces;
2127  bool reverse_normals;
2128  bool success;
2129 //
2130 // Initialize local data.
2131 //
2132  iarg = 0;
2133  ierror = 0;
2134  reverse_faces = false;
2135  reverse_normals = false;
2136 //
2137 // Initialize the graphics data.
2138 //
2139  data_init ( );
2140 //
2141 // Get the -RN option, -RF option, and the input file name.
2142 //
2143  iarg = iarg + 1;
2144  strcpy ( filein_name, argv[iarg] );
2145 
2146  if ( s_eqi ( filein_name, "-RN" ) )
2147  {
2148  reverse_normals = true;
2149  cout << "\n";
2150  cout << "COMMAND_LINE: Reverse_Normals option requested.\n";
2151  iarg = iarg + 1;
2152  strcpy ( filein_name, argv[iarg] );
2153  }
2154 
2155  if ( s_eqi ( filein_name, "-RF" ) )
2156  {
2157  reverse_faces = true;
2158  cout << "\n";
2159  cout << "COMMAND_LINE: Reverse_Faces option requested.\n";
2160  iarg = iarg + 1;
2161  strcpy ( filein_name, argv[iarg] );
2162  }
2163 //
2164 // Read the input.
2165 //
2166  success = data_read ( );
2167 
2168  if ( !success )
2169  {
2170  cout << "\n";
2171  cout << "COMMAND_LINE - Fatal error!\n";
2172  cout << " Failure reported from DATA_READ.\n";
2173  return 1;
2174  }
2175 //
2176 // Reverse the normal vectors if requested.
2177 //
2178  if ( reverse_normals )
2179  {
2180 
2181  for ( icor3 = 0; icor3 < cor3_num; icor3++ )
2182  {
2183  for ( i = 0; i < 3; i++ )
2184  {
2185  cor3_normal[i][icor3] = - cor3_normal[i][icor3];
2186  }
2187  }
2188 
2189  for ( iface = 0; iface < face_num; iface++ )
2190  {
2191  for ( i = 0; i < 3; i++ )
2192  {
2193  face_normal[i][iface] = - face_normal[i][iface];
2194  }
2195  }
2196 
2197  for ( iface = 0; iface < face_num; iface++ )
2198  {
2199  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
2200  {
2201  for ( i = 0; i < 3; i++ )
2202  {
2203  vertex_normal[i][ivert][iface] =
2204  - vertex_normal[i][ivert][iface];
2205  }
2206  }
2207  }
2208  cout << "\n";
2209  cout << "COMMAND_LINE - Note:\n";
2210  cout << " Reversed node, face, and vertex normals.\n";
2211  }
2212 //
2213 // Reverse the faces if requested.
2214 //
2215  if ( reverse_faces )
2216  {
2217  face_reverse_order ( );
2218 
2219  cout << "\n";
2220  cout << "COMMAND_LINE - Note:\n";
2221  cout << " Reversed the face definitions.\n";
2222  }
2223 //
2224 // Write the output file.
2225 //
2226  iarg = iarg + 1;
2227  strcpy ( fileout_name, argv[iarg] );
2228 
2229  ierror = data_write ( );
2230 
2231  if ( ierror == 1 )
2232  {
2233  cout << "\n";
2234  cout << "COMMAND_LINE - Fatal error!\n";
2235  cout << " Failure while writing output data.\n";
2236  return 1;
2237  }
2238  return 0;
2239 }
2240 //****************************************************************************80
2241 
2243 
2244 //****************************************************************************80
2245 //
2246 // Purpose:
2247 //
2248 // COR3_NORMAL_SET computes node normal vectors.
2249 //
2250 // Licensing:
2251 //
2252 // This code is distributed under the GNU LGPL license.
2253 //
2254 // Modified:
2255 //
2256 // 18 November 1998
2257 //
2258 // Author:
2259 //
2260 // John Burkardt
2261 //
2262 {
2263  int icor3;
2264  int iface;
2265  int ivert;
2266  int j;
2267  float norm;
2268  float temp;
2269 
2270  for ( icor3 = 0; icor3 < cor3_num; icor3++ )
2271  {
2272  for ( j = 0; j < 3; j++ )
2273  {
2274  cor3_normal[j][icor3] = 0.0;
2275  }
2276  }
2277 //
2278 // Add up the normals at all the faces to which the node belongs.
2279 //
2280  for ( iface = 0; iface < face_num; iface++ )
2281  {
2282  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
2283  {
2284  icor3 = face[ivert][iface];
2285  for ( j = 0; j < 3; j++ )
2286  {
2287  cor3_normal[j][icor3] = cor3_normal[j][icor3]
2288  + vertex_normal[j][ivert][iface];
2289  }
2290  }
2291  }
2292 //
2293 // Renormalize.
2294 //
2295  for ( icor3 = 0; icor3 < cor3_num; icor3++ )
2296  {
2297  norm = 0.0;
2298  for ( j = 0; j < 3; j++ )
2299  {
2300  temp = cor3_normal[j][icor3];
2301  norm = norm + temp * temp;
2302  }
2303 
2304  if ( norm == 0.0 )
2305  {
2306  norm = 3.0;
2307  for ( j = 0; j < 3; j++ )
2308  {
2309  cor3_normal[j][icor3] = 1.0;
2310  }
2311  }
2312 
2313  norm = ( float ) sqrt ( norm );
2314 
2315  for ( j = 0; j < 3; j++ )
2316  {
2317  cor3_normal[j][icor3] = cor3_normal[j][icor3] / norm;
2318  }
2319  }
2320 
2321  return;
2322 }
2323 //****************************************************************************80
2324 
2325 void cor3_range ( )
2326 
2327 //****************************************************************************80
2328 //
2329 // Purpose:
2330 //
2331 // COR3_RANGE computes the coordinate minima and maxima.
2332 //
2333 // Licensing:
2334 //
2335 // This code is distributed under the GNU LGPL license.
2336 //
2337 // Modified:
2338 //
2339 // 31 August 1998
2340 //
2341 // Author:
2342 //
2343 // John Burkardt
2344 //
2345 {
2346  int i;
2347  float xave;
2348  float xmax;
2349  float xmin;
2350  float yave;
2351  float ymax;
2352  float ymin;
2353  float zave;
2354  float zmax;
2355  float zmin;
2356 
2357  xave = cor3[0][0];
2358  xmax = cor3[0][0];
2359  xmin = cor3[0][0];
2360 
2361  yave = cor3[1][0];
2362  ymax = cor3[1][0];
2363  ymin = cor3[1][0];
2364 
2365  zave = cor3[2][0];
2366  zmax = cor3[2][0];
2367  zmin = cor3[2][0];
2368 
2369  for ( i = 1; i < cor3_num; i++ )
2370  {
2371  xave = xave + cor3[0][i];
2372  if ( cor3[0][i] < xmin )
2373  {
2374  xmin = cor3[0][i];
2375  }
2376  if ( xmax < cor3[0][i] )
2377  {
2378  xmax = cor3[0][i];
2379  }
2380 
2381  yave = yave + cor3[1][i];
2382  if ( cor3[1][i] < ymin )
2383  {
2384  ymin = cor3[1][i];
2385  }
2386  if ( ymax < cor3[1][i] )
2387  {
2388  ymax = cor3[1][i];
2389  }
2390 
2391  zave = zave + cor3[2][i];
2392  if ( cor3[2][i] < zmin )
2393  {
2394  zmin = cor3[2][i];
2395  }
2396  if ( zmax < cor3[2][i] )
2397  {
2398  zmax = cor3[2][i];
2399  }
2400  }
2401 
2402  xave = xave / cor3_num;
2403  yave = yave / cor3_num;
2404  zave = zave / cor3_num;
2405 
2406  cout << "\n";
2407  cout << "COR3_RANGE - Data range:\n";
2408  cout << "\n";
2409  cout << " Minimum Average Maximum Range\n";
2410  cout << "\n";
2411  cout << "X " << setw(10) << xmin << " "
2412  << setw(10) << xave << " "
2413  << setw(10) << xmax << " "
2414  << setw(10) << xmax - xmin << "\n";
2415  cout << "Y " << setw(10) << ymin << " "
2416  << setw(10) << yave << " "
2417  << setw(10) << ymax << " "
2418  << setw(10) << ymax - ymin << "\n";
2419  cout << "Z " << setw(10) << zmin << " "
2420  << setw(10) << zave << " "
2421  << setw(10) << zmax << " "
2422  << setw(10) << zmax - zmin << "\n";
2423 
2424  return;
2425 }
2426 //****************************************************************************80
2427 
2428 void data_check ( )
2429 
2430 //****************************************************************************80
2431 //
2432 // Purpose:
2433 //
2434 // DATA_CHECK checks the input data.
2435 //
2436 // Licensing:
2437 //
2438 // This code is distributed under the GNU LGPL license.
2439 //
2440 // Modified:
2441 //
2442 // 02 May 2005
2443 //
2444 // Author:
2445 //
2446 // John Burkardt
2447 //
2448 {
2449  int iface;
2450  int nfix;
2451 
2452  if ( COLOR_MAX < color_num )
2453  {
2454  cout << "\n";
2455  cout << "DATA_CHECK - Warning!\n";
2456  cout << " The input data requires " << color_num << " colors.\n";
2457  cout << " There was only room for " << COLOR_MAX << "\n";
2458  cout << "\n";
2459  cout << " To correct this problem, you can change the internal\n";
2460  cout << " value of COLOR_MAX, recompile, and rerun the program.\n";
2461  color_num = COLOR_MAX;
2462  }
2463 
2464  if ( COR3_MAX < cor3_num )
2465  {
2466  cout << "\n";
2467  cout << "DATA_CHECK - Warning!\n";
2468  cout << " The input data requires " << cor3_num << " points.\n";
2469  cout << " There was only room for " << COR3_MAX << "\n";
2470  cout << "\n";
2471  cout << " To correct this problem, you can change the internal\n";
2472  cout << " value of COR3_MAX, recompile, and rerun the program.\n";
2473  cor3_num = COR3_MAX;
2474  }
2475 
2476  if ( FACE_MAX < face_num )
2477  {
2478  cout << "\n";
2479  cout << "DATA_CHECK - Warning!\n";
2480  cout << " The input data requires " << face_num << " faces.\n";
2481  cout << " There was only room for " << FACE_MAX << "\n";
2482  cout << "\n";
2483  cout << " To correct this problem, you can change the internal\n";
2484  cout << " value of FACE_MAX, recompile, and rerun the program.\n";
2485  face_num = FACE_MAX;
2486  }
2487 
2488  if ( LINES_MAX < line_num )
2489  {
2490  cout << "\n";
2491  cout << "DATA_CHECK - Warning!\n";
2492  cout << " The input data requires " << line_num << " line items.\n";
2493  cout << " There was only room for " << LINES_MAX << ".\n";
2494  cout << "\n";
2495  cout << " To correct this problem, you can change the internal\n";
2496  cout << " value of LINES_MAX, recompile, and rerun the program.\n";
2497  line_num = LINES_MAX;
2498  }
2499 
2500  nfix = 0;
2501 
2502  for ( iface = 0; iface < face_num; iface++ )
2503  {
2504  if ( ORDER_MAX < face_order[iface] )
2505  {
2506  face_order[iface] = ORDER_MAX;
2507  nfix = nfix + 1;
2508  }
2509  }
2510 
2511  if ( 0 < nfix )
2512  {
2513  cout << "\n";
2514  cout << "DATA_CHECK - Warning!\n";
2515  cout << " Corrected " << nfix
2516  << " faces using more than " << ORDER_MAX
2517  << " vertices per face.\n";
2518  }
2519 
2520  for ( i = 0; i < material_num; i++ )
2521  {
2522  if ( strcmp ( material_name[i], "" ) == 0 )
2523  {
2524  strcpy ( material_name[i], "Material_0000" );
2525  }
2526  }
2527 
2528  for ( i = 0; i < texture_num; i++ )
2529  {
2530  if ( strcmp ( texture_name[i], "" ) == 0 )
2531  {
2532  strcpy ( texture_name[i], "Texture_0000" );
2533  }
2534  }
2535 
2536  cout << "\n";
2537  cout << "DATA_CHECK - Data checked.\n";
2538 
2539  return;
2540 }
2541 //****************************************************************************80
2542 
2543 void data_init ( )
2544 
2545 //****************************************************************************80
2546 //
2547 // Purpose:
2548 //
2549 // DATA_INIT initializes the internal graphics data.
2550 //
2551 // Licensing:
2552 //
2553 // This code is distributed under the GNU LGPL license.
2554 //
2555 // Modified:
2556 //
2557 // 04 July 2000
2558 //
2559 // Author:
2560 //
2561 // John Burkardt
2562 //
2563 {
2564  int i;
2565  int iface;
2566  int ivert;
2567  int j;
2568  int k;
2569 
2570  strcpy( anim_name, "" );
2571 
2572  for ( i = 0; i < 3; i++ )
2573  {
2574  background_rgb[i] = 0.0;
2575  }
2576 
2577  for ( i = 0; i < 3; i++ )
2578  {
2579  for ( j = 0; j < COR3_MAX; j++ )
2580  {
2581  cor3[i][j] = 0.0;
2582  }
2583  }
2584 
2585  for ( i = 0; i < COR3_MAX; i++ )
2586  {
2587  cor3_material[i] = 0;
2588  }
2589 
2590  for ( i = 0; i < 3; i++ )
2591  {
2592  for ( j = 0; j < COR3_MAX; j++ )
2593  {
2594  cor3_normal[i][j] = 0.0;
2595  }
2596  }
2597 
2598  for ( j = 0; j < COR3_MAX; j++ )
2599  {
2600  cor3_tex_uv[0][j] = 0.0;
2601  cor3_tex_uv[1][j] = 0.0;
2602  }
2603 
2604  for ( iface = 0; iface < FACE_MAX; iface++ )
2605  {
2606  for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
2607  {
2608  face[ivert][iface] = 0;
2609  }
2610  }
2611 
2612  for ( iface = 0; iface < FACE_MAX; iface++ )
2613  {
2614  face_flags[iface] = 6;
2615  }
2616 
2617  for ( iface = 0; iface < FACE_MAX; iface++ )
2618  {
2619  face_material[iface] = 0;
2620  }
2621 
2622  for ( iface = 0; iface < FACE_MAX; iface++ )
2623  {
2624  for ( i = 0; i < 3; i++ )
2625  {
2626  face_normal[i][iface] = 0;
2627  }
2628  }
2629 
2630  for ( iface = 0; iface < FACE_MAX; iface++ )
2631  {
2632  face_object[iface] = -1;
2633  }
2634 
2635  for ( iface = 0; iface < FACE_MAX; iface++ )
2636  {
2637  face_order[iface] = 0;
2638  }
2639 
2640  for ( iface = 0; iface < FACE_MAX; iface++ )
2641  {
2642  face_smooth[iface] = 1;
2643  }
2644 
2645  for ( i = 0; i < LINES_MAX; i++ )
2646  {
2647  line_dex[i] = -1;
2648  }
2649 
2650  for ( i = 0; i < LINES_MAX; i++ )
2651  {
2652  line_material[i] = 0;
2653  }
2654 
2655  strcpy ( material_binding, "DEFAULT" );
2656 
2657  for ( j = 0; j < MATERIAL_MAX; j++ )
2658  {
2659  strcpy ( material_name[j], "Material_0000" );
2660  }
2661 
2662  for ( i = 0; i < 4; i++ )
2663  {
2664  for ( j = 0; j < MATERIAL_MAX; j++ )
2665  {
2666  material_rgba[i][j] = 0.0;
2667  }
2668  }
2669 
2670  strcpy ( normal_binding, "DEFAULT" );
2671 
2672  for ( j = 0; j < ORDER_MAX*FACE_MAX; j++ )
2673  {
2674  for ( i = 0; i < 3; i++ )
2675  {
2676  normal_temp[i][j] = 0;
2677  }
2678  }
2679 
2680  color_num = 0;
2681  cor3_num = 0;
2682  face_num = 0;
2683  group_num = 0;
2684  line_num = 0;
2685  material_num = 0;
2686  object_num = 0;
2687  texture_num = 0;
2688 
2689  strcpy ( object_name, "IVCON" );
2690 
2691  for ( i = 0; i < 3; i++ )
2692  {
2693  origin[i] = 0.0;
2694  }
2695 
2696  for ( i = 0; i < 3; i++ )
2697  {
2698  pivot[i] = 0.0;
2699  }
2700 
2701  for ( j = 0; j < COLOR_MAX; j++ )
2702  {
2703  rgbcolor[0][j] = 0.299;
2704  rgbcolor[1][j] = 0.587;
2705  rgbcolor[2][j] = 0.114;
2706  }
2707 
2708  strcpy ( texture_binding, "DEFAULT" );
2709 
2710  for ( j = 0; j < TEXTURE_MAX; j++ )
2711  {
2712  strcpy ( texture_name[j], "Texture_0000" );
2713  }
2714 
2716 
2717  for ( iface = 0; iface < FACE_MAX; iface++ )
2718  {
2719  for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
2720  {
2721  vertex_material[ivert][iface] = 0;
2722  }
2723  }
2724 
2725  for ( iface = 0; iface < FACE_MAX; iface++ )
2726  {
2727  for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
2728  {
2729  for ( i = 0; i < 3; i++ )
2730  {
2731  vertex_normal[i][ivert][iface] = 0.0;
2732  }
2733  }
2734  }
2735 
2736  for ( j = 0; j < 3; j++ )
2737  {
2738  for ( k = 0; k < FACE_MAX; k++ )
2739  {
2740  vertex_rgb[0][j][k] = 0.299;
2741  vertex_rgb[1][j][k] = 0.587;
2742  vertex_rgb[2][j][k] = 0.114;
2743  }
2744  }
2745 
2746  for ( iface = 0; iface < FACE_MAX; iface++ )
2747  {
2748  for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
2749  {
2750  for ( i = 0; i < 2; i++ )
2751  {
2752  vertex_tex_uv[i][ivert][iface] = 0.0;
2753  }
2754  }
2755  }
2756 
2757  if ( debug )
2758  {
2759  cout << "\n";
2760  cout << "DATA_INIT: Graphics data initialized.\n";
2761  }
2762 
2763  return;
2764 }
2765 //****************************************************************************80
2766 
2767 bool data_read ( )
2768 
2769 //****************************************************************************80
2770 //
2771 // Purpose:
2772 //
2773 // DATA_READ reads a file into internal graphics data.
2774 //
2775 // Licensing:
2776 //
2777 // This code is distributed under the GNU LGPL license.
2778 //
2779 // Modified:
2780 //
2781 // 08 September 2003
2782 //
2783 // Author:
2784 //
2785 // John Burkardt
2786 //
2787 // Parameters:
2788 //
2789 // Output, bool DATA_READ, is TRUE if the data was read successfully.
2790 //
2791 {
2792  ifstream file_in;
2793  FILE *filein;
2794  char *filein_type;
2795  int icor3;
2796  int ierror;
2797  int iface;
2798  int iline;
2799  int ivert;
2800  int ntemp;
2801 //
2802 // Retrieve the input file type.
2803 //
2804  filein_type = file_ext ( filein_name );
2805 
2806  if ( filein_type == NULL )
2807  {
2808  cout << "\n";
2809  cout << "DATA_READ - Fatal error!\n";
2810  cout << " Could not determine the type of '" << filein_name << "'.\n";
2811  return false;
2812  }
2813  else if ( debug )
2814  {
2815  cout << "\n";
2816  cout << "DATA_READ: Input file has type " << filein_type << ".\n";
2817  }
2818 //
2819 // Initialize some data.
2820 //
2821  max_order2 = 0;
2822  bad_num = 0;
2823  bytes_num = 0;
2824  comment_num = 0;
2825  dup_num = 0;
2826  text_num = 0;
2827 //
2828 // Open the file.
2829 //
2830  if ( s_eqi ( filein_type, "3DS" ) ||
2831  s_eqi ( filein_type, "STLB" ) ||
2832  s_eqi ( filein_type, "TRIB" ) )
2833  {
2834  filein = fopen ( filein_name, "rb" );
2835 
2836  if ( filein == NULL )
2837  {
2838  cout << "\n";
2839  cout << "DATA_READ - Fatal error!\n";
2840  cout << " Could not open the input file '" << filein_name << "'!\n";
2841  return false;
2842  }
2843  }
2844  else if ( s_eqi ( filein_type, "OFF" ) )
2845  {
2846  file_in.open ( filein_name );
2847 
2848  if ( !file_in )
2849  {
2850  cout << "\n";
2851  cout << "DATA_READ - Fatal error!\n";
2852  cout << " Could not open the input file '" << filein_name << "'!\n";
2853  return false;
2854  }
2855  }
2856  else
2857  {
2858  filein = fopen ( filein_name, "r" );
2859 
2860  if ( filein == NULL )
2861  {
2862  cout << "\n";
2863  cout << "DATA_READ - Fatal error!\n";
2864  cout << " Could not open the input file '" << filein_name << "'!\n";
2865  return false;
2866  }
2867  }
2868 //
2869 // Read the information in the file.
2870 //
2871  if ( s_eqi ( filein_type, "3DS" ) )
2872  {
2873  ierror = tds_read ( filein );
2874 //
2875 // Cleanup: distribute the node textures to the vertices.
2876 //
2877  if ( ierror == 0 )
2878  {
2879  for ( iface = 0; iface < face_num; iface++ )
2880  {
2881  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
2882  {
2883  icor3 = face[ivert][iface];
2884  vertex_tex_uv[0][ivert][iface] = cor3_tex_uv[0][icor3];
2885  vertex_tex_uv[1][ivert][iface] = cor3_tex_uv[1][icor3];
2886  }
2887  }
2888 
2889  }
2890 
2891  }
2892  else if ( s_eqi ( filein_type, "ASE" ) )
2893  {
2894  ierror = ase_read ( filein );
2895 
2896  if ( ierror == 0 )
2897  {
2900  }
2901 
2902  }
2903  else if ( s_eqi ( filein_type, "BYU" ) )
2904  {
2905  ierror = byu_read ( filein );
2906  }
2907  else if ( s_eqi ( filein_type, "DXF" ) )
2908  {
2909  ierror = dxf_read ( filein );
2910  }
2911  else if ( s_eqi ( filein_type, "GMOD" ) )
2912  {
2913  ierror = gmod_read ( filein );
2914  }
2915  else if ( s_eqi ( filein_type, "HRC" ) )
2916  {
2917  ierror = hrc_read ( filein );
2918  }
2919  else if ( s_eqi ( filein_type, "IV" ) )
2920  {
2921  ierror = iv_read ( filein );
2922  }
2923  else if ( s_eqi ( filein_type, "OBJ" ) )
2924  {
2925  ierror = obj_read ( filein );
2926  }
2927  else if ( s_eqi ( filein_type, "OFF" ) )
2928  {
2929  ierror = off_read ( file_in );
2930  }
2931  else if ( s_eqi ( filein_type, "SMF" ) )
2932  {
2933  ierror = smf_read ( filein );
2934  }
2935  else if (
2936  s_eqi ( filein_type, "STL" ) ||
2937  s_eqi ( filein_type, "STLA") )
2938  {
2939  ierror = stla_read ( filein );
2940  }
2941  else if ( s_eqi ( filein_type, "STLB") )
2942  {
2943  ierror = stlb_read ( filein );
2944  }
2945  else if (
2946  s_eqi ( filein_type, "TRI" ) ||
2947  s_eqi ( filein_type, "TRIA") )
2948  {
2949  ierror = tria_read ( filein );
2950  }
2951  else if ( s_eqi ( filein_type, "TRIB") )
2952  {
2953  ierror = trib_read ( filein );
2954  }
2955  else if ( s_eqi ( filein_type, "VLA" ) )
2956  {
2957  ierror = vla_read ( filein );
2958  }
2959  else
2960  {
2961  cout << "\n";
2962  cout << "DATA_READ - Fatal error!\n";
2963  cout << " Unacceptable input file type.\n";
2964  return false;
2965  }
2966 
2967  if ( s_eqi ( filein_type, "OFF" ) )
2968  {
2969  file_in.close ( );
2970  }
2971  else
2972  {
2973  fclose ( filein );
2974  }
2975 
2976  if ( debug )
2977  {
2978  cout << "DATA_READ: Finished reading the data file.\n";
2979  }
2980 //
2981 // Catch errors reported by the various reading routines.
2982 //
2983  if ( ierror == ERROR )
2984  {
2985  cout << "\n";
2986  cout << "DATA_READ - Fatal error!\n";
2987  cout << " There was an error reported while reading input data.\n";
2988  return false;
2989  }
2990 //
2991 // Restore the transformation matrix.
2992 //
2994 //
2995 // Report on what we read.
2996 //
2997  if ( face_num < FACE_MAX )
2998  {
2999  ntemp = face_num;
3000  }
3001  else
3002  {
3003  ntemp = FACE_MAX;
3004  }
3005 
3006  max_order2 = i4vec_max ( ntemp, face_order );
3007 
3008  data_report ( );
3009 //
3010 // Warn about any errors that occurred during reading.
3011 //
3012  if ( ierror == ERROR )
3013  {
3014  cout << "\n";
3015  cout << "DATA_READ - Fatal error!\n";
3016  cout << " An error occurred while reading the input file.\n";
3017  return false;
3018  }
3019 //
3020 // Check the data.
3021 // You MUST wait until after this check before doing other computations,
3022 // since COR3_NUM and other variables could be much larger than the legal
3023 // maximums, until corrected by DATA_CHECK.
3024 //
3025  data_check ( );
3026 //
3027 // MATERIALS FIXUPS:
3028 //
3029 // If there are no materials at all, define one.
3030 //
3031  if ( material_num < 1 )
3032  {
3033  material_num = 1;
3034  strcpy ( material_name[0], "Material_0000" );
3035  material_rgba[0][0] = 0.7;
3036  material_rgba[1][0] = 0.7;
3037  material_rgba[2][0] = 0.7;
3038  material_rgba[3][0] = 1.0;
3039  }
3040 //
3041 // If a node has not been assigned a material, set it to material 0.
3042 //
3043  for ( icor3 = 0; icor3 < cor3_num; icor3++ )
3044  {
3045  if ( cor3_material[icor3] < 0 || material_num - 1 < cor3_material[icor3] )
3046  {
3047  cor3_material[icor3] = 0;
3048  }
3049  }
3050 //
3051 // If a vertex has not been assigned a material, set it to material 0.
3052 //
3053  for ( iface = 0; iface < face_num; iface++ )
3054  {
3055  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
3056  {
3057  if ( vertex_material[ivert][iface] < 0 ||
3058  material_num - 1 < vertex_material[ivert][iface] )
3059  {
3060  vertex_material[ivert][iface] = 0;
3061  }
3062  }
3063  }
3064 //
3065 // If a face has not been assigned a material, set it to material 0.
3066 //
3067  for ( iface = 0; iface < face_num; iface++ )
3068  {
3069  if ( face_material[iface] < 0 || material_num - 1 < face_material[iface] )
3070  {
3071  face_material[iface] = 0;
3072  }
3073  }
3074 //
3075 // If a line item has not been assigned a material, set it to material 0.
3076 //
3077  for ( iline = 0; iline < line_num; iline++ )
3078  {
3079  if ( line_dex[iline] == -1 )
3080  {
3081  line_material[iline] = -1;
3082  }
3083  else if ( line_material[iline] < 0 ||
3084  material_num - 1 < line_material[iline] )
3085  {
3086  line_material[iline] = 0;
3087  }
3088  }
3089 //
3090 // Delete edges of zero length.
3091 //
3092  edge_null_delete ( );
3093 //
3094 // Compute the area of each face.
3095 //
3096  face_area_set ( );
3097 //
3098 // Delete faces with zero area.
3099 //
3100  face_null_delete ( );
3101 //
3102 // Recompute zero face-vertex normals from vertex positions.
3103 //
3104  vertex_normal_set ( );
3105 //
3106 // Compute the node normals from the vertex normals.
3107 //
3108  cor3_normal_set ( );
3109 //
3110 // Recompute zero face normals by averaging face-vertex normals.
3111 //
3112  face_normal_ave ( );
3113 //
3114 // Report on the nodal coordinate range.
3115 //
3116  cor3_range ( );
3117 
3118  return true;
3119 }
3120 //****************************************************************************80
3121 
3122 void data_report ( )
3123 
3124 //****************************************************************************80
3125 //
3126 // Purpose:
3127 //
3128 // DATA_REPORT gives a summary of the contents of the data file.
3129 //
3130 // Licensing:
3131 //
3132 // This code is distributed under the GNU LGPL license.
3133 //
3134 // Modified:
3135 //
3136 // 24 May 1999
3137 //
3138 // Author:
3139 //
3140 // John Burkardt
3141 //
3142 {
3143  cout << "\n";
3144  cout << "DATA_REPORT - The input file contains:\n";
3145  cout << "\n";
3146  cout << " Bad data items " << bad_num << "\n";
3147  cout << " Text lines " << text_num << "\n";
3148  cout << " Text bytes (binary data) " << bytes_num << "\n";
3149  cout << " Colors " << color_num << "\n";
3150  cout << " Comments " << comment_num << "\n";
3151  cout << " Duplicate points " << dup_num << "\n";
3152  cout << " Faces " << face_num << "\n";
3153  cout << " Groups " << group_num << "\n";
3154  cout << " Vertices per face, maximum " << max_order2 << "\n";
3155  cout << " Line items " << line_num << "\n";
3156  cout << " Points " << cor3_num << "\n";
3157  cout << " Objects " << object_num << "\n";
3158 
3159  return;
3160 }
3161 //****************************************************************************80
3162 
3163 int data_write ( )
3164 
3165 //****************************************************************************80
3166 //
3167 // Purpose:
3168 //
3169 // DATA_WRITE writes the internal graphics data to a file.
3170 //
3171 // Licensing:
3172 //
3173 // This code is distributed under the GNU LGPL license.
3174 //
3175 // Modified:
3176 //
3177 // 22 May 1999
3178 //
3179 // Author:
3180 //
3181 // John Burkardt
3182 //
3183 {
3184  FILE *fileout;
3185  char *fileout_type;
3186  int line_num_save;
3187  int result;
3188 
3189  result = 0;
3190 //
3191 // Retrieve the output file type.
3192 //
3193  fileout_type = file_ext ( fileout_name );
3194 
3195  if ( fileout_type == NULL )
3196  {
3197  cout << "\n";
3198  cout << "DATA_WRITE - Fatal error!\n";
3199  cout << " Could not determine the output file type.\n";
3200  return 1;
3201  }
3202 //
3203 // Open the output file.
3204 //
3205  if ( s_eqi ( fileout_type, "3DS" ) ||
3206  s_eqi ( fileout_type, "STLB" ) ||
3207  s_eqi ( fileout_type, "TRIB" ) )
3208  {
3209  fileout = fopen ( fileout_name, "wb" );
3210  }
3211  else
3212  {
3213  fileout = fopen ( fileout_name, "w" );
3214  }
3215 
3216  if ( fileout == NULL )
3217  {
3218  cout << "\n";
3219  cout << "DATA_WRITE - Fatal error!\n";
3220  cout << " Could not open the output file!\n";
3221  return 1;
3222  }
3223 //
3224 // Write the output file.
3225 //
3226  if ( s_eqi ( fileout_type, "3DS" ) )
3227  {
3228  tds_pre_process();
3229  result = tds_write ( fileout );
3230  }
3231  else if ( s_eqi ( fileout_type, "ASE" ) )
3232  {
3233  result = ase_write ( fileout );
3234  }
3235  else if ( s_eqi ( fileout_type, "BYU" ) )
3236  {
3237  result = byu_write ( fileout );
3238  }
3239  else if ( s_eqi ( fileout_type, "DXF" ) )
3240  {
3241  result = dxf_write ( fileout );
3242  }
3243  else if ( s_eqi ( fileout_type, "GMOD" ) )
3244  {
3245  result = gmod_write ( fileout );
3246  }
3247  else if ( s_eqi ( fileout_type, "HRC" ) )
3248  {
3249  result = hrc_write ( fileout );
3250  }
3251  else if ( s_eqi ( fileout_type, "IV" ) )
3252  {
3253  result = iv_write ( fileout );
3254  }
3255  else if ( s_eqi ( fileout_type, "OBJ" ) )
3256  {
3257  result = obj_write ( fileout );
3258  }
3259  else if ( s_eqi ( fileout_type, "OFF" ) )
3260  {
3261  result = off_write ( fileout );
3262  }
3263  else if ( s_eqi ( fileout_type, "POV" ) )
3264  {
3265  result = pov_write ( fileout );
3266  }
3267  else if ( s_eqi ( fileout_type, "SMF" ) )
3268  {
3269  result = smf_write ( fileout );
3270  }
3271  else if (
3272  s_eqi ( fileout_type, "STL" ) ||
3273  s_eqi ( fileout_type, "STLA" ) )
3274  {
3275  result = stla_write ( fileout );
3276  }
3277  else if ( s_eqi ( fileout_type, "STLB" ) )
3278  {
3279  result = stlb_write ( fileout );
3280  }
3281  else if ( s_eqi ( fileout_type, "TEC" ) )
3282  {
3283  result = tec_write ( fileout );
3284  }
3285  else if (
3286  s_eqi ( fileout_type, "TRI" ) ||
3287  s_eqi ( fileout_type, "TRIA" ) )
3288  {
3289  result = tria_write ( fileout );
3290  }
3291  else if ( s_eqi ( fileout_type, "TRIB" ) )
3292  {
3293  result = trib_write ( fileout );
3294  }
3295  else if ( s_eqi ( fileout_type, "TXT" ) )
3296  {
3297  result = txt_write ( fileout );
3298  }
3299  else if ( s_eqi ( fileout_type, "UCD" ) )
3300  {
3301  result = ucd_write ( fileout );
3302  }
3303  else if ( s_eqi ( fileout_type, "VLA" ) )
3304  {
3305  line_num_save = line_num;
3306 
3307  if ( 0 < face_num )
3308  {
3309  cout << "\n";
3310  cout << "DATA_WRITE - Note:\n";
3311  cout << " Face information will temporarily be converted to\n";
3312  cout << " line information for output to a VLA file.\n";
3313 
3314  face_to_line ( );
3315 
3316  if ( LINES_MAX < line_num )
3317  {
3318  cout << "\n";
3319  cout << "DATA_WRITE - Warning:\n";
3320  cout << " Some face information was lost.\n";
3321  cout << " The maximum number of lines is " << LINES_MAX << ".\n";
3322  cout << " The number of lines needed is " << line_num << ".\n";
3323  line_num = LINES_MAX;
3324  }
3325 
3326  }
3327 
3328  result = vla_write ( fileout );
3329 
3330  line_num = line_num_save;
3331 
3332  }
3333  else if ( s_eqi ( fileout_type, "WRL" ) )
3334  {
3335  result = wrl_write ( fileout );
3336  }
3337  else if ( s_eqi ( fileout_type, "XGL" ) )
3338  {
3339  result = xgl_write ( fileout );
3340  }
3341  else
3342  {
3343  result = ERROR;
3344  cout << "\n";
3345  cout << "DATA_WRITE - Fatal error!\n";
3346  cout << " Unacceptable output file type '" << fileout_type << "'.\n";
3347  }
3348 //
3349 // Close the output file.
3350 //
3351  fclose ( fileout );
3352 
3353  if ( result == ERROR )
3354  {
3355  return 1;
3356  }
3357  else
3358  {
3359  return 0;
3360  }
3361 }
3362 //****************************************************************************80
3363 
3364 int dxf_read ( FILE *filein )
3365 
3366 //****************************************************************************80
3367 //
3368 // Purpose:
3369 //
3370 // DXF_READ reads an AutoCAD DXF file.
3371 //
3372 // Example:
3373 //
3374 // 0
3375 // SECTION
3376 // 2
3377 // HEADER
3378 // 999
3379 // diamond.dxf created by IVREAD.
3380 // 999
3381 // Original data in diamond.obj.
3382 // 0
3383 // ENDSEC
3384 // 0
3385 // SECTION
3386 // 2
3387 // TABLES
3388 // 0
3389 // ENDSEC
3390 // 0
3391 // SECTION
3392 // 2
3393 // BLOCKS
3394 // 0
3395 // ENDSEC
3396 // 0
3397 // SECTION
3398 // 2
3399 // ENTITIES
3400 // 0
3401 // LINE
3402 // 8
3403 // 0
3404 // 10
3405 // 0.00 (X coordinate of beginning of line.)
3406 // 20
3407 // 0.00 (Y coordinate of beginning of line.)
3408 // 30
3409 // 0.00 (Z coordinate of beginning of line.)
3410 // 11
3411 // 1.32 (X coordinate of end of line.)
3412 // 21
3413 // 1.73 (Y coordinate of end of line.)
3414 // 31
3415 // 2.25 (Z coordinate of end of line.)
3416 // 0
3417 // 3DFACE
3418 // 8
3419 // Cube
3420 // 10
3421 // -0.50 (X coordinate of vertex 1)
3422 // 20
3423 // 0.50 (Y coordinate of vertex 1)
3424 // 30
3425 // 1.0 (Z coordinate of vertex 1)
3426 // 11
3427 // 0.50 (X coordinate of vertex 2)
3428 // 21
3429 // 0.50 (Y coordinate of vertex 2)
3430 // 31
3431 // 1.0 (Z coordinate of vertex 2)
3432 // 12
3433 // 0.50 (X coordinate of vertex 3)
3434 // 22
3435 // 0.50 (Y coordinate of vertex 3)
3436 // 32
3437 // 0.00 (Z coordinate of vertex 3)
3438 // 0
3439 // ENDSEC
3440 // 0
3441 // EOF
3442 //
3443 // Licensing:
3444 //
3445 // This code is distributed under the GNU LGPL license.
3446 //
3447 // Modified:
3448 //
3449 // 23 May 1999
3450 //
3451 // Author:
3452 //
3453 // John Burkardt
3454 //
3455 {
3456  int code;
3457  int count;
3458  float cvec[3];
3459  int icor3;
3460  char input1[LINE_MAX_LEN];
3461  char input2[LINE_MAX_LEN];
3462  int ivert;
3463  float rval;
3464  int width;
3465  int linemode;
3466  int cpos;
3467 
3468  linemode = 0;
3469  ivert = 0;
3470 //
3471 // Read the next two lines of the file into INPUT1 and INPUT2.
3472 //
3473 
3474  for ( ;; )
3475  {
3476 
3477 //
3478 // INPUT1 should contain a single integer, which tells what INPUT2
3479 // will contain.
3480 //
3481  if ( fgets ( input1, LINE_MAX_LEN, filein ) == NULL )
3482  {
3483  break;
3484  }
3485 
3486  text_num = text_num + 1;
3487 
3488  count = sscanf ( input1, "%d%n", &code, &width );
3489  if ( count <= 0 )
3490  {
3491  break;
3492  }
3493 //
3494 // Read the second line, and interpret it according to the code.
3495 //
3496  if ( fgets ( input2, LINE_MAX_LEN, filein ) == NULL )
3497  {
3498  break;
3499  }
3500 
3501  text_num = text_num + 1;
3502 
3503  if ( code == 0 )
3504  {
3505 
3506 //
3507 // Finish off the face.
3508 //
3509  if ( 0 < ivert )
3510  {
3511  face_order[face_num] = ivert;
3512  face_num = face_num + 1;
3513  ivert = 0;
3514  }
3515 
3516  if ( strncmp( input2, "LINE", 4 ) == 0 )
3517  {
3518  linemode = 1;
3519  }
3520  else if ( strncmp( input2, "3DFACE", 6 ) == 0 )
3521  {
3522  linemode = 0;
3523  ivert = 0;
3524  }
3525  }
3526  else
3527  {
3528  for (cpos = 0; input1[cpos] == ' '; cpos++)
3529  { };
3530 
3531  if ( input1[cpos] == '1' || input1[cpos] == '2' || input1[cpos] == '3' )
3532  {
3533  count = sscanf ( input2, "%e%n", &rval, &width );
3534 
3535  switch ( input1[cpos] )
3536  {
3537  case '1':
3538  if ( 0 < line_num )
3539  {
3540  if ( linemode )
3541  {
3542  line_dex[line_num] = - 1;
3543  line_material[line_num] = - 1;
3544  line_num = line_num + 1;
3545  }
3546  }
3547  cvec[0] = rval;
3548  break;
3549 
3550  case '2':
3551  cvec[1] = rval;
3552  break;
3553 
3554  case '3':
3555  cvec[2] = rval;
3556 
3557  if ( cor3_num < 1000 )
3558  {
3559  icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
3560  }
3561  else
3562  {
3563  icor3 = -1;
3564  }
3565 
3566  if ( icor3 == -1 )
3567  {
3568  icor3 = cor3_num;
3569  if ( cor3_num < COR3_MAX )
3570  {
3571  cor3[0][cor3_num] = cvec[0];
3572  cor3[1][cor3_num] = cvec[1];
3573  cor3[2][cor3_num] = cvec[2];
3574  }
3575  cor3_num = cor3_num + 1;
3576  }
3577  else
3578  {
3579  dup_num = dup_num + 1;
3580  }
3581 
3582  if ( linemode )
3583  {
3584  line_dex[line_num] = icor3;
3585  line_material[line_num] = 0;
3586  line_num = line_num + 1;
3587  }
3588  else
3589  {
3590  face[ivert][face_num] = icor3;
3591  ivert = ivert + 1;
3592  }
3593  break;
3594 
3595  default:
3596  break;
3597  }
3598  }
3599  }
3600  }
3601 
3602  if ( 0 < line_num )
3603  {
3604  if ( linemode )
3605  {
3606  line_dex[line_num] = - 1;
3607  line_material[line_num] = - 1;
3608  line_num = line_num + 1;
3609  }
3610  }
3611  return 0;
3612 }
3613 //****************************************************************************80
3614 
3615 int dxf_write ( FILE *fileout )
3616 
3617 //****************************************************************************80
3618 //
3619 // Purpose:
3620 //
3621 // DXF_WRITE writes graphics information to an AutoCAD DXF file.
3622 //
3623 // Example:
3624 //
3625 // 0
3626 // SECTION
3627 // 2
3628 // HEADER
3629 // 999
3630 // diamond.dxf created by IVREAD.
3631 // 999
3632 // Original data in diamond.obj.
3633 // 0
3634 // ENDSEC
3635 // 0
3636 // SECTION
3637 // 2
3638 // TABLES
3639 // 0
3640 // ENDSEC
3641 // 0
3642 // SECTION
3643 // 2
3644 // BLOCKS
3645 // 0
3646 // ENDSEC
3647 // 0
3648 // SECTION
3649 // 2
3650 // ENTITIES
3651 // 0
3652 // LINE
3653 // 8
3654 // 0
3655 // 10
3656 // 0.00 (X coordinate of beginning of line.)
3657 // 20
3658 // 0.00 (Y coordinate of beginning of line.)
3659 // 30
3660 // 0.00 (Z coordinate of beginning of line.)
3661 // 11
3662 // 1.32 (X coordinate of end of line.)
3663 // 21
3664 // 1.73 (Y coordinate of end of line.)
3665 // 31
3666 // 2.25 (Z coordinate of end of line.)
3667 // 0
3668 // 3DFACE
3669 // 8
3670 // Cube
3671 // 10
3672 // -0.50 (X coordinate of vertex 1)
3673 // 20
3674 // 0.50 (Y coordinate of vertex 1)
3675 // 30
3676 // 1.0 (Z coordinate of vertex 1)
3677 // 11
3678 // 0.50 (X coordinate of vertex 2)
3679 // 21
3680 // 0.50 (Y coordinate of vertex 2)
3681 // 31
3682 // 1.0 (Z coordinate of vertex 2)
3683 // 12
3684 // 0.50 (X coordinate of vertex 3)
3685 // 22
3686 // 0.50 (Y coordinate of vertex 3)
3687 // 32
3688 // 0.00 (Z coordinate of vertex 3)
3689 // 0
3690 // ENDSEC
3691 // 0
3692 // EOF
3693 //
3694 // Licensing:
3695 //
3696 // This code is distributed under the GNU LGPL license.
3697 //
3698 // Modified:
3699 //
3700 // 16 May 1999
3701 //
3702 // Author:
3703 //
3704 // John Burkardt
3705 //
3706 {
3707  int icor3;
3708  int iline;
3709  int iface;
3710  int ivert;
3711  int jcor3;
3712  bool newline;
3713  int text_num;
3714 //
3715 // Initialize.
3716 //
3717  text_num = 0;
3718 
3719  fprintf ( fileout, " 0\n" );
3720  fprintf ( fileout, "SECTION\n" );
3721  fprintf ( fileout, " 2\n" );
3722  fprintf ( fileout, "HEADER\n" );
3723  fprintf ( fileout, "999\n" );
3724  fprintf ( fileout, "%s created by IVCON.\n", fileout_name );
3725  fprintf ( fileout, "999\n" );
3726  fprintf ( fileout, "Original data in %s.\n", filein_name );
3727  fprintf ( fileout, " 0\n" );
3728  fprintf ( fileout, "ENDSEC\n" );
3729  text_num = text_num + 10;
3730 
3731  fprintf ( fileout, " 0\n" );
3732  fprintf ( fileout, "SECTION\n" );
3733  fprintf ( fileout, " 2\n" );
3734  fprintf ( fileout, "TABLES\n" );
3735  fprintf ( fileout, " 0\n" );
3736  fprintf ( fileout, "ENDSEC\n" );
3737  text_num = text_num + 6;
3738 
3739  fprintf ( fileout, " 0\n" );
3740  fprintf ( fileout, "SECTION\n" );
3741  fprintf ( fileout, " 2\n" );
3742  fprintf ( fileout, "BLOCKS\n" );
3743  fprintf ( fileout, " 0\n" );
3744  fprintf ( fileout, "ENDSEC\n" );
3745  text_num = text_num + 6;
3746 
3747  fprintf ( fileout, " 0\n" );
3748  fprintf ( fileout, "SECTION\n" );
3749  fprintf ( fileout, " 2\n" );
3750  fprintf ( fileout, "ENTITIES\n" );
3751  text_num = text_num + 4;
3752 //
3753 // Handle lines.
3754 //
3755  jcor3 = 0;
3756  newline = true;
3757 
3758  for ( iline = 0; iline < line_num; iline++ )
3759  {
3760  icor3 = line_dex[iline];
3761 
3762  if ( icor3 == -1 )
3763  {
3764  newline = true;
3765  }
3766  else
3767  {
3768  if ( !newline )
3769  {
3770  fprintf ( fileout, " 0\n" );
3771  fprintf ( fileout, "LINE\n" );
3772  fprintf ( fileout, " 8\n" );
3773  fprintf ( fileout, " 0\n" );
3774  fprintf ( fileout, " 10\n" );
3775  fprintf ( fileout, "%f\n", cor3[0][jcor3] );
3776  fprintf ( fileout, " 20\n" );
3777  fprintf ( fileout, "%f\n", cor3[1][jcor3] );
3778  fprintf ( fileout, " 30\n" );
3779  fprintf ( fileout, "%f\n", cor3[2][jcor3] );
3780  fprintf ( fileout, " 11\n" );
3781  fprintf ( fileout, "%f\n", cor3[0][icor3] );
3782  fprintf ( fileout, " 21\n" );
3783  fprintf ( fileout, "%f\n", cor3[1][icor3] );
3784  fprintf ( fileout, " 31\n" );
3785  fprintf ( fileout, "%f\n", cor3[2][icor3] );
3786 
3787  text_num = text_num + 16;
3788  }
3789  jcor3 = icor3;
3790  newline = false;
3791  }
3792  }
3793 //
3794 // Handle faces.
3795 // (If FACE_ORDER is greater than 10, you're sure to have problems here)
3796 //
3797  for ( iface = 0; iface < face_num; iface++ )
3798  {
3799  fprintf ( fileout, " 0\n" );
3800  fprintf ( fileout, "3DFACE\n" );
3801  fprintf ( fileout, " 8\n" );
3802  fprintf ( fileout, " Cube\n" );
3803  text_num = text_num + 4;
3804 
3805  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
3806  {
3807  icor3 = face[ivert][iface];
3808 
3809  fprintf ( fileout, "1%d\n", ivert );
3810  fprintf ( fileout, "%f\n", cor3[0][icor3] );
3811  fprintf ( fileout, "2%d\n", ivert );
3812  fprintf ( fileout, "%f\n", cor3[1][icor3] );
3813  fprintf ( fileout, "3%d\n", ivert );
3814  fprintf ( fileout, "%f\n", cor3[2][icor3] );
3815 
3816  text_num = text_num + 6;
3817  }
3818  }
3819 
3820  fprintf ( fileout, " 0\n" );
3821  fprintf ( fileout, "ENDSEC\n" );
3822  fprintf ( fileout, " 0\n" );
3823  fprintf ( fileout, "EOF\n" );
3824  text_num = text_num + 4;
3825 //
3826 // Report.
3827 //
3828  cout << "\n";
3829  cout << "DXF_WRITE - Wrote " << text_num << " text lines.\n";
3830 
3831  return 0;
3832 }
3833 //****************************************************************************80
3834 
3835 int edge_count ( )
3836 
3837 //****************************************************************************80
3838 //
3839 // Purpose:
3840 //
3841 // EDGE_COUNT determines the number of edges in a graph.
3842 //
3843 // Discussion:
3844 //
3845 // The routine extracts the successive pairs of vertices that
3846 // define each edge of a face. It reorders each pair so that
3847 // the lesser element is listed first. It sorts the entire list.
3848 // Then it counts the unique entries.
3849 //
3850 // Licensing:
3851 //
3852 // This code is distributed under the GNU LGPL license.
3853 //
3854 // Modified:
3855 //
3856 // 08 September 2003
3857 //
3858 // Author:
3859 //
3860 // John Burkardt
3861 //
3862 // Parameters:
3863 //
3864 // Output, int EDGE_COUNT, the number of unique edges.
3865 //
3866 {
3867  int *edge;
3868  int edge_num;
3869  int edge_num_old;
3870  int i;
3871  int iface;
3872  int indx;
3873  int isgn;
3874  int j;
3875  int k;
3876  int vert;
3877  int vert2;
3878 //
3879 // First count the number of edges with duplication.
3880 //
3881  edge_num = 0;
3882  for ( iface = 0; iface < face_num; iface++ )
3883  {
3884  edge_num = edge_num + face_order[iface];
3885  }
3886 //
3887 // Allocate space, and store the edges.
3888 //
3889  edge = new int[edge_num*2];
3890 
3891  edge_num = 0;
3892  for ( iface = 0; iface < face_num; iface++ )
3893  {
3894  for ( vert = 0; vert < face_order[iface]; vert++ )
3895  {
3896  i = face[vert][iface];
3897  vert2 = i4_wrap ( vert+1, 0, face_order[iface]-1 );
3898  j = face[vert2][iface];
3899  edge[0+edge_num*2] = i4_min ( i, j );
3900  edge[1+edge_num*2] = i4_max ( i, j );
3901  edge_num = edge_num + 1;
3902  }
3903  }
3904 //
3905 // Sort the edges.
3906 //
3907  i = 0;
3908  indx = 0;
3909  isgn = 0;
3910  j = 0;
3911 //
3912 // Call the external heap sorter.
3913 //
3914  for ( ; ; )
3915  {
3916  sort_heap_external ( edge_num, &indx, &i, &j, isgn );
3917 //
3918 // Interchange the I and J objects.
3919 //
3920  if ( 0 < indx )
3921  {
3922  k = edge[0+i*2];
3923  edge[0+i*2] = edge[0+j*2];
3924  edge[0+j*2] = k;
3925  k = edge[1+i*2];
3926  edge[1+i*2] = edge[1+j*2];
3927  edge[1+j*2] = k;
3928  }
3929 //
3930 // Compare the I and J objects.
3931 //
3932  else if ( indx < 0 )
3933  {
3934  if ( edge[0+i*2] < edge[0+j*2] )
3935  {
3936  isgn = -1;
3937  }
3938  else if ( edge[0+i*2] == edge[0+j*2] )
3939  {
3940  if ( edge[1+i*2] < edge[1+j*2] )
3941  {
3942  isgn = -1;
3943  }
3944  else if ( edge[1+i*2] == edge[1+j*2] )
3945  {
3946  isgn = 0;
3947  }
3948  else
3949  {
3950  isgn = 1;
3951  }
3952  }
3953  else
3954  {
3955  isgn = 1;
3956  }
3957  }
3958  else if ( indx == 0 )
3959  {
3960  break;
3961  }
3962 
3963  }
3964 //
3965 // Count the unique entries.
3966 //
3967  edge_num_old = edge_num;
3968 
3969  edge_num = 0;
3970 
3971  for ( i = 0; i < edge_num_old; i++ )
3972  {
3973  if ( i == 0 )
3974  {
3975  edge_num = 1;
3976  }
3977  else
3978  {
3979  if ( edge[0+(i-1)*2] != edge[0+i*2] ||
3980  edge[1+(i-1)*2] != edge[1+i*2] )
3981  {
3982  edge_num = edge_num + 1;
3983  }
3984  }
3985 
3986  }
3987 
3988  delete [] edge;
3989 
3990  return edge_num;
3991 }
3992 //****************************************************************************80
3993 
3995 
3996 //****************************************************************************80
3997 //
3998 // Purpose:
3999 //
4000 // EDGE_NULL_DELETE deletes face edges with zero length.
4001 //
4002 // Licensing:
4003 //
4004 // This code is distributed under the GNU LGPL license.
4005 //
4006 // Modified:
4007 //
4008 // 16 July 1999
4009 //
4010 // Author:
4011 //
4012 // John Burkardt
4013 //
4014 {
4015  float distsq;
4016  int face2[ORDER_MAX];
4017  int face_order2;
4018  int iface;
4019  int inode;
4020  int ivert;
4021  int j;
4022  int jnode;
4023  int jvert;
4024  int edge_num;
4025  int edge_num_del;
4026  float vertex_normal2[3][ORDER_MAX];
4027  float x;
4028  float y;
4029  float z;
4030 
4031  edge_num = 0;
4032  edge_num_del = 0;
4033 //
4034 // Consider each face.
4035 //
4036  for ( iface = 0; iface < face_num; iface++ )
4037  {
4038 //
4039 // Consider each pair of consecutive vertices.
4040 //
4041  face_order2 = 0;
4042 
4043  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
4044  {
4045  edge_num = edge_num + 1;
4046 
4047  jvert = ivert + 1;
4048  if ( face_order[iface] <= jvert )
4049  {
4050  jvert = 0;
4051  }
4052 
4053  inode = face[ivert][iface];
4054  jnode = face[jvert][iface];
4055 
4056 
4057  x = cor3[0][inode] - cor3[0][jnode];
4058  y = cor3[1][inode] - cor3[1][jnode];
4059  z = cor3[2][inode] - cor3[2][jnode];
4060 
4061  distsq = x * x + y * y + z * z;
4062 
4063  if ( distsq != 0.0 )
4064  {
4065  face2[face_order2] = face[ivert][iface];
4066  vertex_normal2[0][face_order2] = vertex_normal[0][ivert][iface];
4067  vertex_normal2[1][face_order2] = vertex_normal[1][ivert][iface];
4068  vertex_normal2[2][face_order2] = vertex_normal[2][ivert][iface];
4069  face_order2 = face_order2 + 1;
4070  }
4071  else
4072  {
4073  edge_num_del = edge_num_del + 1;
4074  }
4075 
4076  }
4077 
4078  face_order[iface] = face_order2;
4079  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
4080  {
4081  face[ivert][iface] = face2[ivert];
4082  for ( j = 0; j < 3; j++ )
4083  {
4084  vertex_normal[j][ivert][iface] = vertex_normal2[j][ivert];
4085  }
4086  }
4087 
4088  }
4089 
4090  cout << "\n";
4091  cout << "EDGE_NULL_DELETE:\n";
4092  cout << " There are a total of " << edge_num << " edges.\n";
4093  cout << " Of these, " << edge_num_del << " were of zero length,\n";
4094  cout << " and were deleted.\n";
4095 
4096  return;
4097 }
4098 //****************************************************************************80
4099 
4101 
4102 //****************************************************************************80
4103 //
4104 // Purpose:
4105 //
4106 // FACE_AREA_SET computes the area of the faces.
4107 //
4108 // Discussion:
4109 //
4110 // The area is the sum of the areas of the triangles formed by
4111 // node N with consecutive pairs of nodes.
4112 //
4113 // Licensing:
4114 //
4115 // This code is distributed under the GNU LGPL license.
4116 //
4117 // Modified:
4118 //
4119 // 17 July 1999
4120 //
4121 // Author:
4122 //
4123 // John Burkardt
4124 //
4125 // Reference:
4126 //
4127 // Adrian Bowyer and John Woodwark,
4128 // A Programmer's Geometry,
4129 // Butterworths, 1983.
4130 //
4131 {
4132  float alpha;
4133  float area_max;
4134  float area_min;
4135  float area_tri;
4136  float base;
4137  float dot;
4138  float height;
4139  int i;
4140  int i1;
4141  int i2;
4142  int i3;
4143  int iface;
4144  int face_num_del;
4145  float tol;
4146  float x;
4147  float x1;
4148  float x2;
4149  float x3;
4150  float y;
4151  float y1;
4152  float y2;
4153  float y3;
4154  float z;
4155  float z1;
4156  float z2;
4157  float z3;
4158 
4159  for ( iface = 0; iface < face_num; iface++ )
4160  {
4161  face_area[iface] = 0.0;
4162 
4163  for ( i = 0; i < face_order[iface]-2; i++ )
4164  {
4165  i1 = face[i][iface];
4166  i2 = face[i+1][iface];
4167  i3 = face[i+2][iface];
4168 
4169  x1 = cor3[0][i1];
4170  y1 = cor3[1][i1];
4171  z1 = cor3[2][i1];
4172 
4173  x2 = cor3[0][i2];
4174  y2 = cor3[1][i2];
4175  z2 = cor3[2][i2];
4176 
4177  x3 = cor3[0][i3];
4178  y3 = cor3[1][i3];
4179  z3 = cor3[2][i3];
4180 //
4181 // Find the projection of (P3-P1) onto (P2-P1).
4182 //
4183  dot =
4184  ( x2 - x1 ) * ( x3 - x1 ) +
4185  ( y2 - y1 ) * ( y3 - y1 ) +
4186  ( z2 - z1 ) * ( z3 - z1 );
4187 
4188  base = sqrt (
4189  ( x2 - x1 ) * ( x2 - x1 )
4190  + ( y2 - y1 ) * ( y2 - y1 )
4191  + ( z2 - z1 ) * ( z2 - z1 ) );
4192 //
4193 // The height of the triangle is the length of (P3-P1) after its
4194 // projection onto (P2-P1) has been subtracted.
4195 //
4196  if ( base == 0.0 )
4197  {
4198  height = 0.0;
4199  }
4200  else
4201  {
4202  alpha = dot / ( base * base );
4203 
4204  x = x3 - x1 - alpha * ( x2 - x1 );
4205  y = y3 - y1 - alpha * ( y2 - y1 );
4206  z = z3 - z1 - alpha * ( z2 - z1 );
4207 
4208  height = sqrt ( x * x + y * y + z * z );
4209  }
4210 
4211  area_tri = 0.5 * base * height;
4212  face_area[iface] = face_area[iface] + area_tri;
4213 
4214  }
4215 
4216  }
4217 
4218  area_min = face_area[0];
4219  area_max = face_area[0];
4220 
4221  for ( iface = 1; iface < face_num; iface++ )
4222  {
4223  if ( face_area[iface] < area_min )
4224  {
4225  area_min = face_area[iface];
4226  }
4227  if ( area_max < face_area[iface] )
4228  {
4229  area_max = face_area[iface];
4230  }
4231  }
4232 
4233  cout << "\n";
4234  cout << "FACE_AREA_SET:\n";
4235  cout << " Minimum face area is " << area_min << "\n";
4236  cout << " Maximum face area is " << area_max << "\n";
4237 
4238  tol = area_max / 10000.0;
4239 
4240  if ( area_min < tol )
4241  {
4242  face_num_del = 0;
4243 
4244  for ( iface = 0; iface < face_num; iface++ )
4245  {
4246  if ( face_area[iface] < tol )
4247  {
4248  face_order[iface] = 0;
4249  face_num_del = face_num_del + 1;
4250  }
4251  }
4252 
4253  cout << " Marked " << face_num_del << " tiny faces for deletion.\n";
4254 
4255  }
4256 
4257  return;
4258 }
4259 //****************************************************************************80
4260 
4262 
4263 //****************************************************************************80
4264 //
4265 // Purpose:
4266 //
4267 // FACE_NORMAL_AVE sets face normals as average of face vertex normals.
4268 //
4269 // Licensing:
4270 //
4271 // This code is distributed under the GNU LGPL license.
4272 //
4273 // Modified:
4274 //
4275 // 09 October 1998
4276 //
4277 // Author:
4278 //
4279 // John Burkardt
4280 //
4281 {
4282  int i;
4283  int iface;
4284  int ivert;
4285  int nfix;
4286  float norm;
4287  float x;
4288  float y;
4289  float z;
4290 
4291  if ( face_num <= 0 )
4292  {
4293  return;
4294  }
4295 
4296  nfix = 0;
4297 
4298  for ( iface = 0; iface < face_num; iface++ )
4299  {
4300 //
4301 // Check the norm of the current normal vector.
4302 //
4303  x = face_normal[0][iface];
4304  y = face_normal[1][iface];
4305  z = face_normal[2][iface];
4306  norm = ( float ) sqrt ( x * x + y * y + z * z );
4307 
4308  if ( norm == 0.0 )
4309  {
4310  nfix = nfix + 1;
4311 
4312  for ( i = 0; i < 3; i++ )
4313  {
4314  face_normal[i][iface] = 0.0;
4315  }
4316 
4317  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
4318  {
4319  for ( i = 0; i < 3; i++ )
4320  {
4321  face_normal[i][iface] = face_normal[i][iface] +
4322  vertex_normal[i][ivert][iface];
4323  }
4324  }
4325 
4326  x = face_normal[0][iface];
4327  y = face_normal[1][iface];
4328  z = face_normal[2][iface];
4329  norm = ( float ) sqrt ( x * x + y * y + z * z );
4330 
4331  if ( norm == 0.0 )
4332  {
4333  for ( i = 0; i < 3; i++ )
4334  {
4335  face_normal[i][iface] = ( float ) ( 1.0 / sqrt ( 3.0 ) );
4336  }
4337  }
4338  else
4339  {
4340  for ( i = 0; i < 3; i++ )
4341  {
4342  face_normal[i][iface] = face_normal[i][iface] / norm;
4343  }
4344  }
4345  }
4346  }
4347 
4348  if ( 0 < nfix )
4349  {
4350  cout << "\n";
4351  cout << "FACE_NORMAL_AVE: Recomputed " << nfix << " face normals\n";
4352  cout << " by averaging face vertex normals.\n";
4353  }
4354  return;
4355 }
4356 //****************************************************************************80
4357 
4359 
4360 //****************************************************************************80
4361 //
4362 // Purpose:
4363 //
4364 // FACE_NULL_DELETE deletes faces of order less than 3.
4365 //
4366 // Discussion:
4367 //
4368 // Thanks to Susan M. Fisher, University of North Carolina,
4369 // Department of Computer Science, for pointing out a coding error
4370 // in FACE_NULL_DELETE that was overwriting all the data!
4371 //
4372 // Licensing:
4373 //
4374 // This code is distributed under the GNU LGPL license.
4375 //
4376 // Modified:
4377 //
4378 // 30 November 1999
4379 //
4380 // Author:
4381 //
4382 // John Burkardt
4383 //
4384 {
4385  int iface;
4386  int ivert;
4387  int j;
4388  int face_num2;
4389 //
4390 // FACE_NUM2 is the number of faces we'll keep.
4391 //
4392  face_num2 = 0;
4393 //
4394 // Check every face.
4395 //
4396  for ( iface = 0; iface < face_num; iface++ )
4397  {
4398 //
4399 // Keep it only if it has order 3 or more.
4400 //
4401  if ( 3 <= face_order[iface] )
4402  {
4403 //
4404 // We don't have to slide data down in the array until
4405 // NUMFACE2 and IFACE get out of synch, that is, after
4406 // we've discarded at least one face.
4407 //
4408  if ( face_num2 != iface )
4409  {
4410  face_area[face_num2] = face_area[iface];
4411  face_material[face_num2] = face_material[iface];
4412  face_order[face_num2] = face_order[iface];
4413  for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
4414  {
4415  face[ivert][face_num2] = face[ivert][iface];
4416  vertex_material[ivert][face_num2] = vertex_material[ivert][iface];
4417  for ( j = 0; j < 3; j++ )
4418  {
4419  vertex_normal[j][ivert][face_num2] = vertex_normal[j][ivert][iface];
4420  }
4421  }
4422 
4423  }
4424 //
4425 // Update the count only after we've used the un-incremented value
4426 // as a pointer.
4427 //
4428  face_num2 = face_num2 + 1;
4429 
4430  }
4431 
4432  }
4433 
4434  cout << "\n";
4435  cout << "FACE_NULL_DELETE\n";
4436  cout << " There are a total of " << face_num << " faces.\n";
4437  cout << " Of these, " << face_num2 << " passed the order test.\n";
4438 
4439  face_num = face_num2;
4440 
4441  return;
4442 }
4443 //****************************************************************************80
4444 
4445 int face_print ( int iface )
4446 
4447 //****************************************************************************80
4448 //
4449 // Purpose:
4450 //
4451 // FACE_PRINT prints out information about a face.
4452 //
4453 // Licensing:
4454 //
4455 // This code is distributed under the GNU LGPL license.
4456 //
4457 // Modified:
4458 //
4459 // 31 August 1998
4460 //
4461 // Author:
4462 //
4463 // John Burkardt
4464 //
4465 {
4466  int ivert;
4467  int j;
4468  int k;
4469 
4470  if ( iface < 0 || face_num-1 < iface )
4471  {
4472  cout << "\n";
4473  cout << "FACE_PRINT - Fatal error!\n";
4474  cout << " Face indices must be between 1 and " << face_num << "\n";
4475  cout << " But your requested value was " << iface << "\n";
4476  return 1;
4477  }
4478 
4479  cout << "\n";
4480  cout << "FACE_PRINT\n";
4481  cout << " Information about face " << iface << "\n";
4482  cout << "\n";
4483  cout << " Number of vertices is " << face_order[iface] << "\n";
4484  cout << "\n";
4485  cout << " Vertex list:\n";
4486  cout << " Vertex #, Node #, Material #, X, Y, Z:\n";
4487  cout << "\n";
4488  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
4489  {
4490  j = face[ivert][iface];
4491  k = vertex_material[ivert][iface];
4492  cout
4493  << setw(6) << ivert << " "
4494  << setw(6) << j << " "
4495  << setw(6) << k << " "
4496  << setw(10) << cor3[0][j] << " "
4497  << setw(10) << cor3[1][j] << " "
4498  << setw(10) << cor3[2][j] << "\n";
4499  }
4500 
4501  cout << "\n";
4502  cout << " Face normal vector:\n";
4503  cout << "\n";
4504  cout
4505  << setw(10) << face_normal[0][iface] << " "
4506  << setw(10) << face_normal[1][iface] << " "
4507  << setw(10) << face_normal[2][iface] << "\n";
4508 
4509  cout << "\n";
4510  cout << " Vertex face normals:\n";;
4511  cout << "\n";
4512  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
4513  {
4514  cout
4515  << setw(6) << ivert << " "
4516  << setw(10) << vertex_normal[0][ivert][iface] << " "
4517  << setw(10) << vertex_normal[1][ivert][iface] << " "
4518  << setw(10) << vertex_normal[2][ivert][iface] << "\n";
4519  }
4520 
4521  return 0;
4522 
4523 }
4524 //****************************************************************************80
4525 
4527 
4528 //****************************************************************************80
4529 //
4530 // Purpose:
4531 //
4532 // FACE_REVERSE_ORDER reverses the order of the nodes in each face.
4533 //
4534 // Discussion:
4535 //
4536 // Reversing the order of the nodes requires that the normal vectors
4537 // be reversed as well, so this routine will automatically reverse
4538 // the normals associated with nodes, vertices and faces.
4539 //
4540 // Licensing:
4541 //
4542 // This code is distributed under the GNU LGPL license.
4543 //
4544 // Modified:
4545 //
4546 // 28 June 1999
4547 //
4548 // Author:
4549 //
4550 // John Burkardt
4551 //
4552 {
4553  int i;
4554  int iface;
4555  int itemp;
4556  int ivert;
4557  int j;
4558  int m;
4559  float temp;
4560 
4561  for ( iface = 0; iface < face_num; iface++ )
4562  {
4563  m = face_order[iface];
4564 
4565  for ( ivert = 0; ivert < ( m / 2 ); ivert++ )
4566  {
4567  itemp = face[ivert][iface];
4568  face[ivert][iface] = face[m-1-ivert][iface];
4569  face[m-1-ivert][iface] = itemp;
4570 
4571  itemp = vertex_material[ivert][iface];
4572  vertex_material[ivert][iface] = vertex_material[m-1-ivert][iface];
4573  vertex_material[m-1-ivert][iface] = itemp;
4574 
4575  for ( j = 0; j < 3; j++ )
4576  {
4577  temp = vertex_normal[j][ivert][iface];
4578  vertex_normal[j][ivert][iface] = vertex_normal[j][m-1-ivert][iface];
4579  vertex_normal[j][m-1-ivert][iface] = temp;
4580  }
4581 
4582  for ( j = 0; j < 2; j++ )
4583  {
4584  temp = vertex_tex_uv[j][ivert][iface];
4585  vertex_tex_uv[j][ivert][iface] = vertex_tex_uv[j][m-1-ivert][iface];
4586  vertex_tex_uv[j][m-1-ivert][iface] = temp;
4587  }
4588 
4589  }
4590 
4591  }
4592 
4593  for ( i = 0; i < cor3_num; i++ )
4594  {
4595  for ( j = 0; j < 3; j++ )
4596  {
4597  cor3_normal[j][i] = - cor3_normal[j][i];
4598  }
4599  }
4600 
4601  for ( i = 0; i < face_num; i++ )
4602  {
4603  for ( j = 0; j < 3; j++ )
4604  {
4605  face_normal[j][i] = - face_normal[j][i];
4606  }
4607  }
4608 
4609  cout << "\n";
4610  cout << "FACE_REVERSE_ORDER\n";
4611  cout << " Each list of nodes defining a face\n";
4612  cout << " has been reversed; related information,\n";
4613  cout << " including normal vectors, was also updated.\n";
4614 
4615  return;
4616 }
4617 //****************************************************************************80
4618 
4620 
4621 //****************************************************************************80
4622 //
4623 // Purpose:
4624 //
4625 // FACE_SUBSET selects a subset of the current faces as the new object.
4626 //
4627 // Discussion:
4628 //
4629 // The original graphic object is overwritten by the new one.
4630 //
4631 // Licensing:
4632 //
4633 // This code is distributed under the GNU LGPL license.
4634 //
4635 // Modified:
4636 //
4637 // 12 October 1998
4638 //
4639 // Author:
4640 //
4641 // John Burkardt
4642 //
4643 //
4644 {
4645  int i;
4646  int iface;
4647  int iface1;
4648  int iface2;
4649  int inc;
4650  int ivert;
4651  int j;
4652  int k;
4653  int cor3_num2;
4654 
4655  line_num = 0;
4656 //
4657 // Get the first and last faces to save, IFACE1 and IFACE2.
4658 //
4659  cout << "\n";
4660  cout << "Enter lowest face number to save between 0 and "
4661  << face_num - 1 << ": ";
4662  scanf ( "%d", &iface1 );
4663  if ( iface1 < 0 || face_num - 1 < iface1 )
4664  {
4665  cout << "Illegal choice!\n";
4666  return 1;
4667  }
4668 
4669  cout << "\n";
4670  cout << "Enter highest face number to save between "
4671  << iface1 << " and " << face_num - 1 << ": ";
4672  scanf ( "%d", &iface2 );
4673  if ( iface2 < iface1 || face_num - 1 < iface2 )
4674  {
4675  cout << "Illegal choice!\n";
4676  return 1;
4677  }
4678 
4679  inc = iface1;
4680 //
4681 // "Slide" the data for the saved faces down the face arrays.
4682 //
4683  for ( iface = 0; iface < iface2 + 1 - iface1; iface++ )
4684  {
4685  face_order[iface] = face_order[iface+inc];
4686  for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
4687  {
4688  face[ivert][iface] = face[ivert][iface+inc];
4689  vertex_material[ivert][iface] = vertex_material[ivert][iface+inc];
4690  for ( i = 0; i < 3; i++ )
4691  {
4692  vertex_normal[i][ivert][iface] =
4693  vertex_normal[i][ivert][iface+inc];
4694  vertex_rgb[i][ivert][iface] = vertex_rgb[i][ivert][iface+inc];
4695  }
4696  }
4697  for ( i = 0; i < 3; i++ )
4698  {
4699  face_normal[i][iface] = face_normal[i][iface+inc];
4700  }
4701  }
4702 //
4703 // Now reset the number of faces.
4704 //
4705  face_num = iface2 + 1 - iface1;
4706 //
4707 // Now, for each point I, set LIST(I) = J if point I is the J-th
4708 // point we are going to save, and 0 otherwise. Then J will be
4709 // the new label of point I.
4710 //
4711  for ( i = 0; i < cor3_num; i++ )
4712  {
4713  list[i] = -1;
4714  }
4715 
4716  cor3_num2 = 0;
4717 
4718  for ( iface = 0; iface < face_num; iface++ )
4719  {
4720  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
4721  {
4722  j = face[ivert][iface];
4723  if ( list[j] == -1 )
4724  {
4725  cor3_num2 = cor3_num2 + 1;
4726  list[j] = cor3_num2;
4727  }
4728  }
4729  }
4730 //
4731 // Now make the nonzero list entries rise in order, so that
4732 // we can compress the COR3 data in a minute.
4733 //
4734  cor3_num2 = 0;
4735 
4736  for ( i = 0; i < cor3_num; i++ )
4737  {
4738  if ( list[i] != -1 )
4739  {
4740  list[i] = cor3_num2;
4741  cor3_num2 = cor3_num2 + 1;
4742  }
4743  }
4744 //
4745 // Relabel the FACE array with the new node indices.
4746 //
4747  for ( iface = 0; iface < face_num; iface++ )
4748  {
4749  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
4750  {
4751  j = face[ivert][iface];
4752  face[ivert][iface] = list[j];
4753  }
4754  }
4755 //
4756 // Rebuild the COR3 array by sliding data down.
4757 //
4758  for ( i = 0; i < cor3_num; i++ )
4759  {
4760  k = list[i];
4761  if ( k != -1 )
4762  {
4763  for ( j = 0; j < 3; j++ )
4764  {
4765  cor3[j][k] = cor3[j][i];
4766  }
4767  }
4768  }
4769 
4770  cor3_num = cor3_num2;
4771 
4772  return 0;
4773 }
4774 //****************************************************************************80
4775 
4777 
4778 //****************************************************************************80
4779 //
4780 // Purpose:
4781 //
4782 // FACE_TO_LINE converts face information to line information.
4783 //
4784 // Discussion:
4785 //
4786 // In some cases, the graphic information represented by polygonal faces
4787 // must be converted to a representation based solely on line segments.
4788 // This is particularly true if a VLA file is being written.
4789 //
4790 // Licensing:
4791 //
4792 // This code is distributed under the GNU LGPL license.
4793 //
4794 // Modified:
4795 //
4796 // 26 May 1999
4797 //
4798 // Author:
4799 //
4800 // John Burkardt
4801 //
4802 {
4803  int icor3;
4804  int iface;
4805  int ivert;
4806  int jcor3;
4807  int jvert;
4808 //
4809 // Case 0:
4810 // No line pruning.
4811 //
4812  if ( line_prune == 0 )
4813  {
4814  for ( iface = 0; iface < face_num; iface++ )
4815  {
4816  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
4817  {
4818  icor3 = face[ivert][iface];
4819 
4820  line_num = line_num + 1;
4821  if ( line_num <= LINES_MAX )
4822  {
4823  line_dex[line_num] = icor3;
4824  line_material[line_num] = vertex_material[ivert][iface];
4825  }
4826  }
4827 
4828  ivert = 0;
4829  icor3 = face[ivert][iface];
4830 
4831  line_num = line_num + 1;
4832  if ( line_num <= LINES_MAX )
4833  {
4834  line_dex[line_num] = icor3;
4835  line_material[line_num] = vertex_material[ivert][iface];
4836  }
4837 
4838  line_num = line_num + 1;
4839  if ( line_num <= LINES_MAX )
4840  {
4841  line_dex[line_num] = -1;
4842  line_material[line_num] = -1;
4843  }
4844  }
4845 
4846  }
4847 //
4848 // Case 2:
4849 // Simple-minded line pruning.
4850 // Only draw line (I,J) if I < J.
4851 //
4852  else
4853  {
4854  for ( iface = 0; iface < face_num; iface++ )
4855  {
4856  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
4857  {
4858  icor3 = face[ivert][iface];
4859 
4860  if ( ivert + 1 < face_order[iface] )
4861  {
4862  jvert = ivert + 1;
4863  }
4864  else
4865  {
4866  jvert = 0;
4867  }
4868 
4869  jcor3 = face[jvert][iface];
4870 
4871  if ( icor3 < jcor3 )
4872  {
4873  if ( line_num + 3 < LINES_MAX )
4874  {
4875  line_num = line_num + 1;
4876  line_dex[line_num] = icor3;
4877  line_material[line_num] = vertex_material[ivert][iface];
4878 
4879  line_num = line_num + 1;
4880  line_dex[line_num] = jcor3;
4881  line_material[line_num] = vertex_material[jvert][iface];
4882 
4883  line_num = line_num + 1;
4884  line_dex[line_num] = -1;
4885  line_material[line_num] = -1;
4886 
4887  }
4888  }
4889  }
4890  }
4891 
4892  }
4893 
4894  return;
4895 }
4896 //****************************************************************************80
4897 
4899 
4900 //****************************************************************************80
4901 //
4902 // Purpose:
4903 //
4904 // FACE_TO_VERTEX_MAT extends face material definitions to vertices.
4905 //
4906 // Discussion:
4907 //
4908 // Assuming material indices are defined for all the faces, this
4909 // routine assigns to each vertex of a face the material of that face.
4910 //
4911 // Licensing:
4912 //
4913 // This code is distributed under the GNU LGPL license.
4914 //
4915 // Modified:
4916 //
4917 // 22 May 1999
4918 //
4919 // Author:
4920 //
4921 // John Burkardt
4922 //
4923 {
4924  int iface;
4925  int ivert;
4926 
4927  for ( iface = 0; iface < face_num; iface++ )
4928  {
4929  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
4930  {
4931  vertex_material[ivert][iface] = face_material[iface];
4932  }
4933  }
4934 
4935  return;
4936 }
4937 //****************************************************************************80
4938 
4939 char *file_ext ( char *file_name )
4940 
4941 //****************************************************************************80
4942 //
4943 // Purpose:
4944 //
4945 // FILE_EXT picks out the extension in a file name.
4946 //
4947 // Licensing:
4948 //
4949 // This code is distributed under the GNU LGPL license.
4950 //
4951 // Modified:
4952 //
4953 // 21 July 1998
4954 //
4955 // Author:
4956 //
4957 // John Burkardt
4958 //
4959 {
4960  int i;
4961 
4962  i = ch_index_last ( file_name, '.' );
4963 
4964  if ( i == -1 )
4965  {
4966  return NULL;
4967  }
4968  else
4969  {
4970  return file_name + i + 1;
4971  }
4972 }
4973 //****************************************************************************80
4974 
4975 float float_read ( FILE *filein )
4976 
4977 //****************************************************************************80
4978 //
4979 // Purpose:
4980 //
4981 // FLOAT_READ reads 1 float from a binary file.
4982 //
4983 // Licensing:
4984 //
4985 // This code is distributed under the GNU LGPL license.
4986 //
4987 // Modified:
4988 //
4989 // 24 May 1999
4990 //
4991 // Author:
4992 //
4993 // John Burkardt
4994 //
4995 {
4996  float rval;
4997  float temp;
4998 
4999  fread ( &temp, sizeof ( float ), 1, filein );
5000 
5001  if ( byte_swap )
5002  {
5003  rval = float_reverse_bytes ( temp );
5004  }
5005  else
5006  {
5007  rval = temp;
5008  }
5009 
5010  return rval;
5011 }
5012 //****************************************************************************80
5013 
5014 float float_reverse_bytes ( float x )
5015 
5016 //****************************************************************************80
5017 //
5018 // Purpose:
5019 //
5020 // FLOAT_REVERSE_BYTES reverses the four bytes in a float.
5021 //
5022 // Licensing:
5023 //
5024 // This code is distributed under the GNU LGPL license.
5025 //
5026 // Modified:
5027 //
5028 // 24 May 1999
5029 //
5030 // Author:
5031 //
5032 // John Burkardt
5033 //
5034 // Parameters:
5035 //
5036 // X, a float whose bytes are to be reversed.
5037 //
5038 // FLOAT_REVERSE_BYTES, a float with bytes in reverse order from those in X.
5039 //
5040 {
5041  char c;
5042  union {
5043  float yfloat;
5044  char ychar[4];
5045  } y;
5046 
5047  y.yfloat = x;
5048 
5049  c = y.ychar[0];
5050  y.ychar[0] = y.ychar[3];
5051  y.ychar[3] = c;
5052 
5053  c = y.ychar[1];
5054  y.ychar[1] = y.ychar[2];
5055  y.ychar[2] = c;
5056 
5057  return ( y.yfloat );
5058 }
5059 //****************************************************************************80
5060 
5061 int float_write ( FILE *fileout, float float_val )
5062 
5063 //****************************************************************************80
5064 //
5065 // Purpose:
5066 //
5067 // FLOAT_WRITE writes 1 float to a binary file.
5068 //
5069 // Licensing:
5070 //
5071 // This code is distributed under the GNU LGPL license.
5072 //
5073 // Modified:
5074 //
5075 // 23 September 1998
5076 //
5077 // Author:
5078 //
5079 // John Burkardt
5080 //
5081 {
5082  int nbyte = sizeof ( float );
5083  float temp;
5084 
5085  if ( byte_swap )
5086  {
5087  temp = float_reverse_bytes ( float_val );
5088  }
5089  else
5090  {
5091  temp = float_val;
5092  }
5093 
5094  fwrite ( &temp, nbyte, 1, fileout );
5095 
5096  return nbyte;
5097 }
5098 //****************************************************************************80
5099 
5101 
5102 //****************************************************************************80
5103 //
5104 // Purpose:
5105 //
5106 // GMOD_ARCH_CHECK inquires into some features of the computer architecture.
5107 //
5108 // Licensing:
5109 //
5110 // This code is distributed under the GNU LGPL license.
5111 //
5112 // Modified:
5113 //
5114 // 02 September 2003
5115 //
5116 // Author:
5117 //
5118 // Zik Saleeba
5119 //
5120 // Parameters:
5121 //
5122 // Output, bool GMOD_ARCH_CHECK is TRUE if the size of a float is four bytes
5123 // and we use IEEE floats (either big-endian or little-endian).
5124 //
5125 {
5126  static unsigned char one[4];
5127  int temp;
5128 
5129  temp = sizeof ( float );
5130  if ( temp != 4 )
5131  {
5132  return false;
5133  }
5134 
5135  *(float *)one = 1.0;
5136 //
5137 // Little endian IEEE floats.
5138 //
5139  if ( one[0] == 0 && one[1] == 0 && one[2] == 128 && one[3] == 63 )
5140  {
5141  return true;
5142  }
5143 //
5144 // Big endian IEEE floats.
5145 //
5146  if ( one[0] == 63 && one[1] == 128 && one[2] == 0 && one[3] == 0 )
5147  {
5148  return true;
5149  }
5150 
5151  return false;
5152 }
5153 //****************************************************************************80
5154 
5155 int gmod_read ( FILE *filein )
5156 
5157 //****************************************************************************80
5158 //
5159 // Purpose:
5160 //
5161 // GMOD_READ reads a golgotha GMOD file.
5162 //
5163 // Licensing:
5164 //
5165 // This code is distributed under the GNU LGPL license.
5166 //
5167 // Modified:
5168 //
5169 // 19 May 1999
5170 //
5171 // Author:
5172 //
5173 // Zik Saleeba
5174 //
5175 
5176 //
5177 //golgotha GMOD file format:
5178 //
5179 //
5180 // FILE HEADER
5181 //
5182 //w32 magic number f9 fa 63 1e
5183 //w32 number of sections
5184 //[ number of sections
5185 // w32 section id
5186 // w32 section offset
5187 //]
5188 //
5189 //
5190 // TEXTURE NAME SECTION - section id = 0x13 (19)
5191 //
5192 //w16 number of faces
5193 //[ number of faces
5194 // w16 texture name length
5195 // [ texture name length
5196 // w8 texture name character
5197 // ]
5198 //]
5199 //
5200 //
5201 //
5202 // MODEL QUADS SECTION - section id = 0x12 (18)
5203 //
5204 //w16 number of faces
5205 //[ number of faces
5206 // [ four vertices
5207 // w16 vertex index
5208 // float xpos (0.0-1.0)
5209 // float ypos (0.0-1.0)
5210 // ]
5211 // float scale
5212 // w16 flags
5213 // float xnormal (normal should be normalised)
5214 // float ynormal
5215 // float znormal
5216 //]
5217 //
5218 //
5219 // VERTEX ARRAY SECTION - section id = 0x14 (20)
5220 //
5221 //w16 number of vertices
5222 //w16 number of animations
5223 //w16 length of animation name
5224 //[ length of animation name
5225 // w8 animation name character
5226 //]
5227 //w16 number of frames in animation
5228 //[ number of frames in animation
5229 // [ number of vertices
5230 // float xpos
5231 // float ypos
5232 // float zpos
5233 // float xnormal
5234 // float ynormal
5235 // float znormal
5236 // ]
5237 //]
5238 //
5239 {
5240  unsigned char MagicNumber[4];
5241  unsigned long int NumSections;
5242  int SectionCount;
5243  unsigned long int SectionID[GMOD_MAX_SECTIONS];
5244  unsigned long int SectionOffset[GMOD_MAX_SECTIONS];
5245 
5246  unsigned short NumAnimations;
5247  unsigned short NumFrames;
5248  unsigned short FaceCount;
5249  unsigned short TextureCount;
5250  int VertexCount;
5251 
5252  float Scale;
5253  unsigned short Flags;
5254  unsigned short TextureNameLen;
5255  unsigned short AnimationNameLen;
5256  int Order;
5257  int MaxCor = 0;
5258 //
5259 // Check if we can handle this architecture
5260 //
5261  if ( !gmod_arch_check ( ) )
5262  {
5263  cout << "\n";
5264  cout << "GMOD_READ - This architecture not supported.\n";
5265  return 1;
5266  }
5267 
5268 //
5269 // Read the file header
5270 //
5271 //
5272 // Read the magic number
5273 //
5274  fread(MagicNumber, 1, 4, filein);
5275  if ( MagicNumber[0] != 0xf9 ||
5276  MagicNumber[1] != 0xfa ||
5277  MagicNumber[2] != 0x63 ||
5278  MagicNumber[3] != 0x1e)
5279  {
5280  cout << "GMOD_READ - Bad magic number on GMOD file.\n";
5281  return 1;
5282  }
5283 
5284  NumSections = gmod_read_w32(filein);
5285  if ( GMOD_MAX_SECTIONS <= NumSections )
5286  {
5287  cout << "\n";
5288  cout << "GMOD_READ - Fatal error!\n";
5289  cout << " Too many sections (" << NumSections << ") in GMOD file.\n";
5290  cout << " Please increase static limit GMOD_MAX_SECTIONS\n";
5291  return 1;
5292  }
5293 
5294 //
5295 // Read the sections.
5296 //
5297 
5298  for ( SectionCount = 0; SectionCount < ( int ) NumSections; SectionCount++ )
5299  {
5300  SectionID[SectionCount] = gmod_read_w32(filein);
5301  SectionOffset[SectionCount] = gmod_read_w32(filein);
5302  }
5303 //
5304 // Read each successive section.
5305 //
5306  for ( SectionCount = 0; SectionCount < ( int ) NumSections; SectionCount++ )
5307  {
5308 //
5309 // Go to the start of the section.
5310 //
5311  fseek ( filein, ( long int ) SectionOffset[SectionCount], SEEK_SET );
5312 //
5313 // What type of section is it?
5314 //
5315  switch (SectionID[SectionCount])
5316  {
5317 //
5318 // Model section.
5319 //
5321 //
5322 // Get the number of faces.
5323 //
5324  face_num = gmod_read_w16 ( filein );
5325 
5326  if ( FACE_MAX < face_num )
5327  {
5328  cout << "\n";
5329  cout << "GMOD_READ - Fatal error!\n";
5330  cout << " Too many faces (" << face_num << ") in GMOD file.\n";
5331  cout << " Increase the size of FACE_MAX.\n";
5332  return 1;
5333  }
5334 //
5335 // Get the information on each face.
5336 //
5337  for ( FaceCount = 0; FaceCount < ( unsigned short ) face_num; FaceCount++ )
5338  {
5339  Order = 0;
5340  for ( VertexCount = 0; VertexCount < 4; VertexCount++ )
5341  {
5342 //
5343 // Read the vertex index
5344 //
5345  face[VertexCount][FaceCount] = gmod_read_w16(filein);
5346 
5347  if (face[VertexCount][FaceCount] != GMOD_UNUSED_VERTEX)
5348  {
5349  Order = VertexCount+1;
5350  if ( MaxCor < face[VertexCount][FaceCount] )
5351  {
5352  MaxCor = face[VertexCount][FaceCount];
5353  }
5354  }
5355 //
5356 // Read the texture position.
5357 //
5358  vertex_tex_uv[0][VertexCount][FaceCount] = gmod_read_float(filein);
5359  vertex_tex_uv[1][VertexCount][FaceCount] = gmod_read_float(filein);
5360  }
5361 //
5362 // Scale and flags.
5363 //
5364  fread(&Scale, sizeof(Scale), 1, filein);
5365  Flags = gmod_read_w16(filein);
5366 
5367  if ( debug )
5368  {
5369  cout << "Flags = " << Flags << "\n";
5370  }
5371 //
5372 // Normal vector.
5373 //
5374  face_normal[0][FaceCount] = gmod_read_float(filein);
5375  face_normal[1][FaceCount] = gmod_read_float(filein);
5376  face_normal[2][FaceCount] = gmod_read_float(filein);
5377 //
5378 // The order is the number of used vertices.
5379 //
5380  face_order[FaceCount] = Order;
5381  }
5382  break;
5383 //
5384 // Texture name section.
5385 //
5387 //
5388 // Get the number of textures.
5389 //
5390  texture_num = gmod_read_w16(filein);
5391  if ( TEXTURE_MAX < texture_num )
5392  {
5393  cout << "GMOD_READ - Fatal error!\n";
5394  cout << " Too many texture maps (" << texture_num << ").\n";
5395  cout << " Increase static limit TEXTURE_MAX.\n";
5396  return 1;
5397  }
5399 
5400  for (TextureCount = 0; TextureCount < ( unsigned short ) texture_num;
5401  TextureCount++)
5402  {
5403 //
5404 // read the texture name
5405 //
5406  TextureNameLen = gmod_read_w16(filein);
5407  fread ( texture_name[TextureCount], sizeof(char), TextureNameLen, filein);
5408  texture_name[TextureCount][TextureNameLen] = '\0';
5409  }
5410  break;
5411 //
5412 // Vertex section.
5413 //
5415 //
5416 // Get the number of vertices.
5417 //
5418  cor3_num = gmod_read_w16(filein);
5419  if ( COR3_MAX < cor3_num )
5420  {
5421  cout << "GMOD_READ - Fatal error!\n";
5422  cout << " Too many vertices (" << cor3_num << ").\n";
5423  cout << " Increase static limit COR3_MAX.\n";
5424  return 1;
5425  }
5426 //
5427 // Get the number of animations.
5428 //
5429  NumAnimations = gmod_read_w16(filein);
5430 
5431  if ( 1 < NumAnimations )
5432  {
5433  cout << "\n";
5434  cout << "GMOD_READ - Fatal error!\n";
5435  cout << " GMOD files can only handle one animation.\n";
5436  cout << " This file contains " << NumAnimations << ".\n";
5437  return 1;
5438  }
5439 //
5440 // Read the animation name.
5441 //
5442  AnimationNameLen = gmod_read_w16(filein);
5443  fread ( anim_name, sizeof(char), AnimationNameLen, filein);
5444  anim_name[AnimationNameLen] = '\0';
5445 //
5446 // Get the number of frames of animation.
5447 //
5448  NumFrames = gmod_read_w16(filein);
5449  if ( 1 < NumFrames )
5450  {
5451  cout << "\n";
5452  cout << "GMOD_READ - Warning!\n";
5453  cout << " Too many frames of animation (" << NumFrames << ").\n";
5454  cout << " Will only use 1.\n";
5455  }
5456 //
5457 // Go through all the vertices, reading each one
5458 //
5459  for (VertexCount = 0; VertexCount < cor3_num; VertexCount++)
5460  {
5461 //
5462 // Read the vertex.
5463 //
5464  cor3[0][VertexCount] = gmod_read_float(filein);
5465  cor3[1][VertexCount] = gmod_read_float(filein);
5466  cor3[2][VertexCount] = gmod_read_float(filein);
5467 //
5468 // Read the normal.
5469 //
5470  cor3_normal[0][VertexCount] = gmod_read_float(filein);
5471  cor3_normal[1][VertexCount] = gmod_read_float(filein);
5472  cor3_normal[2][VertexCount] = gmod_read_float(filein);
5473  }
5474  break;
5475 
5476  default:
5477  continue;
5478  }
5479  }
5480 
5481 //
5482 // Set some other stray info.
5483 //
5484  line_num = 0;
5485 
5486 //
5487 // Check for sanity.
5488 //
5489  if ( cor3_num <= MaxCor )
5490  {
5491  cout << "\n";
5492  cout << "GMOD_READ - Fatal error!\n";
5493  cout << " Maximum coordinate index (" << MaxCor << ")\n";
5494  cout << " exceeds number of coordinates (" << cor3_num << ").\n";
5495  return 1;
5496  }
5497 
5498  return 0;
5499 }
5500 //****************************************************************************80
5501 
5502 float gmod_read_float ( FILE *filein )
5503 
5504 //****************************************************************************80
5505 //
5506 // Purpose:
5507 //
5508 // GMOD_READ_FLOAT reads a float from a Golgotha GMOD file.
5509 //
5510 // Licensing:
5511 //
5512 // This code is distributed under the GNU LGPL license.
5513 //
5514 // Modified:
5515 //
5516 // 19 May 1999
5517 //
5518 // Author:
5519 //
5520 // Zik Saleeba
5521 //
5522 {
5523  int endian = 1;
5524  unsigned char *out_pos;
5525  int i;
5526  float Val;
5527 //
5528 // We're little-endian, which is native for GMOD floats.
5529 //
5530  if (*(char *)&endian == 1)
5531  {
5532  fread(&Val, sizeof(Val), 1, filein);
5533  }
5534 //
5535 // We're big-endian. Flip them.
5536 //
5537  else
5538  {
5539  out_pos = (unsigned char *)&Val;
5540  for ( i = sizeof(Val)-1; 0 <= i ; i-- )
5541  {
5542  *(out_pos+i) = fgetc(filein);
5543  }
5544  }
5545 
5546  return Val;
5547 }
5548 //****************************************************************************80
5549 
5550 unsigned short gmod_read_w16 ( FILE *filein )
5551 
5552 //****************************************************************************80
5553 //
5554 // Purpose:
5555 //
5556 // GMOD_READ_W16 reads a 16 bit word from a Golgotha GMOD file.
5557 //
5558 // Licensing:
5559 //
5560 // This code is distributed under the GNU LGPL license.
5561 //
5562 // Modified:
5563 //
5564 // 19 May 1999
5565 //
5566 // Author:
5567 //
5568 // Zik Saleeba
5569 //
5570 {
5571  unsigned char Byte1;
5572  unsigned char Byte2;
5573 
5574  Byte1 = fgetc ( filein );
5575  Byte2 = fgetc ( filein );
5576 
5577  return Byte1 | (((unsigned short)Byte2) << 8);
5578 }
5579 //****************************************************************************80
5580 
5581 unsigned long gmod_read_w32 ( FILE *filein )
5582 
5583 //****************************************************************************80
5584 //
5585 // Purpose:
5586 //
5587 // GMOD_READ_W32 reads a 32 bit word from a Golgotha GMOD file.
5588 //
5589 // Licensing:
5590 //
5591 // This code is distributed under the GNU LGPL license.
5592 //
5593 // Modified:
5594 //
5595 // 19 May 1999
5596 //
5597 // Author:
5598 //
5599 // Zik Saleeba
5600 //
5601 {
5602  unsigned char Byte1, Byte2, Byte3, Byte4;
5603 
5604  Byte1 = fgetc(filein);
5605  Byte2 = fgetc(filein);
5606  Byte3 = fgetc(filein);
5607  Byte4 = fgetc(filein);
5608 
5609  return Byte1 |
5610  (((unsigned long)Byte2) << 8) |
5611  (((unsigned long)Byte3) << 16) |
5612  (((unsigned long)Byte4) << 24);
5613 }
5614 //****************************************************************************80
5615 
5616 int gmod_write ( FILE *fileout )
5617 
5618 //****************************************************************************80
5619 //
5620 // Purpose:
5621 //
5622 // GMOD_WRITE writes a Golgotha GMOD file.
5623 //
5624 // Licensing:
5625 //
5626 // This code is distributed under the GNU LGPL license.
5627 //
5628 // Modified:
5629 //
5630 // 19 May 1999
5631 //
5632 // Author:
5633 //
5634 // Zik Saleeba
5635 //
5636 {
5637  static unsigned char MagicNumber[4] = { 0xf9, 0xfa, 0x63, 0x1e };
5638  unsigned long NumSections;
5639  unsigned long SectionHeaderPos;
5640  unsigned long TextureNameSectionPos;
5641  unsigned long ModelSectionPos;
5642  unsigned long VertexSectionPos;
5643 
5644  int VertexCount;
5645  int FaceCount;
5646  int TextureCount;
5647  unsigned long SectionCount;
5648  float Scale;
5649  float Min[3];
5650  float Max[3];
5651  int CorNumber;
5652  int DimensionCount;
5653  float MaxWidth;
5654 //
5655 // Check if we can handle this architecture.
5656 //
5657  if ( !gmod_arch_check ( ) )
5658  {
5659  cout << "\n";
5660  cout << "GMOD_WRITE - Fatal error!\n";
5661  cout << " This architecture not supported.\n";
5662  return 1;
5663  }
5664 //
5665 // Write the file header.
5666 //
5667 
5668 //
5669 // Write the magic number.
5670 //
5671  fwrite ( MagicNumber, sizeof(char), 4, fileout );
5672 //
5673 // Write the number of sections.
5674 //
5675  NumSections = 3;
5676  gmod_write_w32 ( NumSections, fileout );
5677 //
5678 // Write a dummy section header which we'll overwrite later.
5679 //
5680  SectionHeaderPos = ftell ( fileout );
5681  for (SectionCount = 0; SectionCount < NumSections; SectionCount++)
5682  {
5683  gmod_write_w32 ( 0, fileout );
5684  gmod_write_w32 ( 0, fileout );
5685  }
5686 //
5687 // Texture name section.
5688 //
5689 
5690 //
5691 // Take note of where we are in the file.
5692 //
5693  TextureNameSectionPos = ftell ( fileout );
5694 //
5695 // Write the number of textures.
5696 //
5697  gmod_write_w16 ( ( unsigned short ) face_num, fileout );
5698 //
5699 // Write the texture names.
5700 //
5701  for ( TextureCount = 0; TextureCount < face_num; TextureCount++ )
5702  {
5703  gmod_write_w16 ( ( unsigned short ) strlen ( texture_name[TextureCount] ),
5704  fileout );
5705 
5706  fwrite ( texture_name[TextureCount], strlen ( texture_name[TextureCount] ),
5707  1, fileout );
5708  }
5709 //
5710 // Model section.
5711 //
5712 
5713 //
5714 // Take note of where we are in the file.
5715 //
5716 
5717  ModelSectionPos = ftell(fileout);
5718 
5719 //
5720 // Write the number of faces.
5721 //
5722  gmod_write_w16 ( ( unsigned short ) face_num, fileout );
5723 //
5724 // Write the information on each face.
5725 //
5726  for ( FaceCount = 0; FaceCount < face_num; FaceCount++ )
5727  {
5728 
5729  for (VertexCount = 0; VertexCount < ((face_order[FaceCount] < 4) ? face_order[FaceCount] : 4); VertexCount++)
5730  {
5731 //
5732 // Write the vertex index.
5733 //
5734  gmod_write_w16 ( ( unsigned short ) face[VertexCount][FaceCount], fileout );
5735 //
5736 // Write the texture position.
5737 //
5738  gmod_write_float ( vertex_tex_uv[0][VertexCount][FaceCount], fileout );
5739  gmod_write_float ( vertex_tex_uv[1][VertexCount][FaceCount], fileout );
5740  }
5741 
5742 //
5743 // Write any extra vertices which are unused.
5744 //
5745  for ( ; VertexCount < 4; VertexCount++ )
5746  {
5747 //
5748 // Write the vertex index.
5749 //
5750  gmod_write_w16 ( GMOD_UNUSED_VERTEX, fileout );
5751 //
5752 // Write the texture position.
5753 //
5754  gmod_write_float ( vertex_tex_uv[0][VertexCount][FaceCount], fileout );
5755 
5756  gmod_write_float ( vertex_tex_uv[1][VertexCount][FaceCount], fileout );
5757  }
5758 //
5759 // Scale and flags.
5760 //
5761 
5762 //
5763 // Find the bounding box.
5764 //
5765  for ( DimensionCount = 0; DimensionCount < 3; DimensionCount++ )
5766  {
5767  CorNumber = face[0][FaceCount];
5768  Min[DimensionCount] = cor3[DimensionCount][CorNumber];
5769  Max[DimensionCount] = cor3[DimensionCount][CorNumber];
5770 
5771  for (VertexCount = 1; VertexCount < ((face_order[FaceCount] < 4) ? face_order[FaceCount] : 4); VertexCount++)
5772  {
5773 
5774  CorNumber = face[VertexCount][FaceCount];
5775 
5776  if ( cor3[DimensionCount][CorNumber] < Min[DimensionCount] )
5777  Min[DimensionCount] = cor3[DimensionCount][CorNumber];
5778 
5779  if (Max[DimensionCount] < cor3[DimensionCount][CorNumber])
5780  Max[DimensionCount] = cor3[DimensionCount][CorNumber];
5781  }
5782  }
5783 //
5784 // The scale is the "width" of the face for mipmapping -
5785 // I just take the maximum bounding box dimension.
5786 //
5787  MaxWidth = Max[0] - Min[0];
5788  for ( DimensionCount = 1; DimensionCount < 3; DimensionCount++ )
5789  {
5790 
5791  if ( MaxWidth < Max[DimensionCount] - Min[DimensionCount] )
5792  MaxWidth = Max[DimensionCount] - Min[DimensionCount];
5793  }
5794  Scale = MaxWidth;
5795  fwrite ( &Scale, sizeof(Scale), 1, fileout );
5796 //
5797 // Flags are just nothing.
5798 //
5799  gmod_write_w16 ( 0, fileout );
5800 //
5801 // Normal vector.
5802 //
5803  gmod_write_float ( face_normal[0][FaceCount], fileout );
5804  gmod_write_float ( face_normal[1][FaceCount], fileout );
5805  gmod_write_float ( face_normal[2][FaceCount], fileout );
5806  }
5807 //
5808 // Vertex section.
5809 //
5810 
5811 //
5812 // Take note of where we are in the file.
5813 //
5814  VertexSectionPos = ftell ( fileout );
5815 //
5816 // Write the number of vertices.
5817 //
5818  gmod_write_w16 ( ( unsigned short ) cor3_num, fileout );
5819 //
5820 // Write the number of animations.
5821 //
5822  gmod_write_w16 ( 1, fileout );
5823 //
5824 // Write the animation name.
5825 //
5826  gmod_write_w16 ( 0, fileout );
5827 //
5828 // Write the number of frames of animation.
5829 //
5830  gmod_write_w16 ( 1, fileout );
5831 //
5832 // Go through all the vertices, writing each one.
5833 //
5834  for ( VertexCount = 0; VertexCount < cor3_num; VertexCount++ )
5835  {
5836 //
5837 // Write the vertex.
5838 //
5839  gmod_write_float ( cor3[0][VertexCount], fileout );
5840  gmod_write_float ( cor3[1][VertexCount], fileout );
5841  gmod_write_float ( cor3[2][VertexCount], fileout );
5842 //
5843 // Write the normal.
5844 //
5845  gmod_write_float ( cor3_normal[0][VertexCount], fileout );
5846  gmod_write_float ( cor3_normal[1][VertexCount], fileout );
5847  gmod_write_float ( cor3_normal[2][VertexCount], fileout );
5848  }
5849 //
5850 // Now rewrite the section header.
5851 //
5852 
5853 //
5854 // Go back to the section header.
5855 //
5856  fseek ( fileout, ( long int ) SectionHeaderPos, SEEK_SET );
5857 //
5858 // Write the texture name section header.
5859 //
5861  gmod_write_w32 ( TextureNameSectionPos, fileout );
5862 //
5863 // Write the model section header.
5864 //
5866  gmod_write_w32 ( ModelSectionPos, fileout );
5867 //
5868 // Write the vertex section header.
5869 //
5871  gmod_write_w32 ( VertexSectionPos, fileout );
5872 
5873  return 0;
5874 }
5875 //****************************************************************************80
5876 
5877 void gmod_write_float ( float Val, FILE *fileout )
5878 
5879 //****************************************************************************80
5880 //
5881 // Purpose:
5882 //
5883 // GMOD_WRITE_FLOAT writes a float to a Golgotha GMOD file.
5884 //
5885 // Licensing:
5886 //
5887 // This code is distributed under the GNU LGPL license.
5888 //
5889 // Modified:
5890 //
5891 // 19 May 1999
5892 //
5893 // Author:
5894 //
5895 // Zik Saleeba
5896 //
5897 {
5898  int endian = 1;
5899  unsigned char *out_pos;
5900  int i;
5901 //
5902 // We're little-endian, which is native for GMOD floats.
5903 //
5904  if (*(char *)&endian == 1)
5905  {
5906 
5907  fwrite ( &Val, sizeof(Val), 1, fileout );
5908  }
5909 //
5910 // We're big-endian, flip `em.
5911 //
5912  else
5913  {
5914  out_pos = (unsigned char *)&Val;
5915  for ( i = sizeof(Val)-1; 0 <= i; i-- )
5916  {
5917  fputc(*(out_pos+i), fileout);
5918  }
5919  }
5920  return;
5921 }
5922 //****************************************************************************80
5923 
5924 void gmod_write_w16 ( unsigned short Val, FILE *fileout )
5925 
5926 //****************************************************************************80
5927 //
5928 // Purpose:
5929 //
5930 // GMOD_WRITE_W16 writes a 16 bit word to a Golgotha GMOD file.
5931 //
5932 // Licensing:
5933 //
5934 // This code is distributed under the GNU LGPL license.
5935 //
5936 // Modified:
5937 //
5938 // 13 September 2000
5939 //
5940 // Author:
5941 //
5942 // Zik Saleeba
5943 //
5944 {
5945  unsigned char OutByte[2];
5946 
5947  OutByte[0] = (unsigned char)(Val & 0xff);
5948  OutByte[1] = (unsigned char)(Val >> 8);
5949 
5950  fwrite ( OutByte, sizeof(unsigned char), 2, fileout );
5951 
5952  return;
5953 }
5954 //****************************************************************************80
5955 
5956 void gmod_write_w32 ( unsigned long Val, FILE *fileout )
5957 
5958 //****************************************************************************80
5959 //
5960 // Purpose:
5961 //
5962 // GMOD_WRITE writes a 32 bit word to a Golgotha GMOD file.
5963 //
5964 // Licensing:
5965 //
5966 // This code is distributed under the GNU LGPL license.
5967 //
5968 // Modified:
5969 //
5970 // 19 May 1999
5971 //
5972 // Author:
5973 //
5974 // Zik Saleeba
5975 //
5976 {
5977  unsigned char OutByte[4];
5978 
5979  OutByte[0] = (unsigned char)(Val & 0xff);
5980  OutByte[1] = (unsigned char)((Val >> 8) & 0xff);
5981  OutByte[2] = (unsigned char)((Val >> 16) & 0xff);
5982  OutByte[3] = (unsigned char)((Val >> 24) & 0xff);
5983 
5984  fwrite ( OutByte, sizeof(unsigned char), 4, fileout );
5985 
5986  return;
5987 }
5988 //****************************************************************************80
5989 
5990 void hello ( )
5991 
5992 //****************************************************************************80
5993 //
5994 // Purpose:
5995 //
5996 // HELLO prints an explanatory header message.
5997 //
5998 // Licensing:
5999 //
6000 // This code is distributed under the GNU LGPL license.
6001 //
6002 // Modified:
6003 //
6004 // 04 July 2000
6005 //
6006 // Author:
6007 //
6008 // John Burkardt
6009 //
6010 {
6011  cout << "\n";
6012  cout << "Hello: This is IVCON,\n";
6013  cout << " for 3D graphics file conversion.\n";
6014  cout << "\n";
6015  cout << " \".3ds\" 3D Studio Max binary;\n";
6016  cout << " \".ase\" 3D Studio Max ASCII export;\n";
6017  cout << " \".byu\" Movie.BYU surface geometry;\n";
6018  cout << " \".dxf\" DXF;\n";
6019  cout << " \".gmod\" Golgotha model;\n";
6020  cout << " \".hrc\" SoftImage hierarchy;\n";
6021  cout << " \".iv\" SGI Open Inventor;\n";
6022  cout << " \".obj\" WaveFront Advanced Visualizer;\n";
6023  cout << " \".off\" GEOMVIEW Object File Format;\n";
6024  cout << " \".pov\" Persistence of Vision (output only);\n";
6025  cout << " \".smf\" Michael Garland's format;\n";
6026  cout << " \".stl\" ASCII StereoLithography;\n";
6027  cout << " \".stla\" ASCII StereoLithography;\n";
6028  cout << " \".stlb\" Binary StereoLithography;\n";
6029  cout << " \".tec\" TECPLOT (output only);\n";
6030  cout << " \".tri\" [Greg Hood ASCII triangle format];\n";
6031  cout << " \".tria\" [Greg Hood ASCII triangle format];\n";
6032  cout << " \".trib\" [Greg Hood binary triangle format];\n";
6033  cout << " \".txt\" Text (output only);\n";
6034  cout << " \".ucd\" AVS UCD file(output only);\n";
6035  cout << " \".vla\" VLA;\n";
6036  cout << " \".wrl\" VRML (Virtual Reality Modeling Language) (output only).\n";
6037  cout << " \".xgl\" XML/OpenGL format (output only);\n";
6038  cout << "\n";
6039  cout << " Current limits include:\n";
6040  cout << " " << FACE_MAX << " faces.\n";
6041  cout << " " << LINES_MAX << " line items.\n";
6042  cout << " " << COR3_MAX << " points.\n";
6043  cout << " " << ORDER_MAX << " face order.\n";
6044  cout << " " << MATERIAL_MAX << " materials.\n";
6045  cout << " " << TEXTURE_MAX << " textures.\n";
6046  cout << "\n";
6047  cout << " Last modification: 04 September 2003.\n";
6048 
6049  return;
6050 }
6051 //****************************************************************************80
6052 
6053 void help ( )
6054 
6055 //****************************************************************************80
6056 //
6057 // Purpose:
6058 //
6059 // HELP prints a list of the interactive commands.
6060 //
6061 // Licensing:
6062 //
6063 // This code is distributed under the GNU LGPL license.
6064 //
6065 // Modified:
6066 //
6067 // 26 May 1999
6068 //
6069 // Author:
6070 //
6071 // John Burkardt
6072 //
6073 {
6074  cout << "\n";
6075  cout << "Commands:\n";
6076  cout << "\n";
6077  cout << "< file Read data from input file;\n";
6078  cout << "<< file Append data in input file to current data;\n";
6079  cout << "> file Write output file;\n";
6080  cout << "B Switch the binary file byte-swapping mode;\n";
6081  cout << "D Switch the debugging mode;\n";
6082  cout << "F Print information about one face;\n";
6083  cout << "H Print this help list;\n";
6084  cout << "I Info, print out recent changes;\n";
6085  cout << "LINES Convert face information to lines;\n";
6086  cout << "N Recompute normal vectors;\n";
6087  cout << "P Set LINE_PRUNE option.\n";
6088  cout << "Q Quit;\n";
6089  cout << "R Reverse the normal vectors.\n";
6090  cout << "S Select face subset (NOT WORKING).\n";
6091  cout << "T Transform the data.\n";
6092  cout << "W Reverse the face node ordering.\n";
6093 
6094  return;
6095 }
6096 //****************************************************************************80
6097 
6098 int hrc_read ( FILE *filein )
6099 
6100 //****************************************************************************80
6101 //
6102 // Purpose:
6103 //
6104 // HRC_READ reads graphics information from a SoftImage HRC file.
6105 //
6106 // Example:
6107 //
6108 // HRCH: Softimage 4D Creative Environment v3.00
6109 //
6110 //
6111 // model
6112 // {
6113 // name "cube_10x10"
6114 // scaling 1.000 1.000 1.000
6115 // rotation 0.000 0.000 0.000
6116 // translation 0.000 0.000 0.000
6117 //
6118 // mesh
6119 // {
6120 // flag ( PROCESS )
6121 // discontinuity 60.000
6122 //
6123 // vertices 8
6124 // {
6125 // [0] position -5.000 -5.000 -5.000
6126 // [1] position -5.000 -5.000 5.000
6127 // [2] position -5.000 5.000 -5.000
6128 // [3] position -5.000 5.000 5.000
6129 // [4] position 5.000 -5.000 -5.000
6130 // [5] position 5.000 -5.000 5.000
6131 // [6] position 5.000 5.000 -5.000
6132 // [7] position 5.000 5.000 5.000
6133 // }
6134 //
6135 // polygons 6
6136 // {
6137 // [0] nodes 4
6138 // {
6139 // [0] vertex 0
6140 // normal -1.000 0.000 0.000
6141 // uvTexture 0.000 0.000
6142 // vertexColor 255 178 178 178
6143 // [1] vertex 1
6144 // normal -1.000 0.000 0.000
6145 // uvTexture 0.000 0.000
6146 // vertexColor 255 178 178 178
6147 // [2] vertex 3
6148 // normal -1.000 0.000 0.000
6149 // uvTexture 0.000 0.000
6150 // vertexColor 255 178 178 178
6151 // [3] vertex 2
6152 // normal -1.000 0.000 0.000
6153 // uvTexture 0.000 0.000
6154 // vertexColor 255 178 178 178
6155 // }
6156 // material 0
6157 // [1] nodes 4
6158 // {
6159 // [0] vertex 1
6160 // normal 0.000 0.000 1.000
6161 // uvTexture 0.000 0.000
6162 // vertexColor 255 178 178 178
6163 // [1] vertex 5
6164 //
6165 // ...etc.....
6166 //
6167 // [5] nodes 4
6168 // {
6169 // [0] vertex 2
6170 // normal 0.000 1.000 0.000
6171 // uvTexture 0.000 0.000
6172 // vertexColor 255 178 178 178
6173 // [1] vertex 3
6174 // normal 0.000 1.000 0.000
6175 // uvTexture 0.000 0.000
6176 // vertexColor 255 178 178 178
6177 // [2] vertex 7
6178 // normal 0.000 1.000 0.000
6179 // uvTexture 0.000 0.000
6180 // vertexColor 255 178 178 178
6181 // [3] vertex 6
6182 // normal 0.000 1.000 0.000
6183 // uvTexture 0.000 0.000
6184 // vertexColor 255 178 178 178
6185 // }
6186 // material 0
6187 // }
6188 //
6189 // edges 12
6190 // {
6191 // [1] vertices 3 2
6192 // [2] vertices 2 0
6193 // [3] vertices 0 1
6194 // [4] vertices 1 3
6195 // [5] vertices 7 3
6196 // [6] vertices 1 5
6197 // [7] vertices 5 7
6198 // [8] vertices 6 7
6199 // [9] vertices 5 4
6200 // [10] vertices 4 6
6201 // [11] vertices 2 6
6202 // [12] vertices 4 0
6203 // }
6204 // }
6205 //
6206 // material [0]
6207 // {
6208 // name "kazoo"
6209 // type PHONG
6210 // ambient 0.0 1.0 0.0
6211 // diffuse 1.0 0.0 0.0
6212 // specular 0.0 0.0 1.0
6213 // exponent 50.0
6214 // reflectivity 0.0
6215 // transparency 0.0
6216 // refracIndex 1.0
6217 // glow 0
6218 // coc 0.0
6219 // }
6220 //
6221 // texture [0]
6222 // {
6223 // name "/usr/users/foss/HOUSE/PICTURES/mellon"
6224 // glbname "t2d1"
6225 // anim STATIC
6226 // method XY
6227 // repeat 1 1
6228 // scaling 1.000 1.000
6229 // offset 0.000 0.000
6230 // pixelInterp
6231 // effect INTENSITY
6232 // blending 1.000
6233 // ambient 0.977
6234 // diffuse 1.000
6235 // specular 0.966
6236 // reflect 0.000
6237 // transp 0.000
6238 // roughness 0.000
6239 // reflMap 1.000
6240 // rotation 0.000
6241 // txtsup_rot 0.000 0.000 0.000
6242 // txtsup_trans 0.000 0.000 0.000
6243 // txtsup_scal 1.000 1.000 1.000
6244 // }
6245 // }
6246 //
6247 // Licensing:
6248 //
6249 // This code is distributed under the GNU LGPL license.
6250 //
6251 // Modified:
6252 //
6253 // 25 June 1999
6254 //
6255 // Author:
6256 //
6257 // John Burkardt
6258 //
6259 {
6260  float b;
6261  int count;
6262  float g;
6263  int i;
6264  int icor3;
6265  int ivert;
6266  int iword;
6267  int jval;
6268  int level;
6269  char *next;
6270  int nlbrack;
6271  int nrbrack;
6272  int cor3_num_old;
6273  float r;
6274  float t;
6275  float temp[3];
6276  int width;
6277  char word[LINE_MAX_LEN];
6278  char word1[LINE_MAX_LEN];
6279  char word2[LINE_MAX_LEN];
6280  char wordm1[LINE_MAX_LEN];
6281  float x;
6282  float y;
6283  float z;
6284 
6285  level = 0;
6286  strcpy ( level_name[0], "Top" );
6287  nlbrack = 0;
6288  nrbrack = 0;
6289  cor3_num_old = cor3_num;
6290  strcpy ( word, " " );
6291  strcpy ( wordm1, " " );
6292 //
6293 // Read a line of text from the file.
6294 //
6295  for ( ;; )
6296  {
6297 
6298  if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
6299  {
6300  break;
6301  }
6302 
6303  text_num = text_num + 1;
6304  next = input;
6305  iword = 0;
6306 //
6307 // Read a word from the line.
6308 //
6309  for ( ;; )
6310  {
6311  strcpy ( wordm1, word );
6312 
6313  count = sscanf ( next, "%s%n", word2, &width );
6314  next = next + width;
6315 
6316  if ( count <= 0 )
6317  {
6318  break;
6319  }
6320 
6321  strcpy ( word, word2 );
6322 
6323  iword = iword + 1;
6324 
6325  if ( iword == 1 )
6326  {
6327  strcpy ( word1, word );
6328  }
6329 //
6330 // The first line of the file must be the header.
6331 //
6332  if ( text_num == 1 )
6333  {
6334  if ( strcmp ( word1, "HRCH:" ) != 0 )
6335  {
6336  cout << "\n";
6337  cout << "HRC_READ - Fatal error!\n";
6338  cout << " The input file has a bad header.\n";;
6339  return 1;
6340  }
6341  else
6342  {
6343  comment_num = comment_num + 1;
6344  }
6345  break;
6346  }
6347 //
6348 // If the word is a curly bracket, count it.
6349 //
6350  if ( strcmp ( word, "{" ) == 0 )
6351  {
6352  nlbrack = nlbrack + 1;
6353  level = nlbrack - nrbrack;
6354  strcpy ( level_name[level], wordm1 );
6355  if ( debug )
6356  {
6357  cout << "New level: " << level_name[level] << "\n";;
6358  }
6359  }
6360  else if ( strcmp ( word, "}" ) == 0 )
6361  {
6362  nrbrack = nrbrack + 1;
6363 
6364  if ( nlbrack < nrbrack )
6365  {
6366  cout << "\n";
6367  cout << "HRC_READ - Fatal error!\n";
6368  cout << " Extraneous right bracket on line " << text_num << ".\n";
6369  cout << " Processing field " << level_name[level] << "\n";
6370  return 1;
6371  }
6372  }
6373 //
6374 // CONTROLPOINTS
6375 //
6376  if ( strcmp ( level_name[level], "controlpoints" ) == 0 )
6377  {
6378 
6379  if ( strcmp ( word, "{" ) == 0 )
6380  {
6381  }
6382  else if ( strcmp ( word, "}" ) == 0 )
6383  {
6384  if ( line_num < LINES_MAX )
6385  {
6386  line_dex[line_num] = -1;
6387  line_material[line_num] = 0;
6388  }
6389  line_num = line_num + 1;
6390  level = nlbrack - nrbrack;
6391  }
6392  else if ( word[0] == '[' )
6393  {
6394  }
6395  else if ( strcmp ( word, "position" ) == 0 )
6396  {
6397  count = sscanf ( next, "%f%n", &x, &width );
6398  next = next + width;
6399 
6400  count = sscanf ( next, "%f%n", &y, &width );
6401  next = next + width;
6402 
6403  count = sscanf ( next, "%f%n", &z, &width );
6404  next = next + width;
6405 
6406  temp[0] = x;
6407  temp[1] = y;
6408  temp[2] = z;
6409 
6410  if ( cor3_num < 1000 )
6411  {
6412  icor3 = rcol_find ( cor3, 3, cor3_num, temp );
6413  }
6414  else
6415  {
6416  icor3 = -1;
6417  }
6418 
6419  if ( icor3 == -1 )
6420  {
6421  icor3 = cor3_num;
6422  if ( cor3_num < COR3_MAX )
6423  {
6424  cor3[0][cor3_num] = x;
6425  cor3[1][cor3_num] = y;
6426  cor3[2][cor3_num] = z;
6427  }
6428  cor3_num = cor3_num + 1;
6429 
6430  }
6431  else
6432  {
6433  dup_num = dup_num + 1;
6434  }
6435 
6436  if ( line_num < LINES_MAX )
6437  {
6438  line_dex[line_num] = icor3;
6439  line_material[line_num] = 0;
6440  }
6441  line_num = line_num + 1;
6442  }
6443  else
6444  {
6445  bad_num = bad_num + 1;
6446  cout << "CONTROLPOINTS: Bad data " << word << "\n";
6447  return 1;
6448  }
6449 
6450  }
6451 //
6452 // EDGES
6453 //
6454  else if ( strcmp ( level_name[level], "edges" ) == 0 )
6455  {
6456  if ( strcmp( word, "{" ) == 0 )
6457  {
6458  }
6459  else if ( strcmp ( word, "}" ) == 0 )
6460  {
6461  level = nlbrack - nrbrack;
6462  }
6463  else if ( word[0] == '[' )
6464  {
6465  }
6466  else if ( strcmp ( word, "vertices" ) == 0 )
6467  {
6468 
6469  count = sscanf ( next, "%d%n", &jval, &width );
6470  next = next + width;
6471 
6472  if ( line_num < LINES_MAX )
6473  {
6474  line_dex[line_num] = jval + cor3_num_old;
6475  line_material[line_num] = 0;
6476  }
6477  line_num = line_num + 1;
6478 
6479  count = sscanf ( next, "%d%n", &jval, &width );
6480  next = next + width;
6481 
6482  if ( line_num < LINES_MAX )
6483  {
6484  line_dex[line_num] = jval + cor3_num_old;
6485  line_material[line_num] = 0;
6486  }
6487  line_num = line_num + 1;
6488 
6489  if ( line_num < LINES_MAX )
6490  {
6491  line_dex[line_num] = -1;
6492  line_material[line_num] = -1;
6493  }
6494  line_num = line_num + 1;
6495 
6496  }
6497  else
6498  {
6499  bad_num = bad_num + 1;
6500  cout << "EDGES: Bad data " << word << "\n";
6501  return 1;
6502  }
6503 
6504  }
6505 //
6506 // MATERIAL
6507 //
6508  else if ( strcmp ( level_name[level], "material" ) == 0 )
6509  {
6510  if ( strcmp ( word, "{" ) == 0 )
6511  {
6512  material_num = material_num + 1;
6513  }
6514  else if ( strcmp ( word, "}" ) == 0 )
6515  {
6516  level = nlbrack - nrbrack;
6517  }
6518  else if ( word[0] == '[' )
6519  {
6520  }
6521  else if ( strcmp ( word, "ambient" ) == 0 )
6522  {
6523  }
6524  else if ( strcmp ( word, "coc" ) == 0 )
6525  {
6526  }
6527  else if ( strcmp ( word, "diffuse" ) == 0 )
6528  {
6529 
6530  count = sscanf ( next, "%f%n", &r, &width );
6531  next = next + width;
6532  material_rgba[0][material_num-1] = r;
6533 
6534  count = sscanf ( next, "%f%n", &g, &width );
6535  next = next + width;
6536  material_rgba[0][material_num-1] = g;
6537 
6538  count = sscanf ( next, "%f%n", &b, &width );
6539  next = next + width;
6540  material_rgba[0][material_num-1] = b;
6541 
6542  }
6543  else if ( strcmp ( word, "exponent" ) == 0 )
6544  {
6545  }
6546  else if ( strcmp ( word, "glow" ) == 0 )
6547  {
6548  }
6549  else if ( strcmp ( word, "name" ) == 0 )
6550  {
6551  count = sscanf ( next, "%s%n", word, &width );
6552  next = next + width;
6553  strcpy ( material_name[material_num-1], word );
6554  }
6555  else if ( strcmp ( word, "reflectivity" ) == 0 )
6556  {
6557  }
6558  else if ( strcmp ( word, "refracindex" ) == 0 )
6559  {
6560  }
6561  else if ( strcmp ( word, "specular" ) == 0 )
6562  {
6563  }
6564  else if ( strcmp ( word, "transparency" ) == 0 )
6565  {
6566  count = sscanf ( next, "%f%n", &t, &width );
6567  next = next + width;
6568  material_rgba[3][material_num-1] = 1.0 - t;
6569  }
6570  else if ( strcmp ( word, "type" ) == 0 )
6571  {
6572  }
6573  else
6574  {
6575  bad_num = bad_num + 1;
6576  cout << "MATERIAL: Bad data " << word << "\n";
6577  return 1;
6578  }
6579  }
6580 //
6581 // MESH
6582 //
6583  else if ( strcmp ( level_name[level], "mesh" ) == 0 )
6584  {
6585  if ( strcmp ( word, "{" ) == 0 )
6586  {
6587  }
6588  else if ( strcmp ( word, "}" ) == 0 )
6589  {
6590  level = nlbrack - nrbrack;
6591  }
6592  else if ( strcmp ( word, "discontinuity" ) == 0 )
6593  {
6594  break;
6595  }
6596  else if ( strcmp ( word, "edges" ) == 0 )
6597  {
6598  break;
6599  }
6600  else if ( strcmp ( word, "flag" ) == 0 )
6601  {
6602  break;
6603  }
6604  else if ( strcmp ( word, "polygons" ) == 0 )
6605  {
6606  break;
6607  }
6608  else if ( strcmp ( word, "vertices" ) == 0 )
6609  {
6610  break;
6611  }
6612  else
6613  {
6614  bad_num = bad_num + 1;
6615  cout << "MESH: Bad data " << word << "\n";
6616  return 1;
6617  }
6618 
6619  }
6620 //
6621 // MODEL
6622 //
6623  else if ( strcmp ( level_name[level], "model" ) == 0 )
6624  {
6625  if ( strcmp ( word, "{" ) == 0 )
6626  {
6627  }
6628  else if ( strcmp ( word, "}" ) == 0 )
6629  {
6630  level = nlbrack - nrbrack;
6631  }
6632  else if ( strcmp ( word, "material" ) == 0 )
6633  {
6634  break;
6635  }
6636  else if ( strcmp ( word, "mesh" ) == 0 )
6637  {
6638  break;
6639  }
6640  else if ( strcmp ( word, "name" ) == 0 )
6641  {
6642  break;
6643  }
6644  else if ( strcmp ( word, "patch" ) == 0 )
6645  {
6646  break;
6647  }
6648  else if ( strcmp ( word, "rotation" ) == 0 )
6649  {
6650  break;
6651  }
6652  else if ( strcmp ( word, "scaling" ) == 0 )
6653  {
6654  break;
6655  }
6656  else if ( strcmp ( word, "spline" ) == 0 )
6657  {
6658  break;
6659  }
6660  else if ( strcmp ( word, "translation" ) == 0 )
6661  {
6662  break;
6663  }
6664  else
6665  {
6666  bad_num = bad_num + 1;
6667  cout << "MODEL: Bad data " << word << "\n";
6668  return 1;
6669  }
6670 
6671  }
6672 //
6673 // NODES
6674 //
6675  else if ( strcmp ( level_name[level], "nodes" ) == 0 )
6676  {
6677  if ( strcmp ( word, "{" ) == 0 )
6678  {
6679  ivert = 0;
6680  face_order[face_num] = 0;
6681  face_num = face_num + 1;
6682  }
6683  else if ( strcmp ( word, "}" ) == 0 )
6684  {
6685  level = nlbrack - nrbrack;
6686  }
6687  else if ( word[0] == '[' )
6688  {
6689  }
6690  else if ( strcmp ( word, "normal" ) == 0 )
6691  {
6692  count = sscanf ( next, "%f%n", &x, &width );
6693  next = next + width;
6694 
6695  count = sscanf ( next, "%f%n", &y, &width );
6696  next = next + width;
6697 
6698  count = sscanf ( next, "%f%n", &z, &width );
6699  next = next + width;
6700 
6701  if ( ivert < ORDER_MAX && face_num < FACE_MAX )
6702  {
6703  vertex_normal[0][ivert-1][face_num-1] = x;
6704  vertex_normal[1][ivert-1][face_num-1] = y;
6705  vertex_normal[2][ivert-1][face_num-1] = z;
6706  }
6707 
6708  }
6709  else if ( strcmp ( word, "uvTexture" ) == 0 )
6710  {
6711  count = sscanf ( next, "%f%n", &x, &width );
6712  next = next + width;
6713 
6714  count = sscanf ( next, "%f%n", &y, &width );
6715  next = next + width;
6716 
6717  if ( ivert < ORDER_MAX && face_num < FACE_MAX )
6718  {
6719  vertex_tex_uv[0][ivert-1][face_num-1] = x;
6720  vertex_tex_uv[1][ivert-1][face_num-1] = y;
6721  }
6722  }
6723  else if ( strcmp ( word, "vertex" ) == 0 )
6724  {
6725  count = sscanf ( next, "%d%n", &jval, &width );
6726  next = next + width;
6727 
6728  if ( ivert < ORDER_MAX && face_num < FACE_MAX )
6729  {
6730  face_order[face_num-1] = face_order[face_num-1] + 1;
6731  face[ivert][face_num-1] = jval;
6732  }
6733  ivert = ivert + 1;
6734 
6735  }
6736 //
6737 // Right now, we don't do anything with the vertexColor information.
6738 //
6739  else if ( strcmp ( word, "vertexColor" ) == 0 )
6740  {
6741  count = sscanf ( next, "%d%n", &jval, &width );
6742  next = next + width;
6743 
6744  count = sscanf ( next, "%d%n", &jval, &width );
6745  next = next + width;
6746 
6747  count = sscanf ( next, "%d%n", &jval, &width );
6748  next = next + width;
6749 
6750  count = sscanf ( next, "%d%n", &jval, &width );
6751  next = next + width;
6752  }
6753  else
6754  {
6755  bad_num = bad_num + 1;
6756  cout << "NODES: Bad data " << word << "\n";
6757  return 1;
6758  }
6759 
6760  }
6761 //
6762 // PATCH
6763 // I don't know what to do with this yet.
6764 //
6765  else if ( strcmp ( level_name[level], "patch" ) == 0 )
6766  {
6767  if ( strcmp ( word, "{" ) == 0 )
6768  {
6769  }
6770  else if ( strcmp ( word, "}" ) == 0 )
6771  {
6772  level = nlbrack - nrbrack;
6773  }
6774  else if ( strcmp ( word, "approx_type" ) == 0 )
6775  {
6776  }
6777  else if ( strcmp ( word, "controlpoints" ) == 0 )
6778  {
6779  }
6780  else if ( strcmp ( word, "curv_u" ) == 0 )
6781  {
6782  }
6783  else if ( strcmp ( word, "curv_v" ) == 0 )
6784  {
6785  }
6786  else if ( strcmp ( word, "recmin" ) == 0 )
6787  {
6788  }
6789  else if ( strcmp ( word, "recmax" ) == 0 )
6790  {
6791  }
6792  else if ( strcmp ( word, "recursion" ) == 0 )
6793  {
6794  }
6795  else if ( strcmp ( word, "spacial" ) == 0 )
6796  {
6797  }
6798  else if ( strcmp ( word, "taggedpoints" ) == 0 )
6799  {
6800  }
6801  else if ( strcmp ( word, "ucurve" ) == 0 )
6802  {
6803  }
6804  else if ( strcmp ( word, "ustep" ) == 0 )
6805  {
6806  }
6807  else if ( strcmp ( word, "utension" ) == 0 )
6808  {
6809  }
6810  else if ( strcmp ( word, "utype" ) == 0 )
6811  {
6812  }
6813  else if ( strcmp ( word, "vclose" ) == 0 )
6814  {
6815  }
6816  else if ( strcmp ( word, "vcurve" ) == 0 )
6817  {
6818  }
6819  else if ( strcmp ( word, "viewdep" ) == 0 )
6820  {
6821  }
6822  else if ( strcmp ( word, "vpoint" ) == 0 )
6823  {
6824  }
6825  else if ( strcmp ( word, "vstep" ) == 0 )
6826  {
6827  }
6828  else if ( strcmp ( word, "vtension" ) == 0 )
6829  {
6830  }
6831  else if ( strcmp ( word, "vtype" ) == 0 )
6832  {
6833  }
6834  else
6835  {
6836  bad_num = bad_num + 1;
6837  cout << "PATCH: Bad data " << word << "\n";
6838  return 1;
6839  }
6840  }
6841 //
6842 // POLYGONS
6843 //
6844  else if ( strcmp ( level_name[level], "polygons" ) == 0 )
6845  {
6846  if ( strcmp ( word, "{" ) == 0 )
6847  {
6848  }
6849  else if ( strcmp ( word, "}" ) == 0 )
6850  {
6851  level = nlbrack - nrbrack;
6852  }
6853  else if ( word[0] == '[' )
6854  {
6855  }
6856  else if ( strcmp ( word, "material" ) == 0 )
6857  {
6858  count = sscanf ( next, "%d%n", &jval, &width );
6859  next = next + width;
6860 
6861  for ( ivert = 0; ivert < ORDER_MAX; ivert++ )
6862  {
6863  vertex_material[ivert][face_num-1] = jval;
6864  }
6865 
6866  }
6867  else if ( strcmp ( word, "nodes" ) == 0 )
6868  {
6869  count = sscanf ( next, "%s%n", word2, &width );
6870  next = next + width;
6871  }
6872  else
6873  {
6874  bad_num = bad_num + 1;
6875  cout << "POLYGONS: Bad data " << word << "\n";
6876  return 1;
6877  }
6878 
6879  }
6880 //
6881 // SPLINE
6882 //
6883  else if ( strcmp ( level_name[level], "spline" ) == 0 )
6884  {
6885  if ( strcmp ( word, "{" ) == 0 )
6886  {
6887  }
6888  else if ( strcmp ( word, "}" ) == 0 )
6889  {
6890  level = nlbrack - nrbrack;
6891  }
6892  else if ( strcmp ( word, "controlpoints" ) == 0 )
6893  {
6894  break;
6895  }
6896 //
6897 // WHY DON'T YOU READ IN THE OBJECT NAME HERE?
6898 //
6899  else if ( strcmp ( word, "name" ) == 0 )
6900  {
6901  break;
6902  }
6903  else if ( strcmp ( word, "nbKeys" ) == 0 )
6904  {
6905  break;
6906  }
6907  else if ( strcmp ( word, "step" ) == 0 )
6908  {
6909  break;
6910  }
6911  else if ( strcmp ( word, "tension" ) == 0 )
6912  {
6913  break;
6914  }
6915  else if ( strcmp ( word, "type" ) == 0 )
6916  {
6917  break;
6918  }
6919  else
6920  {
6921  bad_num = bad_num + 1;
6922  cout << "SPLINE: Bad data " << word << "\n";
6923  return 1;
6924  }
6925 
6926  }
6927 //
6928 // TAGGEDPOINTS
6929 //
6930  else if ( strcmp ( level_name[level], "taggedpoints" ) == 0 )
6931  {
6932  if ( strcmp ( word, "{" ) == 0 )
6933  {
6934  }
6935  else if ( strcmp ( word, "}" ) == 0 )
6936  {
6937  level = nlbrack - nrbrack;
6938  }
6939  else if ( word[0] == '[' )
6940  {
6941  }
6942  else if ( strcmp ( word, "tagged" ) == 0 )
6943  {
6944  }
6945  else
6946  {
6947  bad_num = bad_num + 1;
6948  cout << "TAGGEDPOINTS: Bad data " << word << "\n";
6949  return 1;
6950  }
6951 
6952  }
6953 //
6954 // TEXTURE
6955 //
6956  else if ( strcmp ( level_name[level], "texture" ) == 0 )
6957  {
6958  if ( strcmp ( word, "{" ) == 0 )
6959  {
6960  texture_num = texture_num + 1;
6961  }
6962  else if ( strcmp ( word, "}" ) == 0 )
6963  {
6964  level = nlbrack - nrbrack;
6965  }
6966  else if ( word[0] == '[' )
6967  {
6968  }
6969  else if ( strcmp ( word, "ambient" ) == 0 )
6970  {
6971  }
6972  else if ( strcmp ( word, "anim" ) == 0 )
6973  {
6974  }
6975  else if ( strcmp ( word, "blending" ) == 0 )
6976  {
6977  }
6978  else if ( strcmp ( word, "diffuse" ) == 0 )
6979  {
6980  }
6981  else if ( strcmp ( word, "effect" ) == 0 )
6982  {
6983  }
6984  else if ( strcmp ( word, "glbname" ) == 0 )
6985  {
6986  }
6987  else if ( strcmp ( word, "method" ) == 0 )
6988  {
6989  }
6990  else if ( strcmp ( word, "name" ) == 0 )
6991  {
6992  count = sscanf ( next, "%s%n", word, &width );
6993  next = next + width;
6994  strcpy ( texture_name[texture_num-1], word );
6995  }
6996  else if ( strcmp ( word, "offset" ) == 0 )
6997  {
6998  }
6999  else if ( strcmp ( word, "pixelinterp" ) == 0 )
7000  {
7001  }
7002  else if ( strcmp ( word, "reflect" ) == 0 )
7003  {
7004  }
7005  else if ( strcmp ( word, "reflmap" ) == 0 )
7006  {
7007  }
7008  else if ( strcmp ( word, "repeat" ) == 0 )
7009  {
7010  }
7011  else if ( strcmp ( word, "rotation" ) == 0 )
7012  {
7013  }
7014  else if ( strcmp ( word, "roughness" ) == 0 )
7015  {
7016  }
7017  else if ( strcmp ( word, "scaling" ) == 0 )
7018  {
7019  }
7020  else if ( strcmp ( word, "specular" ) == 0 )
7021  {
7022  }
7023  else if ( strcmp ( word, "transp" ) == 0 )
7024  {
7025  }
7026  else if ( strcmp ( word, "txtsup_rot" ) == 0 )
7027  {
7028  }
7029  else if ( strcmp ( word, "txtsup_scal" ) == 0 )
7030  {
7031  }
7032  else if ( strcmp ( word, "txtsup_trans" ) == 0 )
7033  {
7034  }
7035  else
7036  {
7037  bad_num = bad_num + 1;
7038  cout << "TEXTURE: Bad data " << word << "\n";
7039  return 1;
7040  }
7041  }
7042 //
7043 // VERTICES
7044 //
7045  else if ( strcmp ( level_name[level], "vertices" ) == 0 )
7046  {
7047  if ( strcmp ( word, "{" ) == 0 )
7048  {
7049  }
7050  else if ( strcmp ( word, "}" ) == 0 )
7051  {
7052  level = nlbrack - nrbrack;
7053  }
7054  else if ( word[0] == '[' )
7055  {
7056  }
7057  else if ( strcmp ( word, "position" ) == 0 )
7058  {
7059  count = sscanf ( next, "%f%n", &x, &width );
7060  next = next + width;
7061 
7062  count = sscanf ( next, "%f%n", &y, &width );
7063  next = next + width;
7064 
7065  count = sscanf ( next, "%f%n", &z, &width );
7066  next = next + width;
7067 
7068  if ( cor3_num < COR3_MAX )
7069  {
7070  cor3[0][cor3_num] = x;
7071  cor3[1][cor3_num] = y;
7072  cor3[2][cor3_num] = z;
7073  }
7074  cor3_num = cor3_num + 1;
7075  }
7076  else
7077  {
7078  bad_num = bad_num + 1;
7079  cout << "VERTICES: Bad data " << word << "\n";
7080  return 1;
7081  }
7082  }
7083 //
7084 // Any other word:
7085 //
7086  else
7087  {
7088  }
7089  }
7090  }
7091 
7092 //
7093 // End of information in file.
7094 //
7095 // Check the "materials" defining a line.
7096 //
7097 // If COORDINDEX is -1, so should be the MATERIALINDEX.
7098 // If COORDINDEX is not -1, then the MATERIALINDEX shouldn"t be either.
7099 //
7100  for ( i = 0; i < line_num; i++ )
7101  {
7102  if ( line_dex[i] == -1 )
7103  {
7104  line_material[i] = -1;
7105  }
7106  else if ( line_material[i] == -1 )
7107  {
7108  line_material[i] = 0;
7109  }
7110 
7111  }
7112  return 0;
7113 }
7114 //****************************************************************************80
7115 
7116 int hrc_write ( FILE* fileout )
7117 
7118 //****************************************************************************80
7119 //
7120 // Purpose:
7121 //
7122 // HRC_WRITE writes graphics data to an HRC SoftImage file.
7123 //
7124 // Example:
7125 //
7126 // HRCH: Softimage 4D Creative Environment v3.00
7127 //
7128 //
7129 // model
7130 // {
7131 // name "cube_10x10"
7132 // scaling 1.000 1.000 1.000
7133 // rotation 0.000 0.000 0.000
7134 // translation 0.000 0.000 0.000
7135 //
7136 // mesh
7137 // {
7138 // flag ( PROCESS )
7139 // discontinuity 60.000
7140 //
7141 // vertices 8
7142 // {
7143 // [0] position -5.000 -5.000 -5.000
7144 // [1] position -5.000 -5.000 5.000
7145 // [2] position -5.000 5.000 -5.000
7146 // [3] position -5.000 5.000 5.000
7147 // [4] position 5.000 -5.000 -5.000
7148 // [5] position 5.000 -5.000 5.000
7149 // [6] position 5.000 5.000 -5.000
7150 // [7] position 5.000 5.000 5.000
7151 // }
7152 //
7153 // polygons 6
7154 // {
7155 // [0] nodes 4
7156 // {
7157 // [0] vertex 0
7158 // normal -1.000 0.000 0.000
7159 // uvTexture 0.000 0.000
7160 // vertexColor 255 178 178 178
7161 // [1] vertex 1
7162 // normal -1.000 0.000 0.000
7163 // uvTexture 0.000 0.000
7164 // vertexColor 255 178 178 178
7165 // [2] vertex 3
7166 // normal -1.000 0.000 0.000
7167 // uvTexture 0.000 0.000
7168 // vertexColor 255 178 178 178
7169 // [3] vertex 2
7170 // normal -1.000 0.000 0.000
7171 // uvTexture 0.000 0.000
7172 // vertexColor 255 178 178 178
7173 // }
7174 // material 0
7175 // [1] nodes 4
7176 // {
7177 // [0] vertex 1
7178 // normal 0.000 0.000 1.000
7179 // uvTexture 0.000 0.000
7180 // vertexColor 255 178 178 178
7181 // [1] vertex 5
7182 //
7183 // ...etc.....
7184 //
7185 // [5] nodes 4
7186 // {
7187 // [0] vertex 2
7188 // normal 0.000 1.000 0.000
7189 // uvTexture 0.000 0.000
7190 // vertexColor 255 178 178 178
7191 // [1] vertex 3
7192 // normal 0.000 1.000 0.000
7193 // uvTexture 0.000 0.000
7194 // vertexColor 255 178 178 178
7195 // [2] vertex 7
7196 // normal 0.000 1.000 0.000
7197 // uvTexture 0.000 0.000
7198 // vertexColor 255 178 178 178
7199 // [3] vertex 6
7200 // normal 0.000 1.000 0.000
7201 // uvTexture 0.000 0.000
7202 // vertexColor 255 178 178 178
7203 // }
7204 // material 0
7205 // }
7206 //
7207 // edges 12
7208 // {
7209 // [1] vertices 3 2
7210 // [2] vertices 2 0
7211 // [3] vertices 0 1
7212 // [4] vertices 1 3
7213 // [5] vertices 7 3
7214 // [6] vertices 1 5
7215 // [7] vertices 5 7
7216 // [8] vertices 6 7
7217 // [9] vertices 5 4
7218 // [10] vertices 4 6
7219 // [11] vertices 2 6
7220 // [12] vertices 4 0
7221 // }
7222 // }
7223 //
7224 // material [0]
7225 // {
7226 // name "kazoo"
7227 // type PHONG
7228 // ambient 0.0 1.0 0.0
7229 // diffuse 1.0 0.0 0.0
7230 // specular 0.0 0.0 1.0
7231 // exponent 50.0
7232 // reflectivity 0.0
7233 // transparency 0.0
7234 // refracIndex 1.0
7235 // glow 0
7236 // coc 0.0
7237 // }
7238 //
7239 // texture [0]
7240 // {
7241 // name "/usr/users/foss/HOUSE/PICTURES/mellon"
7242 // glbname "t2d1"
7243 // anim STATIC
7244 // method XY
7245 // repeat 1 1
7246 // scaling 1.000 1.000
7247 // offset 0.000 0.000
7248 // pixelInterp
7249 // effect INTENSITY
7250 // blending 1.000
7251 // ambient 0.977
7252 // diffuse 1.000
7253 // specular 0.966
7254 // reflect 0.000
7255 // transp 0.000
7256 // roughness 0.000
7257 // reflMap 1.000
7258 // rotation 0.000
7259 // txtsup_rot 0.000 0.000 0.000
7260 // txtsup_trans 0.000 0.000 0.000
7261 // txtsup_scal 1.000 1.000 1.000
7262 // }
7263 // }
7264 //
7265 // Licensing:
7266 //
7267 // This code is distributed under the GNU LGPL license.
7268 //
7269 // Modified:
7270 //
7271 // 25 June 1998
7272 //
7273 // Author:
7274 //
7275 // John Burkardt
7276 //
7277 //
7278 {
7279  int iface;
7280  int ivert;
7281  int j;
7282  int jhi;
7283  int jlo;
7284  int jrel;
7285  int k;
7286  int npts;
7287  int nseg;
7288  int text_num;
7289 
7290  nseg = 0;
7291  text_num = 0;
7292 
7293  fprintf ( fileout, "HRCH: Softimage 4D Creative Environment v3.00\n" );
7294  fprintf ( fileout, "\n" );
7295  fprintf ( fileout, "\n" );
7296  text_num = text_num + 3;
7297 
7298  fprintf ( fileout, "model\n" );
7299  fprintf ( fileout, "{\n" );
7300  fprintf ( fileout, " name \"%s\"\n", object_name );
7301  fprintf ( fileout, " scaling 1.000 1.000 1.000\n" );
7302  fprintf ( fileout, " rotation 0.000 0.000 0.000\n" );
7303  fprintf ( fileout, " translation 0.000 0.000 0.000\n" );
7304  text_num = text_num + 6;
7305 
7306  if ( 0 < face_num )
7307  {
7308  fprintf ( fileout, "\n" );
7309  fprintf ( fileout, " mesh\n" );
7310  fprintf ( fileout, " {\n" );
7311  fprintf ( fileout, " flag ( PROCESS )\n" );
7312  fprintf ( fileout, " discontinuity 60.000\n" );
7313  text_num = text_num + 5;
7314 //
7315 // Point coordinates.
7316 //
7317  if ( 0 < cor3_num )
7318  {
7319  fprintf ( fileout, "\n" );
7320  fprintf ( fileout, " vertices %d\n", cor3_num );
7321  fprintf ( fileout, " {\n" );
7322  text_num = text_num + 3;
7323 
7324  for ( j = 0; j < cor3_num; j++ )
7325  {
7326  fprintf ( fileout, " [%d] position %f %f %f\n", j, cor3[0][j],
7327  cor3[1][j], cor3[2][j] );
7328  text_num = text_num + 1;
7329  }
7330  fprintf ( fileout, " }\n" );
7331  text_num = text_num + 1;
7332  }
7333 //
7334 // Faces.
7335 //
7336  fprintf ( fileout, "\n" );
7337  fprintf ( fileout, " polygons %d\n", face_num );
7338  fprintf ( fileout, " {\n" );
7339  text_num = text_num + 3;
7340 
7341  for ( iface = 0; iface < face_num; iface++ )
7342  {
7343  fprintf ( fileout, " [%d] nodes %d\n", iface, face_order[iface] );
7344  fprintf ( fileout, " {\n" );
7345  text_num = text_num + 2;
7346 
7347  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
7348  {
7349  fprintf ( fileout, " [%d] vertex %d\n", ivert, face[ivert][iface] );
7350  fprintf ( fileout, " normal %f %f %f\n",
7351  vertex_normal[0][ivert][iface],
7352  vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
7353  fprintf ( fileout, " uvTexture %f %f\n",
7354  vertex_tex_uv[0][ivert][iface], vertex_tex_uv[1][ivert][iface] );
7355  fprintf ( fileout, " vertexColor 255 178 178 178\n" );
7356  text_num = text_num + 4;
7357  }
7358  fprintf ( fileout, " }\n" );
7359  fprintf ( fileout, " material %d\n", face_material[iface] );
7360  text_num = text_num + 2;
7361  }
7362  fprintf ( fileout, " }\n" );
7363  fprintf ( fileout, " }\n" );
7364  text_num = text_num + 2;
7365  }
7366 //
7367 // IndexedLineSet.
7368 //
7369  if ( 0 < line_num )
7370  {
7371  nseg = 0;
7372 
7373  jhi = -1;
7374 
7375  for ( ;; )
7376  {
7377  jlo = jhi + 1;
7378 //
7379 // Look for the next index JLO that is not -1.
7380 //
7381  while ( jlo < line_num )
7382  {
7383  if ( line_dex[jlo] != -1 )
7384  {
7385  break;
7386  }
7387  jlo = jlo + 1;
7388  }
7389 
7390  if ( line_num <= jlo )
7391  {
7392  break;
7393  }
7394 //
7395 // Look for the highest following index JHI that is not -1.
7396 //
7397  jhi = jlo + 1;
7398 
7399  while ( jhi < line_num )
7400  {
7401  if ( line_dex[jhi] == -1 )
7402  {
7403  break;
7404  }
7405  jhi = jhi + 1;
7406  }
7407 
7408  jhi = jhi - 1;
7409 //
7410 // Our next line segment involves LINE_DEX indices JLO through JHI.
7411 //
7412  nseg = nseg + 1;
7413  npts = jhi + 1 - jlo;
7414 
7415  fprintf ( fileout, "\n" );
7416  fprintf ( fileout, " spline\n" );
7417  fprintf ( fileout, " {\n" );
7418  fprintf ( fileout, " name \"spl%d\"\n", nseg );
7419  fprintf ( fileout, " type LINEAR\n" );
7420  fprintf ( fileout, " nbKeys %d\n", npts );
7421  fprintf ( fileout, " tension 0.000\n" );
7422  fprintf ( fileout, " step 1\n" );
7423  fprintf ( fileout, "\n" );
7424  text_num = text_num + 9;
7425 
7426  fprintf ( fileout, " controlpoints\n" );
7427  fprintf ( fileout, " {\n" );
7428  text_num = text_num + 2;
7429 
7430  for ( j = jlo; j <= jhi; j++ )
7431  {
7432  jrel = j - jlo;
7433  k = line_dex[j];
7434  fprintf ( fileout, " [%d] position %f %f %f\n", jrel,
7435  cor3[0][k], cor3[1][k], cor3[2][k] );
7436  text_num = text_num + 1;
7437  }
7438 
7439  fprintf ( fileout, " }\n" );
7440  fprintf ( fileout, " }\n" );
7441  text_num = text_num + 2;
7442  }
7443  }
7444 //
7445 // MATERIALS
7446 //
7447  for ( i = 0; i < material_num; i++ )
7448  {
7449  fprintf ( fileout, " material [%d]\n", i );
7450  fprintf ( fileout, " {\n" );
7451  fprintf ( fileout, " name \"%s\"\n", material_name[i] );
7452  fprintf ( fileout, " type PHONG\n" );
7453  fprintf ( fileout, " ambient %f %f %f\n", material_rgba[0][i],
7454  material_rgba[1][i], material_rgba[2][i] );
7455  fprintf ( fileout, " diffuse %f %f %f\n", material_rgba[0][i],
7456  material_rgba[1][i], material_rgba[2][i] );
7457  fprintf ( fileout, " specular %f %f %f\n", material_rgba[0][i],
7458  material_rgba[1][i], material_rgba[2][i] );
7459  fprintf ( fileout, " exponent 50.0\n" );
7460  fprintf ( fileout, " reflectivity 0.0\n" );
7461  fprintf ( fileout, " transparency %f\n", 1.0 - material_rgba[3][i] );
7462  fprintf ( fileout, " refracIndex 1.0\n" );
7463  fprintf ( fileout, " glow 0\n" );
7464  fprintf ( fileout, " coc 0.0\n" );
7465  fprintf ( fileout, " }\n" );
7466 
7467  text_num = text_num + 14;
7468 
7469  }
7470 //
7471 // TEXTURES
7472 //
7473  for ( i = 0; i < texture_num; i++ )
7474  {
7475  fprintf ( fileout, " texture [%d]\n", i );
7476  fprintf ( fileout, " {\n" );
7477  fprintf ( fileout, " name \"%s\"\n", texture_name[i] );
7478  fprintf ( fileout, " glbname \"t2d1\"\n" );
7479  fprintf ( fileout, " anim STATIC\n" );
7480  fprintf ( fileout, " method XY\n" );
7481  fprintf ( fileout, " repeat 1 1\n" );
7482  fprintf ( fileout, " scaling 1.000 1.000\n" );
7483  fprintf ( fileout, " offset 0.000 0.000\n" );
7484  fprintf ( fileout, " pixelInterp\n" );
7485  fprintf ( fileout, " effect INTENSITY\n" );
7486  fprintf ( fileout, " blending 1.000\n" );
7487  fprintf ( fileout, " ambient 0.977\n" );
7488  fprintf ( fileout, " diffuse 1.000\n" );
7489  fprintf ( fileout, " specular 0.966\n" );
7490  fprintf ( fileout, " reflect 0.000\n" );
7491  fprintf ( fileout, " transp 0.000\n" );
7492  fprintf ( fileout, " roughness 0.000\n" );
7493  fprintf ( fileout, " reflMap 1.000\n" );
7494  fprintf ( fileout, " rotation 0.000\n" );
7495  fprintf ( fileout, " txtsup_rot 0.000 0.000 0.000\n" );
7496  fprintf ( fileout, " txtsup_trans 0.000 0.000 0.000\n" );
7497  fprintf ( fileout, " txtsup_scal 1.000 1.000 1.000\n" );
7498  fprintf ( fileout, " }\n" );
7499 
7500  text_num = text_num + 25;
7501 
7502  }
7503  fprintf ( fileout, "}\n" );
7504  text_num = text_num + 1;
7505 //
7506 // Report.
7507 //
7508  cout << "\n";
7509  cout << "HRC_WRITE - Wrote " << text_num << " text lines.\n";
7510 
7511  return 0;
7512 }
7513 //****************************************************************************80
7514 
7515 int i4_max ( int i1, int i2 )
7516 
7517 //****************************************************************************80
7518 //
7519 // Purpose:
7520 //
7521 // I4_MAX returns the maximum of two I4s.
7522 //
7523 // Licensing:
7524 //
7525 // This code is distributed under the GNU LGPL license.
7526 //
7527 // Modified:
7528 //
7529 // 13 October 1998
7530 //
7531 // Author:
7532 //
7533 // John Burkardt
7534 //
7535 // Parameters:
7536 //
7537 // Input, int I1, I2, are two integers to be compared.
7538 //
7539 // Output, int I4_MAX, the larger of I1 and I2.
7540 //
7541 {
7542  if ( i2 < i1 )
7543  {
7544  return i1;
7545  }
7546  else
7547  {
7548  return i2;
7549  }
7550 
7551 }
7552 //****************************************************************************80
7553 
7554 int i4_min ( int i1, int i2 )
7555 
7556 //****************************************************************************80
7557 //
7558 // Purpose:
7559 //
7560 // I4_MIN returns the smaller of two I4's.
7561 //
7562 // Licensing:
7563 //
7564 // This code is distributed under the GNU LGPL license.
7565 //
7566 // Modified:
7567 //
7568 // 13 October 1998
7569 //
7570 // Author:
7571 //
7572 // John Burkardt
7573 //
7574 // Parameters:
7575 //
7576 // Input, int I1, I2, two integers to be compared.
7577 //
7578 // Output, int I4_MIN, the smaller of I1 and I2.
7579 //
7580 {
7581  if ( i1 < i2 )
7582  {
7583  return i1;
7584  }
7585  else
7586  {
7587  return i2;
7588  }
7589 
7590 }
7591 //****************************************************************************80
7592 
7593 int i4_modp ( int i, int j )
7594 
7595 //****************************************************************************80
7596 //
7597 // Purpose:
7598 //
7599 // I4_MODP returns the nonnegative remainder of I4 division.
7600 //
7601 // Discussion:
7602 //
7603 // If
7604 // NREM = I4_MODP ( I, J )
7605 // NMULT = ( I - NREM ) / J
7606 // then
7607 // I = J * NMULT + NREM
7608 // where NREM is always nonnegative.
7609 //
7610 // The MOD function computes a result with the same sign as the
7611 // quantity being divided. Thus, suppose you had an angle A,
7612 // and you wanted to ensure that it was between 0 and 360.
7613 // Then mod(A,360) would do, if A was positive, but if A
7614 // was negative, your result would be between -360 and 0.
7615 //
7616 // On the other hand, I4_MODP(A,360) is between 0 and 360, always.
7617 //
7618 // Example:
7619 //
7620 // I J MOD I4_MODP I4_MODP Factorization
7621 //
7622 // 107 50 7 7 107 = 2 * 50 + 7
7623 // 107 -50 7 7 107 = -2 * -50 + 7
7624 // -107 50 -7 43 -107 = -3 * 50 + 43
7625 // -107 -50 -7 43 -107 = 3 * -50 + 43
7626 //
7627 // Licensing:
7628 //
7629 // This code is distributed under the GNU LGPL license.
7630 //
7631 // Modified:
7632 //
7633 // 26 May 1999
7634 //
7635 // Author:
7636 //
7637 // John Burkardt
7638 //
7639 // Parameters:
7640 //
7641 // Input, int I, the number to be divided.
7642 //
7643 // Input, int J, the number that divides I.
7644 //
7645 // Output, int I4_MODP, the nonnegative remainder when I is
7646 // divided by J.
7647 //
7648 {
7649  int value;
7650 
7651  if ( j == 0 )
7652  {
7653  cout << "\n";
7654  cout << "I4_MODP - Fatal error!\n";
7655  cout << " I4_MODP ( I, J ) called with J = " << j << "\n";
7656  exit ( 1 );
7657  }
7658 
7659  value = i % j;
7660 
7661  if ( value < 0 )
7662  {
7663  value = value + abs ( j );
7664  }
7665 
7666  return value;
7667 }
7668 //****************************************************************************80
7669 
7670 int i4_wrap ( int ival, int ilo, int ihi )
7671 
7672 //****************************************************************************80
7673 //
7674 // Purpose:
7675 //
7676 // I4_WRAP forces an I4 to lie between given limits by wrapping.
7677 //
7678 // Example:
7679 //
7680 // ILO = 4, IHI = 8
7681 //
7682 // I I4_WRAP
7683 //
7684 // -2 8
7685 // -1 4
7686 // 0 5
7687 // 1 6
7688 // 2 7
7689 // 3 8
7690 // 4 4
7691 // 5 5
7692 // 6 6
7693 // 7 7
7694 // 8 8
7695 // 9 4
7696 // 10 5
7697 // 11 6
7698 // 12 7
7699 // 13 8
7700 // 14 4
7701 //
7702 // Licensing:
7703 //
7704 // This code is distributed under the GNU LGPL license.
7705 //
7706 // Modified:
7707 //
7708 // 19 August 2003
7709 //
7710 // Author:
7711 //
7712 // John Burkardt
7713 //
7714 // Parameters:
7715 //
7716 // Input, int IVAL, an integer value.
7717 //
7718 // Input, int ILO, IHI, the desired bounds for the integer value.
7719 //
7720 // Output, int I4_WRAP, a "wrapped" version of IVAL.
7721 //
7722 {
7723  int jhi;
7724  int jlo;
7725  int value;
7726  int wide;
7727 
7728  jlo = i4_min ( ilo, ihi );
7729  jhi = i4_max ( ilo, ihi );
7730 
7731  wide = jhi + 1 - jlo;
7732 
7733  if ( wide == 1 )
7734  {
7735  value = jlo;
7736  }
7737  else
7738  {
7739  value = jlo + i4_modp ( ival - jlo, wide );
7740  }
7741 
7742  return value;
7743 }
7744 //****************************************************************************80
7745 
7747 
7748 //****************************************************************************80
7749 //
7750 // Purpose:
7751 //
7752 // INIT_PROGRAM_DATA initializes the internal program data.
7753 //
7754 // Licensing:
7755 //
7756 // This code is distributed under the GNU LGPL license.
7757 //
7758 // Modified:
7759 //
7760 // 26 May 1999
7761 //
7762 // Author:
7763 //
7764 // John Burkardt
7765 //
7766 {
7767  byte_swap = false;
7768  debug = false;
7769  line_prune = 1;
7770  color_num = 0;
7771  cor3_num = 0;
7772  face_num = 0;
7773  line_num = 0;
7774 
7775  if ( debug )
7776  {
7777  cout << "\n";
7778  cout << "INIT_PROGRAM_DATA: Program data initialized.\n";
7779  }
7780 
7781  return;
7782 
7783 }
7784 //****************************************************************************80
7785 
7786 int interact ( )
7787 
7788 //****************************************************************************80
7789 //
7790 // Purpose:
7791 //
7792 // INTERACT carries on an interactive session with the user.
7793 //
7794 // Licensing:
7795 //
7796 // This code is distributed under the GNU LGPL license.
7797 //
7798 // Modified:
7799 //
7800 // 09 May 2005
7801 //
7802 // Author:
7803 //
7804 // John Burkardt
7805 //
7806 {
7807  int i;
7808  int icor3;
7809  int ierror;
7810  int iface;
7811  int itemp;
7812  int ivert;
7813  int j;
7814  int jvert;
7815  int m;
7816  char *next;
7817  bool success;
7818  float temp;
7819  float x;
7820  float y;
7821  float z;
7822 
7823  strcpy ( filein_name, "NO_IN_NAME" );
7824  strcpy ( fileout_name, "NO_OUT_NAME" );
7825 //
7826 // Say hello.
7827 //
7828  hello ( );
7829 //
7830 // Get the next user command.
7831 //
7832  cout << "\n";
7833  cout << "Enter command (H for help)\n";
7834 
7835  while ( fgets ( input, LINE_MAX_LEN, stdin ) != NULL )
7836  {
7837 //
7838 // Advance to the first nonspace character in INPUT.
7839 //
7840  for ( next = input; *next != '\0' && ch_is_space ( *next ); next++ )
7841  {
7842  }
7843 //
7844 // Skip blank lines and comments.
7845 //
7846  if ( *next == '\0' )
7847  {
7848  continue;
7849  }
7850 //
7851 // Command: << FILENAME
7852 // Append new data to current graphics information.
7853 //
7854  if ( *next == '<' && *(next+1) == '<' )
7855  {
7856  next = next + 2;
7857  sscanf ( next, "%s", filein_name );
7858 
7859  success = data_read ( );
7860 
7861  if ( !success )
7862  {
7863  cout << "\n";
7864  cout << "INTERACT - Fatal error!\n";
7865  cout << " Failure reported from DATA_READ.\n";
7866  }
7867  }
7868 //
7869 // Command: < FILENAME
7870 //
7871  else if ( *next == '<' )
7872  {
7873  next = next + 1;
7874  sscanf ( next, "%s", filein_name );
7875 
7876  data_init ( );
7877 
7878  success = data_read ( );
7879 
7880  if ( !success )
7881  {
7882  cout << "\n";
7883  cout << "INTERACT - Fatal error!\n";
7884  cout << " DATA_READ failed to read input data.\n";
7885  }
7886  }
7887 //
7888 // Command: > FILENAME
7889 //
7890  else if ( *next == '>' )
7891  {
7892  next = next + 1;
7893  sscanf ( next, "%s", fileout_name );
7894 
7895  ierror = data_write ( );
7896 
7897  if ( ierror == ERROR )
7898  {
7899  cout << "\n";
7900  cout << "INTERACT - Fatal error!\n";
7901  cout << " OUTPUT_DATA failed to write output data.\n";
7902  }
7903 
7904  }
7905 //
7906 // B: Switch byte swapping option.
7907 //
7908  else if ( *next == 'B' || *next == 'b' )
7909  {
7910  if ( byte_swap )
7911  {
7912  byte_swap = false;
7913  cout << "Byte_swapping reset to FALSE.\n";
7914  }
7915  else
7916  {
7917  byte_swap = true;
7918  cout << "Byte_swapping reset to TRUE.\n";
7919  }
7920 
7921  }
7922 //
7923 // D: Switch debug option.
7924 //
7925  else if ( *next == 'D' || *next == 'd' )
7926  {
7927  if ( debug )
7928  {
7929  debug = false;
7930  cout << "Debug reset to FALSE.\n";
7931  }
7932  else
7933  {
7934  debug = true;
7935  cout << "Debug reset to TRUE.\n";
7936  }
7937  }
7938 //
7939 // F: Check a face.
7940 //
7941  else if ( *next == 'f' || *next == 'F' )
7942  {
7943  cout << "\n";
7944  cout << " Enter a face index between 0 and " << face_num-1 << "\n";
7945  scanf ( "%d", &iface );
7946  face_print ( iface );
7947  }
7948 //
7949 // H: Help
7950 //
7951  else if ( *next == 'h' || *next == 'H' )
7952  {
7953  help ( );
7954  }
7955 //
7956 // I: Print change information.
7957 //
7958  else if ( *next == 'i' || *next == 'I')
7959  {
7960  news ( );
7961  }
7962 //
7963 // LINES:
7964 // Convert face information to lines.
7965 //
7966  else if ( *next == 'l' || *next == 'L')
7967  {
7968  if ( 0 < face_num )
7969  {
7970  cout << "\n";
7971  cout << "INTERACT - Note:\n";
7972  cout << " Face information will be converted\n";
7973  cout << " to line information.\n";
7974 
7975  face_to_line ( );
7976 
7977  if ( LINES_MAX < line_num )
7978  {
7979  cout << "\n";
7980  cout << "INTERACT - Note:\n";
7981  cout << " Some face information was lost.\n";
7982  cout << " The maximum number of lines is " << LINES_MAX << "\n";
7983  cout << " but we would need at least " << line_num << ".\n";
7984 
7985  line_num = LINES_MAX;
7986 
7987  }
7988 
7989  face_num = 0;
7990  }
7991  else
7992  {
7993  cout << "\n";
7994  cout << "INTERACT - Note:\n";
7995  cout << " There were no faces to convert.\n";
7996 
7997  }
7998 
7999  }
8000 //
8001 // N: Recompute normal vectors.
8002 //
8003  else if ( *next == 'n' || *next == 'N' )
8004  {
8005  for ( iface = 0; iface < face_num; iface++ )
8006  {
8007  for ( i = 0; i < 3; i++ )
8008  {
8009  face_normal[i][iface] = 0.0;
8010  }
8011  }
8012 
8013  for ( iface = 0; iface < face_num; iface++ )
8014  {
8015  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
8016  {
8017  for ( i = 0; i < 3; i++ )
8018  {
8019  vertex_normal[i][ivert][iface] = 0.0;
8020  }
8021  }
8022  }
8023 
8024  vertex_normal_set ( );
8025 
8026  cor3_normal_set ( );
8027 
8028  face_normal_ave ( );
8029  }
8030 //
8031 // P: Line pruning optiont
8032 //
8033  else if ( *next == 'p' || *next == 'P' )
8034  {
8035  cout << "\n";
8036  cout << "INTERACT - SET LINE PRUNING OPTION.\n";
8037  cout << "\n";
8038  cout << " LINE_PRUNE = 0 means no line pruning.\n";
8039  cout << " nonzero means line pruning.\n";
8040  cout << "\n";
8041  cout << " Current value is LINE_PRUNE = " << line_prune << ".\n";
8042  cout << "\n";
8043  cout << " Enter new value for LINE_PRUNE.\n";
8044 
8045  if ( fgets ( input, LINE_MAX_LEN, stdin ) == NULL )
8046  {
8047  cout << " ??? Error trying to read input.\n" ;
8048  }
8049  else
8050  {
8051  sscanf ( input, "%d", &line_prune );
8052  cout << " New value is LINE_PRUNE = " << line_prune << ".\n";
8053  }
8054  }
8055 //
8056 // Q: Quit
8057 //
8058  else if ( *next == 'q' || *next == 'Q' )
8059  {
8060  cout << "\n";
8061  cout << "INTERACT - Normal end of execution.\n";
8062  return 0;
8063  }
8064 //
8065 // R: Reverse normal vectors.
8066 //
8067  else if ( *next == 'r' || *next == 'R' )
8068  {
8069  for ( icor3 = 0; icor3 < cor3_num; icor3++ )
8070  {
8071  for ( i = 0; i < 3; i++ )
8072  {
8073  cor3_normal[i][icor3] = - cor3_normal[i][icor3];
8074  }
8075  }
8076 
8077  for ( iface = 0; iface < face_num; iface++ )
8078  {
8079  for ( i = 0; i < 3; i++ )
8080  {
8081  face_normal[i][iface] = - face_normal[i][iface];
8082  }
8083  }
8084 
8085  for ( iface = 0; iface < face_num; iface++ )
8086  {
8087  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
8088  {
8089  for ( i = 0; i < 3; i++ )
8090  {
8091  vertex_normal[i][ivert][iface] =
8092  - vertex_normal[i][ivert][iface];
8093  }
8094  }
8095  }
8096  cout << "\n";
8097  cout << "INTERACT - Note:\n";
8098  cout << " Reversed node, face and vertex normals.\n";
8099  }
8100 //
8101 // S: Select a few faces, discard the rest.
8102 //
8103  else if ( *next == 's' || *next == 'S' )
8104  {
8105  face_subset ( );
8106  }
8107 //
8108 // T: Transform the data.
8109 //
8110  else if ( *next == 't' || *next == 'T' )
8111  {
8112  cout << "\n";
8113  cout << "For now, we only offer point scaling.\n";
8114  cout << "Enter X, Y, Z scale factors:\n";
8115 
8116  scanf ( "%f %f %f", &x, &y, &z );
8117 
8118  for ( j = 0; j < cor3_num; j++ )
8119  {
8120  cor3[0][j] = x * cor3[0][j];
8121  cor3[1][j] = y * cor3[1][j];
8122  cor3[2][j] = z * cor3[2][j];
8123  }
8124 
8125  for ( iface = 0; iface < face_num; iface++ )
8126  {
8127  for ( i = 0; i < 3; i++ )
8128  {
8129  face_normal[i][iface] = 0.0;
8130  }
8131  }
8132 
8133  for ( iface = 0; iface < face_num; iface++ )
8134  {
8135  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
8136  {
8137  for ( i = 0; i < 3; i++ )
8138  {
8139  vertex_normal[i][ivert][iface] = 0.0;
8140  }
8141  }
8142  }
8143 
8144  vertex_normal_set ( );
8145 
8146  cor3_normal_set ( );
8147 
8148  face_normal_ave ( );
8149  }
8150 //
8151 // U: Renumber faces, count objects:
8152 //
8153  else if ( *next == 'u' || *next == 'U' )
8154  {
8155  }
8156 //
8157 // V: Convert polygons to triangles:
8158 //
8159  else if ( *next == 'v' || *next == 'V' )
8160  {
8161  }
8162 //
8163 // W: Reverse the face node ordering.
8164 //
8165  else if ( *next == 'w' || *next == 'W' )
8166  {
8167  if ( 0 < face_num )
8168  {
8169  for ( iface = 0; iface < face_num; iface++ )
8170  {
8171  m = face_order[iface];
8172 
8173  for ( ivert = 0; ivert < m/2; ivert++ )
8174  {
8175  jvert = m - ivert - 1;
8176 
8177  itemp = face[ivert][iface];
8178  face[ivert][iface] = face[jvert][iface];
8179  face[jvert][iface] = itemp;
8180 
8181  itemp = vertex_material[ivert][iface];
8182  vertex_material[ivert][iface] = vertex_material[jvert][iface];
8183  vertex_material[jvert][iface] = itemp;
8184 
8185  for ( i = 0; i < 3; i++ )
8186  {
8187  temp = vertex_normal[i][ivert][iface];
8188  vertex_normal[i][ivert][iface] =
8189  vertex_normal[i][jvert][iface];
8190  vertex_normal[i][jvert][iface] = temp;
8191  }
8192  }
8193  }
8194  cout << "\n";
8195  cout << "INTERACT - Note:\n";
8196  cout << " Reversed face node ordering.\n";
8197  }
8198  }
8199 //
8200 // Command: ???
8201 //
8202  else
8203  {
8204  cout << "\n";
8205  cout << "INTERACT: Warning!\n";
8206  cout << " Your command was not recognized.\n";
8207  }
8208 
8209  cout << "\n";
8210  cout << "Enter command (H for help)\n";
8211 
8212  }
8213  return 0;
8214 }
8215 //****************************************************************************80
8216 
8217 int iv_read ( FILE *filein )
8218 
8219 //****************************************************************************80
8220 //
8221 // Purpose:
8222 //
8223 // IV_READ reads graphics information from an Inventor file.
8224 //
8225 // Example:
8226 //
8227 // #Inventor V2.0 ascii
8228 //
8229 // Separator {
8230 // Info {
8231 // string "Inventor file generated by IVCON.
8232 // Original data in file cube.iv."
8233 // }
8234 // Separator {
8235 // LightModel {
8236 // model PHONG
8237 // }
8238 // MatrixTransform { matrix
8239 // 0.9 0.0 0.0 0.0
8240 // 0.0 -0.9 0.0 0.0
8241 // 0.0 0.0 -1.5 0.0
8242 // 0.0 0.0 0.0 1.0
8243 // }
8244 // Material {
8245 // ambientColor 0.2 0.2 0.2
8246 // diffuseColor [
8247 // 0.8 0.8 0.8,
8248 // 0.7 0.1 0.1,
8249 // 0.1 0.8 0.2,
8250 // ]
8251 // emissiveColor 0.0 0.0 0.0
8252 // specularColor 0.0 0.0 0.0
8253 // shininess 0.2
8254 // transparency [
8255 // 0.0, 0.5, 1.0,
8256 // ]
8257 // }
8258 // Texture2 {
8259 // filename "fred.rgb"
8260 // wrapS REPEAT
8261 // wrapT REPEAT
8262 // model MODULATE
8263 // blendColor 0.0 0.0 0.0
8264 // }
8265 //
8266 // MaterialBinding {
8267 // value PER_VERTEX_INDEXED
8268 // }
8269 // NormalBinding {
8270 // value PER_VERTEX_INDEXED
8271 // }
8272 // TextureCoordinateBinding {
8273 // value PER_VERTEX_INDEXED
8274 // }
8275 //
8276 // ShapeHints {
8277 // vertexOrdering COUNTERCLOCKWISE
8278 // shapeType UNKNOWN_SHAPE_TYPE
8279 // faceType CONVEX
8280 // creaseAngle 6.28319
8281 // }
8282 //
8283 // Coordinate3 {
8284 // point [
8285 // 8.59816 5.55317 -3.05561,
8286 // 8.59816 2.49756 0.000000E+00,
8287 // ...etc...
8288 // 2.48695 2.49756 -3.05561,
8289 // ]
8290 // }
8291 //
8292 // Normal {
8293 // vector [
8294 // 0.71 0.71 0.0,
8295 // ...etc...
8296 // 0.32 0.32 0.41,
8297 // ]
8298 // }
8299 //
8300 // TextureCoordinate2 {
8301 // point [
8302 // 0.0 1.0,
8303 // 0.1, 0.8,
8304 // ...etc...
8305 // 0.4 0.7,
8306 // ]
8307 // }
8308 //
8309 // IndexedLineSet {
8310 // coordIndex [
8311 // 0, 1, 2, -1,
8312 // 3, 4, 5, -1,
8313 // 7, 8, 9, -1,
8314 // ...etc...
8315 // 189, 190, 191, -1,
8316 // ]
8317 // materialIndex [
8318 // 0, 0, 0, -1,
8319 // 1, 1, 1, -1,
8320 // 2, 2, 2, -1,
8321 // ...etc...
8322 // 64, 64, 64, -1,
8323 // ]
8324 // }
8325 //
8326 // IndexedFaceSet {
8327 // coordIndex [
8328 // 0, 1, 2, -1,
8329 // 3, 4, 5, -1,
8330 // 7, 8, 9, -1,
8331 // ...etc...
8332 // 189, 190, 191, -1,
8333 // ]
8334 // materialIndex [
8335 // 0, 0, 0, -1,
8336 // 1, 1, 1, -1,
8337 // 2, 2, 2, -1,
8338 // ...etc...
8339 // 64, 64, 64, -1,
8340 // ]
8341 // normalIndex [
8342 // 0, 0, 0, -1,
8343 // 1, 1, 1, -1,
8344 // 2, 2, 2, -1,
8345 // ...etc...
8346 // 64, 64, 64, -1,
8347 // ]
8348 // textureCoordIndex [
8349 // 0, 0, 0, -1,
8350 // 1, 1, 1, -1,
8351 // 2, 2, 2, -1,
8352 // ...etc...
8353 // 64, 64, 64, -1,
8354 // ]
8355 // }
8356 //
8357 // IndexedTriangleStripSet {
8358 // vertexProperty VertexProperty {
8359 // vertex [ x y z,
8360 // ...
8361 // x y z ]
8362 // normal [ x y z,
8363 // ...
8364 // x y z ]
8365 // materialBinding OVERALL
8366 // normalBinding PER_VERTEX_INDEXED
8367 // }
8368 // coordIndex [
8369 // i, j, k, l, m, -1,
8370 // n, o, p, q, r, s, t, u, -1,
8371 // v, w, x, -1
8372 // ..., -1 ]
8373 // normalIndex -1
8374 // }
8375 //
8376 // }
8377 // }
8378 //
8379 // Licensing:
8380 //
8381 // This code is distributed under the GNU LGPL license.
8382 //
8383 // Modified:
8384 //
8385 // 01 July 1999
8386 //
8387 // Author:
8388 //
8389 // John Burkardt
8390 //
8391 {
8392  char c;
8393  int count;
8394  int i;
8395  int icol;
8396  int icolor;
8397  int icface;
8398  int inormface;
8399  int iface_num;
8400  int irow;
8401  int iuv;
8402  int ivert;
8403  int iword;
8404  int ix;
8405  int ixyz;
8406  int iy;
8407  int iz;
8408  int j;
8409  int jval;
8410  int level;
8411  char *next;
8412  int nlbrack;
8413  int nrbrack;
8414  int nu;
8415  int null_index;
8416  int cor3_num_old;
8417  int line_num2;
8418  int face_num2;
8419  int normal_num_temp;
8420  int text_numure_temp;
8421  int nv;
8422  int result;
8423  float rval;
8424  int width;
8425  char word[LINE_MAX_LEN];
8426  char word1[LINE_MAX_LEN];
8427  char wordm1[LINE_MAX_LEN];
8428  float xvec[3];
8429 
8430  icface = 0;
8431  icol = -1;
8432  inormface = 0;
8433  iface_num = face_num;
8434  irow = 0;
8435  ix = 0;
8436  ixyz = 0;
8437  iy = 0;
8438  iz = 0;
8439  jval = 0;
8440  level = 0;
8441  strcpy ( level_name[0], "Top" );
8442  nlbrack = 0;
8443  nrbrack = 0;
8444  nu = 0;
8445  cor3_num_old = cor3_num;
8446  face_num2 = face_num;
8447  line_num2 = line_num;
8448  normal_num_temp = 0;
8449  text_numure_temp = 0;
8450  nv = 0;
8451  rval = 0.0;
8452  strcpy ( word, " " );
8453  strcpy ( wordm1, " " );
8454 //
8455 // Read the next line of text from the input file.
8456 //
8457  for ( ;; )
8458  {
8459  if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL )
8460  {
8461  break;
8462  }
8463 
8464  text_num = text_num + 1;
8465  next = input;
8466  iword = 0;
8467 //
8468 // Remove all commas from the line, so we can use SSCANF to read
8469 // numeric items.
8470 //
8471  i = 0;
8472  while ( input[i] != '\0' )
8473  {
8474  if ( input[i] == ',' )
8475  {
8476  input[i] = ' ';
8477  }
8478  i++;
8479  }
8480 //
8481 // Force brackets and braces to be buffered by spaces.
8482 //
8483  i = 0;
8484  while ( input[i] != '\0' )
8485  {
8486  i++;
8487  }
8488  null_index = i;
8489 
8490  i = 0;
8491  while ( input[i] != '\0' && i < LINE_MAX_LEN )
8492  {
8493  if ( input[i] == '[' || input[i] == ']' ||
8494  input[i] == '{' || input[i] == '}' )
8495  {
8496  result = ch_pad ( &i, &null_index, input, LINE_MAX_LEN );
8497  if ( result == ERROR )
8498  {
8499  break;
8500  }
8501  }
8502  else
8503  {
8504  i++;
8505  }
8506  }
8507 //
8508 // Read a word from the line.
8509 //
8510  for ( ;; )
8511  {
8512  strcpy ( wordm1, word );
8513  strcpy ( word, " " );
8514 
8515  count = sscanf ( next, "%s%n", word, &width );
8516  next = next + width;
8517 
8518  if ( count <= 0 )
8519  {
8520  break;
8521  }
8522 
8523  iword = iword + 1;
8524 
8525  if ( iword == 1 )
8526  {
8527  strcpy ( word1, word );
8528  }
8529 //
8530 // The first line of the file must be the header.
8531 //
8532  if ( text_num == 1 )
8533  {
8534  if ( !s_eqi ( word1, "#Inventor" ) )
8535  {
8536  cout << "\n";
8537  cout << "IV_READ - Fatal error!\n";
8538  cout << " The input file has a bad header.\n";
8539  return 1;
8540  }
8541  else
8542  {
8543  comment_num = comment_num + 1;
8544  }
8545  break;
8546  }
8547 //
8548 // A comment begins anywhere with '#'.
8549 // Skip the rest of the line.
8550 //
8551  if ( word[1] == '#' )
8552  {
8553  comment_num = comment_num + 1;
8554  break;
8555  }
8556 //
8557 // If the word is a curly or square bracket, count it.
8558 // If the word is a left bracket, the previous word is the name of a node.
8559 //
8560  if ( strcmp ( word, "{" ) == 0 || strcmp ( word, "[" ) == 0 )
8561  {
8562  nlbrack = nlbrack + 1;
8563  level = nlbrack - nrbrack;
8564  strcpy ( level_name[level], wordm1 );
8565  if ( debug )
8566  {
8567  cout << "Begin level: " << wordm1 << "\n";
8568  }
8569  }
8570  else if ( strcmp ( word, "}" ) == 0 || strcmp ( word, "]" ) == 0 )
8571  {
8572  nrbrack = nrbrack + 1;
8573 
8574  if ( nlbrack < nrbrack )
8575  {
8576  cout << "\n";
8577  cout << "IV_READ - Fatal error!\n";
8578  cout << " Extraneous right bracket on line " << text_num << ".\n";
8579  cout << " Currently processing field " << level_name[level] << "\n";
8580  return 1;
8581  }
8582  }
8583 //
8584 // BASECOLOR
8585 //
8586  if ( s_eqi ( level_name[level], "BASECOLOR" ) )
8587  {
8588  if ( strcmp ( word, "{" ) == 0 )
8589  {
8590  }
8591  else if ( strcmp ( word, "}" ) == 0 )
8592  {
8593  level = nlbrack - nrbrack;
8594  }
8595  else if ( s_eqi ( word, "RGB" ) )
8596  {
8597  }
8598  else
8599  {
8600  bad_num = bad_num + 1;
8601  cout << "Bad data " << word << "\n";
8602  }
8603  }
8604 //
8605 // COORDINATE3
8606 //
8607  else if ( s_eqi ( level_name[level], "COORDINATE3" ) )
8608  {
8609  if ( strcmp ( word, "{" ) == 0 )
8610  {
8611  }
8612  else if ( strcmp ( word, "}" ) == 0 )
8613  {
8614  level = nlbrack - nrbrack;
8615  }
8616  else if ( s_eqi ( word, "POINT" ) )
8617  {
8618  }
8619  else
8620  {
8621  bad_num = bad_num + 1;
8622  cout << "COORDINATE3: Bad data " << word << "\n";
8623  }
8624  }
8625 //
8626 // COORDINATE4
8627 //
8628  else if ( s_eqi ( level_name[level], "COORDINATE4" ) )
8629  {
8630  if ( strcmp ( word, "{" ) == 0 )
8631  {
8632  }
8633  else if ( strcmp ( word, "}" ) == 0 )
8634  {
8635  level = nlbrack - nrbrack;
8636  }
8637  else if ( s_eqi ( word, "POINT" ) )
8638  {
8639  }
8640  else
8641  {
8642  bad_num = bad_num + 1;
8643  cout << "COORDINATE4: Bad data " << word << "\n";
8644  }
8645  }
8646 //
8647 // COORDINDEX
8648 //
8649  else if ( s_eqi ( level_name[level], "COORDINDEX" ) )
8650  {
8651  if ( strcmp ( word, "[" ) == 0 )
8652  {
8653  ivert = 0;
8654  }
8655  else if ( strcmp ( word, "]" ) == 0 )
8656  {
8657  level = nlbrack - nrbrack;
8658  }
8659 //
8660 // (indexedlineset) COORDINDEX
8661 //
8662  else if ( s_eqi ( level_name[level-1], "INDEXEDLINESET" ) )
8663  {
8664 
8665  count = sscanf ( word, "%d%n", &jval, &width );
8666 
8667  if ( 0 < count )
8668  {
8669  if ( jval < -1 )
8670  {
8671  bad_num = bad_num + 1;
8672  }
8673  else
8674  {
8675  if ( line_num < LINES_MAX )
8676  {
8677  if ( jval != -1 )
8678  {
8679  jval = jval + cor3_num_old;
8680  }
8681  line_dex[line_num] = jval;
8682  }
8683  line_num = line_num + 1;
8684  }
8685  }
8686  else
8687  {
8688  bad_num = bad_num + 1;
8689  }
8690  }
8691 //
8692 // (indexedfaceset) COORDINDEX
8693 // Warning: If the list of indices is not terminated with a final -1, then
8694 // the last face won't get counted.
8695 //
8696  else if ( s_eqi ( level_name[level-1], "INDEXEDFACESET" ) )
8697  {
8698  count = sscanf ( word, "%d%n", &jval, &width );
8699 
8700  if ( 0 < count )
8701  {
8702  if ( jval == -1 )
8703  {
8704  ivert = 0;
8705  face_num = face_num + 1;
8706  }
8707  else
8708  {
8709  if ( ivert == 0 )
8710  {
8711  if ( face_num < FACE_MAX )
8712  {
8713  face_order[face_num] = 0;
8714  }
8715  }
8716  if ( face_num < FACE_MAX )
8717  {
8719  face[ivert][face_num] = jval + cor3_num_old;
8720  ivert = ivert + 1;
8721  }
8722  }
8723  }
8724  }
8725 //
8726 // (indexednurbssurface) COORDINDEX
8727 //
8728  else if ( s_eqi ( level_name[level-1], "INDEXEDNURBSSURFACE" ) )
8729  {
8730  }
8731 //
8732 // (indexedtrianglestripset) COORDINDEX
8733 //
8734 // First three coordinate indices I1, I2, I3 define a triangle.
8735 // Next triangle is defined by I2, I3, I4 (actually, I4, I3, I2
8736 // to stay with same counterclockwise sense).
8737 // Next triangle is defined by I3, I4, I5 ( do not need to reverse
8738 // odd numbered triangles) and so on.
8739 // List is terminated with -1.
8740 //
8741  else if ( s_eqi ( level_name[level-1], "INDEXEDTRIANGLESTRIPSET" ) )
8742  {
8743  count = sscanf ( word, "%d%n", &jval, &width );
8744 
8745  if ( 0 < count )
8746  {
8747  if ( jval == -1 )
8748  {
8749  ivert = 0;
8750  }
8751  else
8752  {
8753  ix = iy;
8754  iy = iz;
8755  iz = jval + cor3_num_old;
8756 
8757  if ( ivert == 0 )
8758  {
8759  if ( face_num < FACE_MAX )
8760  {
8761  face[ivert][face_num] = jval + cor3_num_old;
8762  face_order[face_num] = 3;
8763  }
8764  }
8765  else if ( ivert == 1 )
8766  {
8767  if ( face_num < FACE_MAX )
8768  {
8769  face[ivert][face_num] = jval + cor3_num_old;
8770  }
8771  }
8772  else if ( ivert == 2 )
8773  {
8774  if ( face_num < FACE_MAX )
8775  {
8776  face[ivert][face_num] = jval + cor3_num_old;
8777  }
8778  face_num = face_num + 1;
8779  }
8780  else
8781  {
8782  if ( face_num < FACE_MAX )
8783  {
8784  face_order[face_num] = 3;
8785  if ( ( ivert % 2 ) == 0 )
8786  {
8787  face[0][face_num] = ix;
8788  face[1][face_num] = iy;
8789  face[2][face_num] = iz;
8790  }
8791  else
8792  {
8793  face[0][face_num] = iz;
8794  face[1][face_num] = iy;
8795  face[2][face_num] = ix;
8796  }
8797  }
8798  face_num = face_num + 1;
8799  }
8800  ivert = ivert + 1;
8801 //
8802 // Very very tentative guess as to how indices into the normal
8803 // vector array are set up...
8804 //
8805  if ( face_num < FACE_MAX && 2 < ivert )
8806  {
8807  for ( i = 0; i < 3; i++ )
8808  {
8809  face_normal[i][face_num] = normal_temp[i][ix];
8810  }
8811  }
8812  }
8813  }
8814  }
8815  }
8816 //
8817 // INDEXEDFACESET
8818 //
8819  else if ( s_eqi ( level_name[level], "INDEXEDFACESET" ) )
8820  {
8821  if ( strcmp ( word, "{" ) == 0 )
8822  {
8823  }
8824  else if ( strcmp ( word, "}" ) == 0 )
8825  {
8826  level = nlbrack - nrbrack;
8827  }
8828  else if ( s_eqi ( word, "COORDINDEX" ) )
8829  {
8830  ivert = 0;
8831  }
8832  else if ( s_eqi ( word, "MATERIALINDEX" ) )
8833  {
8834  }
8835  else if ( s_eqi ( word, "NORMALINDEX" ) )
8836  {
8837  }
8838  else if ( s_eqi ( word, "TEXTURECOORDINDEX" ) )
8839  {
8840  if ( texture_num <= 0 )
8841  {
8842  texture_num = 1;
8843  strcpy ( texture_name[0], "Texture_0000" );
8844  }
8845  }
8846  else
8847  {
8848  bad_num = bad_num + 1;
8849  cout << "Bad data " << word << "\n";
8850  }
8851  }
8852 //
8853 // INDEXEDLINESET
8854 //
8855  else if ( s_eqi ( level_name[level], "INDEXEDLINESET" ) )
8856  {
8857  if ( strcmp ( word, "{" ) == 0 )
8858  {
8859  }
8860  else if ( strcmp ( word, "}" ) == 0 )
8861  {
8862  level = nlbrack - nrbrack;
8863  }
8864  else if ( s_eqi ( word, "COORDINDEX" ) )
8865  {
8866  }
8867  else if ( s_eqi ( word, "MATERIALINDEX" ) )
8868  {
8869  }
8870  else
8871  {
8872  bad_num = bad_num + 1;
8873  cout << "Bad data " << word << "\n";
8874  }
8875  }
8876 //
8877 // INDEXEDNURBSSURFACE
8878 //
8879  else if ( s_eqi ( level_name[level], "INDEXEDNURBSSURFACE" ) )
8880  {
8881  if ( strcmp ( word, "{" ) == 0 )
8882  {
8883  }
8884  else if ( strcmp ( word, "}" ) == 0 )
8885  {
8886  level = nlbrack - nrbrack;
8887  }
8888  else if ( s_eqi ( word, "NUMUCONTROLPOINTS" ) )
8889  {
8890  count = sscanf ( word, "%d%n", &jval, &width );
8891 
8892  if ( 0 < count )
8893  {
8894  nu = jval;
8895  if ( debug )
8896  {
8897  cout << "NU = " << nu << "\n";
8898  }
8899  }
8900  else
8901  {
8902  nu = 0;
8903  bad_num = bad_num + 1;
8904  cout << "Bad data " << word << "\n";
8905  }
8906  }
8907  else if ( s_eqi ( word, "NUMVCONTROLPOINTS" ) )
8908  {
8909  count = sscanf ( word, "%d%n", &jval, &width );
8910 
8911  if ( 0 < count )
8912  {
8913  nv = jval;
8914  if ( debug )
8915  {
8916  cout << "NV = " << nv << "\n";
8917  }
8918  }
8919  else
8920  {
8921  nv = 0;
8922  bad_num = bad_num + 1;
8923  }
8924  }
8925  else if ( s_eqi ( word, "COORDINDEX" ) )
8926  {
8927  }
8928  else if ( s_eqi ( word, "UKNOTVECTOR" ) )
8929  {
8930  }
8931  else if ( s_eqi ( word, "VKNOTVECTOR" ) )
8932  {
8933  }
8934  else
8935  {
8936  bad_num = bad_num + 1;
8937  cout << "Bad data " << word << "\n";
8938  }
8939  }
8940 //
8941 // INDEXEDTRIANGLESTRIPSET
8942 //
8943  else if ( s_eqi ( level_name[level], "INDEXEDTRIANGLESTRIPSET" ) )
8944  {
8945  if ( strcmp ( word, "{" ) == 0 )
8946  {
8947  }
8948  else if ( strcmp ( word, "}" ) == 0 )
8949  {
8950  level = nlbrack - nrbrack;
8951  }
8952  else if ( s_eqi ( word, "VERTEXPROPERTY" ) )
8953  {
8954  count = sscanf ( next, "%s%n", word, &width );
8955  next = next + width;
8956  }
8957  else if ( s_eqi ( word, "COORDINDEX" ) )
8958  {
8959  ivert = 0;
8960  }
8961  else if ( s_eqi ( word, "NORMALINDEX" ) )
8962  {
8963  count = sscanf ( next, "%s%n", word, &width );
8964  next = next + width;
8965  }
8966  else
8967  {
8968  bad_num = bad_num + 1;
8969  cout << "Bad data " << word << "\n";
8970  }
8971  }
8972 //
8973 // INFO
8974 //
8975  else if ( s_eqi ( level_name[level], "INFO" ) )
8976  {
8977  if ( strcmp ( word, "{" ) == 0 )
8978  {
8979  }
8980  else if ( strcmp ( word, "}" ) == 0 )
8981  {
8982  level = nlbrack - nrbrack;
8983  }
8984  else if ( s_eqi ( word, "STRING" ) )
8985  {
8986  }
8987  else if ( strcmp ( word, "\"" ) == 0 )
8988  {
8989  }
8990  else
8991  {
8992  }
8993  }
8994 //
8995 // LIGHTMODEL
8996 // Read, but ignore.
8997 //
8998  else if ( s_eqi ( level_name[level], "LIGHTMODEL" ) )
8999  {
9000  if ( strcmp ( word, "{" ) == 0 )
9001  {
9002  }
9003  else if ( strcmp ( word, "}" ) == 0 )
9004  {
9005  level = nlbrack - nrbrack;
9006  }
9007  else if ( s_eqi ( word, "model" ) )
9008  {
9009  }
9010  else
9011  {
9012  }
9013  }
9014 //
9015 // MATERIAL
9016 // Read, but ignore.
9017 //
9018  else if ( s_eqi ( level_name[level],"MATERIAL" ) )
9019  {
9020  if ( strcmp ( word, "{" ) == 0 )
9021  {
9022  }
9023  else if ( strcmp ( word, "}" ) == 0 )
9024  {
9025  level = nlbrack - nrbrack;
9026  }
9027  else if ( s_eqi ( word, "AMBIENTCOLOR" ) )
9028  {
9029  }
9030  else if ( s_eqi ( word, "EMISSIVECOLOR" ) )
9031  {
9032  }
9033  else if ( s_eqi ( word, "DIFFUSECOLOR" ) )
9034  {
9035  }
9036  else if ( s_eqi ( word, "SHININESS" ) )
9037  {
9038  }
9039  else if ( s_eqi ( word, "SPECULARCOLOR" ) )
9040  {
9041  }
9042  else if ( s_eqi ( word, "TRANSPARENCY" ) )
9043  {
9044  }
9045  else
9046  {
9047  }
9048  }
9049 //
9050 // MATERIALBINDING
9051 // Read, but ignore
9052 //
9053  else if ( s_eqi ( level_name[level], "MATERIALBINDING" ) )
9054  {
9055  if ( strcmp ( word, "{" ) == 0 )
9056  {
9057  }
9058  else if ( strcmp ( word, "}" ) == 0 )
9059  {
9060  level = nlbrack - nrbrack;
9061  }
9062  else if ( s_eqi ( word, "VALUE" ) )
9063  {
9064  count = sscanf ( next, "%s%n", material_binding, &width );
9065  next = next + width;
9066  }
9067  else
9068  {
9069  count = sscanf ( next, "%f%n", &rval, &width );
9070  next = next + width;
9071 
9072  if ( 0 < count )
9073  {
9074  }
9075  else
9076  {
9077  bad_num = bad_num + 1;
9078  cout << "Bad data " << word << "\n";
9079  }
9080  }
9081  }
9082 //
9083 // MATERIALINDEX
9084 //
9085  else if ( s_eqi ( level_name[level], "MATERIALINDEX" ) )
9086  {
9087  if ( strcmp ( word, "[" ) == 0 )
9088  {
9089  ivert = 0;
9090  }
9091  else if ( strcmp ( word, "]" ) == 0 )
9092  {
9093  level = nlbrack - nrbrack;
9094  }
9095 //
9096 // (indexedfaceset) MATERIALINDEX
9097 //
9098  else if ( s_eqi ( level_name[level-1], "INDEXEDFACESET" ) )
9099  {
9100  count = sscanf ( word, "%d%n", &jval, &width );
9101 
9102  if ( 0 < count )
9103  {
9104  if ( jval == -1 )
9105  {
9106  ivert = 0;
9107  face_num2 = face_num2 + 1;
9108  }
9109  else
9110  {
9111  if ( face_num2 < FACE_MAX )
9112  {
9113  if ( jval != -1 )
9114  {
9115  jval = jval + cor3_num_old;
9116  }
9117  vertex_material[ivert][face_num2] = jval;
9118  ivert = ivert + 1;
9119  }
9120  }
9121  }
9122  else
9123  {
9124  bad_num = bad_num + 1;
9125  cout << "Bad data " << word << "\n";
9126  }
9127  }
9128 //
9129 // (indexedlineset) MATERIALINDEX
9130 //
9131  else if ( s_eqi ( level_name[level-1], "INDEXEDLINESET" ) )
9132  {
9133  count = sscanf ( word, "%d%n", &jval, &width );
9134 
9135  if ( 0 < count )
9136  {
9137  if ( line_num2 < LINES_MAX )
9138  {
9139  if ( jval != -1 )
9140  {
9141  jval = jval + cor3_num_old;
9142  }
9143  line_material[line_num2] = jval;
9144  line_num2 = line_num2 + 1;
9145  }
9146  }
9147  else
9148  {
9149  bad_num = bad_num + 1;
9150  cout << "Bad data " << word << "\n";
9151  }
9152  }
9153  else
9154  {
9155  count = sscanf ( word, "%d%n", &jval, &width );
9156 
9157  if ( 0 < count )
9158  {
9159  }
9160  else
9161  {
9162  bad_num = bad_num + 1;
9163  cout << "Bad data " << word << "\n";
9164  }
9165  }
9166  }
9167 //
9168 // MATRIXTRANSFORM.
9169 //
9170  else if ( s_eqi ( level_name[level], "MATRIXTRANSFORM" ) )
9171  {
9172  if ( strcmp ( word, "{" ) == 0 )
9173  {
9174  }
9175  else if ( strcmp ( word, "}" ) == 0 )
9176  {
9177  level = nlbrack - nrbrack;
9178  }
9179  else if ( s_eqi ( word, "MATRIX" ) )
9180  {
9181  icol = -1;
9182  irow = 0;
9183  }
9184  else
9185  {
9186  count = sscanf ( word, "%f%n", &rval, &width );
9187 
9188  if ( 0 < count )
9189  {
9190  icol = icol + 1;
9191  if ( 3 < icol )
9192  {
9193  icol = 0;
9194  irow = irow + 1;
9195  if ( 3 < irow )
9196  {
9197  irow = 0;
9198  }
9199  }
9200 
9201  transform_matrix[irow][icol] = rval;
9202  }
9203 
9204  }
9205  }
9206 //
9207 // NORMAL
9208 // The field "VECTOR" may be followed by three numbers,
9209 // (handled here), or by a square bracket, and sets of three numbers.
9210 //
9211  else if ( s_eqi ( level_name[level], "NORMAL" ) )
9212  {
9213 //
9214 // (vertexproperty) NORMAL
9215 //
9216  if ( s_eqi ( level_name[level-1], "VERTEXPROPERTY" ) )
9217  {
9218  if ( strcmp ( word, "[" ) == 0 )
9219  {
9220  ixyz = 0;
9221  }
9222  else if ( strcmp ( word, "]" ) == 0 )
9223  {
9224  level = nlbrack - nrbrack;
9225  }
9226  else
9227  {
9228 
9229  count = sscanf ( word, "%f%n", &rval, &width );
9230 
9231  if ( 0 < count )
9232  {
9233 
9234  if ( inormface < FACE_MAX )
9235  {
9236  face_normal[ixyz][inormface] = rval;
9237  }
9238 
9239  ixyz = ixyz + 1;
9240  if ( 2 < ixyz )
9241  {
9242  ixyz = 0;
9243  inormface = inormface + 1;
9244  }
9245  }
9246  }
9247  }
9248 //
9249 // (anythingelse) NORMAL
9250 //
9251  else
9252  {
9253  if ( strcmp ( word, "{" ) == 0 )
9254  {
9255  ixyz = 0;
9256  }
9257  else if ( strcmp ( word, "}" ) == 0 )
9258  {
9259  level = nlbrack - nrbrack;
9260  }
9261  else if ( s_eqi ( word, "VECTOR" ) )
9262  {
9263  }
9264  else
9265  {
9266  count = sscanf ( word, "%f%n", &rval, &width );
9267 
9268  if ( 0 < count )
9269  {
9270 
9271 //
9272 // COMMENTED OUT!
9273 //
9274 // if ( nfnorm < FACE_MAX )
9275 // {
9276 // normal[ixyz][nfnorm] = rval;
9277 // }
9278 //
9279 //
9280  ixyz = ixyz + 1;
9281  if ( 2 < ixyz )
9282  {
9283  ixyz = 0;
9284  }
9285  }
9286  else
9287  {
9288  bad_num = bad_num + 1;
9289  cout << "Bad data " << word << "\n";
9290  }
9291  }
9292  }
9293  }
9294 //
9295 // NORMALBINDING
9296 // Read, but ignore
9297 //
9298  else if ( s_eqi ( level_name[level], "NORMALBINDING" ) )
9299  {
9300 
9301  if ( strcmp ( word, "{" ) == 0 )
9302  {
9303  }
9304  else if ( strcmp ( word, "}" ) == 0 )
9305  {
9306  level = nlbrack - nrbrack;
9307  }
9308  else if ( s_eqi ( word, "VALUE" ) )
9309  {
9310  count = sscanf ( next, "%s%n", normal_binding, &width );
9311  next = next + width;
9312  }
9313  else
9314  {
9315  count = sscanf ( word, "%f%n", &rval, &width );
9316 
9317  if ( 0 < count )
9318  {
9319  }
9320  else
9321  {
9322  bad_num = bad_num + 1;
9323  cout << "Bad data " << word << "\n";
9324  }
9325  }
9326  }
9327 //
9328 // NORMALINDEX
9329 //
9330  else if ( s_eqi ( level_name[level], "NORMALINDEX" ) )
9331  {
9332 //
9333 // (indexedtrianglestripset) NORMALINDEX
9334 //
9335  if ( s_eqi ( level_name[level-1], "INDEXEDTRIANGLESTRIPSET" ) )
9336  {
9337  count = sscanf ( word, "%d%n", &jval, &width );
9338 
9339  if ( 0 < count )
9340  {
9341  }
9342  else if ( strcmp ( word, "[" ) == 0 )
9343  {
9344  }
9345  else if ( strcmp ( word, "]" ) == 0 )
9346  {
9347  }
9348  }
9349 //
9350 // (anythingelse) NORMALINDEX
9351 //
9352  else
9353  {
9354 
9355  if ( strcmp ( word, "[" ) == 0 )
9356  {
9357  ivert = 0;
9358  }
9359  else if ( strcmp ( word, "]" ) == 0 )
9360  {
9361  level = nlbrack - nrbrack;
9362  }
9363  else
9364  {
9365  count = sscanf ( word, "%d%n", &jval, &width );
9366 
9367  if ( 0 < count )
9368  {
9369  if ( jval == -1 )
9370  {
9371  ivert = 0;
9372  iface_num = iface_num + 1;
9373  }
9374  else
9375  {
9376  if ( iface_num < FACE_MAX )
9377  {
9378  for ( i = 0; i < 3; i++ )
9379  {
9380  vertex_normal[i][ivert][iface_num] = normal_temp[i][jval];
9381  }
9382  ivert = ivert + 1;
9383  }
9384  }
9385  }
9386  else
9387  {
9388  bad_num = bad_num + 1;
9389  cout << "Bad data " << word << "\n";
9390  }
9391  }
9392  }
9393  }
9394 //
9395 // (coordinate3) POINT
9396 //
9397  else if ( s_eqi ( level_name[level], "POINT" ) )
9398  {
9399  if ( s_eqi ( level_name[level-1], "COORDINATE3" ) )
9400  {
9401  if ( strcmp ( word, "[" ) == 0 )
9402  {
9403  ixyz = 0;
9404  cor3_num_old = cor3_num;
9405  }
9406  else if ( strcmp ( word, "]" ) == 0 )
9407  {
9408  level = nlbrack - nrbrack;
9409  }
9410  else
9411  {
9412  count = sscanf ( word, "%f%n", &rval, &width );
9413 
9414  if ( 0 < count )
9415  {
9416  if ( cor3_num < COR3_MAX )
9417  {
9418  xvec[ixyz] = rval;
9419  }
9420 
9421  ixyz = ixyz + 1;
9422 
9423  if ( ixyz == 3 )
9424  {
9425  ixyz = 0;
9426 
9427  tmat_mxp ( transform_matrix, xvec, xvec );
9428 
9429  cor3[0][cor3_num] = xvec[0];
9430  cor3[1][cor3_num] = xvec[1];
9431  cor3[2][cor3_num] = xvec[2];
9432 
9433  cor3_num = cor3_num + 1;
9434 
9435  continue;
9436  }
9437  }
9438  else
9439  {
9440  bad_num = bad_num + 1;
9441  break;
9442  }
9443  }
9444  }
9445 //
9446 // (texturecoodinate2) POINT
9447 //
9448  else if ( s_eqi ( level_name[level-1], "TEXTURECOORDINATE2" ) )
9449  {
9450  if ( strcmp ( word, "[" ) == 0 )
9451  {
9452  iuv = 0;
9453  text_numure_temp = 0;
9454  }
9455  else if ( strcmp ( word, "]" ) == 0 )
9456  {
9457  level = nlbrack - nrbrack;
9458  }
9459  else
9460  {
9461 
9462  count = sscanf ( word, "%f%n", &rval, &width );
9463 
9464  if ( 0 < count )
9465  {
9466 
9467  texture_temp[iuv][text_numure_temp] = rval;
9468 
9469  iuv = iuv + 1;
9470  if ( iuv == 2 )
9471  {
9472  iuv = 0;
9473  text_numure_temp = text_numure_temp + 1;
9474  }
9475  }
9476  else
9477  {
9478  cout << "TextureCoordinate2 { Point [: Bad data\n";
9479  bad_num = bad_num + 1;
9480  break;
9481  }
9482  }
9483  }
9484  }
9485 //
9486 // RGB
9487 //
9488  else if ( s_eqi ( level_name[level],"RGB" ) )
9489  {
9490 //
9491 // (basecolor) RGB
9492 //
9493  if ( s_eqi ( level_name[level-1], "BASECOLOR" ) )
9494  {
9495  if ( strcmp ( word, "[" ) == 0 )
9496  {
9497  icolor = 0;
9498  }
9499  else if ( strcmp ( word, "]" ) == 0 )
9500  {
9501  level = nlbrack - nrbrack;
9502  }
9503  else
9504  {
9505  count = sscanf ( word, "%f%n", &rval, &width );
9506 
9507  if ( 0 < count )
9508  {
9509 
9510  rgbcolor[icolor][color_num] = rval;
9511  icolor = icolor + 1;
9512 
9513  if ( icolor == 3 )
9514  {
9515  icolor = 0;
9516  color_num = color_num + 1;
9517  }
9518  }
9519  else
9520  {
9521  bad_num = bad_num + 1;
9522  cout << "Bad data " << word << "\n";
9523  }
9524  }
9525  }
9526 //
9527 // (anythingelse RGB)
9528 //
9529  else
9530  {
9531  cout << "HALSBAND DES TODES!\n";
9532 
9533  if ( strcmp ( word, "[" ) == 0 )
9534  {
9535  icolor = 0;
9536  ivert = 0;
9537  }
9538  else if ( strcmp ( word, "]" ) == 0 )
9539  {
9540  level = nlbrack - nrbrack;
9541  }
9542  else
9543  {
9544 
9545  count = sscanf ( word, "%f%n", &rval, &width );
9546 
9547  if ( 0 < count )
9548  {
9549 
9550  if ( icface < FACE_MAX )
9551  {
9552 
9553  vertex_rgb[icolor][ivert][icface] = rval;
9554 
9555  icolor = icolor + 1;
9556  if ( icolor == 3 )
9557  {
9558  icolor = 0;
9559  color_num = color_num + 1;
9560  ivert = ivert + 1;
9561  if ( ivert == face_order[icface] )
9562  {
9563  ivert = 0;
9564  icface = icface + 1;
9565  }
9566  }
9567  }
9568  }
9569  else
9570  {
9571  bad_num = bad_num + 1;
9572  cout << "Bad data " << word << "\n";
9573  }
9574  }
9575  }
9576 
9577  }
9578 //
9579 // SEPARATOR
9580 //
9581  else if ( s_eqi ( level_name[level], "SEPARATOR" ) )
9582  {
9583  if ( strcmp ( word, "{" ) == 0 )
9584  {
9585  }
9586  else if ( strcmp ( word, "}" ) == 0 )
9587  {
9588  level = nlbrack - nrbrack;
9589  }
9590  else
9591  {
9592  }
9593  }
9594 //
9595 // SHAPEHINTS
9596 // Read, but ignore.
9597 //
9598  else if ( s_eqi ( level_name[level], "SHAPEHINTS" ) )
9599  {
9600  if ( strcmp ( word, "{" ) == 0 )
9601  {
9602  }
9603  else if ( strcmp ( word, "}" ) == 0 )
9604  {
9605  level = nlbrack - nrbrack;
9606  }
9607  else if ( s_eqi ( word, "CREASEANGLE" ) )
9608  {
9609  count = sscanf ( next, "%f%n", &rval, &width );
9610  next = next + width;
9611 
9612  if ( count <= 0 )
9613  {
9614  bad_num = bad_num + 1;
9615  cout << "Bad data " << word << "\n";
9616  }
9617  }
9618  else if ( s_eqi ( word, "FACETYPE" ) )
9619  {
9620  count = sscanf ( next, "%s%n", word, &width );
9621  next = next + width;
9622  }
9623  else if ( s_eqi ( word, "SHAPETYPE" ) )
9624  {
9625  count = sscanf ( next, "%s%n", word, &width );
9626  next = next + width;
9627  }
9628  else if ( s_eqi ( word, "VERTEXORDERING" ) )
9629  {
9630  count = sscanf ( next, "%s%n", word, &width );
9631  next = next + width;
9632  }
9633  else
9634  {
9635  bad_num = bad_num + 1;
9636  cout << "Bad data " << word << "\n";
9637  }
9638  }
9639 //
9640 // TEXTURE2
9641 //
9642  else if ( s_eqi ( level_name[level], "TEXTURE2" ) )
9643  {
9644  if ( strcmp ( word, "{" ) == 0 )
9645  {
9646  }
9647  else if ( strcmp ( word, "}" ) == 0 )
9648  {
9649  level = nlbrack - nrbrack;
9650  texture_num = texture_num + 1;
9651  }
9652  else if ( s_eqi ( word, "BLENDCOLOR" ) )
9653  {
9654  }
9655 //
9656 // NEED TO REMOVE QUOTES SURROUNDING TEXTURE NAME.
9657 //
9658  else if ( s_eqi ( word, "FILENAME" ) )
9659  {
9660  count = sscanf ( next, "%s%n", word, &width );
9661  next = next + width;
9662 
9663  strcpy ( texture_name[texture_num], word );
9664 
9665  i = 0;
9666  j = 0;
9667  do
9668  {
9669  c = texture_name[texture_num][i];
9670  i = i + 1;
9671  if ( c != '"' )
9672  {
9673  texture_name[texture_num][j] = c;
9674  j = j + 1;
9675  }
9676  } while ( c != '\0' );
9677 
9678  }
9679  else if ( s_eqi ( word, "IMAGE" ) )
9680  {
9681  }
9682  else if ( s_eqi ( word, "MODEL" ) )
9683  {
9684  count = sscanf ( next, "%s%n", word, &width );
9685  next = next + width;
9686  }
9687  else if ( s_eqi ( word, "WRAPS" ) )
9688  {
9689  count = sscanf ( next, "%s%n", word, &width );
9690  next = next + width;
9691  }
9692  else if ( s_eqi ( word, "WRAPT" ) )
9693  {
9694  count = sscanf ( next, "%s%n", word, &width );
9695  next = next + width;
9696  }
9697  else
9698  {
9699  }
9700  }
9701 //
9702 // TEXTURECOORDINATE2
9703 //
9704  else if ( s_eqi ( level_name[level], "TEXTURECOORDINATE2" ) )
9705  {
9706  if ( strcmp ( word, "{" ) == 0 )
9707  {
9708  }
9709  else if ( strcmp ( word, "}" ) == 0 )
9710  {
9711  level = nlbrack - nrbrack;
9712  }
9713  else if ( s_eqi ( word, "POINT" ) )
9714  {
9715  }
9716  else
9717  {
9718  bad_num = bad_num + 1;
9719  cout << "TEXTURECOORDINATE2: Bad data " << word << "\n";
9720  }
9721  }
9722 //
9723 // TEXTURECOORDINATEBINDING
9724 //
9725  else if ( s_eqi ( level_name[level], "TEXTURECOORDINATEBINDING" ) )
9726  {
9727  if ( strcmp ( word, "{" ) == 0 )
9728  {
9729  }
9730  else if ( strcmp ( word, "}" ) == 0 )
9731  {
9732  level = nlbrack - nrbrack;
9733  }
9734  else if ( s_eqi ( word, "VALUE" ) )
9735  {
9736  count = sscanf ( next, "%s%n", texture_binding, &width );
9737  next = next + width;
9738  }
9739  else
9740  {
9741  bad_num = bad_num + 1;
9742  cout << "Bad data " << word << "\n";
9743  }
9744  }
9745 //
9746 // TEXTURECOORDINDEX
9747 //
9748  else if ( s_eqi ( level_name[level], "TEXTURECOORDINDEX" ) )
9749  {
9750  if ( strcmp ( word, "[" ) == 0 )
9751  {
9752  ivert = 0;
9753  iface_num = 0;
9754  }
9755  else if ( strcmp ( word, "]" ) == 0 )
9756  {
9757  level = nlbrack - nrbrack;
9758  }
9759  else
9760  {
9761  count = sscanf ( word, "%d%n", &jval, &width );
9762 
9763  if ( 0 < count )
9764  {
9765  if ( jval == - 1 )
9766  {
9767  ivert = 0;
9768  }
9769  else
9770  {
9771  if ( iface_num < FACE_MAX )
9772  {
9773  vertex_tex_uv[0][ivert][iface_num] = texture_temp[0][jval];
9774  vertex_tex_uv[1][ivert][iface_num] = texture_temp[1][jval];
9775  }
9776 
9777  ivert = ivert + 1;
9778 
9779  if ( ivert == face_order[iface_num] )
9780  {
9781  ivert = 0;
9782  iface_num = iface_num + 1;
9783  }
9784  }
9785 
9786  }
9787  else
9788  {
9789  bad_num = bad_num + 1;
9790  cout << "Bad data " << word << "\n";
9791  }
9792 
9793  }
9794  }
9795 //
9796 // UKNOTVECTOR
9797 //
9798  else if ( s_eqi ( level_name[level], "UKNOTVECTOR" ) )
9799  {
9800  if ( strcmp ( word, "[" ) == 0 )
9801  {
9802  continue;
9803  }
9804  else if ( strcmp ( word, "]" ) == 0 )
9805  {
9806  level = nlbrack - nrbrack;
9807  continue;
9808  }
9809  else
9810  {
9811  count = sscanf ( word, "%d%n", &jval, &width );
9812  }
9813  }
9814 //
9815 // VECTOR
9816 //
9817  else if ( s_eqi ( level_name[level], "VECTOR" ) )
9818  {
9819  if ( strcmp ( word, "[" ) == 0 )
9820  {
9821  }
9822  else if ( strcmp ( word, "]" ) == 0 )
9823  {
9824  level = nlbrack - nrbrack;
9825  }
9826 //
9827 // (normal) VECTOR
9828 //
9829  else if ( s_eqi ( level_name[level-1], "NORMAL" ) )
9830  {
9831 
9832  count = sscanf ( word, "%f%n", &rval, &width );
9833 
9834  if ( 0 < count )
9835  {
9836  if ( normal_num_temp < ORDER_MAX * FACE_MAX )
9837  {
9838  normal_temp[ixyz][normal_num_temp] = rval;
9839  ixyz = ixyz + 1;
9840  if ( ixyz == 3 )
9841  {
9842  ixyz = 0;
9843  normal_num_temp = normal_num_temp + 1;
9844  }
9845  }
9846  }
9847  else
9848  {
9849  bad_num = bad_num + 1;
9850  cout << "NORMAL VECTOR: bad data " << word << "\n";
9851  }
9852  }
9853  }
9854 //
9855 // (vertexproperty) VERTEX
9856 //
9857  else if ( s_eqi ( level_name[level], "VERTEX" ) )
9858  {
9859  if ( s_eqi ( level_name[level-1], "VERTEXPROPERTY" ) )
9860  {
9861  if ( strcmp ( word, "[" ) == 0 )
9862  {
9863  ixyz = 0;
9864  cor3_num_old = cor3_num;
9865  }
9866  else if ( strcmp ( word, "]" ) == 0 )
9867  {
9868  level = nlbrack - nrbrack;
9869  }
9870  else
9871  {
9872  count = sscanf ( word, "%f%n", &rval, &width );
9873 
9874  if ( 0 < count )
9875  {
9876  if ( cor3_num < COR3_MAX )
9877  {
9878  cor3[ixyz][cor3_num] = rval;
9879  }
9880  ixyz = ixyz + 1;
9881  if ( ixyz == 3 )
9882  {
9883  ixyz = 0;
9884  cor3_num = cor3_num + 1;
9885  }
9886 
9887  }
9888  else
9889  {
9890  bad_num = bad_num + 1;
9891  cout << "Bad data " << word << "\n";
9892  }
9893  }
9894  }
9895  }
9896 //
9897 // (indexedtrianglestripset) VERTEXPROPERTY
9898 //
9899  else if ( s_eqi ( level_name[level], "VERTEXPROPERTY" ) )
9900  {
9901  if ( strcmp ( word, "{" ) == 0 )
9902  {
9903  }
9904  else if ( strcmp ( word, "}" ) == 0 )
9905  {
9906  level = nlbrack - nrbrack;
9907  }
9908  else if ( s_eqi ( word, "VERTEX" ) )
9909  {
9910  }
9911  else if ( s_eqi ( word, "NORMAL" ) )
9912  {
9913  ixyz = 0;
9914  }
9915  else if ( s_eqi ( word, "MATERIALBINDING" ) )
9916  {
9917  count = sscanf ( next, "%s%n", word, &width );
9918  next = next + width;
9919  }
9920  else if ( s_eqi ( word, "NORMALBINDING" ) )
9921  {
9922  count = sscanf ( next, "%s%n", word, &width );
9923  next = next + width;
9924  }
9925  else
9926  {
9927  bad_num = bad_num + 1;
9928  cout << "Bad data " << word << "\n";
9929  }
9930  }
9931 //
9932 // VKNOTVECTOR
9933 //
9934  else if ( s_eqi ( level_name[level], "VKNOTVECTOR" ) )
9935  {
9936  if ( strcmp ( word, "[" ) == 0 )
9937  {
9938  continue;
9939  }
9940  else if ( strcmp ( word, "]" ) == 0 )
9941  {
9942  level = nlbrack - nrbrack;
9943  continue;
9944  }
9945  else
9946  {
9947  count = sscanf ( word, "%d%n", &jval, &width );
9948  }
9949  }
9950 //
9951 // Any other word:
9952 //
9953  else
9954  {
9955  }
9956  }
9957  }
9958 //
9959 // Reset the transformation matrix to the identity,
9960 // because, presumably, we've applied it by now.
9961 //
9963 
9964  return 0;
9965 }
9966 //****************************************************************************80
9967 
9968 int iv_write ( FILE *fileout )
9969 
9970 //****************************************************************************80
9971 //
9972 // Purpose:
9973 //
9974 // IV_WRITE writes graphics information to an Inventor file.
9975 //
9976 // Licensing:
9977 //
9978 // This code is distributed under the GNU LGPL license.
9979 //
9980 // Modified:
9981 //
9982 // 29 June 1999
9983 //
9984 // Author:
9985 //
9986 // John Burkardt
9987 //
9988 {
9989  int icor3;
9990  int iface;
9991  int itemp;
9992  int ivert;
9993  int j;
9994  int length;
9995  int text_num;
9996 
9997  text_num = 0;
9998 
9999  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 
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;
10922  }
10923 //
10924 // If there's a slash, skip to the next slash, and extract the
10925 // index of the normal vector.
10926 //
10927  if ( *next2 == '/' )
10928  {
10929  for ( next3 = next2 + 1; next3 < token2 + LINE_MAX_LEN; next3++ )
10930  {
10931  if ( *next3 == '/' )
10932  {
10933  next3 = next3 + 1;
10934  count = sscanf ( next3, "%d%n", &node, &width );
10935 
10936  node = node - 1;
10937  if ( 0 <= node && node < vertex_normal_num )
10938  {
10939  for ( i = 0; i < 3; i++ )
10940  {
10941  vertex_normal[i][ivert][face_num] = normal_temp[i][node];
10942  }
10943  }
10944  break;
10945  }
10946  }
10947  }
10948  ivert = ivert + 1;
10949  }
10950  face_num = face_num + 1;
10951  }
10952 //
10953 // G
10954 // Group name.
10955 //
10956  else if ( s_eqi ( token, "G" ) )
10957  {
10958  continue;
10959  }
10960 //
10961 // HOLE
10962 // Inner trimming hole.
10963 //
10964  else if ( s_eqi ( token, "HOLE" ) )
10965  {
10966  continue;
10967  }
10968 //
10969 // L
10970 // I believe OBJ line node indices are 1 based rather than 0 based.
10971 // So we have to decrement them before loading them into LINE_DEX.
10972 //
10973  else if ( s_eqi ( token, "L" ) )
10974  {
10975  for ( ;; )
10976  {
10977  count = sscanf ( next, "%d%n", &node, &width );
10978  next = next + width;
10979 
10980  if ( count != 1 )
10981  {
10982  break;
10983  }
10984 
10985  if ( line_num < LINES_MAX )
10986  {
10987  line_dex[line_num] = node-1;
10988  line_material[line_num] = 0;
10989  }
10990  line_num = line_num + 1;
10991 
10992  }
10993 
10994  if ( line_num < LINES_MAX )
10995  {
10996  line_dex[line_num] = -1;
10997  line_material[line_num] = -1;
10998  }
10999  line_num = line_num + 1;
11000 
11001  }
11002 //
11003 // LOD
11004 // Level of detail.
11005 //
11006  else if ( s_eqi ( token, "LOD" ) )
11007  {
11008  continue;
11009  }
11010 //
11011 // MG
11012 // Merging group.
11013 //
11014  else if ( s_eqi ( token, "MG" ) )
11015  {
11016  continue;
11017  }
11018 //
11019 // MTLLIB
11020 // Material library.
11021 //
11022 
11023  else if ( s_eqi ( token, "MTLLIB" ) )
11024  {
11025  continue;
11026  }
11027 //
11028 // O
11029 // Object name.
11030 //
11031  else if ( s_eqi ( token, "O" ) )
11032  {
11033  continue;
11034  }
11035 //
11036 // P
11037 // Point.
11038 //
11039  else if ( s_eqi ( token, "P" ) )
11040  {
11041  continue;
11042  }
11043 //
11044 // PARM
11045 // Parameter values.
11046 //
11047  else if ( s_eqi ( token, "PARM" ) )
11048  {
11049  continue;
11050  }
11051 //
11052 // S
11053 // Smoothing group
11054 //
11055  else if ( s_eqi ( token, "S" ) )
11056  {
11057  continue;
11058  }
11059 //
11060 // SCRV
11061 // Special curve.
11062 //
11063  else if ( s_eqi ( token, "SCRV" ) )
11064  {
11065  continue;
11066  }
11067 //
11068 // SHADOW_OBJ
11069 // Shadow casting.
11070 //
11071  else if ( s_eqi ( token, "SHADOW_OBJ" ) )
11072  {
11073  continue;
11074  }
11075 //
11076 // SP
11077 // Special point.
11078 //
11079  else if ( s_eqi ( token, "SP" ) )
11080  {
11081  continue;
11082  }
11083 //
11084 // STECH
11085 // Surface approximation technique.
11086 //
11087  else if ( s_eqi ( token, "STECH" ) )
11088  {
11089  continue;
11090  }
11091 //
11092 // STEP
11093 // Stepsize.
11094 //
11095  else if ( s_eqi ( token, "CURV" ) )
11096  {
11097  continue;
11098  }
11099 //
11100 // SURF
11101 // Surface.
11102 //
11103  else if ( s_eqi ( token, "SURF" ) )
11104  {
11105  continue;
11106  }
11107 //
11108 // TRACE_OBJ
11109 // Ray tracing.
11110 //
11111  else if ( s_eqi ( token, "TRACE_OBJ" ) )
11112  {
11113  continue;
11114  }
11115 //
11116 // TRIM
11117 // Outer trimming loop.
11118 //
11119  else if ( s_eqi ( token, "TRIM" ) )
11120  {
11121  continue;
11122  }
11123 //
11124 // USEMTL
11125 // Material name.
11126 //
11127  else if ( s_eqi ( token, "USEMTL" ) )
11128  {
11129  continue;
11130  }
11131 //
11132 // V X Y Z W
11133 // Geometric vertex.
11134 // W is optional, a weight for rational curves and surfaces.
11135 // The default for W is 1.
11136 //
11137  else if ( s_eqi ( token, "V" ) )
11138  {
11139  sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
11140 
11141  if ( cor3_num < COR3_MAX )
11142  {
11143  cor3[0][cor3_num] = r1;
11144  cor3[1][cor3_num] = r2;
11145  cor3[2][cor3_num] = r3;
11146  }
11147 
11148  cor3_num = cor3_num + 1;
11149 
11150  }
11151 //
11152 // VN
11153 // Vertex normals.
11154 //
11155  else if ( s_eqi ( token, "VN" ) )
11156  {
11157  sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
11158 
11159  if ( vertex_normal_num < ORDER_MAX * FACE_MAX )
11160  {
11161  normal_temp[0][vertex_normal_num] = r1;
11162  normal_temp[1][vertex_normal_num] = r2;
11163  normal_temp[2][vertex_normal_num] = r3;
11164  }
11165 
11166  vertex_normal_num = vertex_normal_num + 1;
11167 
11168  }
11169 //
11170 // VT
11171 // Vertex texture.
11172 //
11173  else if ( s_eqi ( token, "VT" ) )
11174  {
11175  continue;
11176  }
11177 //
11178 // VP
11179 // Parameter space vertices.
11180 //
11181  else if ( s_eqi ( token, "VP" ) )
11182  {
11183  continue;
11184  }
11185 //
11186 // Unrecognized
11187 //
11188  else
11189  {
11190  bad_num = bad_num + 1;
11191  }
11192 
11193  }
11194  return 0;
11195 }
11196 //****************************************************************************80
11197 
11198 int obj_write ( FILE *fileout )
11199 
11200 //****************************************************************************80
11201 //
11202 // Purpose:
11203 //
11204 // OBJ_WRITE writes a Wavefront OBJ file.
11205 //
11206 // Example:
11207 //
11208 // # magnolia.obj
11209 //
11210 // mtllib ./vp.mtl
11211 //
11212 // g
11213 // v -3.269770 -39.572201 0.876128
11214 // v -3.263720 -39.507999 2.160890
11215 // ...
11216 // v 0.000000 -9.988540 0.000000
11217 // g stem
11218 // s 1
11219 // usemtl brownskn
11220 // f 8 9 11 10
11221 // f 12 13 15 14
11222 // ...
11223 // f 788 806 774
11224 //
11225 // Licensing:
11226 //
11227 // This code is distributed under the GNU LGPL license.
11228 //
11229 // Modified:
11230 //
11231 // 01 September 1998
11232 //
11233 // Author:
11234 //
11235 // John Burkardt
11236 //
11237 // Parameters:
11238 //
11239 // Input, FILE *FILEOUT, a pointer to the output file.
11240 //
11241 {
11242  int i;
11243  int iface;
11244  int indexvn;
11245  int ivert;
11246  int k;
11247  bool next;
11248  int text_num;
11249  float w;
11250 //
11251 // Initialize.
11252 //
11253  text_num = 0;
11254  w = 1.0;
11255 
11256  fprintf ( fileout, "# %s created by IVCON.\n", fileout_name );
11257  fprintf ( fileout, "# Original data in %s.\n", filein_name );
11258  fprintf ( fileout, "\n" );
11259  fprintf ( fileout, "g %s\n", object_name );
11260  fprintf ( fileout, "\n" );
11261 
11262  text_num = text_num + 5;
11263 //
11264 // V: vertex coordinates.
11265 //
11266  for ( i = 0; i < cor3_num; i++ )
11267  {
11268  fprintf ( fileout, "v %f %f %f %f\n",
11269  cor3[0][i], cor3[1][i], cor3[2][i], w );
11270  text_num = text_num + 1;
11271  }
11272 //
11273 // VN: Vertex face normal vectors.
11274 //
11275  if ( 0 < face_num )
11276  {
11277  fprintf ( fileout, "\n" );
11278  text_num = text_num + 1;
11279  }
11280 
11281  for ( iface = 0; iface < face_num; iface++ )
11282  {
11283  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
11284  {
11285  fprintf ( fileout, "vn %f %f %f\n", vertex_normal[0][ivert][iface],
11286  vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
11287  text_num = text_num + 1;
11288  }
11289  }
11290 //
11291 // F: faces.
11292 //
11293  if ( 0 < face_num )
11294  {
11295  fprintf ( fileout, "\n" );
11296  text_num = text_num + 1;
11297  }
11298 
11299  indexvn = 0;
11300 
11301  for ( iface = 0; iface < face_num; iface++ )
11302  {
11303  fprintf ( fileout, "f" );
11304  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
11305  {
11306  indexvn = indexvn + 1;
11307  fprintf ( fileout, " %d//%d", face[ivert][iface]+1, indexvn );
11308  }
11309  fprintf ( fileout, "\n" );
11310  text_num = text_num + 1;
11311  }
11312 //
11313 // L: lines.
11314 //
11315  if ( 0 < line_num )
11316  {
11317  fprintf ( fileout, "\n" );
11318  text_num = text_num + 1;
11319  }
11320 
11321  next = true;
11322 
11323  for ( i = 0; i < line_num; i++ )
11324  {
11325  k = line_dex[i];
11326 
11327  if ( k == -1 )
11328  {
11329  fprintf ( fileout, "\n" );
11330  text_num = text_num + 1;
11331  next = true;
11332  }
11333  else
11334  {
11335  if ( next )
11336  {
11337  fprintf ( fileout, "l" );
11338  next = false;
11339  }
11340  fprintf ( fileout, " %d", k+1 );
11341  }
11342 
11343  }
11344 
11345  fprintf ( fileout, "\n" );
11346  text_num = text_num + 1;
11347 //
11348 // Report.
11349 //
11350  cout << "\n";
11351  cout << "OBJ_WRITE - Wrote " << text_num << " text lines.\n";
11352 
11353  return 0;
11354 }
11355 //****************************************************************************80
11356 
11357 int off_read ( ifstream &file_in )
11358 
11359 //****************************************************************************80
11360 //
11361 // Purpose:
11362 //
11363 // OFF_READ reads a GEOMVIEW OFF file.
11364 //
11365 // Example:
11366 //
11367 // OFF
11368 // 8 6 12
11369 // 0.0 0.0 0.0
11370 // 0.0 0.0 1.0
11371 // 0.0 1.0 0.0
11372 // 0.0 1.0 1.0
11373 // 1.0 0.0 0.0
11374 // 1.0 0.0 1.0
11375 // 1.0 1.0 0.0
11376 // 1.0 1.0 1.0
11377 // 4 0 2 3 1
11378 // 4 4 5 7 6
11379 // 4 0 1 5 4
11380 // 4 2 6 7 3
11381 // 4 0 4 6 2
11382 // 4 1 3 7 5
11383 //
11384 // Licensing:
11385 //
11386 // This code is distributed under the GNU LGPL license.
11387 //
11388 // Modified:
11389 //
11390 // 05 September 2003
11391 //
11392 // Author:
11393 //
11394 // John Burkardt
11395 //
11396 // Parameters:
11397 //
11398 // Input, ifstream &FILE_IN, a pointer to the OFF file.
11399 //
11400 // Output, int *COR3_NUM, the number of nodes.
11401 //
11402 // Output, int *FACE_NUM, the number of faces.
11403 {
11404  int cor3_num2;
11405  int edge_num;
11406  bool error;
11407  int face_num2;
11408  int ivec[21];
11409  int j;
11410  int last;
11411  char line[255];
11412  int noncomment_num;
11413  int order;
11414  float rvec[3];
11415  int text_num;
11416  int vert;
11417 //
11418 // Read the optional "OFF" line, and the line with the number of nodes,
11419 // faces and edges.
11420 //
11421  noncomment_num = 0;
11422  text_num = 0;
11423 
11424  while ( 1 )
11425  {
11426  file_in.getline ( line, sizeof ( line ) );
11427 
11428  if ( file_in.eof ( ) )
11429  {
11430  cout << "\n";
11431  cout << "OFF_READ - Fatal error!\n";
11432  cout << " End-of-file before anything was read.\n";
11433  cout << " Number of text lines read = " << text_num << "\n";
11434  return 1;
11435  }
11436 
11437  text_num = text_num + 1;
11438 
11439  if ( line[0] == '#' || s_len_trim ( line ) == 0 )
11440  {
11441  continue;
11442  }
11443 
11444  noncomment_num = noncomment_num + 1;
11445 
11446  if ( line[0] == 'O' &&
11447  line[1] == 'F' &&
11448  line[2] == 'F' )
11449  {
11450  if ( noncomment_num == 1 )
11451  {
11452  continue;
11453  }
11454  else
11455  {
11456  cout << "\n";
11457  cout << "OFF_READ - Fatal error!\n";
11458  cout << " The 'OFF' tag, if used, must be the first noncomment\n";
11459  cout << " line in the file.\n";
11460  cout << " Number of text lines read = " << text_num << "\n";
11461  return 1;
11462  }
11463  }
11464 
11465  error = s_to_i4vec ( line, 3, ivec );
11466 
11467  if ( error )
11468  {
11469  cout << "\n";
11470  cout << "OFF_READ - Fatal error!\n";
11471  cout << " Error from S_TO_I4VEC while trying to extract\n";
11472  cout << " COR3_NUM FACE_NUM EDGE_NUM record.\n";
11473  cout << " Number of text lines read = " << text_num << "\n";
11474  cout << " Current line = \"" << line << "\"\n";
11475  return 1;
11476  }
11477 
11478  cor3_num = ivec[0];
11479  face_num = ivec[1];
11480  edge_num = ivec[2];
11481  break;
11482 
11483  }
11484 //
11485 // Read the lines that define the vertex coordinates
11486 //
11487 // Each line has the form "X Y Z"
11488 //
11489  cor3_num2 = 0;
11490 
11491  while ( cor3_num2 < cor3_num )
11492  {
11493  file_in.getline ( line, sizeof ( line ) );
11494 
11495  if ( file_in.eof ( ) )
11496  {
11497  cout << "\n";
11498  cout << "OFF_READ - Fatal error!\n";
11499  cout << " End of file while reading X Y Z coordinate data.\n";
11500  cout << " Number of text lines read = " << text_num << "\n";
11501  return 1;
11502  }
11503 
11504  text_num = text_num + 1;
11505 
11506  if ( line[0] == '#' || s_len_trim ( line ) == 0 )
11507  {
11508  continue;
11509  }
11510  noncomment_num = noncomment_num + 1;
11511 
11512  error = s_to_r4vec ( line, 3, rvec );
11513 
11514  if ( error )
11515  {
11516  cout << "\n";
11517  cout << "OFF_READ - Fatal error!\n";
11518  cout << " Error from S_TO_R4VEC while trying to extract X Y Z data.\n";
11519  cout << " Number of text lines read = " << text_num << "\n";
11520  return 1;
11521  }
11522 
11523  for ( j = 0; j < 3; j++ )
11524  {
11525  cor3[j][cor3_num2] = rvec[j];
11526  }
11527 
11528  cor3_num2 = cor3_num2 + 1;
11529  }
11530 //
11531 // Read the lines that define the faces.
11532 //
11533 // Each line has the form " n V1 V2 V3 ... Vn"
11534 //
11535  face_num2 = 0;
11536 
11537  while ( face_num2 < face_num )
11538  {
11539  file_in.getline ( line, sizeof ( line ) );
11540 
11541  if ( file_in.eof ( ) )
11542  {
11543  cout << "\n";
11544  cout << "OFF_READ - Fatal error!\n";
11545  cout << " End of file while reading face data.\n";
11546  cout << " Number of text lines read = " << text_num << "\n";
11547  return 1;
11548  }
11549 
11550  text_num = text_num + 1;
11551 
11552  if ( line[0] == '#' || s_len_trim ( line ) == 0 )
11553  {
11554  continue;
11555  }
11556 
11557  noncomment_num = noncomment_num + 1;
11558 
11559  order = s_to_i4 ( line, &last, &error );
11560 
11561  if ( error )
11562  {
11563  cout << "\n";
11564  cout << "OFF_READ - Fatal error!\n";
11565  cout << " Error from S_TO_I4 while extracting face order.\n";
11566  cout << " Number of text lines read = " << text_num << "\n";
11567  return 1;
11568  }
11569 
11570  face_order[face_num2] = order;
11571 
11572  error = s_to_i4vec ( line, order+1, ivec );
11573 
11574  if ( error )
11575  {
11576  cout << "\n";
11577  cout << "OFF_READ - Fatal error!\n";
11578  cout << " Error from S_TO_I4VEC while extracting face indices.\n";
11579  cout << " Number of text lines read = " << text_num << "\n";
11580  return 1;
11581  }
11582 
11583  for ( vert = 0; vert < order; vert++ )
11584  {
11585  face[vert][face_num2] = ivec[vert+1];
11586  }
11587 
11588  face_num2 = face_num2 + 1;
11589  }
11590 
11591  cout << "\n";
11592  cout << "OFF_READ read " << text_num << " lines.\n";
11593 
11594  return 0;
11595 }
11596 //****************************************************************************80
11597 
11598 int off_write ( FILE *fileout )
11599 
11600 //****************************************************************************80
11601 //
11602 // Purpose:
11603 //
11604 // OFF_WRITE writes graphics information to a GEOMVIEW OFF file.
11605 //
11606 // Example:
11607 //
11608 // OFF
11609 // 8 6 12
11610 // 0.0 0.0 0.0
11611 // 0.0 0.0 1.0
11612 // 0.0 1.0 0.0
11613 // 0.0 1.0 1.0
11614 // 1.0 0.0 0.0
11615 // 1.0 0.0 1.0
11616 // 1.0 1.0 0.0
11617 // 1.0 1.0 1.0
11618 // 4 0 2 3 1
11619 // 4 4 5 7 6
11620 // 4 0 1 5 4
11621 // 4 2 6 7 3
11622 // 4 0 4 6 2
11623 // 4 1 3 7 5
11624 //
11625 // Licensing:
11626 //
11627 // This code is distributed under the GNU LGPL license.
11628 //
11629 // Modified:
11630 //
11631 // 28 August 2003
11632 //
11633 // Author:
11634 //
11635 // John Burkardt
11636 //
11637 // Parameters:
11638 //
11639 // Input, FILE *FILEOUT, a pointer to the output file.
11640 //
11641 {
11642  int edge_num;
11643  int i;
11644  int iface;
11645  int ivert;
11646  int j;
11647  int text_num;
11648 //
11649 // "Magic Number"
11650 //
11651  text_num = 0;
11652  fprintf ( fileout, "OFF\n" );
11653  text_num = text_num + 1;
11654 //
11655 // Compute EDGE_NUM.
11656 //
11657  edge_num = edge_count ( );
11658 //
11659 // Counts.
11660 //
11661  fprintf ( fileout, "%d %d %d\n", cor3_num, face_num, edge_num );
11662  text_num = text_num + 1;
11663 //
11664 // Vertex coordinates.
11665 //
11666  for ( j = 0; j < cor3_num; j++ )
11667  {
11668  for ( i = 0; i < 3; i++ )
11669  {
11670  fprintf ( fileout, "%f ", cor3[i][j] );
11671  }
11672  fprintf ( fileout, "\n" );
11673  text_num = text_num + 1;
11674  }
11675 //
11676 // Face count, and vertex indices.
11677 //
11678  for ( iface = 0; iface < face_num; iface++ )
11679  {
11680  fprintf ( fileout, "%d ", face_order[iface] );
11681 
11682  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
11683  {
11684  fprintf ( fileout, "%d ", face[ivert][iface] );
11685  }
11686  fprintf ( fileout, "\n" );
11687  text_num = text_num + 1;
11688 
11689  }
11690 //
11691 // Report.
11692 //
11693  cout << "\n";
11694  cout << "OFF_WRITE - Wrote " << text_num
11695  << " text lines to " << fileout_name << "\n";
11696 
11697  return 0;
11698 }
11699 //****************************************************************************80
11700 
11701 int pov_write ( FILE *fileout )
11702 
11703 //****************************************************************************80
11704 //
11705 // Purpose:
11706 //
11707 // POV_WRITE writes graphics information to a POV file.
11708 //
11709 // Example:
11710 //
11711 // // cone.pov created by IVCON.
11712 // // Original data in cone.iv
11713 //
11714 // #version 3.0
11715 // #include "colors.inc"
11716 // #include "shapes.inc"
11717 // global_settings { assumed_gamma 2.2 }
11718 //
11719 // camera {
11720 // right < 4/3, 0, 0>
11721 // up < 0, 1, 0 >
11722 // sky < 0, 1, 0 >
11723 // angle 20
11724 // location < 0, 0, -300 >
11725 // look_at < 0, 0, 0>
11726 // }
11727 //
11728 // light_source { < 20, 50, -100 > color White }
11729 //
11730 // background { color SkyBlue }
11731 //
11732 // #declare RedText = texture {
11733 // pigment { color rgb < 0.8, 0.2, 0.2> }
11734 // finish { ambient 0.2 diffuse 0.5 }
11735 // }
11736 //
11737 // #declare BlueText = texture {
11738 // pigment { color rgb < 0.2, 0.2, 0.8> }
11739 // finish { ambient 0.2 diffuse 0.5 }
11740 // }
11741 // mesh {
11742 // smooth_triangle {
11743 // < 0.29, -0.29, 0.0>, < 0.0, 0.0, -1.0 >,
11744 // < 38.85, 10.03, 0.0>, < 0.0, 0.0, -1.0 >,
11745 // < 40.21, -0.29, 0.0>, < 0.0, 0.0, -1.0 >
11746 // texture { RedText } }
11747 // ...
11748 // smooth_triangle {
11749 // < 0.29, -0.29, 70.4142 >, < 0.0, 0.0, 1.0 >,
11750 // < 8.56, -2.51, 70.4142 >, < 0.0, 0.0, 1.0 >,
11751 // < 8.85, -0.29, 70.4142 >, < 0.0, 0.0, 1.0 >
11752 // texture { BlueText } }
11753 // }
11754 //
11755 // Licensing:
11756 //
11757 // This code is distributed under the GNU LGPL license.
11758 //
11759 // Modified:
11760 //
11761 // 08 October 1998
11762 //
11763 // Author:
11764 //
11765 // John Burkardt
11766 //
11767 {
11768  int i;
11769  int j;
11770  int jj;
11771  int jlo;
11772  int k;
11773  int text_num;
11774 
11775  text_num = 0;
11776  fprintf ( fileout, "// %s created by IVCON.\n", fileout_name );
11777  fprintf ( fileout, "// Original data in %s.\n", filein_name );
11778  text_num = text_num + 2;
11779 //
11780 // Initial declarations.
11781 //
11782  fprintf ( fileout, "\n" );
11783  fprintf ( fileout, "#version 3.0\n" );
11784  fprintf ( fileout, "#include \"colors.inc\"\n" );
11785  fprintf ( fileout, "#include \"shapes.inc\"\n" );
11786  fprintf ( fileout, "global_settings { assumed_gamma 2.2 }\n" );
11787  fprintf ( fileout, "\n" );
11788  fprintf ( fileout, "camera {\n" );
11789  fprintf ( fileout, " right < 4/3, 0, 0>\n" );
11790  fprintf ( fileout, " up < 0, 1, 0 >\n" );
11791  fprintf ( fileout, " sky < 0, 1, 0 >\n" );
11792  fprintf ( fileout, " angle 20\n" );
11793  fprintf ( fileout, " location < 0, 0, -300 >\n" );
11794  fprintf ( fileout, " look_at < 0, 0, 0>\n" );
11795  fprintf ( fileout, "}\n" );
11796  fprintf ( fileout, "\n" );
11797  fprintf ( fileout, "light_source { < 20, 50, -100 > color White }\n" );
11798  fprintf ( fileout, "\n" );
11799  fprintf ( fileout, "background { color SkyBlue }\n" );
11800 
11801  text_num = text_num + 15;
11802 //
11803 // Declare RGB textures.
11804 //
11805  fprintf ( fileout, "\n" );
11806  fprintf ( fileout, "#declare RedText = texture {\n" );
11807  fprintf ( fileout, " pigment { color rgb < 0.8, 0.2, 0.2> }\n" );
11808  fprintf ( fileout, " finish { ambient 0.2 diffuse 0.5 }\n" );
11809  fprintf ( fileout, "}\n" );
11810  fprintf ( fileout, "\n" );
11811  fprintf ( fileout, "#declare GreenText = texture {\n" );
11812  fprintf ( fileout, " pigment { color rgb < 0.2, 0.8, 0.2> }\n" );
11813  fprintf ( fileout, " finish { ambient 0.2 diffuse 0.5 }\n" );
11814  fprintf ( fileout, "}\n" );
11815  fprintf ( fileout, "\n" );
11816  fprintf ( fileout, "#declare BlueText = texture {\n" );
11817  fprintf ( fileout, " pigment { color rgb < 0.2, 0.2, 0.8> }\n" );
11818  fprintf ( fileout, " finish { ambient 0.2 diffuse 0.5 }\n" );
11819  fprintf ( fileout, "}\n" );
11820 //
11821 // Write one big object.
11822 //
11823  fprintf ( fileout, "mesh {\n" );
11824  text_num = text_num + 1;
11825 //
11826 // Do the next face.
11827 //
11828  for ( i = 0; i < face_num; i++ )
11829  {
11830 //
11831 // Break the face up into triangles, anchored at node 1.
11832 //
11833  for ( jlo = 0; jlo < face_order[i] - 2; jlo++ )
11834  {
11835  fprintf ( fileout, " smooth_triangle {\n" );
11836  text_num = text_num + 1;
11837 
11838  for ( j = jlo; j < jlo + 3; j++ )
11839  {
11840  if ( j == jlo )
11841  {
11842  jj = 0;
11843  }
11844  else
11845  {
11846  jj = j;
11847  }
11848 
11849  k = face[jj][i];
11850 
11851  fprintf ( fileout, "<%f, %f, %f>, <%f, %f, %f>",
11852  cor3[0][k], cor3[1][k], cor3[2][k],
11853  vertex_normal[0][jj][i],
11854  vertex_normal[1][jj][i],
11855  vertex_normal[2][jj][i] );
11856 
11857  if ( j < jlo + 2 )
11858  {
11859  fprintf ( fileout, ",\n" );
11860  }
11861  else
11862  {
11863  fprintf ( fileout, "\n" );
11864  }
11865  text_num = text_num + 1;
11866 
11867  }
11868 
11869  if (i%6 == 1 )
11870  {
11871  fprintf ( fileout, "texture { RedText } }\n" );
11872  }
11873  else if ( i%2 == 0 )
11874  {
11875  fprintf ( fileout, "texture { BlueText } }\n" );
11876  }
11877  else
11878  {
11879  fprintf ( fileout, "texture { GreenText } }\n" );
11880  }
11881  text_num = text_num + 1;
11882 
11883  }
11884 
11885  }
11886 
11887  fprintf ( fileout, "}\n" );
11888  text_num = text_num + 1;
11889 //
11890 // Report.
11891 //
11892  cout << "\n";
11893  cout << "POV_WRITE - Wrote " << text_num << " text lines.\n";
11894 
11895  return 0;
11896 }
11897 //****************************************************************************80
11898 
11899 int rcol_find ( float a[][COR3_MAX], int m, int n, float r[] )
11900 
11901 //****************************************************************************80
11902 //
11903 // Purpose:
11904 //
11905 // RCOL_FIND finds if a vector occurs in a table.
11906 //
11907 // Discussion:
11908 //
11909 // Explicitly forcing the second dimension to be COR3_MAX is a kludge.
11910 // I have to figure out how to do this as pointer references.
11911 //
11912 // Also, since the array is not sorted, this routine should not be carelessly
11913 // called repeatedly for really big values of N, because you'll waste a
11914 // lot of time.
11915 //
11916 // Licensing:
11917 //
11918 // This code is distributed under the GNU LGPL license.
11919 //
11920 // Modified:
11921 //
11922 // 27 April 1999
11923 //
11924 // Author:
11925 //
11926 // John Burkardt
11927 //
11928 {
11929  int i;
11930  int icol;
11931  int j;
11932 
11933  icol = -1;
11934 
11935  for ( j = 0; j < n; j++ )
11936  {
11937  for ( i = 0; i < m; i++ )
11938  {
11939  if ( a[i][j] != r[i] )
11940  {
11941  break;
11942  }
11943  if ( i == m-1 )
11944  {
11945  return j;
11946  }
11947  }
11948  }
11949 
11950  return icol;
11951 }
11952 //****************************************************************************80
11953 
11954 float rgb_to_hue ( float r, float g, float b )
11955 
11956 //****************************************************************************80
11957 //
11958 // Purpose:
11959 //
11960 // RGB_TO_HUE converts (R,G,B) colors to a hue value between 0 and 1.
11961 //
11962 // Discussion:
11963 //
11964 // The hue computed here should be the same as the H value computed
11965 // for HLS and HSV, except that it ranges from 0 to 1 instead of
11966 // 0 to 360.
11967 //
11968 // A monochromatic color ( white, black, or a shade of gray) does not
11969 // have a hue. This routine will return a special value of H = -1
11970 // for such cases.
11971 //
11972 // Example:
11973 //
11974 // Color R G B H
11975 //
11976 // red 1.0 0.0 0.0 0.00
11977 // yellow 1.0 1.0 0.0 0.16
11978 // green 0.0 1.0 0.0 0.33
11979 // cyan 0.0 1.0 1.0 0.50
11980 // blue 0.0 0.0 1.0 0.67
11981 // magenta 1.0 0.0 1.0 0.83
11982 //
11983 // black 0.0 0.0 0.0 -1.00
11984 // gray 0.5 0.5 0.5 -1.00
11985 // white 1.0 1.0 1.0 -1.00
11986 //
11987 // Licensing:
11988 //
11989 // This code is distributed under the GNU LGPL license.
11990 //
11991 // Modified:
11992 //
11993 // 22 May 1999
11994 //
11995 // Author:
11996 //
11997 // John Burkardt
11998 //
11999 // Parameters:
12000 //
12001 // Input, float R, G, B, the red, green and blue values of the color.
12002 // These values should be between 0 and 1.
12003 //
12004 // Output, float RGB_TO_HUE, the corresponding hue of the color, or -1.0 if
12005 // the color is monochromatic.
12006 //
12007 {
12008  float h;
12009  float rgbmax;
12010  float rgbmin;
12011 //
12012 // Make sure the colors are between 0 and 1.
12013 //
12014  if ( r < 0.0 )
12015  {
12016  r = 0.0;
12017  }
12018  else if ( 1.0 < r )
12019  {
12020  r = 1.0;
12021  }
12022 
12023  if ( g < 0.0 )
12024  {
12025  g = 0.0;
12026  }
12027  else if ( 1.0 < g )
12028  {
12029  g = 1.0;
12030  }
12031 
12032  if ( b < 0.0 )
12033  {
12034  b = 0.0;
12035  }
12036  else if ( 1.0 < b )
12037  {
12038  b = 1.0;
12039  }
12040 //
12041 // Compute the minimum and maximum of R, G and B.
12042 //
12043  rgbmax = r;
12044  if ( rgbmax < g )
12045  {
12046  rgbmax = g;
12047  }
12048  if ( rgbmax < b )
12049  {
12050  rgbmax = b;
12051  }
12052 
12053  rgbmin = r;
12054  if ( g < rgbmin )
12055  {
12056  rgbmin = g;
12057  }
12058  if ( b < rgbmin )
12059  {
12060  rgbmin = b;
12061  }
12062 //
12063 // If RGBMAX = RGBMIN, the color has no hue.
12064 //
12065  if ( rgbmax == rgbmin )
12066  {
12067  h = - 1.0;
12068  }
12069 //
12070 // Otherwise, we need to determine the dominant color.
12071 //
12072  else
12073  {
12074  if ( r == rgbmax )
12075  {
12076  h = ( g - b ) / ( rgbmax - rgbmin );
12077  }
12078  else if ( g == rgbmax )
12079  {
12080  h = 2.0 + ( b - r ) / ( rgbmax - rgbmin );
12081  }
12082  else if ( b == rgbmax )
12083  {
12084  h = 4.0 + ( r - g ) / ( rgbmax - rgbmin );
12085  }
12086 
12087  h = h / 6.0;
12088 //
12089 // Make sure H lies between 0 and 1.0.
12090 //
12091  if ( h < 0.0 )
12092  {
12093  h = h + 1.0;
12094  }
12095  else if ( 1.0 < h )
12096  {
12097  h = h - 1.0;
12098  }
12099 
12100  }
12101 
12102  return h;
12103 }
12104 //****************************************************************************80
12105 
12106 bool s_eqi ( char *s1, char *s2 )
12107 
12108 //****************************************************************************80
12109 //
12110 // Purpose:
12111 //
12112 // S_EQI reports whether two strings are equal, ignoring case.
12113 //
12114 // Licensing:
12115 //
12116 // This code is distributed under the GNU LGPL license.
12117 //
12118 // Modified:
12119 //
12120 // 05 May 2003
12121 //
12122 // Author:
12123 //
12124 // John Burkardt
12125 //
12126 // Parameters:
12127 //
12128 // Input, char *S1, char *S2, pointers to two strings.
12129 //
12130 // Output, bool S_EQI, is true if the strings are equal.
12131 //
12132 {
12133  int i;
12134  int nchar;
12135  int nchar1;
12136  int nchar2;
12137 
12138  nchar1 = strlen ( s1 );
12139  nchar2 = strlen ( s2 );
12140  nchar = i4_min ( nchar1, nchar2 );
12141 
12142 //
12143 // The strings are not equal if they differ over their common length.
12144 //
12145  for ( i = 0; i < nchar; i++ )
12146  {
12147 
12148  if ( ch_cap ( s1[i] ) != ch_cap ( s2[i] ) )
12149  {
12150  return false;
12151  }
12152  }
12153 //
12154 // The strings are not equal if the longer one includes nonblanks
12155 // in the tail.
12156 //
12157  if ( nchar < nchar1 )
12158  {
12159  for ( i = nchar; i < nchar1; i++ )
12160  {
12161  if ( s1[i] != ' ' )
12162  {
12163  return false;
12164  }
12165  }
12166  }
12167  else if ( nchar < nchar2 )
12168  {
12169  for ( i = nchar; i < nchar2; i++ )
12170  {
12171  if ( s2[i] != ' ' )
12172  {
12173  return false;
12174  }
12175  }
12176  }
12177 
12178  return true;
12179 
12180 }
12181 //****************************************************************************80
12182 
12183 int s_len_trim ( char *s )
12184 
12185 //****************************************************************************80
12186 //
12187 // Purpose:
12188 //
12189 // S_LEN_TRIM returns the length of a string to the last nonblank.
12190 //
12191 // Licensing:
12192 //
12193 // This code is distributed under the GNU LGPL license.
12194 //
12195 // Modified:
12196 //
12197 // 26 April 2003
12198 //
12199 // Author:
12200 //
12201 // John Burkardt
12202 //
12203 // Parameters:
12204 //
12205 // Input, char *S, a pointer to a string.
12206 //
12207 // Output, int S_LEN_TRIM, the length of the string to the last nonblank.
12208 // If S_LEN_TRIM is 0, then the string is entirely blank.
12209 //
12210 {
12211  int n;
12212  char *t;
12213 
12214  n = strlen ( s );
12215  t = s + strlen ( s ) - 1;
12216 
12217  while ( 0 < n )
12218  {
12219  if ( *t != ' ' )
12220  {
12221  return n;
12222  }
12223  t--;
12224  n--;
12225  }
12226 
12227  return n;
12228 }
12229 //****************************************************************************80
12230 
12231 int s_to_i4 ( char *s, int *last, bool *error )
12232 
12233 //****************************************************************************80
12234 //
12235 // Purpose:
12236 //
12237 // S_TO_I4 reads an I4 from a string.
12238 //
12239 // Licensing:
12240 //
12241 // This code is distributed under the GNU LGPL license.
12242 //
12243 // Modified:
12244 //
12245 // 13 June 2003
12246 //
12247 // Author:
12248 //
12249 // John Burkardt
12250 //
12251 // Parameters:
12252 //
12253 // Input, char *S, a string to be examined.
12254 //
12255 // Output, int *LAST, the last character of S used to make IVAL.
12256 //
12257 // Output, bool *ERROR is TRUE if an error occurred.
12258 //
12259 // Output, int *S_TO_I4, the integer value read from the string.
12260 // If the string is blank, then IVAL will be returned 0.
12261 //
12262 {
12263  char c;
12264  int i;
12265  int isgn;
12266  int istate;
12267  int ival;
12268 
12269  *error = false;
12270  istate = 0;
12271  isgn = 1;
12272  i = 0;
12273  ival = 0;
12274 
12275  while ( *s )
12276  {
12277  c = s[i];
12278  i = i + 1;
12279 //
12280 // Haven't read anything.
12281 //
12282  if ( istate == 0 )
12283  {
12284  if ( c == ' ' )
12285  {
12286  }
12287  else if ( c == '-' )
12288  {
12289  istate = 1;
12290  isgn = -1;
12291  }
12292  else if ( c == '+' )
12293  {
12294  istate = 1;
12295  isgn = + 1;
12296  }
12297  else if ( '0' <= c && c <= '9' )
12298  {
12299  istate = 2;
12300  ival = c - '0';
12301  }
12302  else
12303  {
12304  *error = true;
12305  return ival;
12306  }
12307  }
12308 //
12309 // Have read the sign, expecting digits.
12310 //
12311  else if ( istate == 1 )
12312  {
12313  if ( c == ' ' )
12314  {
12315  }
12316  else if ( '0' <= c && c <= '9' )
12317  {
12318  istate = 2;
12319  ival = c - '0';
12320  }
12321  else
12322  {
12323  *error = true;
12324  return ival;
12325  }
12326  }
12327 //
12328 // Have read at least one digit, expecting more.
12329 //
12330  else if ( istate == 2 )
12331  {
12332  if ( '0' <= c && c <= '9' )
12333  {
12334  ival = 10 * (ival) + c - '0';
12335  }
12336  else
12337  {
12338  ival = isgn * ival;
12339  *last = i - 1;
12340  return ival;
12341  }
12342 
12343  }
12344  }
12345 //
12346 // If we read all the characters in the string, see if we're OK.
12347 //
12348  if ( istate == 2 )
12349  {
12350  ival = isgn * ival;
12351  *last = s_len_trim ( s );
12352  }
12353  else
12354  {
12355  *error = true;
12356  *last = 0;
12357  }
12358 
12359  return ival;
12360 }
12361 //****************************************************************************80
12362 
12363 bool s_to_i4vec ( char *s, int n, int ivec[] )
12364 
12365 //****************************************************************************80
12366 //
12367 // Purpose:
12368 //
12369 // S_TO_I4VEC reads an I4VEC from a string.
12370 //
12371 // Licensing:
12372 //
12373 // This code is distributed under the GNU LGPL license.
12374 //
12375 // Modified:
12376 //
12377 // 19 January 2004
12378 //
12379 // Author:
12380 //
12381 // John Burkardt
12382 //
12383 // Parameters:
12384 //
12385 // Input, char *S, the string to be read.
12386 //
12387 // Input, int N, the number of values expected.
12388 //
12389 // Output, int IVEC[N], the values read from the string.
12390 //
12391 // Output, bool S_TO_I4VEC, is TRUE if an error occurred.
12392 //
12393 {
12394  bool error;
12395  int i;
12396  int lchar;
12397 
12398  error = false;
12399 
12400  for ( i = 0; i < n; i++ )
12401  {
12402  ivec[i] = s_to_i4 ( s, &lchar, &error );
12403 
12404  if ( error )
12405  {
12406  cout << "\n";
12407  cout << "S_TO_I4VEC - Fatal error!\n";
12408  cout << " S_TO_I4 returned error while reading item " << i << "\n";
12409  return error;
12410  }
12411 
12412  s = s + lchar;
12413 
12414  }
12415 
12416  return error;
12417 }
12418 //****************************************************************************80
12419 
12420 float s_to_r4 ( char *s, int *lchar, bool *error )
12421 
12422 //****************************************************************************80
12423 //
12424 // Purpose:
12425 //
12426 // S_TO_R4 reads an R4 from a string.
12427 //
12428 // Discussion:
12429 //
12430 // This routine will read as many characters as possible until it reaches
12431 // the end of the string, or encounters a character which cannot be
12432 // part of the real number.
12433 //
12434 // Legal input is:
12435 //
12436 // 1 blanks,
12437 // 2 '+' or '-' sign,
12438 // 2.5 spaces
12439 // 3 integer part,
12440 // 4 decimal point,
12441 // 5 fraction part,
12442 // 6 'E' or 'e' or 'D' or 'd', exponent marker,
12443 // 7 exponent sign,
12444 // 8 exponent integer part,
12445 // 9 exponent decimal point,
12446 // 10 exponent fraction part,
12447 // 11 blanks,
12448 // 12 final comma or semicolon.
12449 //
12450 // with most quantities optional.
12451 //
12452 // Example:
12453 //
12454 // S R
12455 //
12456 // '1' 1.0
12457 // ' 1 ' 1.0
12458 // '1A' 1.0
12459 // '12,34,56' 12.0
12460 // ' 34 7' 34.0
12461 // '-1E2ABCD' -100.0
12462 // '-1X2ABCD' -1.0
12463 // ' 2E-1' 0.2
12464 // '23.45' 23.45
12465 // '-4.2E+2' -420.0
12466 // '17d2' 1700.0
12467 // '-14e-2' -0.14
12468 // 'e2' 100.0
12469 // '-12.73e-9.23' -12.73 * 10.0**(-9.23)
12470 //
12471 // Licensing:
12472 //
12473 // This code is distributed under the GNU LGPL license.
12474 //
12475 // Modified:
12476 //
12477 // 07 August 2003
12478 //
12479 // Author:
12480 //
12481 // John Burkardt
12482 //
12483 // Parameters:
12484 //
12485 // Input, char *S, the string containing the
12486 // data to be read. Reading will begin at position 1 and
12487 // terminate at the end of the string, or when no more
12488 // characters can be read to form a legal real. Blanks,
12489 // commas, or other nonnumeric data will, in particular,
12490 // cause the conversion to halt.
12491 //
12492 // Output, int *LCHAR, the number of characters read from
12493 // the string to form the number, including any terminating
12494 // characters such as a trailing comma or blanks.
12495 //
12496 // Output, bool *ERROR, is true if an error occurred.
12497 //
12498 // Output, float S_TO_R4, the real value that was read from the string.
12499 //
12500 {
12501  char c;
12502  int ihave;
12503  int isgn;
12504  int iterm;
12505  int jbot;
12506  int jsgn;
12507  int jtop;
12508  int nchar;
12509  int ndig;
12510  float r;
12511  float rbot;
12512  float rexp;
12513  float rtop;
12514  char TAB = 9;
12515 
12516  nchar = s_len_trim ( s );
12517  *error = false;
12518  r = 0.0E+00;
12519  *lchar = -1;
12520  isgn = 1;
12521  rtop = 0.0E+00;
12522  rbot = 1.0E+00;
12523  jsgn = 1;
12524  jtop = 0;
12525  jbot = 1;
12526  ihave = 1;
12527  iterm = 0;
12528 
12529  for ( ; ; )
12530  {
12531  c = s[*lchar+1];
12532  *lchar = *lchar + 1;
12533 //
12534 // Blank or TAB character.
12535 //
12536  if ( c == ' ' || c == TAB )
12537  {
12538  if ( ihave == 2 )
12539  {
12540  }
12541  else if ( ihave == 6 || ihave == 7 )
12542  {
12543  iterm = 1;
12544  }
12545  else if ( 1 < ihave )
12546  {
12547  ihave = 11;
12548  }
12549  }
12550 //
12551 // Comma.
12552 //
12553  else if ( c == ',' || c == ';' )
12554  {
12555  if ( ihave != 1 )
12556  {
12557  iterm = 1;
12558  ihave = 12;
12559  *lchar = *lchar + 1;
12560  }
12561  }
12562 //
12563 // Minus sign.
12564 //
12565  else if ( c == '-' )
12566  {
12567  if ( ihave == 1 )
12568  {
12569  ihave = 2;
12570  isgn = -1;
12571  }
12572  else if ( ihave == 6 )
12573  {
12574  ihave = 7;
12575  jsgn = -1;
12576  }
12577  else
12578  {
12579  iterm = 1;
12580  }
12581  }
12582 //
12583 // Plus sign.
12584 //
12585  else if ( c == '+' )
12586  {
12587  if ( ihave == 1 )
12588  {
12589  ihave = 2;
12590  }
12591  else if ( ihave == 6 )
12592  {
12593  ihave = 7;
12594  }
12595  else
12596  {
12597  iterm = 1;
12598  }
12599  }
12600 //
12601 // Decimal point.
12602 //
12603  else if ( c == '.' )
12604  {
12605  if ( ihave < 4 )
12606  {
12607  ihave = 4;
12608  }
12609  else if ( 6 <= ihave && ihave <= 8 )
12610  {
12611  ihave = 9;
12612  }
12613  else
12614  {
12615  iterm = 1;
12616  }
12617  }
12618 //
12619 // Exponent marker.
12620 //
12621  else if ( ch_eqi ( c, 'E' ) || ch_eqi ( c, 'D' ) )
12622  {
12623  if ( ihave < 6 )
12624  {
12625  ihave = 6;
12626  }
12627  else
12628  {
12629  iterm = 1;
12630  }
12631  }
12632 //
12633 // Digit.
12634 //
12635  else if ( ihave < 11 && '0' <= c && c <= '9' )
12636  {
12637  if ( ihave <= 2 )
12638  {
12639  ihave = 3;
12640  }
12641  else if ( ihave == 4 )
12642  {
12643  ihave = 5;
12644  }
12645  else if ( ihave == 6 || ihave == 7 )
12646  {
12647  ihave = 8;
12648  }
12649  else if ( ihave == 9 )
12650  {
12651  ihave = 10;
12652  }
12653 
12654  ndig = ch_to_digit ( c );
12655 
12656  if ( ihave == 3 )
12657  {
12658  rtop = 10.0E+00 * rtop + ( float ) ndig;
12659  }
12660  else if ( ihave == 5 )
12661  {
12662  rtop = 10.0E+00 * rtop + ( float ) ndig;
12663  rbot = 10.0E+00 * rbot;
12664  }
12665  else if ( ihave == 8 )
12666  {
12667  jtop = 10 * jtop + ndig;
12668  }
12669  else if ( ihave == 10 )
12670  {
12671  jtop = 10 * jtop + ndig;
12672  jbot = 10 * jbot;
12673  }
12674  }
12675 //
12676 // Anything else is regarded as a terminator.
12677 //
12678  else
12679  {
12680  iterm = 1;
12681  }
12682 //
12683 // If we haven't seen a terminator, and we haven't examined the
12684 // entire string, go get the next character.
12685 //
12686  if ( iterm == 1 || nchar <= *lchar + 1 )
12687  {
12688  break;
12689  }
12690 
12691  }
12692 //
12693 // If we haven't seen a terminator, and we have examined the
12694 // entire string, then we're done, and LCHAR is equal to NCHAR.
12695 //
12696  if ( iterm != 1 && (*lchar) + 1 == nchar )
12697  {
12698  *lchar = nchar;
12699  }
12700 //
12701 // Number seems to have terminated. Have we got a legal number?
12702 // Not if we terminated in states 1, 2, 6 or 7!
12703 //
12704  if ( ihave == 1 || ihave == 2 || ihave == 6 || ihave == 7 )
12705  {
12706  *error = true;
12707  return r;
12708  }
12709 //
12710 // Number seems OK. Form it.
12711 //
12712  if ( jtop == 0 )
12713  {
12714  rexp = 1.0E+00;
12715  }
12716  else
12717  {
12718  if ( jbot == 1 )
12719  {
12720  rexp = pow ( ( double ) 10.0E+00, ( double ) ( jsgn * jtop ) );
12721  }
12722  else
12723  {
12724  rexp = jsgn * jtop;
12725  rexp = rexp / jbot;
12726  rexp = pow ( ( double ) 10.0E+00, ( double ) rexp );
12727  }
12728 
12729  }
12730 
12731  r = isgn * rexp * rtop / rbot;
12732 
12733  return r;
12734 }
12735 //****************************************************************************80
12736 
12737 bool s_to_r4vec ( char *s, int n, float rvec[] )
12738 
12739 //****************************************************************************80
12740 //
12741 // Purpose:
12742 //
12743 // S_TO_R4VEC reads an R4VEC from a string.
12744 //
12745 // Licensing:
12746 //
12747 // This code is distributed under the GNU LGPL license.
12748 //
12749 // Modified:
12750 //
12751 // 19 February 2001
12752 //
12753 // Author:
12754 //
12755 // John Burkardt
12756 //
12757 // Parameters:
12758 //
12759 // Input, character ( len = * ) S, the string to be read.
12760 //
12761 // Input, integer N, the number of values expected.
12762 //
12763 // Output, real RVEC[N], the values read from the string.
12764 //
12765 // Output, bool S_TO_R4VEC, is true if an error occurred.
12766 //
12767 {
12768  bool error;
12769  int i;
12770  int lchar;
12771 
12772  error = false;
12773 
12774  for ( i = 0; i < n; i++ )
12775  {
12776  rvec[i] = s_to_r4 ( s, &lchar, &error );
12777 
12778  if ( error )
12779  {
12780  return error;
12781  }
12782 
12783  s = s + lchar;
12784 
12785  }
12786 
12787  return error;
12788 }
12789 //****************************************************************************80
12790 
12791 short int short_int_read ( FILE *filein )
12792 
12793 //****************************************************************************80
12794 //
12795 // Purpose:
12796 //
12797 // SHORT_INT_READ reads a short int from a binary file.
12798 //
12799 // Licensing:
12800 //
12801 // This code is distributed under the GNU LGPL license.
12802 //
12803 // Modified:
12804 //
12805 // 14 October 1998
12806 //
12807 // Author:
12808 //
12809 // John Burkardt
12810 //
12811 {
12812  unsigned char c1;
12813  unsigned char c2;
12814  short int ival;
12815 
12816  c1 = fgetc ( filein );
12817  c2 = fgetc ( filein );
12818 
12819  ival = c1 | ( c2 << 8 );
12820 
12821  return ival;
12822 }
12823 //****************************************************************************80
12824 
12825 int short_int_write ( FILE *fileout, short int short_int_val )
12826 
12827 //****************************************************************************80
12828 //
12829 // Purpose:
12830 //
12831 // SHORT_INT_WRITE writes a short int to a binary file.
12832 //
12833 // Licensing:
12834 //
12835 // This code is distributed under the GNU LGPL license.
12836 //
12837 // Modified:
12838 //
12839 // 14 October 1998
12840 //
12841 // Author:
12842 //
12843 // John Burkardt
12844 //
12845 {
12846  union {
12847  short int yint;
12848  char ychar[2];
12849  } y;
12850 
12851  y.yint = short_int_val;
12852 
12853  if ( byte_swap )
12854  {
12855  fputc ( y.ychar[1], fileout );
12856  fputc ( y.ychar[0], fileout );
12857  }
12858  else
12859  {
12860  fputc ( y.ychar[0], fileout );
12861  fputc ( y.ychar[1], fileout );
12862  }
12863 
12864  return 2;
12865 }
12866 //****************************************************************************80
12867 
12868 int smf_read ( FILE *filein )
12869 
12870 //****************************************************************************80
12871 //
12872 // Purpose:
12873 //
12874 // SMF_READ reads an SMF file.
12875 //
12876 // Example:
12877 //
12878 // #SMF2.0
12879 // # cube_face.smf
12880 // # This example demonstrates how an RGB color can be assigned to
12881 // # each face of an object.
12882 // #
12883 // # First, define the geometry of the cube.
12884 // #
12885 // v 0.0 0.0 0.0
12886 // v 1.0 0.0 0.0
12887 // v 0.0 1.0 0.0
12888 // v 1.0 1.0 0.0
12889 // v 0.0 0.0 1.0
12890 // v 1.0 0.0 1.0
12891 // v 0.0 1.0 1.0
12892 // v 1.0 1.0 1.0
12893 // f 1 4 2
12894 // f 1 3 4
12895 // f 5 6 8
12896 // f 5 8 7
12897 // f 1 2 6
12898 // f 1 6 5
12899 // f 2 4 8
12900 // f 2 8 6
12901 // f 4 3 7
12902 // f 4 7 8
12903 // f 3 1 5
12904 // f 3 5 7
12905 // #
12906 // # Colors will be bound 1 per face.
12907 // #
12908 // bind c face
12909 // c 1.0 0.0 0.0
12910 // c 1.0 0.0 0.0
12911 // c 0.0 1.0 0.0
12912 // c 0.0 1.0 0.0
12913 // c 0.0 0.0 1.0
12914 // c 0.0 0.0 1.0
12915 // c 1.0 1.0 0.0
12916 // c 1.0 1.0 0.0
12917 // c 0.0 1.0 1.0
12918 // c 0.0 1.0 1.0
12919 // c 1.0 0.0 1.0
12920 // c 1.0 0.0 1.0
12921 // #
12922 // # Normal vectors will be bound 1 per face.
12923 // #
12924 // bind n face
12925 // n 0.0 0.0 -1.0
12926 // n 0.0 0.0 -1.0
12927 // n 0.0 0.0 1.0
12928 // n 0.0 0.0 1.0
12929 // n 0.0 -1.0 0.0
12930 // n 0.0 -1.0 0.0
12931 // n 1.0 0.0 0.0
12932 // n 1.0 0.0 0.0
12933 // n 0.0 1.0 0.0
12934 // n 0.0 1.0 0.0
12935 // n -1.0 0.0 0.0
12936 // n -1.0 0.0 0.0
12937 // #
12938 // # Texture coordinate pairs will be bound 1 per face.
12939 // #
12940 // bind r face
12941 // r 0.0 0.0
12942 // r 0.0 0.1
12943 // r 0.0 0.2
12944 // r 0.0 0.3
12945 // r 0.1 0.0
12946 // r 0.1 0.1
12947 // r 0.1 0.2
12948 // r 0.1 0.3
12949 // r 0.2 0.0
12950 // r 0.2 0.1
12951 // r 0.2 0.2
12952 // r 0.2 0.3
12953 //
12954 // Licensing:
12955 //
12956 // This code is distributed under the GNU LGPL license.
12957 //
12958 // Modified:
12959 //
12960 // 03 July 1999
12961 //
12962 // Author:
12963 //
12964 // John Burkardt
12965 //
12966 {
12967  float angle;
12968  char axis;
12969  float b;
12970  char cnr[LINE_MAX_LEN];
12971  int count;
12972  float dx;
12973  float dy;
12974  int face_count;
12975  float g;
12976  int icor3_normal;
12977  int icor3_tex_uv;
12978  int iface_normal;
12979  int iface_tex_uv;
12980  int imat;
12981  int ivert;
12982  int level;
12983  char *next;
12984  int node;
12985  int node_count;
12986  float r;
12987  float r1;
12988  float r2;
12989  float r3;
12990  float rgba[4];
12991  char *string = "Dummy material";
12992  float sx;
12993  float sy;
12994  float sz;
12995  char token[LINE_MAX_LEN];
12996  char token2[LINE_MAX_LEN];
12997  char type[LINE_MAX_LEN];
12998  float u;
12999  float v;
13000  int vertex_base;
13001  int vertex_correction;
13002  int width;
13003  float x;
13004  float xvec[3];
13005  float y;
13006  float z;
13007 
13008  face_count = 0;
13009  icor3_normal = 0;
13010  icor3_tex_uv = 0;
13011  iface_normal = 0;
13012  iface_tex_uv = 0;
13013  level = 0;
13014  node_count = 0;
13015  vertex_base = 0;
13016  vertex_correction = 0;
13017 //
13018 // Read the next line of the file into INPUT.
13019 //
13020  while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL )
13021  {
13022  text_num = text_num + 1;
13023 
13024  if ( debug )
13025  {
13026  cout << "SMF_READ: DEBUG: Reading line #" << text_num << "\n";
13027  }
13028 //
13029 // Advance to the first nonspace character in INPUT.
13030 //
13031  for ( next = input; *next != '\0' && ch_is_space ( *next ); next++ )
13032  {
13033  }
13034 //
13035 // Skip blank lines.
13036 //
13037 
13038  if ( *next == '\0' )
13039  {
13040  continue;
13041  }
13042 //
13043 // Skip comment lines.
13044 //
13045  if ( *next == '#' || *next == '$' )
13046  {
13047  comment_num = comment_num + 1;
13048  continue;
13049  }
13050 //
13051 // Extract the first word in this line.
13052 //
13053  sscanf ( next, "%s%n", token, &width );
13054 //
13055 // Set NEXT to point to just after this token.
13056 //
13057  next = next + width;
13058 //
13059 // BEGIN
13060 // Reset the transformation matrix to identity.
13061 // Node numbering starts at zero again. (Really, this is level based)
13062 // (Really should define a new transformation matrix, and concatenate.)
13063 // (Also, might need to keep track of level.)
13064 //
13065  if ( s_eqi ( token, "BEGIN" ) )
13066  {
13067  level = level + 1;
13068  vertex_base = cor3_num;
13069  group_num = group_num + 1;
13071  }
13072 //
13073 // BIND [c|n|r] [vertex|face]
13074 // Specify the binding for RGB color, Normal, or Texture.
13075 // Options are "vertex" or "face"
13076 //
13077  else if ( s_eqi ( token, "BIND" ) )
13078  {
13079  sscanf ( next, "%s%n", cnr, &width );
13080  next = next + width;
13081 
13082  if ( debug )
13083  {
13084  cout << "CNR = " << cnr << "\n";
13085  }
13086 
13087  sscanf ( next, "%s%n", type, &width );
13088  next = next + width;
13089 
13090  if ( debug )
13091  {
13092  cout << "TYPE = " << type << "\n";
13093  }
13094 
13095  if ( s_eqi ( cnr, "C" ) )
13096  {
13097  if ( s_eqi ( type, "VERTEX" ) )
13098  {
13099  strcpy ( material_binding, "PER_VERTEX" );
13100  }
13101  else if ( s_eqi ( type, "FACE" ) )
13102  {
13103  strcpy ( material_binding, "PER_FACE" );
13104  }
13105  }
13106  else if ( s_eqi ( cnr, "N" ) )
13107  {
13108  if ( s_eqi ( type, "VERTEX" ) )
13109  {
13110  strcpy ( normal_binding, "PER_VERTEX" );
13111  }
13112  else if ( s_eqi ( type, "FACE" ) )
13113  {
13114  strcpy ( normal_binding, "PER_FACE" );
13115  }
13116  }
13117  else if ( s_eqi ( cnr, "R" ) )
13118  {
13119  if ( s_eqi ( type, "VERTEX" ) )
13120  {
13121  strcpy ( texture_binding, "PER_VERTEX" );
13122  }
13123  else if ( s_eqi ( type, "FACE" ) )
13124  {
13125  strcpy ( texture_binding, "PER_FACE" );
13126  }
13127 
13128  }
13129 
13130  }
13131 //
13132 // C <r> <g> <b>
13133 // Specify an RGB color, with R, G, B between 0.0 and 1.0.
13134 //
13135  else if ( s_eqi ( token, "C" ) )
13136  {
13137  sscanf ( next, "%f%n", &r, &width );
13138  next = next + width;
13139 
13140  sscanf ( next, "%f%n", &g, &width );
13141  next = next + width;
13142 
13143  sscanf ( next, "%f%n", &b, &width );
13144  next = next + width;
13145 //
13146 // Set up a temporary material (R,G,B,1.0).
13147 // Add the material to the material database, or find the index of
13148 // a matching material already in.
13149 // Assign the material of the node or face to this index.
13150 //
13151  rgba[0] = r;
13152  rgba[1] = g;
13153  rgba[2] = b;
13154  rgba[3] = 1.0;
13155 
13156  if ( material_num < MATERIAL_MAX )
13157  {
13158  for ( k = 0; k < 4; k++ )
13159  {
13160  material_rgba[k][material_num] = rgba[k];
13161  }
13162 
13163  imat = material_num;
13164  material_num = material_num + 1;
13165 
13166  }
13167  else
13168  {
13169  imat = 0;
13170  }
13171 
13172  if ( s_eqi ( material_binding, "PER_FACE" ) )
13173  {
13174  face_count = face_count + 1;
13175  face_material[face_count] = imat;
13176  }
13177  else if ( s_eqi ( material_binding, "PER_VERTEX" ) )
13178  {
13179  node_count = node_count + 1;
13180  cor3_material[node_count] = imat;
13181 
13182  }
13183  else
13184  {
13185  cout << "\n";
13186  cout << "SMF_READ - Fatal error!\n";
13187  cout << " Material binding undefined!\n";
13188  return 1;
13189 
13190  }
13191 
13192  }
13193 //
13194 // END
13195 // Drop down a level.
13196 //
13197  else if ( s_eqi ( token, "END" ) )
13198  {
13199  level = level - 1;
13200 
13201  if ( level < 0 )
13202  {
13203  cout << "\n";
13204  cout << "SMF_READ - Fatal error!\n";
13205  cout << " More END statements than BEGINs!\n";
13206  return 1;
13207  }
13208  }
13209 //
13210 // F V1 V2 V3
13211 //
13212 // Face.
13213 // A face is defined by the vertices.
13214 // Node indices are 1 based rather than 0 based.
13215 // So we have to decrement them before loading them into FACE.
13216 // Note that vertex indices start back at 0 each time a BEGIN is entered.
13217 // The strategy here won't handle nested BEGIN's, just one at a time.
13218 //
13219 
13220  else if ( s_eqi ( token, "F" ) )
13221  {
13222  ivert = 0;
13223  face_order[face_num] = 0;
13224 //
13225 // Read each item in the F definition as a token, and then
13226 // take it apart.
13227 //
13228  for ( ;; )
13229  {
13230  count = sscanf ( next, "%s%n", token2, &width );
13231  next = next + width;
13232 
13233  if ( count != 1 )
13234  {
13235  break;
13236  }
13237 
13238  count = sscanf ( token2, "%d%n", &node, &width );
13239 
13240  if ( count != 1 )
13241  {
13242  break;
13243  }
13244 
13245  if ( ivert < ORDER_MAX && face_num < FACE_MAX )
13246  {
13247  face[ivert][face_num] = node - 1 + vertex_base;
13248  vertex_material[ivert][face_num] = 0;
13250  }
13251  ivert = ivert + 1;
13252  }
13253  face_num = face_num + 1;
13254  }
13255 //
13256 // N <x> <y> <z>
13257 // Specify a normal vector.
13258 //
13259  else if ( s_eqi ( token, "N" ) )
13260  {
13261  sscanf ( next, "%f%n", &x, &width );
13262  next = next + width;
13263 
13264  sscanf ( next, "%f%n", &y, &width );
13265  next = next + width;
13266 
13267  sscanf ( next, "%f%n", &z, &width );
13268  next = next + width;
13269 
13270  if ( s_eqi ( normal_binding, "PER_FACE" ) )
13271  {
13272  face_normal[0][iface_normal] = x;
13273  face_normal[1][iface_normal] = y;
13274  face_normal[2][iface_normal] = z;
13275 
13276  iface_normal = iface_normal + 1;
13277  }
13278  else if ( s_eqi ( normal_binding, "PER_VERTEX" ) )
13279  {
13280  cor3_normal[0][icor3_normal] = x;
13281  cor3_normal[1][icor3_normal] = y;
13282  cor3_normal[2][icor3_normal] = z;
13283 
13284  icor3_normal = icor3_normal + 1;
13285  }
13286  else
13287  {
13288  cout << "\n";
13289  cout << "SMF_READ - Fatal error!\n";
13290  cout << " Normal binding undefined!\n";
13291  return 1;
13292 
13293  }
13294  }
13295 //
13296 // R <u> <v>
13297 // Specify a texture coordinate.
13298 //
13299  else if ( s_eqi ( token, "R" ) )
13300  {
13301  sscanf ( next, "%f%n", &u, &width );
13302  next = next + width;
13303 
13304  sscanf ( next, "%f%n", &v, &width );
13305  next = next + width;
13306 
13307  if ( s_eqi ( texture_binding, "PER_FACE" ) )
13308  {
13309  face_tex_uv[0][iface_tex_uv] = u;
13310  face_tex_uv[1][iface_tex_uv] = v;
13311 
13312  icor3_tex_uv = icor3_tex_uv + 1;
13313 
13314  }
13315  else if ( s_eqi ( texture_binding, "PER_VERTEX" ) )
13316  {
13317  cor3_tex_uv[0][icor3_tex_uv] = u;
13318  cor3_tex_uv[1][icor3_tex_uv] = v;
13319 
13320  icor3_tex_uv = icor3_tex_uv + 1;
13321  }
13322  else
13323  {
13324  cout << "\n";
13325  cout << "SMF_READ - Fatal error!\n";
13326  cout << " Texture binding undefined!\n";
13327  return 1;
13328  }
13329 
13330  }
13331 //
13332 // ROT [x|y|z] <theta>
13333 //
13334  else if ( s_eqi ( token, "ROT" ) )
13335  {
13336  sscanf ( next, "%c%n", &axis, &width );
13337  next = next + width;
13338 
13339  sscanf ( next, "%f%n", &angle, &width );
13340  next = next + width;
13341 
13343  }
13344 //
13345 // SCALE <sx> <sy> <sz>
13346 //
13347  else if ( s_eqi ( token, "SCALE" ) )
13348  {
13349  sscanf ( next, "%f%n", &sx, &width );
13350  next = next + width;
13351 
13352  sscanf ( next, "%f%n", &sy, &width );
13353  next = next + width;
13354 
13355  sscanf ( next, "%f%n", &sz, &width );
13356  next = next + width;
13357 
13358  tmat_scale ( transform_matrix, transform_matrix, sx, sy, sz );
13359  }
13360 //
13361 // SET VERTEX_CORRECTION <i>
13362 // Specify increment to add to vertex indices in file.
13363 //
13364  else if ( s_eqi ( token, "SET" ) )
13365  {
13366  sscanf ( next, "%s%n", cnr, &width );
13367  next = next + width;
13368 
13369  sscanf ( next, "%d%n", &vertex_correction, &width );
13370  next = next + width;
13371  }
13372 //
13373 // T_SCALE <dx> <dy>
13374 // Specify a scaling to texture coordinates.
13375 //
13376  else if ( s_eqi ( token, "T_SCALE" ) )
13377  {
13378  sscanf ( next, "%f%n", &dx, &width );
13379  next = next + width;
13380 
13381  sscanf ( next, "%f%n", &dy, &width );
13382  next = next + width;
13383  }
13384 //
13385 // T_TRANS <dx> <dy>
13386 // Specify a translation to texture coordinates.
13387 //
13388  else if ( s_eqi ( token, "T_TRANS" ) )
13389  {
13390  sscanf ( next, "%f%n", &dx, &width );
13391  next = next + width;
13392 
13393  sscanf ( next, "%f%n", &dy, &width );
13394  next = next + width;
13395  }
13396 //
13397 // TEX <filename>
13398 // Specify a filename containing the texture.
13399 // (ANY CHANCE THIS IS RIGHT?)
13400 // The compiler warns that STRING is not initialized.
13401 //
13402  else if ( s_eqi ( token, "TEX" ) )
13403  {
13404  sscanf ( next, "%s%n", string, &width );
13405 
13406  for ( i = 0; i < LINE_MAX_LEN; i++ )
13407  {
13408  texture_name[texture_num][i] = string[i];
13409  if ( string[i] == '\0' )
13410  {
13411  break;
13412  }
13413  }
13414 
13415  texture_num = texture_num + 1;
13416  }
13417 //
13418 // TRANS <dx> <dy> <dz>
13419 //
13420  else if ( s_eqi ( token, "TRANS" ) )
13421  {
13422  sscanf ( next, "%f%n", &x, &width );
13423  next = next + width;
13424 
13425  sscanf ( next, "%f%n", &y, &width );
13426  next = next + width;
13427 
13428  sscanf ( next, "%f%n", &z, &width );
13429  next = next + width;
13430 
13432  }
13433 //
13434 // V X Y Z
13435 // Geometric vertex.
13436 //
13437  else if ( s_eqi ( token, "V" ) )
13438  {
13439  sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
13440 
13441  xvec[0] = r1;
13442  xvec[1] = r2;
13443  xvec[2] = r3;
13444 //
13445 // Apply current transformation matrix.
13446 // Right now, we can only handle one matrix, not a stack of
13447 // matrices representing nested BEGIN/END's.
13448 //
13449  tmat_mxp ( transform_matrix, xvec, xvec );
13450 
13451  if ( cor3_num < COR3_MAX )
13452  {
13453  for ( i = 0; i < 3; i++ )
13454  {
13455  cor3[i][cor3_num] = xvec[i];
13456  }
13457  }
13458 
13459  cor3_num = cor3_num + 1;
13460 
13461  }
13462 //
13463 // Unrecognized keyword.
13464 //
13465  else
13466  {
13467  bad_num = bad_num + 1;
13468 
13469  if ( bad_num <= 10 )
13470  {
13471  cout << "\n";
13472  cout << "SMF_READ: Bad data on line " << text_num << ".\n";
13473  }
13474  }
13475 
13476  }
13477 //
13478 // Extend the material definition
13479 // * from the face to the vertices and nodes, or
13480 // * from the vertices to the faces and nodes.
13481 //
13482  if ( strcmp ( material_binding, "PER_FACE" ) == 0 )
13483  {
13485 
13487 
13488  }
13489  else if ( strcmp ( material_binding, "PER_VERTEX" ) == 0 )
13490  {
13492 
13494 
13495  }
13496 
13497  return 0;
13498 }
13499 //****************************************************************************80
13500 
13501 int smf_write ( FILE *fileout )
13502 
13503 //****************************************************************************80
13504 //
13505 // Purpose:
13506 //
13507 // SMF_WRITE writes graphics information to an SMF file.
13508 //
13509 // Example:
13510 //
13511 // #SMF2.0
13512 // # cube_face.smf
13513 // # This example demonstrates how an RGB color can be assigned to
13514 // # each face of an object.
13515 // #
13516 // # First, define the geometry of the cube.
13517 // #
13518 // v 0.0 0.0 0.0
13519 // v 1.0 0.0 0.0
13520 // v 0.0 1.0 0.0
13521 // v 1.0 1.0 0.0
13522 // v 0.0 0.0 1.0
13523 // v 1.0 0.0 1.0
13524 // v 0.0 1.0 1.0
13525 // v 1.0 1.0 1.0
13526 // f 1 4 2
13527 // f 1 3 4
13528 // f 5 6 8
13529 // f 5 8 7
13530 // f 1 2 6
13531 // f 1 6 5
13532 // f 2 4 8
13533 // f 2 8 6
13534 // f 4 3 7
13535 // f 4 7 8
13536 // f 3 1 5
13537 // f 3 5 7
13538 // #
13539 // # Colors will be bound 1 per face.
13540 // #
13541 // bind c face
13542 // c 1.0 0.0 0.0
13543 // c 1.0 0.0 0.0
13544 // c 0.0 1.0 0.0
13545 // c 0.0 1.0 0.0
13546 // c 0.0 0.0 1.0
13547 // c 0.0 0.0 1.0
13548 // c 1.0 1.0 0.0
13549 // c 1.0 1.0 0.0
13550 // c 0.0 1.0 1.0
13551 // c 0.0 1.0 1.0
13552 // c 1.0 0.0 1.0
13553 // c 1.0 0.0 1.0
13554 // #
13555 // # Normal vectors will be bound 1 per face.
13556 // #
13557 // bind n face
13558 // n 0.0 0.0 -1.0
13559 // n 0.0 0.0 -1.0
13560 // n 0.0 0.0 1.0
13561 // n 0.0 0.0 1.0
13562 // n 0.0 -1.0 0.0
13563 // n 0.0 -1.0 0.0
13564 // n 1.0 0.0 0.0
13565 // n 1.0 0.0 0.0
13566 // n 0.0 1.0 0.0
13567 // n 0.0 1.0 0.0
13568 // n -1.0 0.0 0.0
13569 // n -1.0 0.0 0.0
13570 // #
13571 // # Texture coordinate pairs will be bound 1 per face.
13572 // #
13573 // bind r face
13574 // r 0.0 0.0
13575 // r 0.0 0.1
13576 // r 0.0 0.2
13577 // r 0.0 0.3
13578 // r 0.1 0.0
13579 // r 0.1 0.1
13580 // r 0.1 0.2
13581 // r 0.1 0.3
13582 // r 0.2 0.0
13583 // r 0.2 0.1
13584 // r 0.2 0.2
13585 // r 0.2 0.3
13586 //
13587 // Licensing:
13588 //
13589 // This code is distributed under the GNU LGPL license.
13590 //
13591 // Modified:
13592 //
13593 // 05 July 1999
13594 //
13595 // Author:
13596 //
13597 // John Burkardt
13598 //
13599 {
13600  int i;
13601  int icor3;
13602  int iface;
13603  int imat;
13604  int ivert;
13605  int text_num;
13606 //
13607 // Initialize.
13608 //
13609  text_num = 0;
13610 
13611  fprintf ( fileout, "#$SMF 2.0\n" );
13612  fprintf ( fileout, "#$vertices %d\n", cor3_num );
13613  fprintf ( fileout, "#$faces %d\n", face_num );
13614  fprintf ( fileout, "#\n" );
13615  fprintf ( fileout, "# %s created by IVCON.\n", fileout_name );
13616  fprintf ( fileout, "# Original data in %s.\n", filein_name );
13617  fprintf ( fileout, "#\n" );
13618 
13619  text_num = text_num + 7;
13620 //
13621 // V: vertex coordinates.
13622 //
13623  for ( i = 0; i < cor3_num; i++ )
13624  {
13625  fprintf ( fileout, "v %f %f %f\n",
13626  cor3[0][i], cor3[1][i], cor3[2][i] );
13627  text_num = text_num + 1;
13628  }
13629 //
13630 // F: faces.
13631 //
13632  if ( 0 < face_num )
13633  {
13634  fprintf ( fileout, "\n" );
13635  text_num = text_num + 1;
13636  }
13637 
13638  for ( iface = 0; iface < face_num; iface++ )
13639  {
13640  fprintf ( fileout, "f" );
13641  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
13642  {
13643  fprintf ( fileout, " %d", face[ivert][iface]+1 );
13644  }
13645  fprintf ( fileout, "\n" );
13646  text_num = text_num + 1;
13647  }
13648 //
13649 // Material binding.
13650 //
13651  fprintf ( fileout, "bind c vertex\n" );
13652  text_num = text_num + 1;
13653 //
13654 // Material RGB values at each node.
13655 //
13656  for ( icor3 = 0; icor3 < cor3_num; icor3++ )
13657  {
13658  imat = cor3_material[icor3];
13659 
13660  fprintf ( fileout, "c %f %f %f\n", material_rgba[0][imat],
13661  material_rgba[1][imat], material_rgba[2][imat] );
13662 
13663  text_num = text_num + 1;
13664  }
13665 //
13666 // Normal binding.
13667 //
13668  fprintf ( fileout, "bind n vertex\n" );
13669  text_num = text_num + 1;
13670 //
13671 // Normal vector at each node.
13672 //
13673  for ( icor3 = 0; icor3 < cor3_num; icor3++ )
13674  {
13675  fprintf ( fileout, "n %f %f %f\n", cor3_normal[0][icor3],
13676  cor3_normal[1][icor3], cor3_normal[2][icor3] );
13677 
13678  text_num = text_num + 1;
13679  }
13680 
13681  if ( 0 < texture_num )
13682  {
13683 //
13684 // Texture filename.
13685 //
13686  fprintf ( fileout, "tex %s\n", texture_name[0] );
13687  text_num = text_num + 1;
13688 //
13689 // Texture binding.
13690 //
13691  fprintf ( fileout, "bind r vertex\n" );
13692  text_num = text_num + 1;
13693 //
13694 // Texture coordinates at each node.
13695 //
13696  for ( icor3 = 0; icor3 < cor3_num; icor3++ )
13697  {
13698  fprintf ( fileout, "r %f %f\n", cor3_tex_uv[0][icor3],
13699  cor3_tex_uv[1][icor3] );
13700  text_num = text_num + 1;
13701  }
13702 
13703  }
13704 //
13705 // Report.
13706 //
13707  cout << "\n";
13708  cout << "SMF_WRITE - Wrote " << text_num << " text lines.\n";
13709 
13710  return 0;
13711 }
13712 //****************************************************************************80
13713 
13714 void sort_heap_external ( int n, int *indx, int *i, int *j, int isgn )
13715 
13716 //****************************************************************************80
13717 //
13718 // Purpose:
13719 //
13720 // SORT_HEAP_EXTERNAL externally sorts a list of items into linear order.
13721 //
13722 // Discussion:
13723 //
13724 // The actual list is not passed to the routine. Hence it may
13725 // consist of ints, reals, numbers, names, etc. The user,
13726 // after each return from the routine, will be asked to compare or
13727 // interchange two items.
13728 //
13729 // Licensing:
13730 //
13731 // This code is distributed under the GNU LGPL license.
13732 //
13733 // Modified:
13734 //
13735 // 20 May 1999
13736 //
13737 // Author:
13738 //
13739 // Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf.
13740 // C++ version by John Burkardt.
13741 //
13742 // Parameters:
13743 //
13744 // Input, int N, the length of the input list.
13745 //
13746 // Input/output, int *INDX.
13747 //
13748 // The user must set INDX to 0 before the first call.
13749 //
13750 // On return,
13751 //
13752 // if INDX is greater than 0, the user must interchange
13753 // items I and J and recall the routine.
13754 //
13755 // If INDX is less than 0, the user is to compare items I
13756 // and J and return in ISGN a negative value if I is to
13757 // precede J, and a positive value otherwise.
13758 //
13759 // If INDX is 0, the sorting is done.
13760 //
13761 // Output, int *I, *J. On return with INDX positive,
13762 // elements I and J of the user's list should be
13763 // interchanged. On return with INDX negative, elements I
13764 // and J are to be compared by the user.
13765 //
13766 // Input, int ISGN. On return with INDX negative, the
13767 // user should compare elements I and J of the list. If
13768 // item I is to precede item J, set ISGN negative,
13769 // otherwise set ISGN positive.
13770 //
13771 {
13772  static int k = 0;
13773  static int k1 = 0;
13774  static int n1 = 0;
13775 
13776  if ( *indx == 0 )
13777  {
13778 
13779  n1 = n;
13780  k = n / 2;
13781  k1 = k;
13782 
13783  }
13784  else if ( *indx < 0 )
13785  {
13786 
13787  if ( *indx == -2 )
13788  {
13789 
13790  if ( isgn < 0 )
13791  {
13792  *i = *i + 1;
13793  }
13794 
13795  *j = k1 - 1;
13796  k1 = *i + 1;
13797  *indx = - 1;
13798  return;
13799 
13800  }
13801 
13802  if ( 0 < isgn )
13803  {
13804  *indx = 2;
13805  return;
13806  }
13807 
13808  if ( k <= 1 )
13809  {
13810 
13811  if ( n1 == 1 )
13812  {
13813  *indx = 0;
13814  }
13815  else
13816  {
13817  *i = n1 - 1;
13818  n1 = n1 - 1;
13819  *j = 0;
13820  *indx = 1;
13821  }
13822 
13823  return;
13824 
13825  }
13826 
13827  k = k - 1;
13828  k1 = k;
13829 
13830  }
13831  else if ( *indx == 1 )
13832  {
13833  k1 = k;
13834  }
13835 
13836  for ( ;; )
13837  {
13838 
13839  *i = 2 * k1 - 1;
13840 
13841  if ( *i == n1 - 1 )
13842  {
13843  *j = k1 - 1;
13844  k1 = *i + 1;
13845  *indx = - 1;
13846  return;
13847  }
13848  else if ( *i <= n1 - 1 )
13849  {
13850  *j = *i + 1;
13851  *indx = - 2;
13852  return;
13853  }
13854 
13855  if ( k <= 1 )
13856  {
13857  break;
13858  }
13859 
13860  k = k - 1;
13861  k1 = k;
13862  }
13863 
13864  if ( n1 == 1 )
13865  {
13866  *indx = 0;
13867  }
13868  else
13869  {
13870  *i = n1 - 1;
13871  n1 = n1 - 1;
13872  *j = 0;
13873  *indx = 1;
13874  }
13875 
13876  return;
13877 }
13878 //****************************************************************************80
13879 
13880 int stla_read ( FILE *filein )
13881 
13882 //****************************************************************************80
13883 //
13884 // Purpose:
13885 //
13886 // STLA_READ reads an ASCII STL (stereolithography) file.
13887 //
13888 // Example:
13889 //
13890 // solid MYSOLID
13891 // facet normal 0.4 0.4 0.2
13892 // outerloop
13893 // vertex 1.0 2.1 3.2
13894 // vertex 2.1 3.7 4.5
13895 // vertex 3.1 4.5 6.7
13896 // endloop
13897 // endfacet
13898 // ...
13899 // facet normal 0.2 0.2 0.4
13900 // outerloop
13901 // vertex 2.0 2.3 3.4
13902 // vertex 3.1 3.2 6.5
13903 // vertex 4.1 5.5 9.0
13904 // endloop
13905 // endfacet
13906 // endsolid MYSOLID
13907 //
13908 // Licensing:
13909 //
13910 // This code is distributed under the GNU LGPL license.
13911 //
13912 // Modified:
13913 //
13914 // 20 October 1998
13915 //
13916 // Author:
13917 //
13918 // John Burkardt
13919 //
13920 // Reference:
13921 //
13922 // 3D Systems, Inc,
13923 // Stereolithography Interface Specification,
13924 // October 1989.
13925 //
13926 {
13927  int count;
13928  int i;
13929  int icor3;
13930  int ivert;
13931  char *next;
13932  float r1;
13933  float r2;
13934  float r3;
13935  float r4;
13936  float temp[3];
13937  char token[LINE_MAX_LEN];
13938  int width;
13939 //
13940 // Read the next line of the file into INPUT.
13941 //
13942  while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL )
13943  {
13944  text_num = text_num + 1;
13945 //
13946 // Advance to the first nonspace character in INPUT.
13947 //
13948  for ( next = input; *next != '\0' && ch_is_space ( *next ); next++ )
13949  {
13950  }
13951 //
13952 // Skip blank lines and comments.
13953 //
13954  if ( *next == '\0' || *next == '#' || *next == '!' || *next == '$' )
13955  {
13956  continue;
13957  }
13958 //
13959 // Extract the first word in this line.
13960 //
13961  sscanf ( next, "%s%n", token, &width );
13962 //
13963 // Set NEXT to point to just after this token.
13964 //
13965  next = next + width;
13966 //
13967 // FACET
13968 //
13969  if ( s_eqi ( token, "facet" ) )
13970  {
13971 //
13972 // Get the XYZ coordinates of the normal vector to the face.
13973 //
13974  sscanf ( next, "%*s %e %e %e", &r1, &r2, &r3 );
13975 
13976  if ( face_num < FACE_MAX )
13977  {
13978  face_normal[0][face_num] = r1;
13979  face_normal[1][face_num] = r2;
13980  face_normal[2][face_num] = r3;
13981  }
13982 
13983  fgets ( input, LINE_MAX_LEN, filein );
13984  text_num = text_num + 1;
13985 
13986  ivert = 0;
13987 
13988  for ( ;; )
13989  {
13990  fgets ( input, LINE_MAX_LEN, filein );
13991  text_num = text_num + 1;
13992 
13993  count = sscanf ( input, "%*s %e %e %e", &r1, &r2, &r3 );
13994 
13995  if ( count != 3 )
13996  {
13997  break;
13998  }
13999 
14000  temp[0] = r1;
14001  temp[1] = r2;
14002  temp[2] = r3;
14003 
14004  if ( cor3_num < 1000 )
14005  {
14006  icor3 = rcol_find ( cor3, 3, cor3_num, temp );
14007  }
14008  else
14009  {
14010  icor3 = -1;
14011  }
14012 
14013  if ( icor3 == -1 )
14014  {
14015  icor3 = cor3_num;
14016 
14017  if ( cor3_num < COR3_MAX )
14018  {
14019  for ( i = 0; i < 3; i++ )
14020  {
14021  cor3[i][cor3_num] = temp[i];
14022  }
14023  }
14024  cor3_num = cor3_num + 1;
14025  }
14026  else
14027  {
14028  dup_num = dup_num + 1;
14029  }
14030 
14031  if ( ivert < ORDER_MAX && face_num < FACE_MAX )
14032  {
14033  face[ivert][face_num] = icor3;
14034  vertex_material[ivert][face_num] = 0;
14035  for ( i = 0; i < 3; i++ )
14036  {
14038  }
14039  }
14040 
14041  ivert = ivert + 1;
14042  }
14043 
14044  fgets ( input, LINE_MAX_LEN, filein );
14045  text_num = text_num + 1;
14046 
14047  if ( face_num < FACE_MAX )
14048  {
14049  face_order[face_num] = ivert;
14050  }
14051 
14052  face_num = face_num + 1;
14053 
14054  }
14055 //
14056 // COLOR
14057 //
14058 
14059  else if ( s_eqi ( token, "color" ) )
14060  {
14061  sscanf ( next, "%*s %f %f %f %f", &r1, &r2, &r3, &r4 );
14062  }
14063 //
14064 // SOLID
14065 //
14066  else if ( s_eqi ( token, "solid" ) )
14067  {
14068  object_num = object_num + 1;
14069  }
14070 //
14071 // ENDSOLID
14072 //
14073  else if ( s_eqi ( token, "endsolid" ) )
14074  {
14075  }
14076 //
14077 // Unexpected or unrecognized.
14078 //
14079  else
14080  {
14081  cout << "\n";
14082  cout << "STLA_READ - Fatal error!\n";
14083  cout << " Unrecognized first word on line.\n";
14084  return 1;
14085  }
14086 
14087  }
14088  return 0;
14089 }
14090 //****************************************************************************80
14091 
14092 int stla_write ( FILE *fileout )
14093 
14094 //****************************************************************************80
14095 //
14096 // Purpose:
14097 //
14098 // STLA_WRITE writes an ASCII STL (stereolithography) file.
14099 //
14100 // Discussion:
14101 //
14102 // The polygons in an STL file should only be triangular. This routine
14103 // will try to automatically decompose higher-order polygonal faces into
14104 // suitable triangles, without actually modifying the internal graphics
14105 // data.
14106 //
14107 // Example:
14108 //
14109 // solid MYSOLID
14110 // facet normal 0.4 0.4 0.2
14111 // outerloop
14112 // vertex 1.0 2.1 3.2
14113 // vertex 2.1 3.7 4.5
14114 // vertex 3.1 4.5 6.7
14115 // endloop
14116 // endfacet
14117 // ...
14118 // facet normal 0.2 0.2 0.4
14119 // outerloop
14120 // vertex 2.0 2.3 3.4
14121 // vertex 3.1 3.2 6.5
14122 // vertex 4.1 5.5 9.0
14123 // endloop
14124 // endfacet
14125 // endsolid
14126 //
14127 // Licensing:
14128 //
14129 // This code is distributed under the GNU LGPL license.
14130 //
14131 // Modified:
14132 //
14133 // 01 September 1998
14134 //
14135 // Author:
14136 //
14137 // John Burkardt
14138 //
14139 // Reference:
14140 //
14141 // 3D Systems, Inc,
14142 // Stereolithography Interface Specification,
14143 // October 1989.
14144 //
14145 {
14146  int icor3;
14147  int iface;
14148  int jvert;
14149  int face_num2;
14150  int text_num;
14151 //
14152 // Initialize.
14153 //
14154  text_num = 0;
14155  face_num2 = 0;
14156 
14157  fprintf ( fileout, "solid MYSOLID created by IVCON, original data in %s\n",
14158  filein_name );
14159 
14160  text_num = text_num + 1;
14161 
14162  for ( iface = 0; iface < face_num; iface++ )
14163  {
14164  for ( jvert = 2; jvert < face_order[iface]; jvert++ )
14165  {
14166  face_num2 = face_num2 + 1;
14167 
14168  fprintf ( fileout, " facet normal %f %f %f\n",
14169  face_normal[0][iface], face_normal[1][iface], face_normal[2][iface] );
14170 
14171  fprintf ( fileout, " outer loop\n" );
14172 
14173  icor3 = face[0][iface];
14174  fprintf ( fileout, " vertex %f %f %f\n",
14175  cor3[0][icor3], cor3[1][icor3], cor3[2][icor3] );
14176 
14177  icor3 = face[jvert-1][iface];
14178  fprintf ( fileout, " vertex %f %f %f\n",
14179  cor3[0][icor3], cor3[1][icor3], cor3[2][icor3] );
14180 
14181  icor3 = face[jvert][iface];
14182  fprintf ( fileout, " vertex %f %f %f\n",
14183  cor3[0][icor3], cor3[1][icor3], cor3[2][icor3] );
14184 
14185  fprintf ( fileout, " endloop\n" );
14186  fprintf ( fileout, " endfacet\n" );
14187  text_num = text_num + 7;
14188  }
14189  }
14190 
14191  fprintf ( fileout, "endsolid MYSOLID\n" );
14192  text_num = text_num + 1;
14193 //
14194 // Report.
14195 //
14196  cout << "\n";
14197  cout << "STLA_WRITE - Wrote " << text_num << " text lines.\n";
14198 
14199  if ( face_num != face_num2 )
14200  {
14201  cout << " Number of faces in original data was " << face_num << ".\n";
14202  cout << " Number of triangular faces in decomposed data is "
14203  << face_num2 << ".\n";
14204  }
14205 
14206  return 0;
14207 }
14208 //****************************************************************************80
14209 
14210 int stlb_read ( FILE *filein )
14211 
14212 //****************************************************************************80
14213 //
14214 // Purpose:
14215 //
14216 // STLB_READ reads a binary STL (stereolithography) file.
14217 //
14218 // Example:
14219 //
14220 // 80 byte string = header containing nothing in particular
14221 //
14222 // 4 byte int = number of faces
14223 //
14224 // For each face:
14225 //
14226 // 3 4-byte floats = components of normal vector to face;
14227 // 3 4-byte floats = coordinates of first node;
14228 // 3 4-byte floats = coordinates of second node;
14229 // 3 4-byte floats = coordinates of third and final node;
14230 // 2-byte int = attribute, whose value is 0.
14231 //
14232 // Licensing:
14233 //
14234 // This code is distributed under the GNU LGPL license.
14235 //
14236 // Modified:
14237 //
14238 // 24 May 1999
14239 //
14240 // Author:
14241 //
14242 // John Burkardt
14243 //
14244 // Reference:
14245 //
14246 // 3D Systems, Inc,
14247 // Stereolithography Interface Specification,
14248 // October 1989.
14249 //
14250 {
14251  short int attribute = 0;
14252  char c;
14253  float cvec[3];
14254  int icor3;
14255  int i;
14256  int iface;
14257  int ivert;
14258 //
14259 // 80 byte Header.
14260 //
14261  for ( i = 0; i < 80; i++ )
14262  {
14263  c = ch_read ( filein );
14264  if ( debug )
14265  {
14266  cout << c << "\n";
14267  }
14268  bytes_num = bytes_num + 1;
14269  }
14270 //
14271 // Number of faces.
14272 //
14273  face_num = long_int_read ( filein );
14274  bytes_num = bytes_num + 4;
14275 //
14276 // For each (triangular) face,
14277 // components of normal vector,
14278 // coordinates of three vertices,
14279 // 2 byte "attribute".
14280 //
14281  for ( iface = 0; iface < face_num; iface++ )
14282  {
14283  face_order[iface] = 3;
14284  face_material[iface] = 0;
14285 
14286  for ( i = 0; i < 3; i++ )
14287  {
14288  face_normal[i][iface] = float_read ( filein );
14289  bytes_num = bytes_num + 4;
14290  }
14291 
14292  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
14293  {
14294  for ( i = 0; i < 3; i++ )
14295  {
14296  cvec[i] = float_read ( filein );
14297  bytes_num = bytes_num + 4;
14298  }
14299 
14300  if ( cor3_num < 1000 )
14301  {
14302  icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
14303  }
14304  else
14305  {
14306  icor3 = -1;
14307  }
14308 
14309  if ( icor3 == -1 )
14310  {
14311  icor3 = cor3_num;
14312  if ( cor3_num < COR3_MAX )
14313  {
14314  cor3[0][cor3_num] = cvec[0];
14315  cor3[1][cor3_num] = cvec[1];
14316  cor3[2][cor3_num] = cvec[2];
14317  }
14318  cor3_num = cor3_num + 1;
14319  }
14320  else
14321  {
14322  dup_num = dup_num + 1;
14323  }
14324 
14325  face[ivert][iface] = icor3;
14326 
14327  }
14328  attribute = short_int_read ( filein );
14329  if ( debug )
14330  {
14331  cout << "ATTRIBUTE = " << attribute << "\n";
14332  }
14333  bytes_num = bytes_num + 2;
14334  }
14335 
14336  return 0;
14337 }
14338 //****************************************************************************80
14339 
14340 int stlb_write ( FILE *fileout )
14341 
14342 //****************************************************************************80
14343 //
14344 // Purpose:
14345 //
14346 // STLB_WRITE writes a binary STL (stereolithography) file.
14347 //
14348 // Discussion:
14349 //
14350 // The polygons in an STL file should only be triangular. This routine
14351 // will try to automatically decompose higher-order polygonal faces into
14352 // suitable triangles, without actually modifying the internal graphics
14353 // data.
14354 //
14355 // Example:
14356 //
14357 // 80 byte string = header containing nothing in particular
14358 //
14359 // 4 byte int = number of faces
14360 //
14361 // For each face:
14362 //
14363 // 3 4-byte floats = components of normal vector to face;
14364 // 3 4-byte floats = coordinates of first node;
14365 // 3 4-byte floats = coordinates of second node;
14366 // 3 4-byte floats = coordinates of third and final node;
14367 // 2-byte int = attribute, whose value is 0.
14368 //
14369 // Licensing:
14370 //
14371 // This code is distributed under the GNU LGPL license.
14372 //
14373 // Modified:
14374 //
14375 // 24 May 1999
14376 //
14377 // Author:
14378 //
14379 // John Burkardt
14380 //
14381 // Reference:
14382 //
14383 // 3D Systems, Inc,
14384 // Stereolithography Interface Specification,
14385 // October 1989.
14386 //
14387 {
14388  short int attribute = 0;
14389  char c;
14390  int i;
14391  int icor3;
14392  int iface;
14393  int jvert;
14394  int face_num2;
14395 //
14396 // Write the 80 byte header.
14397 //
14398  for ( i = 0; i < 80; i++ )
14399  {
14400  c = ' ';
14401  bytes_num = bytes_num + ch_write ( fileout, c );
14402  }
14403 //
14404 // Number of faces.
14405 //
14406  face_num2 = 0;
14407  for ( iface = 0; iface < face_num; iface++ )
14408  {
14409  face_num2 = face_num2 + face_order[iface] - 2;
14410  }
14411 
14412  bytes_num = bytes_num + long_int_write ( fileout, face_num2 );
14413 //
14414 // For each (triangular) face,
14415 // components of normal vector,
14416 // coordinates of three vertices,
14417 // 2 byte "attribute".
14418 //
14419  for ( iface = 0; iface < face_num; iface++ )
14420  {
14421  for ( jvert = 2; jvert < face_order[iface]; jvert++ )
14422  {
14423  for ( i = 0; i < 3; i++ )
14424  {
14425  bytes_num = bytes_num + float_write ( fileout, face_normal[i][iface] );
14426  }
14427 
14428  icor3 = face[0][iface];
14429  for ( i = 0; i < 3; i++ )
14430  {
14431  bytes_num = bytes_num + float_write ( fileout, cor3[i][icor3] );
14432  }
14433 
14434  icor3 = face[jvert-1][iface];
14435  for ( i = 0; i < 3; i++ )
14436  {
14437  bytes_num = bytes_num + float_write ( fileout, cor3[i][icor3] );
14438  }
14439 
14440  icor3 = face[jvert][iface];
14441  for ( i = 0; i < 3; i++ )
14442  {
14443  bytes_num = bytes_num + float_write ( fileout, cor3[i][icor3] );
14444  }
14445 
14446  bytes_num = bytes_num + short_int_write ( fileout, attribute );
14447 
14448  }
14449 
14450  }
14451 //
14452 // Report.
14453 //
14454  cout << "\n";
14455  cout << "STLB_WRITE - Wrote " << bytes_num << " bytes.\n";
14456 
14457  if ( face_num != face_num2 )
14458  {
14459  cout << " Number of faces in original data was " << face_num << ".\n";
14460  cout << " Number of triangular faces in decomposed data is "
14461  << face_num2 << ".\n";
14462  }
14463 
14464  return 0;
14465 }
14466 //****************************************************************************80
14467 
14469 
14470 //****************************************************************************80
14471 //
14472 // Purpose:
14473 //
14474 // TDS_PRE_PROCESS divides the monolithic object into acceptably small pieces.
14475 //
14476 // Discussion:
14477 //
14478 // The 3DS binary format allows an unsigned short int for the number of
14479 // points, and number of faces in an object. This limits such quantities
14480 // to 65535. We have at least one interesting object with more faces
14481 // than that. So we need to tag faces and nodes somehow.
14482 //
14483 // Licensing:
14484 //
14485 // This code is distributed under the GNU LGPL license.
14486 //
14487 // Modified:
14488 //
14489 // 14 October 1998
14490 //
14491 // Author:
14492 //
14493 // John Burkardt
14494 //
14495 {
14496 //
14497 // COMMENTED OUT
14498 //
14499 // static unsigned short int BIG = 60000;
14500 //
14501 
14502  return;
14503 }
14504 //****************************************************************************80
14505 
14506 int tds_read ( FILE *filein )
14507 
14508 //****************************************************************************80
14509 //
14510 // Purpose:
14511 //
14512 // TDS_READ reads a 3D Studio MAX binary 3DS file.
14513 //
14514 // Licensing:
14515 //
14516 // This code is distributed under the GNU LGPL license.
14517 //
14518 // Modified:
14519 //
14520 // 20 October 1998
14521 //
14522 // Author:
14523 //
14524 // John Burkardt
14525 //
14526 {
14527  unsigned long int chunk_begin;
14528  unsigned long int chunk_end;
14529  unsigned long int chunk_length;
14530  unsigned long int chunk_length2;
14531  unsigned long int position;
14532  unsigned short int temp_int;
14533  int version;
14534  int views_read;
14535 //
14536 // Initialize.
14537 //
14538  views_read = 0;
14539 
14540  temp_int = tds_read_u_short_int ( filein );
14541 
14542  if ( temp_int == 0x4d4d )
14543  {
14544  if ( debug )
14545  {
14546  cout << "TDS_READ: DEBUG: Read magic number "
14547  << hex << temp_int << "\n";
14548  }
14549 //
14550 // Move to 28 bytes from the beginning of the file.
14551 //
14552  position = 28;
14553  fseek ( filein, ( long ) position, SEEK_SET );
14554  version = fgetc ( filein );
14555 
14556  if ( version < 3 )
14557  {
14558  cout << "\n";
14559  cout << "TDS_READ - Fatal error!\n";
14560  cout << " This routine can only read 3DS version 3 or later.\n";
14561  cout << " The input file is version " << version << ".\n";
14562  return 1;
14563  }
14564 
14565  if ( debug )
14566  {
14567  cout << "TDS_READ: DEBUG: Version number is " << version << ".\n";
14568  }
14569 //
14570 // Move to 2 bytes from the beginning of the file.
14571 // Set CURRENT_POINTER to the first byte of the chunk.
14572 // Set CHUNK_LENGTH to the number of bytes in the chunk.
14573 //
14574  chunk_begin = 0;
14575  position = 2;
14576  fseek ( filein, ( long ) position, SEEK_SET );
14577 
14578  chunk_length = tds_read_u_long_int ( filein );
14579  position = 6;
14580 
14581  chunk_end = chunk_begin + chunk_length;
14582 
14583  if ( debug )
14584  {
14585  cout << "\n";
14586  cout << "TDS_READ:\n";
14587  cout << " Chunk begin = " << chunk_begin << "\n";
14588  cout << " Chunk length = " << chunk_length << "\n";
14589  cout << " Chunk end = " << chunk_end << "\n";
14590  }
14591 
14592  while ( position + 2 < chunk_end )
14593  {
14594  temp_int = tds_read_u_short_int ( filein );
14595  position = position + 2;
14596 
14597  if ( debug )
14598  {
14599  cout << "TDS_READ: Short int = " << hex << temp_int << "\n";
14600  cout << " position = " << position << "\n";
14601  }
14602 
14603  if ( temp_int == 0x0002 )
14604  {
14605  if ( debug )
14606  {
14607  cout << "TDS_READ: Read_Initial_Section:\n";
14608  }
14609  chunk_length2 = tds_read_u_long_int ( filein );
14610  position = position + 4;
14611  position = position - 6 + chunk_length2;
14612  fseek ( filein, ( long ) position, SEEK_SET );
14613  }
14614  else if ( temp_int == 0x3d3d )
14615  {
14616  if ( debug )
14617  {
14618  cout << "TDS_READ: Read_Edit_Section:\n";
14619  }
14620  position = position - 2;
14621  position = position + tds_read_edit_section ( filein, &views_read );
14622  }
14623  else if ( temp_int == 0xb000 )
14624  {
14625  if ( debug )
14626  {
14627  cout << "TDS_READ: Read_Keyframe_Section:\n";
14628  }
14629 
14630  position = position - 2;
14631  position = position + tds_read_keyframe_section ( filein, &views_read );
14632  }
14633  else
14634  {
14635  cout << "\n";
14636  cout << "TDS_READ - Fatal error!\n";
14637  cout << " Unexpected input, position = " << position << "\n";
14638  cout << " TEMP_INT = " << hex << temp_int << "\n";
14639  return 1;
14640  }
14641  }
14642  position = chunk_begin + chunk_length;
14643  fseek ( filein, ( long ) position, SEEK_SET );
14644  }
14645  else
14646  {
14647  cout << "\n";
14648  cout << "TDS_READ - Fatal error!\n";
14649  cout << " Could not find the main section tag.\n";
14650  return 1;
14651  }
14652 
14653  return 0;
14654 }
14655 //****************************************************************************80
14656 
14657 unsigned long tds_read_ambient_section ( FILE *filein )
14658 
14659 //****************************************************************************80
14660 //
14661 // Purpose:
14662 //
14663 // TDS_READ_AMBIENT_SECTION ???
14664 //
14665 // Licensing:
14666 //
14667 // This code is distributed under the GNU LGPL license.
14668 //
14669 {
14670  unsigned long int current_pointer;
14671  bool end_found = false;
14672  int i;
14673  long int pointer;
14674  float rgb_val[3];
14675  unsigned short int temp_int;
14676  unsigned long int temp_pointer;
14677  unsigned long int teller;
14678  unsigned char true_c_val[3];
14679 
14680  current_pointer = ftell ( filein ) - 2;
14681  temp_pointer = tds_read_u_long_int ( filein );
14682  teller = 6;
14683 
14684  while ( !end_found )
14685  {
14686  temp_int = tds_read_u_short_int ( filein );
14687  teller = teller + 2;
14688 
14689  switch ( temp_int )
14690  {
14691  case 0x0010:
14692  if ( debug )
14693  {
14694  cout << " COLOR_F color definition section tag of "
14695  << hex << temp_int << "\n";
14696  }
14697  for ( i = 0; i < 3; i++ )
14698  {
14699  rgb_val[i] = float_read ( filein );
14700  }
14701  if ( debug )
14702  {
14703  cout << "RGB_VAL = "
14704  << setw(10) << rgb_val[0] << " "
14705  << setw(10) << rgb_val[1] << " "
14706  << setw(10) << rgb_val[2] << "\n";
14707  }
14708  teller = teller + 3 * sizeof ( float );
14709  break;
14710  case 0x0011:
14711  if ( debug )
14712  {
14713  cout << " COLOR_24 24 bit color definition section tag of "
14714  << hex << temp_int << "\n";;
14715  }
14716 
14717  for ( i = 0; i < 3; i++ )
14718  {
14719  true_c_val[i] = fgetc ( filein );
14720  }
14721  if ( debug )
14722  {
14723  cout << "TRUE_C_VAL = "
14724  << setw(6) << true_c_val[0] << " "
14725  << setw(6) << true_c_val[1] << " "
14726  << setw(6) << true_c_val[2] << "\n";
14727  }
14728  teller = teller + 3;
14729  break;
14730  default:
14731  break;
14732  }
14733 
14734  if ( temp_pointer <= teller )
14735  {
14736  end_found = true;
14737  }
14738 
14739  }
14740 
14741  pointer = ( long ) ( current_pointer + temp_pointer );
14742  fseek ( filein, pointer, SEEK_SET );
14743 
14744  return ( temp_pointer );
14745 }
14746 //****************************************************************************80
14747 
14748 unsigned long tds_read_background_section ( FILE *filein )
14749 
14750 //****************************************************************************80
14751 //
14752 // Purpose:
14753 //
14754 // TDS_READ_BACKGROUND_SECTION ???
14755 //
14756 // Licensing:
14757 //
14758 // This code is distributed under the GNU LGPL license.
14759 //
14760 {
14761  unsigned long int current_pointer;
14762  bool end_found = false;
14763  int i;
14764  long int pointer;
14765  float rgb_val[3];
14766  unsigned short int temp_int;
14767  unsigned long int temp_pointer;
14768  unsigned long int teller;
14769  unsigned char true_c_val[3];
14770 
14771  current_pointer = ftell ( filein ) - 2;
14772  temp_pointer = tds_read_u_long_int ( filein );
14773  teller = 6;
14774 
14775  while ( !end_found )
14776  {
14777  temp_int = tds_read_u_short_int ( filein );
14778  teller = teller + 2;
14779 
14780  switch ( temp_int )
14781  {
14782  case 0x0010:
14783  if ( debug )
14784  {
14785  cout << " COLOR_F RGB color definition section tag of "
14786  << hex << temp_int << "\n";
14787  }
14788  for ( i = 0; i < 3; i++ )
14789  {
14790  rgb_val[i] = float_read ( filein );
14791  }
14792  if ( debug )
14793  {
14794  cout << "RGB_VAL = "
14795  << setw(10) << rgb_val[0] << " "
14796  << setw(10) << rgb_val[1] << " "
14797  << setw(10) << rgb_val[2] << "\n";
14798  }
14799  teller = teller + 3 * sizeof ( float );
14800  break;
14801  case 0x0011:
14802  if ( debug )
14803  {
14804  cout << " COLOR_24 24 bit color definition section tag of "
14805  << hex << temp_int << "\n";
14806  }
14807 
14808  for ( i = 0; i < 3; i++ )
14809  {
14810  true_c_val[i] = fgetc ( filein );
14811  }
14812  if ( debug )
14813  {
14814  cout << "TRUE_C_VAL = "
14815  << setw(6) << true_c_val[0] << " "
14816  << setw(6) << true_c_val[1] << " "
14817  << setw(6) << true_c_val[2] << "\n";
14818  }
14819  teller = teller + 3;
14820  break;
14821  default:
14822  break;
14823  }
14824 
14825  if ( temp_pointer <= teller )
14826  {
14827  end_found = true;
14828  }
14829 
14830  }
14831 
14832  pointer = ( long ) ( current_pointer + temp_pointer );
14833  fseek ( filein, pointer, SEEK_SET );
14834 
14835  return ( temp_pointer );
14836 }
14837 //****************************************************************************80
14838 
14839 unsigned long tds_read_boolean ( unsigned char *boolean, FILE *filein )
14840 
14841 //****************************************************************************80
14842 //
14843 // Purpose:
14844 //
14845 // TDS_READ_BOOLEAN ???
14846 //
14847 // Licensing:
14848 //
14849 // This code is distributed under the GNU LGPL license.
14850 //
14851 {
14852  unsigned long current_pointer;
14853  long int pointer;
14854  unsigned long temp_pointer;
14855 
14856  current_pointer = ftell ( filein ) - 2;
14857  temp_pointer = tds_read_u_long_int ( filein );
14858 
14859  *boolean = fgetc ( filein );
14860 
14861  pointer = ( long ) ( current_pointer + temp_pointer );
14862  fseek ( filein, pointer, SEEK_SET );
14863 
14864  return ( temp_pointer );
14865 }
14866 //****************************************************************************80
14867 
14868 unsigned long tds_read_camera_section ( FILE *filein )
14869 
14870 //****************************************************************************80
14871 //
14872 // Purpose:
14873 //
14874 // TDS_READ_CAMERA_SECTION ???
14875 //
14876 // Licensing:
14877 //
14878 // This code is distributed under the GNU LGPL license.
14879 //
14880 {
14881  float camera_eye[3];
14882  float camera_focus[3];
14883  unsigned long int current_pointer;
14884  float lens;
14885  long int pointer;
14886  float rotation;
14887  unsigned long int temp_pointer;
14888  unsigned short int u_short_int_val;
14889 
14890  current_pointer = ftell ( filein ) - 2;
14891  temp_pointer = tds_read_u_long_int ( filein );
14892 
14893  camera_eye[0] = float_read ( filein );
14894  camera_eye[1] = float_read ( filein );
14895  camera_eye[2] = float_read ( filein );
14896 
14897  camera_focus[0] = float_read ( filein );
14898  camera_focus[1] = float_read ( filein );
14899  camera_focus[2] = float_read ( filein );
14900 
14901  rotation = float_read ( filein );
14902  lens = float_read ( filein );
14903 
14904  if ( debug )
14905  {
14906  cout << " Found camera viewpoint at XYZ = "
14907  << setw(10) << camera_eye[0] << " "
14908  << setw(10) << camera_eye[1] << " "
14909  << setw(10) << camera_eye[2] << "\n";
14910  cout << " Found camera focus coordinates at XYZ = "
14911  << setw(10) << camera_focus[0] << " "
14912  << setw(10) << camera_focus[1] << " "
14913  << setw(10) << camera_focus[2] << "\n";
14914  cout << " Rotation of camera is: " << rotation << "\n";
14915  cout << " Lens in used camera is: " << lens << " mm.\n";
14916  }
14917 
14918  if ( 0 < ( temp_pointer-38 ) )
14919  {
14920  if ( debug )
14921  {
14922  cout << " Found extra camera sections.\n";
14923  }
14924 
14925  u_short_int_val = tds_read_u_short_int ( filein );
14926 
14927  if ( u_short_int_val == 0x4710 )
14928  {
14929  if ( debug )
14930  {
14931  cout << " CAM_SEE_CONE.\n";
14932  }
14933  tds_read_unknown_section ( filein );
14934  }
14935 
14936  u_short_int_val = tds_read_u_short_int ( filein );
14937 
14938  if ( u_short_int_val == 0x4720 )
14939  {
14940  if ( debug )
14941  {
14942  cout << " CAM_RANGES.\n";
14943  }
14944  tds_read_unknown_section ( filein );
14945  }
14946 
14947  }
14948 
14949  pointer = ( long ) ( current_pointer + temp_pointer );
14950  fseek ( filein, pointer, SEEK_SET );
14951 
14952  return ( temp_pointer );
14953 }
14954 //****************************************************************************80
14955 
14956 unsigned long tds_read_edit_section ( FILE *filein, int *views_read )
14957 
14958 //****************************************************************************80
14959 //
14960 // Purpose:
14961 //
14962 // TDS_READ_EDIT_SECTION ???
14963 //
14964 // Licensing:
14965 //
14966 // This code is distributed under the GNU LGPL license.
14967 //
14968 // Modified:
14969 //
14970 // 18 September 1998
14971 //
14972 {
14973  unsigned long int chunk_length;
14974  unsigned long int current_pointer;
14975  bool end_found = false;
14976  long int pointer;
14977  unsigned long int teller;
14978  unsigned short int temp_int;
14979 
14980  current_pointer = ftell ( filein ) - 2;
14981  chunk_length = tds_read_u_long_int ( filein );
14982  teller = 6;
14983 
14984  while ( !end_found )
14985  {
14986  temp_int = tds_read_u_short_int ( filein );
14987  teller = teller + 2;
14988 
14989  if ( debug )
14990  {
14991  cout << " TDS_READ_EDIT_SECTION processing tag "
14992  << hex << temp_int << "\n";
14993  }
14994 
14995  switch ( temp_int )
14996  {
14997  case 0x1100:
14998  if ( debug )
14999  {
15000  cout << " BIT_MAP section tag of "
15001  << hex << temp_int << "\n";
15002  }
15003  teller = teller + tds_read_unknown_section ( filein );
15004  break;
15005  case 0x1201:
15006  if ( debug )
15007  {
15008  cout << " USE_SOLID_BGND section tag of "
15009  << hex << temp_int << "\n";
15010  }
15011  teller = teller + tds_read_unknown_section ( filein );
15012  break;
15013  case 0x1300:
15014  if ( debug )
15015  {
15016  cout << " V_GRADIENT section tag of "
15017  << hex << temp_int << "\n";
15018  }
15019  teller = teller + tds_read_unknown_section ( filein );
15020  break;
15021  case 0x1400:
15022  teller = teller + tds_read_unknown_section ( filein );
15023  break;
15024  case 0x1420:
15025  teller = teller + tds_read_unknown_section ( filein );
15026  break;
15027  case 0x1450:
15028  teller = teller + tds_read_unknown_section ( filein );
15029  break;
15030  case 0x1500:
15031  teller = teller + tds_read_unknown_section ( filein );
15032  break;
15033  case 0x2200:
15034  teller = teller + tds_read_unknown_section ( filein );
15035  break;
15036  case 0x2201:
15037  teller = teller + tds_read_unknown_section ( filein );
15038  break;
15039  case 0x2210:
15040  teller = teller + tds_read_unknown_section ( filein );
15041  break;
15042  case 0x2300:
15043  teller = teller + tds_read_unknown_section ( filein );
15044  break;
15045  case 0x2302:
15046  teller = teller + tds_read_unknown_section ( filein );
15047  break;
15048  case 0x3000:
15049  teller = teller + tds_read_unknown_section ( filein );
15050  break;
15051  case 0x2100:
15052  if ( debug )
15053  {
15054  cout << " AMBIENT_LIGHT section tag of "
15055  << hex << temp_int << "\n";
15056  }
15057  teller = teller + tds_read_ambient_section ( filein );
15058  break;
15059  case 0x1200:
15060  if ( debug )
15061  {
15062  cout << " SOLID_BGND section tag of "
15063  << hex << temp_int << "\n";
15064  }
15065  teller = teller + tds_read_background_section ( filein );
15066  break;
15067  case 0x0100:
15068  if ( debug )
15069  {
15070  cout << " MASTER_SCALE section tag of "
15071  << hex << temp_int << "\n";
15072  }
15073  teller = teller + tds_read_unknown_section ( filein );
15074  break;
15075  case 0x3d3e:
15076  if ( debug )
15077  {
15078  cout << " MESH_VERSION section tag of "
15079  << hex << temp_int << "\n";
15080  }
15081  teller = teller + tds_read_unknown_section ( filein );
15082  break;
15083  case 0xafff:
15084  if ( debug )
15085  {
15086  cout << " MAT_ENTRY section tag of "
15087  << hex << temp_int << "\n";
15088  }
15089  teller = teller + tds_read_material_section ( filein );
15090  break;
15091  case 0x4000:
15092  if ( debug )
15093  {
15094  cout << " NAMED_OBJECT section tag of "
15095  << hex << temp_int << "\n";
15096  }
15097  teller = teller + tds_read_object_section ( filein );
15098  break;
15099  case 0x7001:
15100  if ( debug )
15101  {
15102  cout << " VIEWPORT_LAYOUT section tag of "
15103  << hex << temp_int << "\n";
15104  }
15105  teller = teller + tds_read_view_section ( filein, views_read );
15106  break;
15107  case 0x7012:
15108  if ( debug )
15109  {
15110  cout << " VIEWPORT_DATA_3 section tag of "
15111  << hex << temp_int << "\n";
15112  }
15113  teller = teller + tds_read_unknown_section ( filein );
15114  break;
15115  case 0x7011:
15116  if ( debug )
15117  {
15118  cout << " VIEWPORT_DATA section tag of "
15119  << hex << temp_int << "\n";
15120  }
15121  teller = teller + tds_read_unknown_section ( filein );
15122  break;
15123  case 0x7020:
15124  if ( debug )
15125  {
15126  cout << " VIEWPORT_SIZE section tag of "
15127  << hex << temp_int << "\n";
15128  }
15129  teller = teller + tds_read_unknown_section ( filein );
15130  break;
15131  default:
15132  if ( debug )
15133  {
15134  cout << " Junk.\n";
15135  }
15136  break;
15137  }
15138 
15139  if ( chunk_length <= teller )
15140  {
15141  end_found = true;
15142  }
15143 
15144  }
15145 
15146  pointer = ( long ) ( current_pointer + chunk_length );
15147 
15148  fseek ( filein, pointer, SEEK_SET );
15149 
15150  return ( chunk_length );
15151 }
15152 //****************************************************************************80
15153 
15154 unsigned long tds_read_keyframe_section ( FILE *filein, int *views_read )
15155 
15156 //****************************************************************************80
15157 //
15158 // Purpose:
15159 //
15160 // TDS_READ_KEYFRAME_SECTION ???
15161 //
15162 // Licensing:
15163 //
15164 // This code is distributed under the GNU LGPL license.
15165 //
15166 {
15167  unsigned long int current_pointer;
15168  bool end_found = false;
15169  long int pointer;
15170  unsigned short int temp_int;
15171  unsigned long int temp_pointer;
15172  unsigned long int teller;
15173 
15174  current_pointer = ftell ( filein ) - 2;
15175  temp_pointer = tds_read_u_long_int ( filein );
15176  teller = 6;
15177 
15178  while ( !end_found )
15179  {
15180  temp_int = tds_read_u_short_int ( filein );
15181  teller = teller + 2;
15182 
15183  switch ( temp_int )
15184  {
15185  case 0x7001:
15186  if ( debug )
15187  {
15188  cout << " VIEWPORT_LAYOUT main definition section tag of "
15189  << hex << temp_int << "\n";
15190  }
15191  teller = teller + tds_read_view_section ( filein, views_read );
15192  break;
15193  case 0xb008:
15194  if ( debug )
15195  {
15196  cout << " KFSEG frames section tag of "
15197  << hex << temp_int << "\n";
15198  }
15199  teller = teller + tds_read_unknown_section ( filein );
15200  break;
15201  case 0xb002:
15202  if ( debug )
15203  {
15204  cout << " OBJECT_NODE_TAG object description section tag of "
15205  << hex << temp_int << "\n";
15206  }
15207  teller = teller + tds_read_keyframe_objdes_section ( filein );
15208  break;
15209  case 0xb009:
15210  if ( debug )
15211  {
15212  cout << " KFCURTIME section tag of "
15213  << hex << temp_int << "\n";
15214  }
15215  teller = teller + tds_read_unknown_section ( filein );
15216  break;
15217  case 0xb00a:
15218  if ( debug )
15219  {
15220  cout << " KFHDR section tag of "
15221  << hex << temp_int << "\n";
15222  }
15223  teller = teller + tds_read_unknown_section ( filein );
15224  break;
15225  default:
15226  break;
15227  }
15228 
15229  if ( temp_pointer <= teller )
15230  {
15231  end_found = true;
15232  }
15233 
15234  }
15235 
15236  pointer = ( long ) ( current_pointer + temp_pointer );
15237  fseek ( filein, pointer, SEEK_SET );
15238 
15239  return ( temp_pointer );
15240 }
15241 //****************************************************************************80
15242 
15243 unsigned long tds_read_keyframe_objdes_section ( FILE *filein )
15244 
15245 //****************************************************************************80
15246 //
15247 // Purpose:
15248 //
15249 // TDS_READ_KEYFRAME_OBJDES_SECTION ???
15250 //
15251 // Licensing:
15252 //
15253 // This code is distributed under the GNU LGPL license.
15254 //
15255 // Modified:
15256 //
15257 // 21 September 1998
15258 //
15259 {
15260  unsigned long int chunk_size;
15261  unsigned long int current_pointer;
15262  bool end_found = false;
15263  long int pointer;
15264  unsigned short int temp_int;
15265  unsigned long int temp_pointer;
15266  unsigned long int teller;
15267  unsigned long int u_long_int_val;
15268  unsigned short int u_short_int_val;
15269 
15270  current_pointer = ftell ( filein ) - 2;
15271  temp_pointer = tds_read_u_long_int ( filein );
15272  teller = 6;
15273 
15274  while ( !end_found )
15275  {
15276  temp_int = tds_read_u_short_int ( filein );
15277  teller = teller + 2;
15278 
15279  switch ( temp_int )
15280  {
15281  case 0xb011:
15282  if ( debug )
15283  {
15284  cout << " INSTANCE_NAME section tag of "
15285  << hex << temp_int << "\n";
15286  }
15287  teller = teller + tds_read_unknown_section ( filein );
15288  break;
15289  case 0xb010:
15290  if ( debug )
15291  {
15292  cout << " NODE_HDR section tag of "
15293  << hex << temp_int << "\n";
15294  }
15295  teller = teller + tds_read_unknown_section ( filein );
15296  break;
15297  case 0xb020:
15298  if ( debug )
15299  {
15300  cout << " POS_TRACK_TAG section tag of "
15301  << hex << temp_int << "\n";
15302  }
15303  chunk_size = tds_read_u_long_int ( filein );
15304  if ( debug )
15305  {
15306  cout << " chunk_size = " << chunk_size << "\n";
15307  }
15308  u_short_int_val = tds_read_u_short_int ( filein );
15309  u_short_int_val = tds_read_u_short_int ( filein );
15310  u_short_int_val = tds_read_u_short_int ( filein );
15311  u_short_int_val = tds_read_u_short_int ( filein );
15312  u_short_int_val = tds_read_u_short_int ( filein );
15313  u_short_int_val = tds_read_u_short_int ( filein );
15314  u_short_int_val = tds_read_u_short_int ( filein );
15315  u_short_int_val = tds_read_u_short_int ( filein );
15316  u_long_int_val = tds_read_u_long_int ( filein );
15317  if ( debug )
15318  {
15319  cout << "u_short_int_val = " << u_short_int_val << "\n";
15320  cout << "u_long_int_val = " << u_long_int_val << "\n";
15321  }
15322  origin[0] = float_read ( filein );
15323  origin[1] = float_read ( filein );
15324  origin[2] = float_read ( filein );
15325  teller = teller + 32;
15326  break;
15327  case 0xb013:
15328  if ( debug )
15329  {
15330  cout << " PIVOT section tag of "
15331  << hex << temp_int << "\n";
15332  }
15333  chunk_size = tds_read_u_long_int ( filein );
15334  pivot[0] = float_read ( filein );
15335  pivot[1] = float_read ( filein );
15336  pivot[2] = float_read ( filein );
15337  teller = teller + 12;
15338  break;
15339  case 0xb014:
15340  if ( debug )
15341  {
15342  cout << " BOUNDBOX section tag of "
15343  << hex << temp_int << "\n";
15344  }
15345  teller = teller + tds_read_unknown_section ( filein );
15346  break;
15347  case 0xb015:
15348  if ( debug )
15349  {
15350  cout << " MORPH_SMOOTH section tag of "
15351  << hex << temp_int << "\n";
15352  }
15353  teller = teller + tds_read_unknown_section ( filein );
15354  break;
15355  case 0xb021:
15356  if ( debug )
15357  {
15358  cout << " ROT_TRACK_TAG section tag of "
15359  << hex << temp_int << "\n";
15360  }
15361  teller = teller + tds_read_unknown_section ( filein );
15362  break;
15363  case 0xb022:
15364  if ( debug )
15365  {
15366  cout << " SCL_TRACK_TAG section tag of "
15367  << hex << temp_int << "\n";
15368  }
15369  teller = teller + tds_read_unknown_section ( filein );
15370  break;
15371  case 0xb030:
15372  if ( debug )
15373  {
15374  cout << " NODE_ID section tag of "
15375  << hex << temp_int << "\n";
15376  }
15377  teller = teller + tds_read_unknown_section ( filein );
15378  break;
15379  default:
15380  break;
15381  }
15382 
15383  if ( temp_pointer <= teller )
15384  {
15385  end_found = true;
15386  }
15387 
15388  }
15389 
15390  pointer = ( long ) ( current_pointer+temp_pointer );
15391  fseek ( filein, pointer, SEEK_SET );
15392 
15393  return ( temp_pointer );
15394 }
15395 //****************************************************************************80
15396 
15397 unsigned long tds_read_light_section ( FILE *filein )
15398 
15399 //****************************************************************************80
15400 //
15401 // Purpose:
15402 //
15403 // TDS_READ_LIGHT_SECTION ???
15404 //
15405 // Licensing:
15406 //
15407 // This code is distributed under the GNU LGPL license.
15408 //
15409 {
15410  unsigned char boolean;
15411  unsigned long int current_pointer;
15412  bool end_found = false;
15413  int i;
15414  float light_coors[3];
15415  long int pointer;
15416  float rgb_val[3];
15417  unsigned long int teller;
15418  unsigned short int temp_int;
15419  unsigned long int temp_pointer;
15420  unsigned char true_c_val[3];
15421 
15422  current_pointer = ftell ( filein ) - 2;
15423  temp_pointer = tds_read_u_long_int ( filein );
15424  teller = 6;
15425 
15426  light_coors[0] = float_read ( filein );
15427  light_coors[1] = float_read ( filein );
15428  light_coors[2] = float_read ( filein );
15429 
15430  teller = teller + 3 * 4;
15431 
15432  if ( debug )
15433  {
15434  cout << " Found light at coordinates XYZ = "
15435  << setw(10) << light_coors[0] << " "
15436  << setw(10) << light_coors[1] << " "
15437  << setw(10) << light_coors[2] << "\n";
15438  }
15439 
15440  while ( !end_found )
15441  {
15442  temp_int = tds_read_u_short_int ( filein );
15443  teller = teller + 2;
15444 
15445  switch ( temp_int )
15446  {
15447  case 0x0010:
15448  if ( debug )
15449  {
15450  cout << " COLOR_F RGB color definition section tag of "
15451  << hex << temp_int << "\n";
15452  }
15453  for ( i = 0; i < 3; i++ )
15454  {
15455  rgb_val[i] = float_read ( filein );
15456  }
15457  if ( debug )
15458  {
15459  cout << " RGB_VAL value set to "
15460  << setw(10) << rgb_val[0] << " "
15461  << setw(10) << rgb_val[1] << " "
15462  << setw(10) << rgb_val[2] << "\n";
15463  }
15464  teller = teller + 3 * sizeof ( float );
15465  break;
15466  case 0x0011:
15467  if ( debug )
15468  {
15469  cout << " COLOR_24 24 bit color definition section tag of "
15470  << hex << temp_int << "\n";
15471  }
15472 
15473  for ( i = 0; i < 3; i++ )
15474  {
15475  true_c_val[i] = fgetc ( filein );
15476  }
15477  if ( debug )
15478  {
15479  cout << " TRUE_C_VAL value set to "
15480  << setw(6) << true_c_val[0] << " "
15481  << setw(6) << true_c_val[1] << " "
15482  << setw(6) << true_c_val[2] << "\n";
15483  }
15484  teller = teller + 3;
15485  break;
15486  case 0x4620:
15487  if ( debug )
15488  {
15489  cout << " DL_OFF section: "
15490  << hex << temp_int << "\n";
15491  }
15492  teller = teller + tds_read_boolean ( &boolean, filein );
15493  if ( debug )
15494  {
15495  if ( boolean == 1 )
15496  {
15497  cout << " Light is on.\n";
15498  }
15499  else
15500  {
15501  cout << " Light is off.\n";
15502  }
15503  }
15504  break;
15505  case 0x4610:
15506  if ( debug )
15507  {
15508  cout << " DL_SPOTLIGHT section tag of "
15509  << hex << temp_int << "\n";
15510  }
15511  teller = teller + tds_read_spot_section ( filein );
15512  break;
15513  case 0x465a:
15514  if ( debug )
15515  {
15516  cout << " DL_OUTER_RANGE section tag of "
15517  << hex << temp_int << "\n";
15518  }
15519  teller = teller + tds_read_unknown_section ( filein );
15520  break;
15521  default:
15522  break;
15523  }
15524 
15525  if ( temp_pointer <= teller )
15526  {
15527  end_found = true;
15528  }
15529 
15530  }
15531 
15532  pointer = ( long ) ( current_pointer + temp_pointer );
15533  fseek ( filein, pointer, SEEK_SET );
15534 
15535  return ( temp_pointer );
15536 }
15537 //****************************************************************************80
15538 
15539 unsigned long int tds_read_u_long_int ( FILE *filein )
15540 
15541 //****************************************************************************80
15542 //
15543 // Purpose:
15544 //
15545 // TDS_READ_U_LONG_INT ???
15546 //
15547 // Licensing:
15548 //
15549 // This code is distributed under the GNU LGPL license.
15550 //
15551 // Modified:
15552 //
15553 // 01 October 1998
15554 //
15555 // Author:
15556 //
15557 // John Burkardt
15558 //
15559 {
15560  union {
15561  unsigned long int yint;
15562  char ychar[4];
15563  } y;
15564 
15565  if ( byte_swap )
15566  {
15567  y.ychar[3] = fgetc ( filein );
15568  y.ychar[2] = fgetc ( filein );
15569  y.ychar[1] = fgetc ( filein );
15570  y.ychar[0] = fgetc ( filein );
15571  }
15572  else
15573  {
15574  y.ychar[0] = fgetc ( filein );
15575  y.ychar[1] = fgetc ( filein );
15576  y.ychar[2] = fgetc ( filein );
15577  y.ychar[3] = fgetc ( filein );
15578  }
15579 
15580  return y.yint;
15581 }
15582 //****************************************************************************80
15583 
15584 int tds_read_long_name ( FILE *filein )
15585 
15586 //****************************************************************************80
15587 //
15588 // Purpose:
15589 //
15590 // TDS_READ_LONG_NAME ???
15591 //
15592 // Licensing:
15593 //
15594 // This code is distributed under the GNU LGPL license.
15595 //
15596 {
15597  unsigned char letter;
15598  unsigned int teller;
15599 
15600  teller = 0;
15601  letter = fgetc ( filein );
15602 //
15603 // Could be a dummy object.
15604 //
15605  if ( letter == 0 )
15606  {
15607  strcpy ( temp_name, "Default_name" );
15608  return -1;
15609  }
15610 
15611  temp_name[teller] = letter;
15612  teller = teller + 1;
15613 
15614  do
15615  {
15616  letter = fgetc ( filein );
15617  temp_name[teller] = letter;
15618  teller = teller + 1;
15619  } while ( letter != 0 );
15620 
15621  temp_name[teller-1] = 0;
15622 
15623  if ( debug )
15624  {
15625  cout << " TDS_READ_LONG_NAME found name: " << temp_name << ".\n";
15626  }
15627 
15628  return teller;
15629 }
15630 //****************************************************************************80
15631 
15632 unsigned long tds_read_matdef_section ( FILE *filein )
15633 
15634 //****************************************************************************80
15635 //
15636 // Purpose:
15637 //
15638 // TDS_READ_MATDEF_SECTION ???
15639 //
15640 // Licensing:
15641 //
15642 // This code is distributed under the GNU LGPL license.
15643 //
15644 {
15645  unsigned long int current_pointer;
15646  long int pointer;
15647  int teller;
15648  unsigned long int temp_pointer;
15649 
15650  current_pointer = ftell ( filein ) - 2;
15651  temp_pointer = tds_read_u_long_int ( filein );
15652 
15653  teller = tds_read_long_name ( filein );
15654 
15655  if ( teller == -1 )
15656  {
15657  if ( debug )
15658  {
15659  cout << " No material name found.\n";
15660  }
15661  }
15662  else
15663  {
15664  strcpy ( mat_name, temp_name );
15665  if ( debug )
15666  {
15667  cout << " Material name " << mat_name << ".\n";
15668  }
15669  }
15670 
15671  pointer = ( long ) ( current_pointer + temp_pointer );
15672  fseek ( filein, pointer, SEEK_SET );
15673 
15674  return ( temp_pointer );
15675 }
15676 //****************************************************************************80
15677 
15678 unsigned long tds_read_material_section ( FILE *filein )
15679 
15680 //****************************************************************************80
15681 //
15682 // Purpose:
15683 //
15684 // TDS_READ_MATERIAL_SECTION ???
15685 //
15686 // Licensing:
15687 //
15688 // This code is distributed under the GNU LGPL license.
15689 //
15690 {
15691  unsigned long int current_pointer;
15692  bool end_found = false;
15693  long int pointer;
15694  unsigned short int temp_int;
15695  unsigned long int temp_pointer;
15696  unsigned long int teller;
15697 
15698  current_pointer = ftell ( filein ) - 2;
15699 
15700  temp_pointer = tds_read_u_long_int ( filein );
15701  teller = 6;
15702 
15703  while ( !end_found )
15704  {
15705  temp_int = tds_read_u_short_int ( filein );
15706  teller = teller + 2;
15707 
15708  switch ( temp_int )
15709  {
15710  case 0xa000:
15711  if ( debug )
15712  {
15713  cout << " MAT_NAME definition section tag of "
15714  << hex << temp_int << "\n";
15715  }
15716  teller = teller + tds_read_matdef_section ( filein );
15717  break;
15718  case 0xa010:
15719  if ( debug )
15720  {
15721  cout << " MAT_AMBIENT definition section tag of "
15722  << hex << temp_int << "\n";
15723  }
15724  teller = teller + tds_read_unknown_section ( filein );
15725  break;
15726  case 0xa020:
15727  if ( debug )
15728  {
15729  cout << " MAT_DIFFUSE definition section tag of "
15730  << hex << temp_int << "\n";
15731  }
15732  teller = teller + tds_read_unknown_section ( filein );
15733  break;
15734  case 0xa030:
15735  if ( debug )
15736  {
15737  cout << " MAT_SPECULAR definition section tag of "
15738  << hex << temp_int << "\n";
15739  }
15740  teller = teller + tds_read_unknown_section ( filein );
15741  break;
15742  case 0xa040:
15743  if ( debug )
15744  {
15745  cout << " MAT_SHININESS definition section tag of "
15746  << hex << temp_int << "\n";
15747  }
15748  teller = teller + tds_read_unknown_section ( filein );
15749  break;
15750  case 0xa041:
15751  if ( debug )
15752  {
15753  cout << " MAT_SHIN2PCT definition section tag of "
15754  << hex << temp_int << "\n";
15755  }
15756  teller = teller + tds_read_unknown_section ( filein );
15757  break;
15758  case 0xa042:
15759  if ( debug )
15760  {
15761  cout << " MAT_SHIN3PCT definition section tag of "
15762  << hex << temp_int << "\n";
15763  }
15764  teller = teller + tds_read_unknown_section ( filein );
15765  break;
15766  case 0xa050:
15767  if ( debug )
15768  {
15769  cout << " MAT_TRANSPARENCY definition section tag of "
15770  << hex << temp_int << "\n";
15771  }
15772  teller = teller + tds_read_unknown_section ( filein );
15773  break;
15774  case 0xa052:
15775  if ( debug )
15776  {
15777  cout << " MAT_XPFALL definition section tag of "
15778  << hex << temp_int << "\n";
15779  }
15780  teller = teller + tds_read_unknown_section ( filein );
15781  break;
15782  case 0xa053:
15783  if ( debug )
15784  {
15785  cout << " MAT_REFBLUR definition section tag of "
15786  << hex << temp_int << "\n";
15787  }
15788  teller = teller + tds_read_unknown_section ( filein );
15789  break;
15790  case 0xa080:
15791  if ( debug )
15792  {
15793  cout << " MAT_SELF_ILLUM definition section tag of "
15794  << hex << temp_int << "\n";
15795  }
15796  teller = teller + tds_read_unknown_section ( filein );
15797  break;
15798  case 0xa081:
15799  if ( debug )
15800  {
15801  cout << " MAT_TWO_SIDE definition section tag of "
15802  << hex << temp_int << "\n";
15803  }
15804  teller = teller + tds_read_unknown_section ( filein );
15805  break;
15806  case 0xa082:
15807  if ( debug )
15808  {
15809  cout << " MAT_DECAL definition section tag of "
15810  << hex << temp_int << "\n";
15811  }
15812  teller = teller + tds_read_unknown_section ( filein );
15813  break;
15814  case 0xa083:
15815  if ( debug )
15816  {
15817  cout << " MAT_ADDITIVE definition section tag of "
15818  << hex << temp_int << "\n";
15819  }
15820  teller = teller + tds_read_unknown_section ( filein );
15821  break;
15822  case 0xa084:
15823  if ( debug )
15824  {
15825  cout << " MAT_SELF_ILPCT definition section tag of "
15826  << hex << temp_int << "\n";
15827  }
15828  teller = teller + tds_read_unknown_section ( filein );
15829  break;
15830  case 0xa085:
15831  if ( debug )
15832  {
15833  cout << " MAT_WIRE definition section tag of "
15834  << hex << temp_int << "\n";
15835  }
15836  teller = teller + tds_read_unknown_section ( filein );
15837  break;
15838  case 0xa086:
15839  if ( debug )
15840  {
15841  cout << " MAT_SUPERSMP definition section tag of "
15842  << hex << temp_int << "\n";
15843  }
15844  teller = teller + tds_read_unknown_section ( filein );
15845  break;
15846  case 0xa087:
15847  if ( debug )
15848  {
15849  cout << " MAT_WIRESIZE definition section tag of "
15850  << hex << temp_int << "\n";
15851  }
15852  teller = teller + tds_read_unknown_section ( filein );
15853  break;
15854  case 0xa088:
15855  if ( debug )
15856  {
15857  cout << " MAT_FACEMAP definition section tag of "
15858  << hex << temp_int << "\n";
15859  }
15860  teller = teller + tds_read_unknown_section ( filein );
15861  break;
15862  case 0xa08a:
15863  if ( debug )
15864  {
15865  cout << " MAT_XPFALLIN definition section tag of "
15866  << hex << temp_int << "\n";
15867  }
15868  teller = teller + tds_read_unknown_section ( filein );
15869  break;
15870  case 0xa08c:
15871  if ( debug )
15872  {
15873  cout << " MAT_PHONGSOFT definition section tag of "
15874  << hex << temp_int << "\n";
15875  }
15876  teller = teller + tds_read_unknown_section ( filein );
15877  break;
15878  case 0xa08e:
15879  if ( debug )
15880  {
15881  cout << " MAT_WIREABS definition section tag of "
15882  << hex << temp_int << "\n";
15883  }
15884  teller = teller + tds_read_unknown_section ( filein );
15885  break;
15886  case 0xa100:
15887  if ( debug )
15888  {
15889  cout << " MAT_SHADING definition section tag of "
15890  << hex << temp_int << "\n";
15891  }
15892  teller = teller + tds_read_unknown_section ( filein );
15893  break;
15894  case 0xa200:
15895  if ( debug )
15896  {
15897  cout << " MAT_TEXMAP definition section tag of "
15898  << hex << temp_int << "\n";
15899  }
15900  teller = teller + tds_read_texmap_section ( filein );
15901 //
15902 // teller = teller + tds_read_unknown_section ( filein );
15903 //
15904  break;
15905  case 0xa204:
15906  if ( debug )
15907  {
15908  cout << " MAT_SPECMAP definition section tag of "
15909  << hex << temp_int << "\n";
15910  }
15911  teller = teller + tds_read_unknown_section ( filein );
15912  break;
15913  case 0xa210:
15914  if ( debug )
15915  {
15916  cout << " MAT_OPACMAP definition section tag of "
15917  << hex << temp_int << "\n";
15918  }
15919  teller = teller + tds_read_unknown_section ( filein );
15920  break;
15921  case 0xa220:
15922  if ( debug )
15923  {
15924  cout << " MAT_REFLMAP definition section tag of "
15925  << hex << temp_int << "\n";
15926  }
15927  teller = teller + tds_read_unknown_section ( filein );
15928  break;
15929  case 0xa230:
15930  if ( debug )
15931  {
15932  cout << " MAT_BUMPMAP definition section tag of "
15933  << hex << temp_int << "\n";
15934  }
15935  teller = teller + tds_read_unknown_section ( filein );
15936  break;
15937  case 0xa353:
15938  if ( debug )
15939  {
15940  cout << " MAT_MAP_TEXBLUR definition section tag of "
15941  << hex << temp_int << "\n";
15942  }
15943  teller = teller + tds_read_unknown_section ( filein );
15944  break;
15945  default:
15946  if ( debug )
15947  {
15948  cout << " Junk section tag of "
15949  << hex << temp_int << "\n";
15950  }
15951  break;
15952  }
15953 
15954  if ( temp_pointer <= teller )
15955  {
15956  end_found = true;
15957  }
15958 
15959  }
15960  pointer = ( long ) ( current_pointer + temp_pointer );
15961 
15962  fseek ( filein, pointer, SEEK_SET );
15963 
15964  return ( temp_pointer );
15965 }
15966 //****************************************************************************80
15967 
15968 int tds_read_name ( FILE *filein )
15969 
15970 //****************************************************************************80
15971 //
15972 // Purpose:
15973 //
15974 // TDS_READ_NAME ???
15975 //
15976 // Licensing:
15977 //
15978 // This code is distributed under the GNU LGPL license.
15979 //
15980 {
15981  unsigned char letter;
15982  unsigned int teller;
15983 
15984  teller = 0;
15985  letter = fgetc ( filein );
15986 //
15987 // Could be a dummy object.
15988 //
15989 
15990  if ( letter == 0 )
15991  {
15992  strcpy ( temp_name, "Default name" );
15993  return (-1);
15994  }
15995 
15996  temp_name[teller] = letter;
15997  teller = teller + 1;
15998 
15999  do
16000  {
16001  letter = fgetc ( filein );
16002  temp_name[teller] = letter;
16003  teller = teller + 1;
16004  } while ( ( letter != 0 ) && ( teller < 12 ) );
16005 
16006  temp_name[teller-1] = 0;
16007 
16008  if ( debug )
16009  {
16010  cout << " TDS_READ_NAME found name: " << temp_name << ".\n";
16011  }
16012 
16013  return 0;
16014 }
16015 //****************************************************************************80
16016 
16017 unsigned long tds_read_obj_section ( FILE *filein )
16018 
16019 //****************************************************************************80
16020 //
16021 // Purpose:
16022 //
16023 // TDS_READ_OBJ_SECTION ???
16024 //
16025 // Discussion:
16026 //
16027 // Thanks to John F Flanagan for some suggested corrections.
16028 //
16029 // Licensing:
16030 //
16031 // This code is distributed under the GNU LGPL license.
16032 //
16033 // Modified:
16034 //
16035 // 30 June 2001
16036 //
16037 {
16038  unsigned short int b;
16039  unsigned long int chunk_size;
16040  unsigned short int color_index;
16041  unsigned long int current_pointer;
16042  bool end_found = false;
16043  unsigned short int g;
16044  int i;
16045  int j;
16046  int cor3_num_base;
16047  int cor3_num_inc;
16048  int face_num_inc;
16049  long int pointer;
16050  unsigned short int r;
16051  unsigned short int temp_int;
16052  unsigned long int temp_pointer;
16053  unsigned long int temp_pointer2;
16054  unsigned long int teller;
16055 
16056  current_pointer = ftell ( filein ) - 2;
16057  temp_pointer = tds_read_u_long_int ( filein );
16058  teller = 6;
16059  cor3_num_base = cor3_num;
16060 
16061  while ( !end_found )
16062  {
16063  temp_int = tds_read_u_short_int ( filein );
16064  teller = teller + 2;
16065 
16066  switch ( temp_int )
16067  {
16068  case 0x4000:
16069  if ( debug )
16070  {
16071  cout << " NAMED_OBJECT section tag of "
16072  << hex << temp_int << "\n";
16073  }
16074  teller = teller + tds_read_unknown_section ( filein );
16075  break;
16076 
16077  case 0x4100:
16078  if ( debug )
16079  {
16080  cout << " N_TRI_OBJECT section tag of "
16081  << hex << temp_int << "\n";
16082  }
16083  teller = teller + tds_read_unknown_section ( filein );
16084  break;
16085 
16086  case 0x4110:
16087 
16088  if ( debug )
16089  {
16090  cout << " POINT_ARRAY section tag of "
16091  << hex << temp_int << "\n";
16092  }
16093 
16094  current_pointer = ftell ( filein ) - 2;
16095  temp_pointer2 = tds_read_u_long_int ( filein );
16096  cor3_num_inc = ( int ) tds_read_u_short_int ( filein );
16097 
16098  for ( i = cor3_num; i < cor3_num + cor3_num_inc; i++ )
16099  {
16100  cor3[0][i] = float_read ( filein );
16101  cor3[1][i] = float_read ( filein );
16102  cor3[2][i] = float_read ( filein );
16103  }
16104 
16105  cor3_num = cor3_num + cor3_num_inc;
16106  teller = teller + temp_pointer2;
16107  break;
16108 
16109  case 0x4111:
16110  if ( debug )
16111  {
16112  cout << " POINT_FLAG_ARRAY faces (2) section tag of "
16113  << hex << temp_int << "\n";
16114  }
16115  teller = teller + tds_read_unknown_section ( filein );
16116  break;
16117 
16118  case 0x4120:
16119 
16120  if ( debug )
16121  {
16122  cout << " FACE_ARRAY section tag of "
16123  << hex << temp_int << "\n";
16124  }
16125 
16126  temp_pointer2 = tds_read_u_long_int ( filein );
16127  face_num_inc = ( int ) tds_read_u_short_int ( filein );
16128 
16129  for ( i = face_num; i < face_num + face_num_inc; i++ )
16130  {
16131  face[0][i] = tds_read_u_short_int ( filein ) + cor3_num_base;
16132  face[1][i] = tds_read_u_short_int ( filein ) + cor3_num_base;
16133  face[2][i] = tds_read_u_short_int ( filein ) + cor3_num_base;
16134  face_order[i] = 3;
16135  face_flags[i] = tds_read_u_short_int ( filein );
16136 //
16137 // Color is given per face, and as 24 bit RGB data packed in one word.
16138 // Extract RGB from the word, and assign R / 255 to each vertex.
16139 //
16140 // Just a guess, JVB, 30 June 2001.
16141 //
16142  temp_int = face_flags[i] & 0x000F;
16143  r = ( temp_int & 0x0004 ) >> 2;
16144  g = ( temp_int & 0x0002 ) >> 1;
16145  b = ( temp_int & 0x0001 );
16146 
16147  for ( j = 0; j < 3; j++ )
16148  {
16149  vertex_rgb[0][j][i] = ( float ) r / 255.0;
16150  vertex_rgb[1][j][i] = ( float ) g / 255.0;
16151  vertex_rgb[2][j][i] = ( float ) b / 255.0;
16152  }
16153 
16154  }
16155 
16156  temp_int = tds_read_u_short_int ( filein );
16157  if ( temp_int == 0x4150 )
16158  {
16159  for ( i = face_num; i < face_num + face_num_inc; i++ )
16160  {
16161  face_smooth[i] = ( int ) tds_read_u_long_int ( filein )
16162  + cor3_num_base;
16163  }
16164  }
16165  face_num = face_num + face_num_inc;
16166  teller = ftell ( filein );
16167  break;
16168 
16169  case 0x4130:
16170  if ( debug )
16171  {
16172  cout << " MSH_MAT_GROUP section tag of "
16173  << hex << temp_int << "\n";
16174  }
16175  teller = teller + tds_read_unknown_section ( filein );
16176  break;
16177 
16178  case 0x4140:
16179  if ( debug )
16180  {
16181  cout << " TEX_VERTS section tag of "
16182  << hex << temp_int << "\n";
16183  }
16184  teller = teller + tds_read_tex_verts_section ( filein );
16185  break;
16186 
16187  case 0x4150:
16188  if ( debug )
16189  {
16190  cout << " SMOOTH_GROUP section tag of "
16191  << hex << temp_int << "\n";
16192  }
16193  teller = teller + tds_read_unknown_section ( filein );
16194  break;
16195 
16196  case 0x4160:
16197 
16198  if ( debug )
16199  {
16200  cout << " MESH_MATRIX section tag of "
16201  << hex << temp_int << "\n";
16202  }
16203 
16204  tds_read_u_long_int ( filein );
16205 
16206  for ( j = 0; j < 4; j++ )
16207  {
16208  for ( i = 0; i < 3; i++ )
16209  {
16210  transform_matrix[j][i] = float_read ( filein );
16211  }
16212  }
16213  transform_matrix[0][3] = 0.0;
16214  transform_matrix[1][3] = 0.0;
16215  transform_matrix[2][3] = 0.0;
16216  transform_matrix[3][3] = 0.0;
16217 
16218  teller = teller + 12 * sizeof ( float );
16219  break;
16220 
16221  case 0x4165:
16222 
16223  if ( debug )
16224  {
16225  cout << " MESH_COLOR section tag of "
16226  << hex << temp_int << "\n";
16227  }
16228 
16229  chunk_size = tds_read_u_long_int ( filein );
16230 
16231  if ( chunk_size == 7 )
16232  {
16233  color_index = fgetc ( filein );
16234  teller = teller + 5;
16235  }
16236  else
16237  {
16238  color_index = tds_read_u_short_int ( filein );
16239  teller = teller + 6;
16240  }
16241  if ( debug )
16242  {
16243  cout << " Color index set to " << color_index << "\n";
16244  }
16245  break;
16246 
16247  case 0x4170:
16248  if ( debug )
16249  {
16250  cout << " MESH_TEXTURE_INFO section tag of "
16251  << hex << temp_int << "\n";
16252  }
16253  teller = teller + tds_read_unknown_section ( filein );
16254  break;
16255 
16256  default:
16257  if ( debug )
16258  {
16259  cout << " JUNK section tag of "
16260  << hex << temp_int << "\n";
16261  }
16262  break;
16263  }
16264 
16265  if ( temp_pointer <= teller )
16266  {
16267  end_found = true;
16268  }
16269 
16270  }
16271 
16272  pointer = ( long int ) ( current_pointer + temp_pointer );
16273  fseek ( filein, pointer, SEEK_SET );
16274 
16275  return ( temp_pointer );
16276 }
16277 //****************************************************************************80
16278 
16279 unsigned long tds_read_object_section ( FILE *filein )
16280 
16281 //****************************************************************************80
16282 //
16283 // Purpose:
16284 //
16285 // TDS_READ_OBJECT_SECTION ???
16286 //
16287 // Licensing:
16288 //
16289 // This code is distributed under the GNU LGPL license.
16290 //
16291 {
16292  bool end_found = false;
16293  unsigned long int current_pointer;
16294  int int_val;
16295  long int pointer;
16296  unsigned short int temp_int;
16297  unsigned long int temp_pointer;
16298  unsigned long int teller;
16299 
16300  current_pointer = ftell ( filein ) - 2;
16301  temp_pointer = tds_read_u_long_int ( filein );
16302  teller = 6;
16303 //
16304 // Why don't you read and save the name here?
16305 //
16306  int_val = tds_read_name ( filein );
16307 
16308  if ( int_val == -1 )
16309  {
16310  if ( debug )
16311  {
16312  cout << " Dummy Object found\n";
16313  }
16314  }
16315  else
16316  {
16317  strcpy ( object_name, temp_name );
16318  }
16319 
16320  while ( !end_found )
16321  {
16322  temp_int = tds_read_u_short_int ( filein );
16323  teller = teller + 2;
16324 
16325  switch ( temp_int )
16326  {
16327  case 0x4700:
16328  if ( debug )
16329  {
16330  cout << " N_CAMERA section tag of "
16331  << hex << temp_int << "\n";
16332  }
16333  teller = teller + tds_read_camera_section ( filein );
16334  break;
16335  case 0x4600:
16336  if ( debug )
16337  {
16338  cout << " N_DIRECT_LIGHT section tag of "
16339  << hex << temp_int << "\n";
16340  }
16341  teller = teller + tds_read_light_section ( filein );
16342  break;
16343  case 0x4100:
16344  if ( debug )
16345  {
16346  cout << " OBJ_TRIMESH section tag of "
16347  << hex << temp_int << "\n";
16348  }
16349  teller = teller + tds_read_obj_section ( filein );
16350  break;
16351  case 0x4010:
16352  if ( debug )
16353  {
16354  cout << " OBJ_HIDDEN section tag of "
16355  << hex << temp_int << "\n";
16356  }
16357  teller = teller + tds_read_unknown_section ( filein );
16358  break;
16359  case 0x4012:
16360  if ( debug )
16361  {
16362  cout << " OBJ_DOESNT_CAST section tag of "
16363  << hex << temp_int << "\n";
16364  }
16365  teller = teller + tds_read_unknown_section ( filein );
16366  break;
16367  default:
16368  break;
16369  }
16370 
16371  if ( temp_pointer <= teller )
16372  {
16373  end_found = true;
16374  }
16375 
16376  }
16377 
16378  pointer = ( long ) ( current_pointer + temp_pointer );
16379 
16380  fseek ( filein, pointer, SEEK_SET );
16381 
16382  return ( temp_pointer );
16383 }
16384 //****************************************************************************80
16385 
16386 unsigned long int tds_read_tex_verts_section ( FILE *filein )
16387 
16388 //****************************************************************************80
16389 //
16390 // Purpose:
16391 //
16392 // TDS_READ_TEX_VERTS_SECTION reads the texture vertex data.
16393 //
16394 // Discussion:
16395 //
16396 // The texture vertex data seems to be associated with nodes. This routine
16397 // distributes that data to vertices (nodes as they make up a particular
16398 // face).
16399 //
16400 // Licensing:
16401 //
16402 // This code is distributed under the GNU LGPL license.
16403 //
16404 // Modified:
16405 //
16406 // 02 July 1999
16407 //
16408 // Author:
16409 //
16410 // John Burkardt
16411 //
16412 {
16413  unsigned long int current_pointer;
16414  int icor3;
16415  long int pointer;
16416  unsigned long int temp_pointer;
16417  unsigned short int n2;
16418 
16419  current_pointer = ftell ( filein ) - 2;
16420  temp_pointer = tds_read_u_long_int ( filein );
16421 
16422  pointer = ( long int ) ( current_pointer + temp_pointer );
16423 
16424  n2 = tds_read_u_short_int ( filein );
16425 
16426  for ( icor3 = 0; icor3 < n2; icor3++ )
16427  {
16428  cor3_tex_uv[0][icor3] = float_read ( filein );
16429  cor3_tex_uv[1][icor3] = float_read ( filein );
16430  }
16431 
16432  fseek ( filein, pointer, SEEK_SET );
16433 
16434  return ( temp_pointer );
16435 }
16436 //****************************************************************************80
16437 
16438 unsigned long tds_read_texmap_section ( FILE *filein )
16439 
16440 //****************************************************************************80
16441 //
16442 // Purpose:
16443 //
16444 // TDS_READ_TEXMAP_SECTION tries to get the TEXMAP name from the TEXMAP section.
16445 //
16446 // Discussion:
16447 //
16448 // The code has room for lots of textures. In this routine, we behave as
16449 // though there were only one, and we stick its name in the first name slot.
16450 //
16451 // Licensing:
16452 //
16453 // This code is distributed under the GNU LGPL license.
16454 //
16455 // Modified:
16456 //
16457 // 30 June 1999
16458 //
16459 // Author:
16460 //
16461 // John Burkardt
16462 //
16463 {
16464  unsigned long int current_pointer;
16465  long int pointer;
16466  int teller;
16467  unsigned long int temp_pointer;
16468 
16469  texture_num = texture_num + 1;
16470 
16471  current_pointer = ftell ( filein ) - 2;
16472  temp_pointer = tds_read_u_long_int ( filein );
16473 
16474  tds_read_u_short_int ( filein );
16475  tds_read_u_short_int ( filein );
16476  tds_read_u_short_int ( filein );
16477  tds_read_u_short_int ( filein );
16478 //
16479 // This next short int should equal A300.
16480 //
16481  tds_read_u_short_int ( filein );
16482  tds_read_u_long_int ( filein );
16483 //
16484 // Now read the TEXMAP file name.
16485 //
16486  teller = tds_read_long_name ( filein );
16487 
16488  if ( teller == -1 )
16489  {
16490  if ( debug )
16491  {
16492  cout << " No TEXMAP name found.\n";
16493  }
16494  }
16495  else
16496  {
16497  strcpy ( texture_name[0], temp_name );
16498  if ( debug )
16499  {
16500  cout << " TEXMAP name " << texture_name[0] << ".\n";
16501  }
16502  }
16503 
16504  pointer = ( long ) ( current_pointer + temp_pointer );
16505  fseek ( filein, pointer, SEEK_SET );
16506 
16507  return ( temp_pointer );
16508 }
16509 //****************************************************************************80
16510 
16511 unsigned short int tds_read_u_short_int ( FILE *filein )
16512 
16513 //****************************************************************************80
16514 //
16515 // Purpose:
16516 //
16517 // TDS_READ_U_SHORT_INT ???
16518 //
16519 // Licensing:
16520 //
16521 // This code is distributed under the GNU LGPL license.
16522 //
16523 {
16524  unsigned char c1;
16525  unsigned char c2;
16526  short int ival;
16527 
16528  c1 = fgetc ( filein );
16529  c2 = fgetc ( filein );
16530 
16531  ival = c1 | ( c2 << 8 );
16532 
16533  return ival;
16534 }
16535 //****************************************************************************80
16536 
16537 unsigned long tds_read_spot_section ( FILE *filein )
16538 
16539 //****************************************************************************80
16540 //
16541 // Purpose:
16542 //
16543 // TDS_READ_SPOT_SECTION ???
16544 //
16545 // Licensing:
16546 //
16547 // This code is distributed under the GNU LGPL license.
16548 //
16549 {
16550  unsigned long int current_pointer;
16551  float falloff;
16552  float hotspot;
16553  long int pointer;
16554  float target[4];
16555  unsigned long int temp_pointer;
16556 
16557  current_pointer = ftell ( filein ) - 2;
16558  temp_pointer = tds_read_u_long_int ( filein );
16559 
16560  target[0] = float_read ( filein );
16561  target[1] = float_read ( filein );
16562  target[2] = float_read ( filein );
16563  hotspot = float_read ( filein );
16564  falloff = float_read ( filein );
16565 
16566  if ( debug )
16567  {
16568  cout << " The target of the spot is XYZ = "
16569  << setw(10) << target[0] << " "
16570  << setw(10) << target[1] << " "
16571  << setw(10) << target[2] << "\n";
16572  cout << " The hotspot of this light is " << hotspot << ".\n";
16573  cout << " The falloff of this light is " << falloff << ".\n";
16574  }
16575 
16576  pointer = ( long ) ( current_pointer + temp_pointer );
16577 
16578  fseek ( filein, pointer, SEEK_SET );
16579 
16580  return ( temp_pointer );
16581 }
16582 //****************************************************************************80
16583 
16584 unsigned long int tds_read_unknown_section ( FILE *filein )
16585 
16586 //****************************************************************************80
16587 //
16588 // Purpose:
16589 //
16590 // TDS_READ_UNKNOWN_SECTION ???
16591 //
16592 // Licensing:
16593 //
16594 // This code is distributed under the GNU LGPL license.
16595 //
16596 {
16597  unsigned long int current_pointer;
16598  long int pointer;
16599  unsigned long int temp_pointer;
16600 
16601  current_pointer = ftell ( filein ) - 2;
16602  temp_pointer = tds_read_u_long_int ( filein );
16603 
16604  pointer = ( long int ) ( current_pointer + temp_pointer );
16605 
16606  fseek ( filein, pointer, SEEK_SET );
16607 
16608  return ( temp_pointer );
16609 }
16610 //****************************************************************************80
16611 
16612 unsigned long tds_read_view_section ( FILE *filein, int *views_read )
16613 
16614 //****************************************************************************80
16615 //
16616 // Purpose:
16617 //
16618 // TDS_READ_VIEW_SECTION ???
16619 //
16620 // Licensing:
16621 //
16622 // This code is distributed under the GNU LGPL license.
16623 //
16624 {
16625  unsigned long int current_pointer;
16626  bool end_found = false;
16627  long int pointer;
16628  unsigned short int temp_int;
16629  unsigned long int temp_pointer;
16630  unsigned long int teller;
16631 
16632  current_pointer = ftell ( filein ) - 2;
16633  temp_pointer = tds_read_u_long_int ( filein );
16634  teller = 6;
16635 
16636  while ( !end_found )
16637  {
16638  temp_int = tds_read_u_short_int ( filein );
16639  teller = teller + 2;
16640 
16641  switch ( temp_int )
16642  {
16643  case 0x7012:
16644  if ( debug )
16645  {
16646  cout << " VIEWPORT_DATA_3 section tag of "
16647  << hex << temp_int << "\n";
16648  }
16649  teller = teller + tds_read_vp_section ( filein, views_read );
16650  break;
16651  case 0x7011:
16652  if ( debug )
16653  {
16654  cout << " VIEWPORT_DATA section tag of "
16655  << hex << temp_int << "\n";
16656  }
16657  teller = teller + tds_read_unknown_section ( filein );
16658  break;
16659  case 0x7020:
16660  if ( debug )
16661  {
16662  cout << " VIEWPORT_SIZE section tag of "
16663  << hex << temp_int << "\n";
16664  }
16665  teller = teller + tds_read_vp_section ( filein, views_read );
16666  break;
16667  default:
16668  break;
16669  }
16670 
16671  if ( temp_pointer <= teller )
16672  {
16673  end_found = true;
16674  }
16675 
16676  if ( 3 < *views_read )
16677  {
16678  end_found = true;
16679  }
16680  }
16681 
16682  pointer = ( long int ) ( current_pointer + temp_pointer );
16683 
16684  fseek ( filein, pointer, SEEK_SET );
16685 
16686  return ( temp_pointer );
16687 }
16688 //****************************************************************************80
16689 
16690 unsigned long tds_read_vp_section ( FILE *filein, int *views_read )
16691 
16692 //****************************************************************************80
16693 //
16694 // Purpose:
16695 //
16696 // TDS_READ_VP_SECTION ???
16697 //
16698 // Licensing:
16699 //
16700 // This code is distributed under the GNU LGPL license.
16701 //
16702 {
16703  unsigned int attribs;
16704  unsigned long int current_pointer;
16705  int i;
16706  int int_val;
16707  long int pointer;
16708  unsigned int port;
16709  unsigned long int temp_pointer;
16710  char *viewports[11] = {
16711  "Bogus",
16712  "Top",
16713  "Bottom",
16714  "Left",
16715  "Right",
16716  "Front",
16717  "Back",
16718  "User",
16719  "Camera",
16720  "Light",
16721  "Disabled"
16722  };
16723 
16724  *views_read = *views_read + 1;
16725 
16726  current_pointer = ftell ( filein ) - 2;
16727  temp_pointer = tds_read_u_long_int ( filein );
16728 
16729  attribs = tds_read_u_short_int ( filein );
16730 
16731  if ( attribs == 3 )
16732  {
16733  if ( debug )
16734  {
16735  cout << "<Snap> active in viewport.\n";
16736  }
16737  }
16738 
16739  if ( attribs == 5 )
16740  {
16741  if ( debug )
16742  {
16743  cout << "<Grid> active in viewport.\n";
16744  }
16745  }
16746 //
16747 // Read 5 INTS to get to the viewport information.
16748 //
16749  for ( i = 1; i < 6; i++ )
16750  {
16751  tds_read_u_short_int ( filein );
16752  }
16753 
16754  port = tds_read_u_short_int ( filein );
16755 //
16756 // Find camera section.
16757 //
16758  if ( ( port == 0xffff ) || ( port == 0 ) )
16759  {
16760  for ( i = 0; i < 12; i++ )
16761  {
16762  tds_read_u_short_int ( filein );
16763  }
16764 
16765  int_val = tds_read_name (filein );
16766 
16767  if ( int_val == -1 )
16768  {
16769  if ( debug )
16770  {
16771  cout << " No Camera name found\n";;
16772  }
16773  }
16774 
16775  port = 0x0008;
16776  }
16777 
16778  if ( debug )
16779  {
16780  cout << "Reading [" << viewports[port]
16781  << "] information with tag: " << port << "\n";
16782  }
16783 
16784  pointer = ( long int ) ( current_pointer + temp_pointer );
16785 
16786  fseek ( filein, pointer, SEEK_SET );
16787 
16788  return ( temp_pointer );
16789 }
16790 //****************************************************************************80
16791 
16792 int tds_write ( FILE *fileout )
16793 
16794 //****************************************************************************80
16795 //
16796 // Purpose:
16797 //
16798 // TDS_WRITE writes graphics information to a 3D Studio Max 3DS file.
16799 //
16800 // Licensing:
16801 //
16802 // This code is distributed under the GNU LGPL license.
16803 //
16804 // Modified:
16805 //
16806 // 14 October 1998
16807 //
16808 // Author:
16809 //
16810 // John Burkardt
16811 //
16812 //
16813 {
16814  float float_val;
16815  int i;
16816  int icor3;
16817  int iface;
16818  int j;
16819  long int l0002;
16820  long int l0100;
16821  long int l3d3d;
16822  long int l3d3e;
16823  long int l4000;
16824  long int l4100;
16825  long int l4110;
16826  long int l4120;
16827  long int l4150;
16828  long int l4160;
16829  long int l4d4d;
16830  long int lb000;
16831  long int lb002;
16832  long int lb00a;
16833  long int lb008;
16834  long int lb009;
16835  long int lb010;
16836  long int lb013;
16837  long int lb020;
16838  long int lb021;
16839  long int lb022;
16840  long int lb030;
16841  long int long_int_val;
16842  int name_length;
16843  short int short_int_val;
16844  unsigned short int u_short_int_val;
16845 
16846  bytes_num = 0;
16847  name_length = strlen ( object_name );
16848 
16849  l0002 = 10;
16850 
16851  l4150 = 2 + 4 + face_num * 4;
16852  l4120 = 2 + 4 + 2 + 4 * face_num * 2 + l4150;
16853  l4160 = 2 + 4 + 4 * 12;
16854  l4110 = 2 + 4 + 2 + cor3_num * 3 * 4;
16855  l4100 = 2 + 4 + l4110 + l4160 + l4120;
16856  l4000 = 2 + 4 + ( name_length + 1 ) + l4100;
16857  l0100 = 2 + 4 + 4;
16858  l3d3e = 2 + 4 + 4;
16859  l3d3d = 2 + 4 + l3d3e + l0100 + l4000;
16860 
16861  lb022 = 2 + 4 + 32;
16862  lb021 = 2 + 4 + 9 * 4;
16863  lb020 = 2 + 4 + 8 * 4;
16864  lb013 = 2 + 4 + 6 * 2;
16865  lb010 = 2 + 4 + ( name_length + 1 ) + 3 * 2;
16866  lb030 = 2 + 4 + 2;
16867  lb002 = 2 + 4 + lb030 + lb010 + lb013 + lb020 + lb021 + lb022;
16868  lb009 = 2 + 4 + 4;
16869  lb008 = 2 + 4 + 2 * 4;
16870  lb00a = 2 + 4 + 2 + 9 + 2 * 2;
16871  lb000 = 2 + 4 + lb00a + lb008 + lb009 + lb002;
16872 
16873  l4d4d = 2 + 4 + l0002 + l3d3d + lb000;
16874 //
16875 // M3DMAGIC begin.
16876 // tag, size.
16877 //
16878  short_int_val = ( short ) 0x4d4d;
16879  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16880  bytes_num = bytes_num + long_int_write ( fileout, l4d4d );
16881 //
16882 // M3D_VERSION begin.
16883 // tag, size, version.
16884 //
16885  short_int_val = ( short ) 0x0002;
16886  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16887  bytes_num = bytes_num + long_int_write ( fileout, l0002 );
16888  long_int_val = 3;
16889  bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
16890 //
16891 // M3D_VERSION end.
16892 // MDATA begin.
16893 // tag, size.
16894 //
16895  short_int_val = ( short ) 0x3d3d;
16896  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16897  bytes_num = bytes_num + long_int_write ( fileout, l3d3d );
16898 //
16899 // MESH_VERSION begin.
16900 // tag, size, version.
16901 //
16902  short_int_val = ( short ) 0x3d3e;
16903  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16904  bytes_num = bytes_num + long_int_write ( fileout, l3d3e );
16905  long_int_val = 3;
16906  bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
16907 //
16908 // MESH_VERSION end.
16909 // MASTER_SCALE begin.
16910 // tag, size, scale.
16911 //
16912  short_int_val = ( short ) 0x0100;
16913  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16914  bytes_num = bytes_num + long_int_write ( fileout, l0100 );
16915  float_val = 1.0;
16916  bytes_num = bytes_num + float_write ( fileout, float_val );
16917 //
16918 // MASTER_SCALE end.
16919 // NAMED_OBJECT begin.
16920 // tag, size, name.
16921 //
16922  short_int_val = ( short ) 0x4000;
16923  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16924  bytes_num = bytes_num + long_int_write ( fileout, l4000 );
16926 //
16927 // N_TRI_OBJECT begin.
16928 // tag, size.
16929 //
16930  short_int_val = ( short ) 0x4100;
16931  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16932  bytes_num = bytes_num + long_int_write ( fileout, l4100 );
16933 //
16934 // POINT_ARRAY begin.
16935 // tag, size, number of points, coordinates of points.
16936 // Warning! number of points could exceed a short!
16937 //
16938  short_int_val = ( short ) 0x4110;
16939  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16940  bytes_num = bytes_num + long_int_write ( fileout, l4110 );
16941 
16942  u_short_int_val = ( unsigned short ) cor3_num;
16943  bytes_num = bytes_num + tds_write_u_short_int ( fileout, u_short_int_val );
16944 
16945  for ( icor3 = 0; icor3 < cor3_num; icor3++ )
16946  {
16947  for ( j = 0; j < 3; j++ )
16948  {
16949  bytes_num = bytes_num + float_write ( fileout, cor3[j][icor3] );
16950  }
16951  }
16952 //
16953 // POINT_ARRAY end.
16954 // MESH_MATRIX begin.
16955 // tag, size, 4 by 3 matrix.
16956 //
16957  short_int_val = ( short ) 0x4160;
16958  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16959  bytes_num = bytes_num + long_int_write ( fileout, l4160 );
16960 
16961  for ( i = 0; i < 4; i++ )
16962  {
16963  for ( j = 0; j < 3; j++ )
16964  {
16965  float_val = transform_matrix[i][j];
16966  bytes_num = bytes_num + float_write ( fileout, float_val );
16967  }
16968  }
16969 //
16970 // MESH_MATRIX end.
16971 // FACE_ARRAY begin.
16972 // tag, size, number of faces, nodes per face.
16973 // Warning: number of faces could exceed a short!
16974 //
16975  short_int_val = ( short ) 0x4120;
16976  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16977  bytes_num = bytes_num + long_int_write ( fileout, l4120 );
16978 
16979  u_short_int_val = ( unsigned short ) face_num;
16980  bytes_num = bytes_num + tds_write_u_short_int ( fileout, u_short_int_val );
16981 
16982  for ( iface = 0; iface < face_num; iface++ )
16983  {
16984  for ( j = 0; j < 3; j++ )
16985  {
16986  short_int_val = face[j][iface];
16987  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16988  }
16989  short_int_val = face_flags[iface];
16990  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16991  }
16992 //
16993 // SMOOTH_GROUP begin.
16994 // tag, size, group for each face.
16995 //
16996  short_int_val = ( short ) 0x4150;
16997  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
16998  bytes_num = bytes_num + long_int_write ( fileout, l4150 );
16999 
17000  for ( iface = 0; iface < face_num; iface++ )
17001  {
17002  long_int_val = face_smooth[iface];
17003  bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17004  }
17005 //
17006 // SMOOTH_GROUP end.
17007 // FACE_ARRAY end.
17008 // N_TRI_OBJECT end.
17009 // NAMED_OBJECT end.
17010 // MDATA end.
17011 // KFDATA begin.
17012 //
17013  short_int_val = ( short ) 0xb000;
17014  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17015  bytes_num = bytes_num + long_int_write ( fileout, lb000 );
17016 //
17017 // KFHDR begin.
17018 // tag, size, revision, filename, animlen.
17019 //
17020  short_int_val = ( short ) 0xb00a;
17021  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17022  bytes_num = bytes_num + long_int_write ( fileout, lb00a );
17023  short_int_val = 5;
17024  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17025  bytes_num = bytes_num + tds_write_string ( fileout, "MAXSCENE" );
17026  short_int_val = 100;
17027  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17028  short_int_val = 0;
17029  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17030 //
17031 // KFHDR end.
17032 // KFSEG begin.
17033 // tag, size, start, end.
17034 //
17035  short_int_val = ( short ) 0xb008;
17036  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17037  bytes_num = bytes_num + long_int_write ( fileout, lb008 );
17038  long_int_val = 0;
17039  bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17040  long_int_val = 100;
17041  bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17042 //
17043 // KFSEG end.
17044 // KFCURTIME begin.
17045 // tag, size, current_frame.
17046 //
17047  short_int_val = ( short ) 0xb009;
17048  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17049  bytes_num = bytes_num + long_int_write ( fileout, lb009 );
17050  long_int_val = 0;
17051  bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17052 //
17053 // KFCURTIME end.
17054 // OBJECT_NODE_TAG begin.
17055 // tag, size.
17056 //
17057  short_int_val = ( short ) 0xb002;
17058  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17059  bytes_num = bytes_num + long_int_write ( fileout, lb002 );
17060 //
17061 // NODE_ID begin.
17062 // tag, size, id.
17063 //
17064  short_int_val = ( short ) 0xb030;
17065  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17066  bytes_num = bytes_num + long_int_write ( fileout, lb030 );
17067  short_int_val = 0;
17068  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17069 //
17070 // NODE_ID end.
17071 // NODE_HDR begin.
17072 // tag, size, object_name, flag1, flag2, hierarchy.
17073 //
17074  short_int_val = ( short ) 0xb010;
17075  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17076  bytes_num = bytes_num + long_int_write ( fileout, lb010 );
17078  short_int_val = 16384;
17079  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17080  short_int_val = 0;
17081  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17082  short_int_val = -1;
17083  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17084 //
17085 // NODE_HDR end.
17086 // PIVOT begin.
17087 // tag, size, pivot_x, pivot_y, pivot_z.
17088 //
17089  short_int_val = ( short ) 0xb013;
17090  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17091  bytes_num = bytes_num + long_int_write ( fileout, lb013 );
17092  for ( i = 0; i < 3; i++ )
17093  {
17094  float_val = pivot[i];
17095  bytes_num = bytes_num + float_write ( fileout, float_val );
17096  }
17097 //
17098 // PIVOT end.
17099 // POS_TRACK_TAG begin.
17100 // tag, size, flag, i1, i2, i3, i4, i5, i6, frame, l1, pos_x, pos_y, pos_z.
17101 //
17102  short_int_val = ( short ) 0xb020;
17103  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17104  bytes_num = bytes_num + long_int_write ( fileout, lb020 );
17105  short_int_val = 0;
17106  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17107  short_int_val = 0;
17108  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17109  short_int_val = 0;
17110  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17111  short_int_val = 0;
17112  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17113  short_int_val = 0;
17114  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17115  short_int_val = 1;
17116  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17117  short_int_val = 0;
17118  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17119  short_int_val = 0;
17120  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17121  long_int_val = 0;
17122  bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17123  for ( i = 0; i < 3; i++ )
17124  {
17125  float_val = origin[i];
17126  bytes_num = bytes_num + float_write ( fileout, float_val );
17127  }
17128 //
17129 // POS_TRACK_TAG end.
17130 // ROT_TRACK_TAG begin.
17131 // tag, size, i1, i2, i3, i4, i5, i6, i7, i8, l1, rad, axis_x, axis_y, axis_z.
17132 //
17133  short_int_val = ( short ) 0xb021;
17134  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17135  bytes_num = bytes_num + long_int_write ( fileout, lb021 );
17136  short_int_val = 0;
17137  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17138  short_int_val = 0;
17139  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17140  short_int_val = 0;
17141  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17142  short_int_val = 0;
17143  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17144  short_int_val = 0;
17145  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17146  short_int_val = 1;
17147  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17148  short_int_val = 0;
17149  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17150  short_int_val = 0;
17151  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17152  long_int_val = 0;
17153  bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17154  float_val = 0.0;
17155  bytes_num = bytes_num + float_write ( fileout, float_val );
17156  bytes_num = bytes_num + float_write ( fileout, float_val );
17157  bytes_num = bytes_num + float_write ( fileout, float_val );
17158  bytes_num = bytes_num + float_write ( fileout, float_val );
17159 //
17160 // ROT_TRACK_TAG end.
17161 // SCL_TRACK_TAG begin.
17162 // tag, size, i1, i2, i3, i4, i5, i6, i7, i8, l1, scale_x, scale_y, scale_z.
17163 //
17164  short_int_val = ( short ) 0xb022;
17165  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17166  bytes_num = bytes_num + long_int_write ( fileout, lb022 );
17167  short_int_val = 0;
17168  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17169  short_int_val = 0;
17170  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17171  short_int_val = 0;
17172  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17173  short_int_val = 0;
17174  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17175  short_int_val = 0;
17176  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17177  short_int_val = 1;
17178  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17179  short_int_val = 0;
17180  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17181  short_int_val = 0;
17182  bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
17183  long_int_val = 0;
17184  bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
17185  float_val = 1.0;
17186  bytes_num = bytes_num + float_write ( fileout, float_val );
17187  bytes_num = bytes_num + float_write ( fileout, float_val );
17188  bytes_num = bytes_num + float_write ( fileout, float_val );
17189 //
17190 // SCL_TRACK_TAG end.
17191 // OBJECT_NODE_TAG end.
17192 // KFDATA end.
17193 // M3DMAGIC end.
17194 //
17195 
17196 //
17197 // Report.
17198 //
17199  cout << "\n";
17200  cout << "TDS_WRITE wrote " << bytes_num << " bytes.\n";
17201 
17202  return 0;
17203 }
17204 //****************************************************************************80
17205 
17206 int tds_write_string ( FILE *fileout, char *string )
17207 
17208 //****************************************************************************80
17209 //
17210 // Purpose:
17211 //
17212 // TDS_WRITE_STRING ???
17213 //
17214 // Licensing:
17215 //
17216 // This code is distributed under the GNU LGPL license.
17217 //
17218 // Modified:
17219 //
17220 // 23 September 1998
17221 //
17222 // Author:
17223 //
17224 // John Burkardt
17225 //
17226 {
17227  char *c;
17228  int nchar;
17229 
17230  nchar = 0;
17231 
17232  for ( c = string; nchar < 12; c++ )
17233  {
17234  fputc ( *c, fileout );
17235  nchar = nchar + 1;
17236 
17237  if ( *c == 0 )
17238  {
17239  return nchar;
17240  }
17241 
17242  }
17243 
17244  return nchar;
17245 }
17246 //****************************************************************************80
17247 
17248 int tds_write_u_short_int ( FILE *fileout, unsigned short int short_int_val )
17249 
17250 //****************************************************************************80
17251 //
17252 // Purpose:
17253 //
17254 // TDS_WRITE_U_SHORT_INT ???
17255 //
17256 // Licensing:
17257 //
17258 // This code is distributed under the GNU LGPL license.
17259 //
17260 // Modified:
17261 //
17262 // 14 October 1998
17263 //
17264 // Author:
17265 //
17266 // John Burkardt
17267 //
17268 {
17269  union {
17270  unsigned short int yint;
17271  char ychar[2];
17272  } y;
17273 
17274  y.yint = short_int_val;
17275 
17276  if ( byte_swap )
17277  {
17278  fputc ( y.ychar[1], fileout );
17279  fputc ( y.ychar[0], fileout );
17280  }
17281  else
17282  {
17283  fputc ( y.ychar[0], fileout );
17284  fputc ( y.ychar[1], fileout );
17285  }
17286 
17287  return 2;
17288 }
17289 //****************************************************************************80
17290 
17291 int tec_write ( FILE *fileout )
17292 
17293 //****************************************************************************80
17294 //
17295 // Purpose:
17296 //
17297 // TEC_WRITE writes graphics information to a TECPLOT file.
17298 //
17299 // Discussion:
17300 //
17301 // The file format used is appropriate for 3D finite element surface
17302 // zone data. Polygons are decomposed into triangles where necessary.
17303 //
17304 // Example:
17305 //
17306 // TITLE = "cube.tec created by IVCON."
17307 // VARIABLES = "X", "Y", "Z", "R", "G", "B"
17308 // ZONE T="TRIANGLES", N=8, E=12, F=FEPOINT, ET=TRIANGLE
17309 // 0.0 0.0 0.0 0.0 0.0 0.0
17310 // 1.0 0.0 0.0 1.0 0.0 0.0
17311 // 1.0 1.0 0.0 1.0 1.0 0.0
17312 // 0.0 1.0 0.0 0.0 1.0 0.0
17313 // 0.0 0.0 1.0 0.0 0.0 1.0
17314 // 1.0 0.0 1.0 1.0 0.0 1.0
17315 // 1.0 1.0 1.0 1.0 1.0 1.0
17316 // 0.0 1.0 1.0 0.0 1.0 1.0
17317 // 1 4 2
17318 // 2 4 3
17319 // 1 5 8
17320 // 1 2 5
17321 // 2 6 5
17322 // 2 3 6
17323 // 3 7 6
17324 // 3 4 7
17325 // 4 8 7
17326 // 4 1 8
17327 // 5 6 8
17328 // 6 7 8
17329 //
17330 // Licensing:
17331 //
17332 // This code is distributed under the GNU LGPL license.
17333 //
17334 // Modified:
17335 //
17336 // 09 June 1999
17337 //
17338 // Author:
17339 //
17340 // John Burkardt
17341 //
17342 {
17343  float b;
17344  int face2[3];
17345  float g;
17346  int icor3;
17347  int iface;
17348  int imat;
17349  int j;
17350  int face_num2;
17351  int text_num;
17352  float r;
17353 //
17354 // Determine the number of triangular faces.
17355 //
17356  face_num2 = 0;
17357  for ( iface = 0; iface < face_num; iface++ )
17358  {
17359  for ( j = 0; j < face_order[iface] - 2; j++ )
17360  {
17361  face_num2 = face_num2 + 1;
17362  }
17363  }
17364 
17365  text_num = 0;
17366 
17367  fprintf ( fileout, "TITLE = \"%s created by IVCON.\"\n", fileout_name );
17368  fprintf ( fileout, "VARIABLES = \"X\", \"Y\", \"Z\", \"R\", \"G\", \"B\"\n" );
17369  fprintf ( fileout,
17370  "ZONE T=\"TRIANGLES\", N=%d, E=%d, F=FEPOINT, ET=TRIANGLE\n",
17371  cor3_num, face_num2 );
17372 
17373  text_num = text_num + 3;
17374 //
17375 // Write out X, Y, Z, R, G, B per node.
17376 //
17377  for ( icor3 = 0; icor3 < cor3_num; icor3++ )
17378  {
17379  imat = cor3_material[icor3];
17380  r = material_rgba[0][imat];
17381  g = material_rgba[1][imat];
17382  b = material_rgba[2][imat];
17383  fprintf ( fileout, "%f %f %f %f %f %f\n", cor3[0][icor3], cor3[1][icor3],
17384  cor3[2][icor3], r, g, b );
17385  text_num = text_num + 1;
17386  }
17387 //
17388 // Do the next face.
17389 //
17390  for ( iface = 0; iface < face_num; iface++ )
17391  {
17392 //
17393 // Break the face up into triangles, anchored at node 1.
17394 //
17395  for ( j = 0; j < face_order[iface] - 2; j++ )
17396  {
17397  face2[0] = face[ 0][iface] + 1;
17398  face2[1] = face[j+1][iface] + 1;
17399  face2[2] = face[j+2][iface] + 1;
17400 
17401  fprintf ( fileout, "%d %d %d\n", face2[0], face2[1], face2[2] );
17402  text_num = text_num + 1;
17403 
17404  }
17405 
17406  }
17407 //
17408 // Report.
17409 //
17410  cout << "\n";
17411  cout << "TEC_WRITE - Wrote " << text_num << " text lines.\n";
17412 
17413  return 0;
17414 }
17415 //****************************************************************************80
17416 
17417 void tmat_init ( float a[4][4] )
17418 
17419 //****************************************************************************80
17420 //
17421 // Purpose:
17422 //
17423 // TMAT_INIT initializes the geometric transformation matrix.
17424 //
17425 // Discussion:
17426 //
17427 // The geometric transformation matrix can be thought of as a 4 by 4
17428 // matrix "A" having components:
17429 //
17430 // r11 r12 r13 t1
17431 // r21 r22 r23 t2
17432 // r31 r32 r33 t3
17433 // 0 0 0 1
17434 //
17435 // This matrix encodes the rotations, scalings and translations that
17436 // are applied to graphical objects.
17437 //
17438 // A point P = (x,y,z) is rewritten in "homogeneous coordinates" as
17439 // PH = (x,y,z,1). Then to apply the transformations encoded in A to
17440 // the point P, we simply compute A * PH.
17441 //
17442 // Individual transformations, such as a scaling, can be represented
17443 // by simple versions of the transformation matrix. If the matrix
17444 // A represents the current set of transformations, and we wish to
17445 // apply a new transformation B, { the original points are
17446 // transformed twice: B * ( A * PH ). The new transformation B can
17447 // be combined with the original one A, to give a single matrix C that
17448 // encodes both transformations: C = B * A.
17449 //
17450 // Licensing:
17451 //
17452 // This code is distributed under the GNU LGPL license.
17453 //
17454 // Modified:
17455 //
17456 // 19 October 1998
17457 //
17458 // Author:
17459 //
17460 // John Burkardt
17461 //
17462 // Reference:
17463 //
17464 // Foley, van Dam, Feiner, Hughes,
17465 // Computer Graphics, Principles and Practice,
17466 // Addison Wesley, Second Edition, 1990.
17467 //
17468 // Parameters:
17469 //
17470 // Input, float A[4][4], the geometric transformation matrix.
17471 //
17472 {
17473  int i;
17474  int j;
17475 
17476  for ( i = 0; i < 4; i++ )
17477  {
17478  for ( j = 0; j < 4; j++ )
17479  {
17480  if ( i == j )
17481  {
17482  a[i][j] = 1.0;
17483  }
17484  else
17485  {
17486  a[i][j] = 0.0;
17487  }
17488  }
17489  }
17490  return;
17491 }
17492 //****************************************************************************80
17493 
17494 void tmat_mxm ( float a[4][4], float b[4][4], float c[4][4] )
17495 
17496 //****************************************************************************80
17497 //
17498 // Purpose:
17499 //
17500 // TMAT_MXM multiplies two geometric transformation matrices.
17501 //
17502 // Discussion:
17503 //
17504 // The product is accumulated in a temporary array, and { assigned
17505 // to the result. Therefore, it is legal for any two, or all three,
17506 // of the arguments to share memory.
17507 //
17508 // Licensing:
17509 //
17510 // This code is distributed under the GNU LGPL license.
17511 //
17512 // Modified:
17513 //
17514 // 19 October 1998
17515 //
17516 // Author:
17517 //
17518 // John Burkardt
17519 //
17520 // Reference:
17521 //
17522 // Foley, van Dam, Feiner, Hughes,
17523 // Computer Graphics, Principles and Practice,
17524 // Addison Wesley, Second Edition, 1990.
17525 //
17526 // Parameters:
17527 //
17528 // Input, float A[4][4], the first geometric transformation matrix.
17529 //
17530 // Input, float B[4][4], the second geometric transformation matrix.
17531 //
17532 // Output, float C[4][4], the product A * B.
17533 //
17534 {
17535  float d[4][4];
17536  int i;
17537  int j;
17538  int k;
17539 
17540  for ( i = 0; i < 4; i++ )
17541  {
17542  for ( k = 0; k < 4; k++ )
17543  {
17544  d[i][k] = 0.0;
17545  for ( j = 0; j < 4; j++ )
17546  {
17547  d[i][k] = d[i][k] + a[i][j] * b[j][k];
17548  }
17549  }
17550  }
17551 
17552  for ( i = 0; i < 4; i++ )
17553  {
17554  for ( j = 0; j < 4; j++ )
17555  {
17556  c[i][j] = d[i][j];
17557  }
17558  }
17559  return;
17560 }
17561 //****************************************************************************80
17562 
17563 void tmat_mxp ( float a[4][4], float x[4], float y[4] )
17564 
17565 //****************************************************************************80
17566 //
17567 // Purpose:
17568 //
17569 // TMAT_MXP multiplies a geometric transformation matrix times a point.
17570 //
17571 // Licensing:
17572 //
17573 // This code is distributed under the GNU LGPL license.
17574 //
17575 // Modified:
17576 //
17577 // 19 October 1998
17578 //
17579 // Author:
17580 //
17581 // John Burkardt
17582 //
17583 // Reference:
17584 //
17585 // Foley, van Dam, Feiner, Hughes,
17586 // Computer Graphics, Principles and Practice,
17587 // Addison Wesley, Second Edition, 1990.
17588 //
17589 // Parameters:
17590 //
17591 // Input, float A[4][4], the geometric transformation matrix.
17592 //
17593 // Input, float X[4], the point to be multiplied. The fourth component
17594 // of X is implicitly assigned the value of 1.
17595 //
17596 // Output, float Y[4], the result of A*X. The product is accumulated in
17597 // a temporary vector, and { assigned to the result. Therefore, it
17598 // is legal for X and Y to share memory.
17599 //
17600 {
17601  int i;
17602  int j;
17603  float z[4];
17604 
17605  for ( i = 0; i < 3; i++ )
17606  {
17607  z[i] = a[i][3];
17608  for ( j = 0; j < 3; j++ )
17609  {
17610  z[i] = z[i] + a[i][j] * x[j];
17611  }
17612  }
17613 
17614  for ( i = 0; i < 3; i++ )
17615  {
17616  y[i] = z[i];
17617  }
17618  return;
17619 }
17620 //****************************************************************************80
17621 
17622 void tmat_mxp2 ( float a[4][4], float x[][3], float y[][3], int n )
17623 
17624 //****************************************************************************80
17625 //
17626 // Purpose:
17627 //
17628 // TMAT_MXP2 multiplies a geometric transformation matrix times N points.
17629 //
17630 // Licensing:
17631 //
17632 // This code is distributed under the GNU LGPL license.
17633 //
17634 // Modified:
17635 //
17636 // 20 October 1998
17637 //
17638 // Author:
17639 //
17640 // John Burkardt
17641 //
17642 // Reference:
17643 //
17644 // Foley, van Dam, Feiner, Hughes,
17645 // Computer Graphics, Principles and Practice,
17646 // Addison Wesley, Second Edition, 1990.
17647 //
17648 // Parameters:
17649 //
17650 // Input, float A[4][4], the geometric transformation matrix.
17651 //
17652 // Input, float X[N][3], the points to be multiplied.
17653 //
17654 // Output, float Y[N][3], the transformed points. Each product is
17655 // accumulated in a temporary vector, and { assigned to the
17656 // result. Therefore, it is legal for X and Y to share memory.
17657 //
17658 //
17659 {
17660  int i;
17661  int j;
17662  int k;
17663  float z[4];
17664 
17665  for ( k = 0; k < n; k++ )
17666  {
17667  for ( i = 0; i < 3; i++ )
17668  {
17669  z[i] = a[i][3];
17670  for ( j = 0; j < 3; j++ )
17671  {
17672  z[i] = z[i] + a[i][j] * x[k][j];
17673  }
17674  }
17675 
17676  for ( i = 0; i < 3; i++ )
17677  {
17678  y[k][i] = z[i];
17679  }
17680 
17681  }
17682  return;
17683 }
17684 //****************************************************************************80
17685 
17686 void tmat_mxv ( float a[4][4], float x[4], float y[4] )
17687 
17688 //****************************************************************************80
17689 //
17690 // Purpose:
17691 //
17692 // TMAT_MXV multiplies a geometric transformation matrix times a vector.
17693 //
17694 // Licensing:
17695 //
17696 // This code is distributed under the GNU LGPL license.
17697 //
17698 // Modified:
17699 //
17700 // 12 August 1999
17701 //
17702 // Author:
17703 //
17704 // John Burkardt
17705 //
17706 // Reference:
17707 //
17708 // Foley, van Dam, Feiner, Hughes,
17709 // Computer Graphics, Principles and Practice,
17710 // Addison Wesley, Second Edition, 1990.
17711 //
17712 // Parameters:
17713 //
17714 // Input, float A[4][4], the geometric transformation matrix.
17715 //
17716 // Input, float X[3], the vector to be multiplied. The fourth component
17717 // of X is implicitly assigned the value of 1.
17718 //
17719 // Output, float Y[3], the result of A*X. The product is accumulated in
17720 // a temporary vector, and assigned to the result. Therefore, it
17721 // is legal for X and Y to share memory.
17722 //
17723 {
17724  int i;
17725  int j;
17726  float z[4];
17727 
17728  for ( i = 0; i < 3; i++ )
17729  {
17730  z[i] = 0.0;
17731  for ( j = 0; j < 3; j++ )
17732  {
17733  z[i] = z[i] + a[i][j] * x[j];
17734  }
17735  z[i] = z[i] + a[i][3];
17736  }
17737 
17738  for ( i = 0; i < 3; i++ )
17739  {
17740  y[i] = z[i];
17741  }
17742  return;
17743 }
17744 //****************************************************************************80
17745 
17746 void tmat_rot_axis ( float a[4][4], float b[4][4], float angle,
17747  char axis )
17748 
17749 //****************************************************************************80
17750 //
17751 // Purpose:
17752 //
17753 // TMAT_ROT_AXIS applies an axis rotation to the geometric transformation matrix.
17754 //
17755 // Licensing:
17756 //
17757 // This code is distributed under the GNU LGPL license.
17758 //
17759 // Modified:
17760 //
17761 // 19 April 1999
17762 //
17763 // Author:
17764 //
17765 // John Burkardt
17766 //
17767 // Reference:
17768 //
17769 // Foley, van Dam, Feiner, Hughes,
17770 // Computer Graphics, Principles and Practice,
17771 // Addison Wesley, Second Edition, 1990.
17772 //
17773 // Parameters:
17774 //
17775 // Input, float A[4][4], the current geometric transformation matrix.
17776 //
17777 // Output, float B[4][4], the modified geometric transformation matrix.
17778 // A and B may share the same memory.
17779 //
17780 // Input, float ANGLE, the angle, in degrees, of the rotation.
17781 //
17782 // Input, character AXIS, is 'X', 'Y' or 'Z', specifying the coordinate
17783 // axis about which the rotation occurs.
17784 //
17785 {
17786  float c[4][4];
17787  float d[4][4];
17788  int i;
17789  int j;
17790  float theta;
17791 
17792  theta = angle * DEG_TO_RAD;
17793 
17794  tmat_init ( c );
17795 
17796  if ( axis == 'X' || axis == 'x' )
17797  {
17798  c[1][1] = cos ( theta );
17799  c[1][2] = - sin ( theta );
17800  c[2][1] = sin ( theta );
17801  c[2][2] = cos ( theta );
17802  }
17803  else if ( axis == 'Y' || axis == 'y' )
17804  {
17805  c[0][0] = cos ( theta );
17806  c[0][2] = sin ( theta );
17807  c[2][0] = - sin ( theta );
17808  c[2][2] = cos ( theta );
17809  }
17810  else if ( axis == 'Z' || axis == 'z' )
17811  {
17812  c[0][0] = cos ( theta );
17813  c[0][1] = - sin ( theta );
17814  c[1][0] = sin ( theta );
17815  c[1][1] = cos ( theta );
17816  }
17817  else
17818  {
17819  cout << "\n";
17820  cout << "TMAT_ROT_AXIS - Fatal error!\n";
17821  cout << " Illegal rotation axis: " << axis << ".\n";
17822  cout << " Legal choices are 'X', 'Y', or 'Z'.\n";
17823  return;
17824  }
17825 
17826  tmat_mxm ( c, a, d );
17827 
17828  for ( i = 0; i < 4; i++ )
17829  {
17830  for ( j = 0; j < 4; j++ )
17831  {
17832  b[i][j] = d[i][j];
17833  }
17834  }
17835  return;
17836 }
17837 //****************************************************************************80
17838 
17839 void tmat_rot_vector ( float a[4][4], float b[4][4], float angle,
17840  float v1, float v2, float v3 )
17841 
17842 //****************************************************************************80
17843 //
17844 // Purpose:
17845 //
17846 // TMAT_ROT_VECTOR applies a rotation about a vector to the geometric transformation matrix.
17847 //
17848 // Licensing:
17849 //
17850 // This code is distributed under the GNU LGPL license.
17851 //
17852 // Modified:
17853 //
17854 // 27 July 1999
17855 //
17856 // Author:
17857 //
17858 // John Burkardt
17859 //
17860 // Reference:
17861 //
17862 // Foley, van Dam, Feiner, Hughes,
17863 // Computer Graphics, Principles and Practice,
17864 // Addison Wesley, Second Edition, 1990.
17865 //
17866 // Parameters:
17867 //
17868 // Input, float A[4][4], the current geometric transformation matrix.
17869 //
17870 // Output, float B[4][4], the modified geometric transformation matrix.
17871 // A and B may share the same memory.
17872 //
17873 // Input, float ANGLE, the angle, in degrees, of the rotation.
17874 //
17875 // Input, float V1, V2, V3, the X, Y and Z coordinates of a (nonzero)
17876 // point defining a vector from the origin. The rotation will occur
17877 // about this axis.
17878 //
17879 {
17880  float c[4][4];
17881  float ca;
17882  float d[4][4];
17883  int i;
17884  int j;
17885  float sa;
17886  float theta;
17887 
17888  if ( v1 * v1 + v2 * v2 + v3 * v3 == 0.0 )
17889  {
17890  return;
17891  }
17892 
17893  theta = angle * DEG_TO_RAD;
17894 
17895  tmat_init ( c );
17896 
17897  ca = cos ( theta );
17898  sa = sin ( theta );
17899 
17900  c[0][0] = v1 * v1 + ca * ( 1.0 - v1 * v1 );
17901  c[0][1] = ( 1.0 - ca ) * v1 * v2 - sa * v3;
17902  c[0][2] = ( 1.0 - ca ) * v1 * v3 + sa * v2;
17903 
17904  c[1][0] = ( 1.0 - ca ) * v2 * v1 + sa * v3;
17905  c[1][1] = v2 * v2 + ca * ( 1.0 - v2 * v2 );
17906  c[1][2] = ( 1.0 - ca ) * v2 * v3 - sa * v1;
17907 
17908  c[2][0] = ( 1.0 - ca ) * v3 * v1 - sa * v2;
17909  c[2][1] = ( 1.0 - ca ) * v3 * v2 + sa * v1;
17910  c[2][2] = v3 * v3 + ca * ( 1.0 - v3 * v3 );
17911 
17912  tmat_mxm ( c, a, d );
17913 
17914  for ( i = 0; i < 4; i++ )
17915  {
17916  for ( j = 0; j < 4; j++ )
17917  {
17918  b[i][j] = d[i][j];
17919  }
17920  }
17921  return;
17922 }
17923 //****************************************************************************80
17924 
17925 void tmat_scale ( float a[4][4], float b[4][4], float sx, float sy,
17926  float sz )
17927 
17928 //****************************************************************************80
17929 //
17930 // Purpose:
17931 //
17932 // TMAT_SCALE applies a scaling to the geometric transformation matrix.
17933 //
17934 // Licensing:
17935 //
17936 // This code is distributed under the GNU LGPL license.
17937 //
17938 // Modified:
17939 //
17940 // 19 October 1998
17941 //
17942 // Author:
17943 //
17944 // John Burkardt
17945 //
17946 // Reference:
17947 //
17948 // Foley, van Dam, Feiner, Hughes,
17949 // Computer Graphics, Principles and Practice,
17950 // Addison Wesley, Second Edition, 1990.
17951 //
17952 // Parameters:
17953 //
17954 // Input, float A[4][4], the current geometric transformation matrix.
17955 //
17956 // Output, float B[4][4], the modified geometric transformation matrix.
17957 // A and B may share the same memory.
17958 //
17959 // Input, float SX, SY, SZ, the scalings to be applied to the X, Y and
17960 // Z coordinates.
17961 //
17962 {
17963  float c[4][4];
17964  float d[4][4];
17965  int i;
17966  int j;
17967 
17968  tmat_init ( c );
17969 
17970  c[0][0] = sx;
17971  c[1][1] = sy;
17972  c[2][2] = sz;
17973 
17974  tmat_mxm ( c, a, d );
17975 
17976  for ( i = 0; i < 4; i++ )
17977  {
17978  for ( j = 0; j < 4; j++ )
17979  {
17980  b[i][j] = d[i][j];
17981  }
17982  }
17983  return;
17984 }
17985 //****************************************************************************80
17986 
17987 void tmat_shear ( float a[4][4], float b[4][4], char *axis, float s )
17988 
17989 //****************************************************************************80
17990 //
17991 // Purpose:
17992 //
17993 // TMAT_SHEAR applies a shear to the geometric transformation matrix.
17994 //
17995 // Licensing:
17996 //
17997 // This code is distributed under the GNU LGPL license.
17998 //
17999 // Modified:
18000 //
18001 // 19 October 1998
18002 //
18003 // Author:
18004 //
18005 // John Burkardt
18006 //
18007 // Reference:
18008 //
18009 // Foley, van Dam, Feiner, Hughes,
18010 // Computer Graphics, Principles and Practice,
18011 // Addison Wesley, Second Edition, 1990.
18012 //
18013 // Parameters:
18014 //
18015 // Input, float A[4][4], the current geometric transformation matrix.
18016 //
18017 // Output, float B[4][4], the modified geometric transformation matrix.
18018 // A and B may share the same memory.
18019 //
18020 // Input, character*3 AXIS, is 'XY', 'XZ', 'YX', 'YZ', 'ZX' or 'ZY',
18021 // specifying the shear equation:
18022 //
18023 // XY: x' = x + s * y;
18024 // XZ: x' = x + s * z;
18025 // YX: y' = y + s * x;
18026 // YZ: y' = y + s * z;
18027 // ZX: z' = z + s * x;
18028 // ZY: z' = z + s * y.
18029 //
18030 // Input, float S, the shear coefficient.
18031 //
18032 {
18033  float c[4][4];
18034  float d[4][4];
18035  int i;
18036  int j;
18037 
18038  tmat_init ( c );
18039 
18040  if ( strcmp ( axis, "XY" ) == 0 || strcmp ( axis, "xy" ) == 0 )
18041  {
18042  c[0][1] = s;
18043  }
18044  else if ( strcmp ( axis, "XZ" ) == 0 || strcmp ( axis, "xz" ) == 0 )
18045  {
18046  c[0][2] = s;
18047  }
18048  else if ( strcmp ( axis, "YX" ) == 0 || strcmp ( axis, "yx" ) == 0 )
18049  {
18050  c[1][0] = s;
18051  }
18052  else if ( strcmp ( axis, "YZ" ) == 0 || strcmp ( axis, "yz" ) == 0 )
18053  {
18054  c[1][2] = s;
18055  }
18056  else if ( strcmp ( axis, "ZX" ) == 0 || strcmp ( axis, "zx" ) == 0 )
18057  {
18058  c[2][0] = s;
18059  }
18060  else if ( strcmp ( axis, "ZY" ) == 0 || strcmp ( axis, "zy" ) == 0 )
18061  {
18062  c[2][1] = s;
18063  }
18064  else
18065  {
18066  cout << "\n";
18067  cout << "TMAT_SHEAR - Fatal error!\n";
18068  cout << " Illegal shear axis: " << axis << ".\n";
18069  cout << " Legal choices are XY, XZ, YX, YZ, ZX, or ZY.\n";
18070  return;
18071  }
18072 
18073  tmat_mxm ( c, a, d );
18074 
18075  for ( i = 0; i < 4; i++ )
18076  {
18077  for ( j = 0; j < 4; j++ )
18078  {
18079  b[i][j] = d[i][j];
18080  }
18081  }
18082  return;
18083 }
18084 //****************************************************************************80
18085 
18086 void tmat_trans ( float a[4][4], float b[4][4], float x, float y,
18087  float z )
18088 
18089 //****************************************************************************80
18090 //
18091 // Purpose:
18092 //
18093 // TMAT_TRANS applies a translation to the geometric transformation matrix.
18094 //
18095 // Licensing:
18096 //
18097 // This code is distributed under the GNU LGPL license.
18098 //
18099 // Modified:
18100 //
18101 // 19 October 1998
18102 //
18103 // Author:
18104 //
18105 // John Burkardt
18106 //
18107 // Reference:
18108 //
18109 // Foley, van Dam, Feiner, Hughes,
18110 // Computer Graphics, Principles and Practice,
18111 // Addison Wesley, Second Edition, 1990.
18112 //
18113 // Parameters:
18114 //
18115 // Input, float A[4][4], the current geometric transformation matrix.
18116 //
18117 // Output, float B[4][4], the modified transformation matrix.
18118 // A and B may share the same memory.
18119 //
18120 // Input, float X, Y, Z, the translation. This may be thought of as the
18121 // point that the origin moves to under the translation.
18122 //
18123 {
18124  int i;
18125  int j;
18126 
18127  for ( i = 0; i < 4; i++ )
18128  {
18129  for ( j = 0; j < 4; j++ )
18130  {
18131  b[i][j] = a[i][j];
18132  }
18133  }
18134  b[0][3] = b[0][3] + x;
18135  b[1][3] = b[1][3] + y;
18136  b[2][3] = b[2][3] + z;
18137 
18138  return;
18139 }
18140 //****************************************************************************80
18141 
18142 int tria_read ( FILE *filein )
18143 
18144 //****************************************************************************80
18145 //
18146 // Purpose:
18147 //
18148 // TRIA_READ reads an ASCII triangle file.
18149 //
18150 // Example:
18151 //
18152 // 12 <-- Number of triangles
18153 //
18154 // (x,y,z) and (nx,ny,nz) of normal vector at:
18155 //
18156 // 0.0 0.0 0.0 0.3 0.3 0.3 node 1 of triangle 1.
18157 // 1.0 0.0 0.0 0.3 0.1 0.3 node 2 of triangle 1,
18158 // 0.0 1.0 0.0 0.3 0.1 0.3 node 3 of triangle 1,
18159 // 1.0 0.5 0.0 0.3 0.1 0.3 node 1 of triangle 2,
18160 // ...
18161 // 0.0 0.5 0.5 0.3 0.1 0.3 node 3 of triangle 12.
18162 //
18163 // Licensing:
18164 //
18165 // This code is distributed under the GNU LGPL license.
18166 //
18167 // Modified:
18168 //
18169 // 22 June 1999
18170 //
18171 // Author:
18172 //
18173 // John Burkardt
18174 //
18175 {
18176  float cvec[3];
18177  int icor3;
18178  int iface;
18179  int iface_hi;
18180  int iface_lo;
18181  int ivert;
18182  int face_num2;
18183  float r1;
18184  float r2;
18185  float r3;
18186  float r4;
18187  float r5;
18188  float r6;
18189 //
18190 // Get the number of triangles.
18191 //
18192  fgets ( input, LINE_MAX_LEN, filein );
18193  text_num = text_num + 1;
18194  sscanf ( input, "%d", &face_num2 );
18195 //
18196 // For each triangle:
18197 //
18198  iface_lo = face_num;
18199  iface_hi = face_num + face_num2;
18200 
18201  for ( iface = iface_lo; iface < iface_hi; iface++ )
18202  {
18203  if ( iface < FACE_MAX )
18204  {
18205  face_order[iface] = 3;
18206  face_material[iface] = 0;
18207  }
18208 //
18209 // For each face:
18210 //
18211  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
18212  {
18213  fgets ( input, LINE_MAX_LEN, filein );
18214  text_num = text_num + 1;
18215  sscanf ( input, "%e %e %e %e %e %e", &r1, &r2, &r3, &r4, &r5, &r6 );
18216 
18217  cvec[0] = r1;
18218  cvec[1] = r2;
18219  cvec[2] = r3;
18220 
18221  if ( cor3_num < 1000 )
18222  {
18223  icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
18224  }
18225  else
18226  {
18227  icor3 = -1;
18228  }
18229 
18230  if ( icor3 == -1 )
18231  {
18232  icor3 = cor3_num;
18233  if ( cor3_num < COR3_MAX )
18234  {
18235  cor3[0][cor3_num] = cvec[0];
18236  cor3[1][cor3_num] = cvec[1];
18237  cor3[2][cor3_num] = cvec[2];
18238  }
18239  cor3_num = cor3_num + 1;
18240  }
18241  else
18242  {
18243  dup_num = dup_num + 1;
18244  }
18245 
18246  if ( iface < FACE_MAX )
18247  {
18248  face[ivert][iface] = icor3;
18249  vertex_material[ivert][iface] = 0;
18250  vertex_normal[0][ivert][iface] = r4;
18251  vertex_normal[1][ivert][iface] = r5;
18252  vertex_normal[2][ivert][iface] = r6;
18253  }
18254 
18255  }
18256  }
18257  face_num = face_num + face_num2;
18258 
18259  return 0;
18260 }
18261 //****************************************************************************80
18262 
18263 int tria_write ( FILE *fileout )
18264 
18265 //****************************************************************************80
18266 //
18267 // Purpose:
18268 //
18269 // TRIA_WRITE writes the graphics data to an ASCII "triangle" file.
18270 //
18271 // Discussion:
18272 //
18273 // This is just a private format that Greg Hood requested from me.
18274 //
18275 // Example:
18276 //
18277 // 12 <-- Number of triangles
18278 //
18279 // (x,y,z) and (nx,ny,nz) of normal vector at:
18280 //
18281 // 0.0 0.0 0.0 0.3 0.3 0.3 node 1 of triangle 1.
18282 // 1.0 0.0 0.0 0.3 0.1 0.3 node 2 of triangle 1,
18283 // 0.0 1.0 0.0 0.3 0.1 0.3 node 3 of triangle 1,
18284 // 1.0 0.5 0.0 0.3 0.1 0.3 node 1 of triangle 2,
18285 // ...
18286 // 0.0 0.5 0.5 0.3 0.1 0.3 node 3 of triangle 12.
18287 //
18288 // Licensing:
18289 //
18290 // This code is distributed under the GNU LGPL license.
18291 //
18292 // Modified:
18293 //
18294 // 10 June 1999
18295 //
18296 // Author:
18297 //
18298 // John Burkardt
18299 //
18300 {
18301  int face2[3];
18302  int icor3;
18303  int iface;
18304  int jlo;
18305  int k;
18306  int face_num2;
18307  int text_num;
18308  float nx;
18309  float ny;
18310  float nz;
18311  float x;
18312  float y;
18313  float z;
18314 
18315  text_num = 0;
18316 //
18317 // Determine the number of triangular faces.
18318 //
18319  face_num2 = 0;
18320  for ( iface = 0; iface < face_num; iface++ )
18321  {
18322  for ( jlo = 0; jlo < face_order[iface] - 2; jlo++ )
18323  {
18324  face_num2 = face_num2 + 1;
18325  }
18326  }
18327 
18328  fprintf ( fileout, "%d\n", face_num2 );
18329  text_num = text_num + 1;
18330 //
18331 // Do the next face.
18332 //
18333  for ( iface = 0; iface < face_num; iface++ )
18334  {
18335 //
18336 // Break the face up into triangles, anchored at node 1.
18337 //
18338  for ( jlo = 0; jlo < face_order[iface] - 2; jlo++ )
18339  {
18340  face2[0] = face[ 0][iface];
18341  face2[1] = face[jlo+1][iface];
18342  face2[2] = face[jlo+2][iface];
18343 
18344  for ( k = 0; k < 3; k++ )
18345  {
18346  icor3 = face2[k];
18347 
18348  x = cor3[0][icor3];
18349  y = cor3[1][icor3];
18350  z = cor3[2][icor3];
18351 
18352  nx = cor3_normal[0][icor3];
18353  ny = cor3_normal[1][icor3];
18354  nz = cor3_normal[2][icor3];
18355 
18356  fprintf ( fileout, "%f %f %f %f %f %f\n", x, y, z, nx, ny, nz );
18357 
18358  text_num = text_num + 1;
18359 
18360  }
18361 
18362  }
18363 
18364  }
18365 //
18366 // Report.
18367 //
18368  cout << "\n";
18369  cout << "TRIA_WRITE - Wrote " << text_num << " text lines.\n";
18370 
18371  return 0;
18372 }
18373 //****************************************************************************80
18374 
18375 int trib_read ( FILE *filein )
18376 
18377 //****************************************************************************80
18378 //
18379 // Purpose:
18380 //
18381 // TRIB_READ reads a binary triangle file.
18382 //
18383 // Example:
18384 //
18385 // 4 byte int = number of triangles
18386 //
18387 // For each triangular face:
18388 //
18389 // 3 4-byte floats = coordinates of first node;
18390 // 3 4-byte floats = components of normal vector at first node;
18391 // 3 4-byte floats = coordinates of second node;
18392 // 3 4-byte floats = components of normal vector at second node;
18393 // 3 4-byte floats = coordinates of third node;
18394 // 3 4-byte floats = components of normal vector at third node.
18395 //
18396 // Licensing:
18397 //
18398 // This code is distributed under the GNU LGPL license.
18399 //
18400 // Modified:
18401 //
18402 // 22 June 1999
18403 //
18404 // Author:
18405 //
18406 // John Burkardt
18407 //
18408 {
18409  float cvec[3];
18410  int icor3;
18411  int i;
18412  int iface;
18413  int iface_hi;
18414  int iface_lo;
18415  int ivert;
18416  int face_num2;
18417 //
18418 // Read the number of triangles in the file.
18419 //
18420  face_num2 = long_int_read ( filein );
18421  bytes_num = bytes_num + 4;
18422 //
18423 // For each (triangular) face,
18424 // read the coordinates and normal vectors of three vertices,
18425 //
18426  iface_lo = face_num;
18427  iface_hi = face_num + face_num2;
18428 
18429  for ( iface = iface_lo; iface < iface_hi; iface++ )
18430  {
18431  if ( iface < FACE_MAX )
18432  {
18433  face_order[iface] = 3;
18434  face_material[iface] = 0;
18435  }
18436 
18437  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
18438  {
18439  for ( i = 0; i < 3; i++ )
18440  {
18441  cvec[i] = float_read ( filein );
18442  bytes_num = bytes_num + 4;
18443  }
18444 
18445  if ( cor3_num < 1000 )
18446  {
18447  icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
18448  }
18449  else
18450  {
18451  icor3 = -1;
18452  }
18453 
18454  if ( icor3 == -1 )
18455  {
18456  icor3 = cor3_num;
18457  if ( cor3_num < COR3_MAX )
18458  {
18459  cor3[0][cor3_num] = cvec[0];
18460  cor3[1][cor3_num] = cvec[1];
18461  cor3[2][cor3_num] = cvec[2];
18462  }
18463  cor3_num = cor3_num + 1;
18464  }
18465  else
18466  {
18467  dup_num = dup_num + 1;
18468  }
18469 
18470  if ( iface < FACE_MAX )
18471  {
18472  face[ivert][iface] = icor3;
18473  vertex_material[ivert][iface] = 0;
18474 
18475  for ( i = 0; i < 3; i++ )
18476  {
18477  vertex_normal[i][ivert][iface] = float_read ( filein );
18478  bytes_num = bytes_num + 4;
18479  }
18480 
18481  }
18482 
18483  }
18484  }
18485 
18486  face_num = face_num + face_num2;
18487 
18488  return 0;
18489 }
18490 //****************************************************************************80
18491 
18492 int trib_write ( FILE *fileout )
18493 
18494 //****************************************************************************80
18495 //
18496 // Purpose:
18497 //
18498 // TRIB_WRITE writes the graphics data to a binary "triangle" file.
18499 //
18500 // Discussion:
18501 //
18502 // This is just a private format that Greg Hood requested from me.
18503 //
18504 // Example:
18505 //
18506 // 12 Number of triangles
18507 // 0.0 x at node 1, triangle 1,
18508 // 0.0 y at node 1, triangle 1,
18509 // 0.0 z at node 1, triangle 1,
18510 // 0.3 nx at node 1, triangle 1,
18511 // 0.3 ny at node 1, triangle 1,
18512 // 0.3 nz at node 1, triangle 1.
18513 // 1.0 x at node 2, triangle 1,
18514 // ...
18515 // 0.7 nz at node 3, triangle 1.
18516 // 1.2 x at node 1, triangle 2,
18517 // ...
18518 // 0.3 nz at node 3, triangle 2.
18519 // 9.3 x at node 1, triangle 3,
18520 // ...
18521 // 0.3 nz at node 3, triangle 12.
18522 //
18523 // Licensing:
18524 //
18525 // This code is distributed under the GNU LGPL license.
18526 //
18527 // Modified:
18528 //
18529 // 16 June 1999
18530 //
18531 // Author:
18532 //
18533 // John Burkardt
18534 //
18535 {
18536  int face2[3];
18537  int icor3;
18538  int iface;
18539  int jlo;
18540  int k;
18541  int face_num2;
18542  float nx;
18543  float ny;
18544  float nz;
18545  float x;
18546  float y;
18547  float z;
18548 
18549  bytes_num = 0;
18550 //
18551 // Determine the number of triangular faces.
18552 //
18553  face_num2 = 0;
18554  for ( iface = 0; iface < face_num; iface++ )
18555  {
18556  for ( jlo = 0; jlo < face_order[iface] - 2; jlo++ )
18557  {
18558  face_num2 = face_num2 + 1;
18559  }
18560  }
18561 
18562  bytes_num = bytes_num + long_int_write ( fileout, face_num2 );
18563 //
18564 // Do the next face.
18565 //
18566  for ( iface = 0; iface < face_num; iface++ )
18567  {
18568 //
18569 // Break the face up into triangles, anchored at node 1.
18570 //
18571  for ( jlo = 0; jlo < face_order[iface] - 2; jlo ++ )
18572  {
18573  face2[0] = face[ 0][iface];
18574  face2[1] = face[jlo+1][iface];
18575  face2[2] = face[jlo+2][iface];
18576 
18577  for ( k = 0; k < 3; k++ )
18578  {
18579  icor3 = face2[k];
18580 
18581  x = cor3[0][icor3];
18582  y = cor3[1][icor3];
18583  z = cor3[2][icor3];
18584 
18585  nx = cor3_normal[0][icor3];
18586  ny = cor3_normal[1][icor3];
18587  nz = cor3_normal[2][icor3];
18588 
18589  bytes_num = bytes_num + float_write ( fileout, x );
18590  bytes_num = bytes_num + float_write ( fileout, y );
18591  bytes_num = bytes_num + float_write ( fileout, z );
18592  bytes_num = bytes_num + float_write ( fileout, nx );
18593  bytes_num = bytes_num + float_write ( fileout, ny );
18594  bytes_num = bytes_num + float_write ( fileout, nz );
18595 
18596  }
18597 
18598  }
18599 
18600  }
18601 //
18602 // Report.
18603 //
18604  cout << "\n";
18605  cout << "TRIB_WRITE - Wrote " << bytes_num << " bytes.\n";
18606 
18607  return 0;
18608 }
18609 //****************************************************************************80
18610 
18611 int txt_write ( FILE *fileout )
18612 
18613 //****************************************************************************80
18614 //
18615 // Purpose:
18616 //
18617 // TXT_WRITE writes the graphics data to a text file.
18618 //
18619 // Licensing:
18620 //
18621 // This code is distributed under the GNU LGPL license.
18622 //
18623 // Modified:
18624 //
18625 // 25 June 1998
18626 //
18627 // Author:
18628 //
18629 // John Burkardt
18630 //
18631 {
18632  int i;
18633  int iface;
18634  int iline;
18635  int imat;
18636  int ivert;
18637  int nitem;
18638  int text_num;
18639 
18640  text_num = 0;
18641 
18642  fprintf ( fileout, "%s created by IVCON.\n", fileout_name );
18643  fprintf ( fileout, "Original data in %s.\n", filein_name );
18644  fprintf ( fileout, "Object name is %s.\n", object_name );
18645  fprintf ( fileout, "Object origin at %f %f %f.\n", origin[0], origin[1],
18646  origin[2] );
18647  fprintf ( fileout, "Object pivot at %f %f %f.\n", pivot[0], pivot[1],
18648  pivot[2] );
18649  text_num = text_num + 5;
18650 //
18651 // TRANSFORMATION MATRIX.
18652 //
18653  fprintf ( fileout, "\n" );
18654  fprintf ( fileout, "Transformation matrix:\n" );
18655  fprintf ( fileout, "\n" );
18656  text_num = text_num + 3;
18657 
18658  for ( i = 0; i < 4; i++ )
18659  {
18660  fprintf ( fileout, " %f %f %f %f\n", transform_matrix[i][0],
18661  transform_matrix[i][1], transform_matrix[i][2], transform_matrix[i][3] );
18662  text_num = text_num + 1;
18663  }
18664 //
18665 // NODES.
18666 //
18667  fprintf ( fileout, "\n" );
18668  fprintf ( fileout, " %d nodes.\n", cor3_num );
18669  text_num = text_num + 2;
18670 
18671  if ( 0 < cor3_num )
18672  {
18673  fprintf ( fileout, "\n" );
18674  fprintf ( fileout, " Node coordinate data:\n" );
18675  fprintf ( fileout, "\n" );
18676  text_num = text_num + 3;
18677 
18678  for ( i = 0; i < cor3_num; i++ )
18679  {
18680  fprintf ( fileout, " %d %f %f %f\n ", i, cor3[0][i], cor3[1][i],
18681  cor3[2][i] );
18682  text_num = text_num + 1;
18683  }
18684 
18685  fprintf ( fileout, "\n" );
18686  fprintf ( fileout, " Node normal vectors:\n" );
18687  fprintf ( fileout, "\n" );
18688  text_num = text_num + 3;
18689 
18690  for ( i = 0; i < cor3_num; i++ )
18691  {
18692  fprintf ( fileout, " %d %f %f %f\n ", i, cor3_normal[0][i],
18693  cor3_normal[1][i], cor3_normal[2][i] );
18694  text_num = text_num + 1;
18695  }
18696 
18697  fprintf ( fileout, "\n" );
18698  fprintf ( fileout, " Node materials:\n" );
18699  fprintf ( fileout, "\n" );
18700  text_num = text_num + 3;
18701 
18702  for ( i = 0; i < cor3_num; i++ )
18703  {
18704  fprintf ( fileout, " %d %d\n ", i, cor3_material[i] );
18705  text_num = text_num + 1;
18706  }
18707 
18708  if ( 0 < texture_num )
18709  {
18710  fprintf ( fileout, "\n" );
18711  fprintf ( fileout, " Node texture coordinates:\n" );
18712  fprintf ( fileout, "\n" );
18713  text_num = text_num + 3;
18714 
18715  for ( i = 0; i < cor3_num; i++ )
18716  {
18717  fprintf ( fileout, " %d %f %f\n ", i, cor3_tex_uv[0][i],
18718  cor3_tex_uv[1][i] );
18719  text_num = text_num + 1;
18720  }
18721  }
18722  }
18723 //
18724 // LINES.
18725 //
18726  fprintf ( fileout, "\n" );
18727  fprintf ( fileout, " %d line data items.\n", line_num );
18728  text_num = text_num + 2;
18729 
18730  if ( 0 < line_num )
18731  {
18732  fprintf ( fileout, "\n" );
18733  fprintf ( fileout, " Line index data:\n" );
18734  fprintf ( fileout, "\n" );
18735  text_num = text_num + 3;
18736 
18737  nitem = 0;
18738 
18739  for ( iline = 0; iline < line_num; iline++ )
18740  {
18741  fprintf ( fileout, " %d", line_dex[iline] );
18742  nitem = nitem + 1;
18743 
18744  if ( iline == line_num - 1 || line_dex[iline] == -1 || 10 <= nitem )
18745  {
18746  nitem = 0;
18747  fprintf ( fileout, "\n" );
18748  text_num = text_num + 1;
18749  }
18750 
18751  }
18752 
18753  fprintf ( fileout, "\n" );
18754  fprintf ( fileout, " Line materials:\n" );
18755  fprintf ( fileout, "\n" );
18756  text_num = text_num + 3;
18757 
18758  nitem = 0;
18759 
18760  for ( iline = 0; iline < line_num; iline++ )
18761  {
18762 
18763  fprintf ( fileout, " %d", line_material[iline] );
18764  nitem = nitem + 1;
18765 
18766  if ( iline == line_num - 1
18767  || line_material[iline] == -1 || 10 <= nitem )
18768  {
18769  nitem = 0;
18770  fprintf ( fileout, "\n" );
18771  text_num = text_num + 1;
18772  }
18773  }
18774 
18775  }
18776 //
18777 // COLOR DATA
18778 //
18779  fprintf ( fileout, "\n" );
18780  fprintf ( fileout, " %d colors.\n", color_num );
18781  text_num = text_num + 2;
18782 //
18783 // FACES.
18784 //
18785  fprintf ( fileout, "\n" );
18786  fprintf ( fileout, " %d faces.\n", face_num );
18787  text_num = text_num + 2;
18788 
18789  if ( 0 < face_num )
18790  {
18791 
18792  fprintf ( fileout, "\n" );
18793  fprintf ( fileout, " Face, Material, Number of vertices, Smoothing, Flags:\n" );
18794  fprintf ( fileout, "\n" );
18795  text_num = text_num + 3;
18796 
18797  for ( iface = 0; iface < face_num; iface++ )
18798  {
18799  fprintf ( fileout, " %d %d %d %d %d\n", iface, face_material[iface],
18800  face_order[iface], face_smooth[iface], face_flags[iface] );
18801  text_num = text_num + 1;
18802  }
18803 
18804  fprintf ( fileout, "\n" );
18805  fprintf ( fileout, " Face, Vertices\n" );
18806  fprintf ( fileout, "\n" );
18807  text_num = text_num + 3;
18808 
18809  for ( iface = 0; iface < face_num; iface++ )
18810  {
18811  fprintf ( fileout, "%d ", iface );
18812  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
18813  {
18814  fprintf ( fileout, " %d", face[ivert][iface] );
18815  }
18816 
18817  fprintf ( fileout, "\n" );
18818  text_num = text_num + 1;
18819  }
18820 
18821  fprintf ( fileout, "\n" );
18822  fprintf ( fileout, " Face normal vectors:\n" );
18823  fprintf ( fileout, "\n" );
18824  text_num = text_num + 3;
18825 
18826  for ( iface = 0; iface < face_num; iface++ )
18827  {
18828  fprintf ( fileout, " %d %f %f %f\n", iface, face_normal[0][iface],
18829  face_normal[1][iface], face_normal[2][iface] );
18830  text_num = text_num + 1;
18831  }
18832 
18833  if ( 0 < texture_num )
18834  {
18835  fprintf ( fileout, "\n" );
18836  fprintf ( fileout, " Face texture coordinates:\n" );
18837  fprintf ( fileout, "\n" );
18838  text_num = text_num + 3;
18839 
18840  for ( iface = 0; iface < face_num; iface++ )
18841  {
18842  fprintf ( fileout, " %d %f %f\n", iface, face_tex_uv[0][iface],
18843  face_tex_uv[1][iface] );
18844  text_num = text_num + 1;
18845  }
18846  }
18847  }
18848 //
18849 // VERTICES.
18850 //
18851  if ( 0 < face_num )
18852  {
18853  fprintf ( fileout, "\n" );
18854  fprintf ( fileout, "Vertex normal vectors:\n" );
18855  text_num = text_num + 2;
18856 
18857  for ( iface = 0; iface < face_num; iface++ )
18858  {
18859  fprintf ( fileout, "\n" );
18860  text_num = text_num + 1;
18861  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
18862  {
18863  fprintf ( fileout, " %d %d %f %f %f\n", iface, ivert,
18864  vertex_normal[0][ivert][iface], vertex_normal[1][ivert][iface],
18865  vertex_normal[2][ivert][iface] );
18866  text_num = text_num + 1;
18867  }
18868  }
18869 
18870  fprintf ( fileout, "\n" );
18871  fprintf ( fileout, "Vertex materials:\n" );
18872  fprintf ( fileout, "\n" );
18873  text_num = text_num + 3;
18874 
18875  for ( iface = 0; iface < face_num; iface++ )
18876  {
18877  fprintf ( fileout, "%d", iface );
18878  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
18879  {
18880  fprintf ( fileout, " %d", vertex_material[ivert][iface] );
18881  }
18882  fprintf ( fileout, "\n" );
18883  text_num = text_num + 1;
18884  }
18885 
18886  if ( 0 < texture_num )
18887  {
18888  fprintf ( fileout, "\n" );
18889  fprintf ( fileout, "Vertex UV texture coordinates:\n" );
18890  fprintf ( fileout, "\n" );
18891  text_num = text_num + 3;
18892 
18893  for ( iface = 0; iface < face_num; iface++ )
18894  {
18895  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
18896  {
18897  fprintf ( fileout, "%d %d %f %f\n", iface, ivert,
18898  vertex_tex_uv[0][ivert][iface], vertex_tex_uv[1][ivert][iface] );
18899  text_num = text_num + 1;
18900  }
18901  }
18902  }
18903  }
18904 //
18905 // MATERIALS.
18906 //
18907  fprintf ( fileout, "\n" );
18908  fprintf ( fileout, "%d materials.\n", material_num );
18909  fprintf ( fileout, "\n" );
18910  fprintf ( fileout, "Index Name R G B A\n" );
18911  fprintf ( fileout, "\n" );
18912 
18913  text_num = text_num + 5;
18914 
18915  for ( imat = 0; imat < material_num; imat++ )
18916  {
18917  fprintf ( fileout, "%d %s %f %f %f %f\n", imat, material_name[imat],
18918  material_rgba[0][imat], material_rgba[1][imat], material_rgba[2][imat],
18919  material_rgba[3][imat] );
18920  text_num = text_num + 1;
18921  }
18922 //
18923 // TEXTURES.
18924 //
18925  fprintf ( fileout, "\n" );
18926  fprintf ( fileout, "%d textures.\n", texture_num );
18927  text_num = text_num + 2;
18928 
18929  if ( 0 < texture_num )
18930  {
18931  fprintf ( fileout, "\n" );
18932  fprintf ( fileout, "Index Name\n" );
18933  fprintf ( fileout, "\n" );
18934  for ( i = 0; i < texture_num; i++ )
18935  {
18936  fprintf ( fileout, "%d %s\n", i, texture_name[i] );
18937  }
18938  text_num = text_num + 3;
18939  }
18940 //
18941 // Report.
18942 //
18943  cout << "\n";
18944  cout << "TXT_WRITE - Wrote " << text_num << " text lines.\n";
18945 
18946  return 0;
18947 }
18948 //****************************************************************************80
18949 
18950 int ucd_write ( FILE *fileout )
18951 
18952 //****************************************************************************80
18953 //
18954 // Purpose:
18955 //
18956 // UCD_WRITE writes graphics data to an AVS UCD file.
18957 //
18958 // Example:
18959 //
18960 // # cube.ucd created by IVREAD.
18961 // #
18962 // # Material RGB to hue map:
18963 // #
18964 // # material R G B Alpha Hue
18965 // #
18966 // # 0 0.94 0.70 0.15 1.000 0.116
18967 // # 1 0.24 0.70 0.85 1.000 0.541
18968 // # 2 0.24 0.00 0.85 1.000 0.666
18969 // #
18970 // # The node data is
18971 // # node # / material # / RGBA / Hue
18972 // #
18973 // 8 6 6 0 0
18974 // 0 0.0 0.0 0.0
18975 // 1 1.0 0.0 0.0
18976 // 2 1.0 1.0 0.0
18977 // 3 0.0 1.0 0.0
18978 // 4 0.0 0.0 1.0
18979 // 5 1.0 0.0 1.0
18980 // 6 1.0 1.0 1.0
18981 // 7 0.0 1.0 1.0
18982 // 0 0 quad 0 1 2 3
18983 // 1 0 quad 0 4 5 1
18984 // 2 0 quad 1 5 6 2
18985 // 3 0 quad 2 6 7 3
18986 // 4 0 quad 3 7 4 0
18987 // 5 0 quad 4 7 6 5
18988 // 3 1 4 1
18989 // material, 0...2
18990 // RGBA, 0-1/0-1/0-1/0-1
18991 // Hue, 0-1
18992 // 0 0 0.94 0.70 0.15 1.0 0.116
18993 // 1 0 0.94 0.70 0.15 1.0 0.116
18994 // 2 0 0.94 0.70 0.15 1.0 0.116
18995 // 3 0 0.94 0.70 0.15 1.0 0.116
18996 // 4 1 0.24 0.70 0.85 1.0 0.541
18997 // 5 1 0.24 0.70 0.85 1.0 0.541
18998 // 6 2 0.24 0.24 0.85 0.0 0.666
18999 // 7 2 0.24 0.24 0.85 0.0 0.666
19000 //
19001 // Licensing:
19002 //
19003 // This code is distributed under the GNU LGPL license.
19004 //
19005 // Modified:
19006 //
19007 // 22 May 1999
19008 //
19009 // Author:
19010 //
19011 // John Burkardt
19012 //
19013 //
19014 {
19015  float a;
19016  float b;
19017  float g;
19018  float h;
19019  int i;
19020  int imat;
19021  int j;
19022  int text_num;
19023  float r;
19024 
19025  text_num = 0;
19026 
19027  fprintf ( fileout, "# %s created by IVREAD.\n", fileout_name );
19028  fprintf ( fileout, "#\n" );
19029  fprintf ( fileout, "# Material RGB to Hue map:\n" );
19030  fprintf ( fileout, "#\n" );
19031  fprintf ( fileout, "# material R G B Alpha Hue\n" );
19032  fprintf ( fileout, "#\n" );
19033 
19034  text_num = text_num + 6;
19035 
19036  for ( j = 0; j < material_num; j++ )
19037  {
19038  r = material_rgba[0][j];
19039  g = material_rgba[1][j];
19040  b = material_rgba[2][j];
19041  a = material_rgba[3][j];
19042  h = rgb_to_hue ( r, g, b );
19043  fprintf ( fileout, "# %d %f %f %f %f %f\n", j, r, g, b, a, h );
19044  text_num = text_num + 1;
19045  }
19046 
19047  fprintf ( fileout, "#\n" );
19048  fprintf ( fileout, "# The node data is\n" );
19049  fprintf ( fileout, "# node # / material # / RGBA / Hue\n" );
19050  fprintf ( fileout, "#\n" );
19051  text_num = text_num + 4;
19052 
19053  fprintf ( fileout, "%d %d 6 0 0\n", cor3_num, face_num );
19054  text_num = text_num + 1;
19055 
19056  for ( j = 0; j < cor3_num; j++ )
19057  {
19058  fprintf ( fileout, "%d %f %f %f\n", j, cor3[0][j], cor3[1][j],
19059  cor3[2][j] );
19060  text_num = text_num + 1;
19061  }
19062 //
19063 // NOTE:
19064 // UCD only accepts triangles and quadrilaterals, not higher order
19065 // polygons. We would need to break polygons up to proceed.
19066 //
19067  for ( j = 0; j < face_num; j++ )
19068  {
19069  fprintf ( fileout, "%d %d", j, face_material[j] );
19070 
19071  if ( face_order[j] == 3 )
19072  {
19073  fprintf ( fileout, " tri" );
19074  }
19075  else if ( face_order[j] == 4 )
19076  {
19077  fprintf ( fileout, " quad" );
19078  }
19079  else
19080  {
19081  fprintf ( fileout, " ???" );
19082  }
19083 
19084  for ( i = 0; i < face_order[j]; i++ )
19085  {
19086  fprintf ( fileout, "%d", face[i][j] );
19087  }
19088  fprintf ( fileout, "\n" );
19089  text_num = text_num + 1;
19090 
19091  }
19092 
19093  fprintf ( fileout, "3 1 4 1\n" );
19094  fprintf ( fileout, "material, 0...%d\n", material_num - 1 );
19095  fprintf ( fileout, "RGBA, 0-1/0-1/0-1/0-1\n" );
19096  fprintf ( fileout, "Hue, 0-1\n" );
19097  text_num = text_num + 4;
19098 
19099  for ( j = 0; j < cor3_num; j++ )
19100  {
19101  imat = cor3_material[j];
19102  r = material_rgba[0][imat];
19103  g = material_rgba[1][imat];
19104  b = material_rgba[2][imat];
19105  a = material_rgba[3][imat];
19106  h = rgb_to_hue ( r, g, b );
19107 
19108  fprintf ( fileout, "%d %d %f %f %f %f %f\n", j, imat, r, g, b, a, h );
19109  text_num = text_num + 1;
19110  }
19111 //
19112 // Report.
19113 //
19114  cout << "\n";
19115  cout << "UCD_WRITE - Wrote " << text_num << " text lines.\n";
19116 
19117  return 0;
19118 }
19119 //****************************************************************************80
19120 
19122 
19123 //****************************************************************************80
19124 //
19125 // Purpose:
19126 //
19127 // VERTEX_NORMAL_SET recomputes the face vertex normal vectors.
19128 //
19129 // Licensing:
19130 //
19131 // This code is distributed under the GNU LGPL license.
19132 //
19133 // Modified:
19134 //
19135 // 12 October 1998
19136 //
19137 // Author:
19138 //
19139 // John Burkardt
19140 //
19141 {
19142  int i;
19143  int i0;
19144  int i1;
19145  int i2;
19146  int iface;
19147  int ivert;
19148  int jp1;
19149  int jp2;
19150  int nfix;
19151  float norm;
19152  float temp;
19153  float x0;
19154  float x1;
19155  float x2;
19156  float xc;
19157  float y0;
19158  float y1;
19159  float y2;
19160  float yc;
19161  float z0;
19162  float z1;
19163  float z2;
19164  float zc;
19165 
19166  if ( face_num <= 0 )
19167  {
19168  return;
19169  }
19170 
19171  nfix = 0;
19172 //
19173 // Consider each face.
19174 //
19175  for ( iface = 0; iface < face_num; iface++ )
19176  {
19177  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
19178  {
19179  norm = 0.0;
19180  for ( i = 0; i < 3; i++ )
19181  {
19182  temp = vertex_normal[i][ivert][iface];
19183  norm = norm + temp * temp;
19184  }
19185  norm = ( float ) sqrt ( norm );
19186 
19187  if ( norm == 0.0 )
19188  {
19189  nfix = nfix + 1;
19190 
19191  i0 = face[ivert][iface];
19192  x0 = cor3[0][i0];
19193  y0 = cor3[1][i0];
19194  z0 = cor3[2][i0];
19195 
19196  jp1 = ivert + 1;
19197  if ( face_order[iface] <= jp1 )
19198  {
19199  jp1 = jp1 - face_order[iface];
19200  }
19201  i1 = face[jp1][iface];
19202  x1 = cor3[0][i1];
19203  y1 = cor3[1][i1];
19204  z1 = cor3[2][i1];
19205 
19206  jp2 = ivert + 2;
19207  if ( face_order[iface] <= jp2 )
19208  {
19209  jp2 = jp2 - face_order[iface];
19210  }
19211  i2 = face[jp2][iface];
19212  x2 = cor3[0][i2];
19213  y2 = cor3[1][i2];
19214  z2 = cor3[2][i2];
19215 
19216  xc = ( y1 - y0 ) * ( z2 - z0 ) - ( z1 - z0 ) * ( y2 - y0 );
19217  yc = ( z1 - z0 ) * ( x2 - x0 ) - ( x1 - x0 ) * ( z2 - z0 );
19218  zc = ( x1 - x0 ) * ( y2 - y0 ) - ( y1 - y0 ) * ( x2 - x0 );
19219 
19220  norm = ( float ) sqrt ( xc * xc + yc * yc + zc * zc );
19221 
19222  if ( norm == 0.0 )
19223  {
19224  xc = ( float ) 1.0 / sqrt ( 3.0 );
19225  yc = ( float ) 1.0 / sqrt ( 3.0 );
19226  zc = ( float ) 1.0 / sqrt ( 3.0 );
19227  }
19228  else
19229  {
19230  xc = xc / norm;
19231  yc = yc / norm;
19232  zc = zc / norm;
19233  }
19234 
19235  vertex_normal[0][ivert][iface] = xc;
19236  vertex_normal[1][ivert][iface] = yc;
19237  vertex_normal[2][ivert][iface] = zc;
19238 
19239  }
19240  }
19241  }
19242 
19243  if ( 0 < nfix )
19244  {
19245  cout << "\n";
19246  cout << "VERTEX_NORMAL_SET: Recomputed " << nfix
19247  << " face vertex normals.\n";
19248  }
19249 
19250  return;
19251 }
19252 //****************************************************************************80
19253 
19255 
19256 //****************************************************************************80
19257 //
19258 // Purpose:
19259 //
19260 // VERTEX_TO_FACE_MATERIAL extends vertex material definitions to faces.
19261 //
19262 // Discussion:
19263 //
19264 // Assuming material indices are defined for all the vertices, this
19265 // routine assigns to each face the material associated with its
19266 // first vertex.
19267 //
19268 // Licensing:
19269 //
19270 // This code is distributed under the GNU LGPL license.
19271 //
19272 // Modified:
19273 //
19274 // 22 May 1999
19275 //
19276 // Author:
19277 //
19278 // John Burkardt
19279 //
19280 {
19281  int iface;
19282  int ivert;
19283 
19284  ivert = 0;
19285  for ( iface = 0; iface < face_num; iface++ )
19286  {
19287  face_material[iface] = vertex_material[ivert][iface];
19288  }
19289 
19290  return;
19291 }
19292 //****************************************************************************80
19293 
19295 
19296 //****************************************************************************80
19297 //
19298 // Purpose:
19299 //
19300 // VERTEX_TO_NODE_MATERIAL extends vertex material definitions to nodes.
19301 //
19302 // Discussion:
19303 //
19304 // A NODE is a point in space.
19305 // A VERTEX is a node as used in a particular face.
19306 // One node may be used as a vertex in several faces, or none.
19307 // This routine simply runs through all the vertices, and assigns
19308 // the material of the vertex to the corresponding node. If a
19309 // node appears as a vertex several times, then the node will
19310 // end up having the material of the vertex that occurs "last".
19311 //
19312 // Licensing:
19313 //
19314 // This code is distributed under the GNU LGPL license.
19315 //
19316 // Modified:
19317 //
19318 // 22 May 1999
19319 //
19320 // Author:
19321 //
19322 // John Burkardt
19323 //
19324 {
19325  int iface;
19326  int ivert;
19327  int node;
19328 
19329  for ( iface = 0; iface < face_num; iface++ )
19330  {
19331  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
19332  {
19333  node = face[ivert][iface];
19334  cor3_material[node] = vertex_material[ivert][iface];
19335  }
19336  }
19337 
19338  return;
19339 }
19340 
19341 //****************************************************************************80
19342 
19343 int vla_read ( FILE *filein )
19344 
19345 //****************************************************************************80
19346 //
19347 // Purpose:
19348 //
19349 // VLA_READ reads a VLA file.
19350 //
19351 // Example:
19352 //
19353 // set comment cube.vla created by IVREAD
19354 // set comment Original data in cube.iv.
19355 // set comment
19356 // set intensity EXPLICIT
19357 // set parametric NON_PARAMETRIC
19358 // set filecontent LINES
19359 // set filetype NEW
19360 // set depthcue 0
19361 // set defaultdraw stellar
19362 // set coordsys RIGHT
19363 // set author IVREAD
19364 // set site Buhl Planetarium
19365 // set library_id UNKNOWN
19366 // P 8.59816 5.55317 -3.05561 1.00000
19367 // L 8.59816 2.49756 0.000000E+00 1.00000
19368 // L 8.59816 2.49756 -3.05561 1.00000
19369 // L 8.59816 5.55317 -3.05561 1.00000
19370 // P 8.59816 5.55317 0.000000E+00 1.00000
19371 // ...etc...
19372 // L 2.48695 2.49756 -3.05561 1.00000
19373 //
19374 // Licensing:
19375 //
19376 // This code is distributed under the GNU LGPL license.
19377 //
19378 // Modified:
19379 //
19380 // 23 May 1999
19381 //
19382 // Author:
19383 //
19384 // John Burkardt
19385 //
19386 {
19387  int i;
19388  int icor3;
19389  int dup_num;
19390  char *next;
19391  int text_num;
19392  float r1;
19393  float r2;
19394  float r3;
19395  float temp[3];
19396  char token[LINE_MAX_LEN];
19397  int width;
19398 //
19399 // Initialize.
19400 //
19401  dup_num = 0;
19402  text_num = 0;
19403 //
19404 // Read the next line of the file into INPUT.
19405 //
19406  while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL )
19407  {
19408  text_num = text_num + 1;
19409 //
19410 // Advance to the first nonspace character in INPUT.
19411 //
19412  for ( next = input; *next != '\0' && ch_is_space ( *next ); next++ )
19413  {
19414  }
19415 //
19416 // Skip blank lines and comments.
19417 //
19418  if ( *next == '\0' || *next == ';' )
19419  {
19420  continue;
19421  }
19422 //
19423 // Extract the first word in this line.
19424 //
19425  sscanf ( next, "%s%n", token, &width );
19426 //
19427 // Set NEXT to point to just after this token.
19428 //
19429  next = next + width;
19430 //
19431 // SET (ignore)
19432 //
19433  if ( s_eqi ( token, "set" ) )
19434  {
19435  }
19436 //
19437 // P (begin a line)
19438 // L (continue a line)
19439 //
19440  else if ( s_eqi ( token, "P" ) || s_eqi ( token, "L" ) )
19441  {
19442  if ( s_eqi ( token, "P" ) )
19443  {
19444  if ( 0 < line_num )
19445  {
19446  if ( line_num < LINES_MAX )
19447  {
19448  line_dex[line_num] = -1;
19449  line_material[line_num] = -1;
19450  line_num = line_num + 1;
19451  }
19452  }
19453  }
19454 
19455  sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
19456 
19457  temp[0] = r1;
19458  temp[1] = r2;
19459  temp[2] = r3;
19460 
19461  if ( cor3_num < 1000 )
19462  {
19463  icor3 = rcol_find ( cor3, 3, cor3_num, temp );
19464  }
19465  else
19466  {
19467  icor3 = -1;
19468  }
19469 
19470  if ( icor3 == -1 )
19471  {
19472  icor3 = cor3_num;
19473 
19474  if ( cor3_num < COR3_MAX )
19475  {
19476  for ( i = 0; i < 3; i++ )
19477  {
19478  cor3[i][cor3_num] = temp[i];
19479  }
19480  }
19481  cor3_num = cor3_num + 1;
19482  }
19483  else
19484  {
19485  dup_num = dup_num + 1;
19486  }
19487 
19488  if ( line_num < LINES_MAX )
19489  {
19490  line_dex[line_num] = icor3;
19491  line_material[line_num] = 0;
19492  line_num = line_num + 1;
19493  }
19494  }
19495 //
19496 // Unexpected or unrecognized.
19497 //
19498  else
19499  {
19500  cout << "\n";
19501  cout << "VLA_READ - Fatal error!\n";
19502  cout << " Unrecognized first word on line.\n";
19503  return 1;
19504  }
19505 
19506  }
19507 
19508  if ( 0 < line_num )
19509  {
19510  if ( line_num < LINES_MAX )
19511  {
19512  line_dex[line_num] = -1;
19513  line_material[line_num] = -1;
19514  line_num = line_num + 1;
19515  }
19516  }
19517 
19518  return 0;
19519 }
19520 //****************************************************************************80
19521 
19522 int vla_write ( FILE *fileout )
19523 
19524 //****************************************************************************80
19525 //
19526 // Purpose:
19527 //
19528 // VLA_WRITE writes internal graphics information to a VLA file.
19529 //
19530 // Discussion:
19531 //
19532 // Comments begin with a semicolon in column 1.
19533 // The X, Y, Z coordinates of points begin with a "P" to
19534 // denote the beginning of a line, and "L" to denote the
19535 // continuation of a line. The fourth entry is intensity, which
19536 // should be between 0.0 and 1.0.
19537 //
19538 // Example:
19539 //
19540 // set comment cube.vla created by IVREAD
19541 // set comment Original data in cube.iv.
19542 // set comment
19543 // set intensity EXPLICIT
19544 // set parametric NON_PARAMETRIC
19545 // set filecontent LINES
19546 // set filetype NEW
19547 // set depthcue 0
19548 // set defaultdraw stellar
19549 // set coordsys RIGHT
19550 // set author IVREAD
19551 // set site Buhl Planetarium
19552 // set library_id UNKNOWN
19553 // P 8.59816 5.55317 -3.05561 1.00000
19554 // L 8.59816 2.49756 0.000000E+00 1.00000
19555 // L 8.59816 2.49756 -3.05561 1.00000
19556 // L 8.59816 5.55317 -3.05561 1.00000
19557 // P 8.59816 5.55317 0.000000E+00 1.00000
19558 // ...etc...
19559 // L 2.48695 2.49756 -3.05561 1.00000
19560 //
19561 // Licensing:
19562 //
19563 // This code is distributed under the GNU LGPL license.
19564 //
19565 // Modified:
19566 //
19567 // 22 May 1999
19568 //
19569 // Author:
19570 //
19571 // John Burkardt
19572 //
19573 {
19574  char c;
19575  int iline;
19576  float intense = 1.0;
19577  int k;
19578  int text_num;
19579 //
19580 // Initialize.
19581 //
19582  text_num = 0;
19583 
19584  fprintf ( fileout, "set comment %s created by IVCON.\n", fileout_name );
19585  fprintf ( fileout, "set comment Original data in %s.\n", filein_name );
19586  fprintf ( fileout, "set comment\n" );
19587  fprintf ( fileout, "set intensity EXPLICIT\n" );
19588  fprintf ( fileout, "set parametric NON_PARAMETRIC\n" );
19589  fprintf ( fileout, "set filecontent LINES\n" );
19590  fprintf ( fileout, "set filetype NEW\n" );
19591  fprintf ( fileout, "set depthcue 0\n" );
19592  fprintf ( fileout, "set defaultdraw stellar\n" );
19593  fprintf ( fileout, "set coordsys RIGHT\n" );
19594  fprintf ( fileout, "set author IVCON\n" );
19595  fprintf ( fileout, "set site Buhl Planetarium\n" );
19596  fprintf ( fileout, "set library_id UNKNOWN\n" );
19597 
19598  text_num = text_num + 13;
19599 
19600  c = 'P';
19601 
19602  for ( iline = 0; iline < line_num; iline++ )
19603  {
19604 
19605  k = line_dex[iline];
19606 
19607  if ( k == -1 )
19608  {
19609  c = 'P';
19610  }
19611  else
19612  {
19613  fprintf ( fileout, "%c %f %f %f %f\n",
19614  c, cor3[0][k], cor3[1][k], cor3[2][k], intense );
19615 
19616  text_num = text_num + 1;
19617 
19618  c = 'L';
19619  }
19620  }
19621 //
19622 // Report.
19623 //
19624  cout << "\n";
19625  cout << "VLA_WRITE - Wrote " << text_num << " text lines.\n";
19626 
19627  return 0;
19628 }
19629 //****************************************************************************80
19630 
19631 int wrl_write ( FILE *fileout )
19632 
19633 //****************************************************************************80
19634 //
19635 // Purpose:
19636 //
19637 // WRL_WRITE writes graphics data to a WRL file.
19638 //
19639 // Example:
19640 //
19641 // #VRML V2.0 utf8
19642 //
19643 // WorldInfo {
19644 // title "cube.iv."
19645 // string "WRL file generated by IVREAD.
19646 // }
19647 //
19648 // Group {
19649 // children [
19650 //
19651 // Shape {
19652 //
19653 // appearance Appearance {
19654 // material Material {
19655 // diffuseColor 0.0 0.0 0.0
19656 // emissiveColor 0.0 0.0 0.0
19657 // shininess 1.0
19658 // }
19659 // } #end of appearance
19660 //
19661 // geometry IndexedLineSet {
19662 //
19663 // coord Coordinate {
19664 // point [
19665 // 8.59816 5.55317 -3.05561
19666 // 8.59816 2.49756 0.000000E+00
19667 // ...etc...
19668 // 2.48695 2.49756 -3.05561
19669 // ]
19670 // }
19671 //
19672 // coordIndex [
19673 // 0 1 2 -1 3 4 5 6 7 8 -
19674 // 9 10 -1 11 12 -1 13 14 15 -1 1
19675 // ...etc...
19676 // 191 -1
19677 // ]
19678 //
19679 // colorPerVertex TRUE
19680 //
19681 // colorIndex [
19682 // 0 0 0 -1 2 3 1 1 4 7 -
19683 // 10 9 -1 7 7 -1 3 2 2 -1 1
19684 // ...etc...
19685 // 180 -1
19686 // ]
19687 //
19688 // } #end of geometry
19689 //
19690 // } #end of Shape
19691 //
19692 // ] #end of children
19693 //
19694 // } #end of Group
19695 //
19696 // Licensing:
19697 //
19698 // This code is distributed under the GNU LGPL license.
19699 //
19700 // Modified:
19701 //
19702 // 23 May 1999
19703 //
19704 // Author:
19705 //
19706 // John Burkardt
19707 //
19708 {
19709  int icor3;
19710  int iface;
19711  int itemp;
19712  int ivert;
19713  int j;
19714  int length;
19715  int ndx;
19716 
19717  text_num = 0;
19718 
19719  fprintf ( fileout, "#VRML V2.0 utf8\n" );
19720  fprintf ( fileout, "\n" );
19721  fprintf ( fileout, " WorldInfo {\n" );
19722  fprintf ( fileout, " title \"%s\"\n", fileout_name );
19723  fprintf ( fileout, " info \"WRL file generated by IVREAD.\"\n" );
19724  fprintf ( fileout, " info \"Original data in %s\"\n", filein_name );
19725  fprintf ( fileout, " }\n" );
19726  fprintf ( fileout, "\n" );
19727  fprintf ( fileout, " Group {\n" );
19728  fprintf ( fileout, " children [\n" );
19729  fprintf ( fileout, " Shape {\n" );
19730  fprintf ( fileout, " appearance Appearance {\n" );
19731  fprintf ( fileout, " material Material {\n" );
19732  fprintf ( fileout, " diffuseColor 0.0 0.0 0.0\n" );
19733  fprintf ( fileout, " emissiveColor 0.0 0.0 0.0\n" );
19734  fprintf ( fileout, " shininess 1.0\n" );
19735  fprintf ( fileout, " }\n" );
19736  fprintf ( fileout, " }\n" );
19737 
19738  text_num = text_num + 18;
19739 //
19740 // IndexedLineSet
19741 //
19742  if ( 0 < line_num )
19743  {
19744  fprintf ( fileout, " geometry IndexedLineSet {\n" );
19745 //
19746 // IndexedLineSet coord
19747 //
19748  fprintf ( fileout, " coord Coordinate {\n" );
19749  fprintf ( fileout, " point [\n" );
19750 
19751  text_num = text_num + 3;
19752 
19753  for ( icor3 = 0; icor3 < cor3_num; icor3++ )
19754  {
19755  fprintf ( fileout, " %f %f %f\n", cor3[0][icor3],
19756  cor3[1][icor3], cor3[2][icor3] );
19757  text_num = text_num + 1;
19758  }
19759 
19760  fprintf ( fileout, " ]\n" );
19761  fprintf ( fileout, " }\n" );
19762  text_num = text_num + 2;
19763 //
19764 // IndexedLineSet coordIndex.
19765 //
19766  fprintf ( fileout, " coordIndex [\n" );
19767 
19768  text_num = text_num + 1;
19769 
19770  length = 0;
19771  for ( j = 0; j < line_num; j++ )
19772  {
19773  fprintf ( fileout, "%d ", line_dex[j] );
19774  length = length + 1;
19775  if ( line_dex[j] == -1 || 10 <= length || j == line_num - 1 )
19776  {
19777  fprintf ( fileout, "\n" );
19778  text_num = text_num + 1;
19779  length = 0;
19780  }
19781  }
19782 
19783  fprintf ( fileout, " ]\n" );
19784  text_num = text_num + 1;
19785 //
19786 // Colors. (materials)
19787 //
19788  fprintf ( fileout, " color Color {\n" );
19789  fprintf ( fileout, " color [\n" );
19790  text_num = text_num + 2;
19791 
19792  for ( j = 0; j < material_num; j++ )
19793  {
19794  fprintf ( fileout, " %f %f %f\n", material_rgba[0][j],
19795  material_rgba[1][j], material_rgba[2][j] );
19796  text_num = text_num + 1;
19797  }
19798 
19799  fprintf ( fileout, " ]\n" );
19800  fprintf ( fileout, " }\n" );
19801  fprintf ( fileout, " colorPerVertex TRUE\n" );
19802 //
19803 // IndexedLineset colorIndex
19804 //
19805  fprintf ( fileout, " colorIndex [\n" );
19806 
19807  text_num = text_num + 4;
19808 
19809  length = 0;
19810  for ( j = 0; j < line_num; j++ )
19811  {
19812  fprintf ( fileout, "%d ", line_material[j] );
19813  length = length + 1;
19814  if ( line_dex[j] == -1 || 10 <= length || j == line_num - 1 )
19815  {
19816  fprintf ( fileout, "\n" );
19817  text_num = text_num + 1;
19818  length = 0;
19819  }
19820  }
19821 
19822  fprintf ( fileout, " ]\n" );
19823  fprintf ( fileout, " }\n" );
19824  text_num = text_num + 2;
19825 
19826  }
19827 //
19828 // End of IndexedLineSet
19829 //
19830 // IndexedFaceSet
19831 //
19832  if ( 0 < face_num )
19833  {
19834 
19835  fprintf ( fileout, " geometry IndexedFaceSet {\n" );
19836 //
19837 // IndexedFaceSet coord
19838 //
19839  fprintf ( fileout, " coord Coordinate {\n" );
19840  fprintf ( fileout, " point [\n" );
19841 
19842  text_num = text_num + 3;
19843 
19844  for ( icor3 = 0; icor3 < cor3_num; icor3++ )
19845  {
19846  fprintf ( fileout, " %f %f %f\n", cor3[0][icor3],
19847  cor3[1][icor3], cor3[2][icor3] );
19848 
19849  text_num = text_num + 1;
19850  }
19851 
19852  fprintf ( fileout, " ]\n" );
19853  fprintf ( fileout, " }\n" );
19854 //
19855 // IndexedFaceSet coordIndex.
19856 //
19857  fprintf ( fileout, " coordIndex [\n" );
19858 
19859  text_num = text_num + 3;
19860 
19861  length = 0;
19862 
19863  for ( iface = 0; iface < face_num; iface++ )
19864  {
19865  for ( ivert = 0; ivert <= face_order[iface]; ivert++ )
19866  {
19867  if ( ivert <= face_order[iface] )
19868  {
19869  itemp = face[ivert][iface];
19870  }
19871  else
19872  {
19873  itemp = 0;
19874  }
19875 
19876  fprintf ( fileout, "%d ", itemp );
19877  length = length + 1;
19878 
19879  if ( itemp == -1 || 10 <= length ||
19880  ( iface == face_num - 1 && ivert == face_order[iface] ) )
19881  {
19882  fprintf ( fileout, "\n" );
19883  text_num = text_num + 1;
19884  length = 0;
19885  }
19886 
19887  }
19888 
19889  }
19890 
19891  fprintf ( fileout, " ]\n" );
19892  text_num = text_num + 1;
19893 //
19894 // IndexedFaceset colorIndex
19895 //
19896  fprintf ( fileout, " colorIndex [\n" );
19897  text_num = text_num + 1;
19898 
19899  length = 0;
19900  ndx = 0;
19901 
19902  for ( iface = 0; iface < face_num; iface++ )
19903  {
19904  for ( ivert = 0; ivert <= face_order[iface]; ivert++ )
19905  {
19906 
19907  if ( ivert <= face_order[iface] )
19908  {
19909  itemp = vertex_material[ivert][iface];
19910  ndx = ndx + 1;
19911  }
19912  else
19913  {
19914  itemp = 0;
19915  }
19916 
19917  fprintf ( fileout, "%d ", itemp );
19918  length = length + 1;
19919 
19920  if ( itemp == -1 || 10 <= length ||
19921  ( iface == face_num - 1 && ivert == face_order[iface] ) )
19922  {
19923 
19924  fprintf ( fileout, "\n" );
19925  text_num = text_num + 1;
19926  length = 0;
19927 
19928  }
19929 
19930  }
19931 
19932  }
19933 
19934  fprintf ( fileout, " ]\n" );
19935  fprintf ( fileout, " }\n" );
19936  text_num = text_num + 2;
19937 
19938  }
19939 //
19940 // End of IndexedFaceSet
19941 //
19942 // End of:
19943 // Shape
19944 // children
19945 // Group
19946 //
19947  fprintf ( fileout, " }\n" );
19948  fprintf ( fileout, " ]\n" );
19949  fprintf ( fileout, " }\n" );
19950 
19951  text_num = text_num + 3;
19952 //
19953 // Report.
19954 //
19955  cout << "\n";
19956  cout << "WRL_WRITE - Wrote " << text_num << " text lines.\n";
19957 
19958  return 0;
19959 }
19960 //****************************************************************************80
19961 
19962 int xgl_write ( FILE *fileout )
19963 
19964 //****************************************************************************80
19965 //
19966 // Purpose:
19967 //
19968 // XGL_WRITE writes an XGL file.
19969 //
19970 // Discussion:
19971 //
19972 // Two corrections to the routine were pointed out by
19973 // Mike Phillips, msphil AT widowmaker.com, on 17 September 2001,
19974 // and are gratefully acknowledged.
19975 //
19976 // Example:
19977 //
19978 // <WORLD>
19979 //
19980 // <BACKGROUND>
19981 // <BACKCOLOR> 0.1, 0.1, 0.1 </BACKCOLOR>
19982 // </BACKGROUND>
19983 //
19984 // <LIGHTING>
19985 // <AMBIENT> 0.2, 0.1, 0.1 </AMBIENT>
19986 // <DIRECTIONALLIGHT>
19987 // <DIFFUSE> 0.1, 0.2, 0.1 </DIFFUSE>
19988 // <DIRECTION> 0, 0, 100 </DIRECTION>
19989 // <SPECULAR> 0.1, 0.1, 0.2 </SPECULAR>
19990 // </DIRECTIONALLIGHT>
19991 // </LIGHTING>
19992 //
19993 // <MESH ID = "0">
19994 //
19995 // <P ID="0"> -0.5, -0.5, 1 </P>
19996 // <P ID="1"> 0.5, -0.5, 1 </P>
19997 // <P ID="2"> 0.5, 0.5, 1 </P>
19998 // <P ID="3"> -0.5, 0.5, 1 </P>
19999 // <P ID="4"> 0.5, -0.5, 0 </P>
20000 // <P ID="5"> -0.5, -0.5, 0 </P>
20001 // <P ID="6"> -0.5, 0.5, 0 </P>
20002 // <P ID="7"> 0.5, 0.5, 0 </P>
20003 //
20004 // <N ID="0"> -0.408248, -0.408248, 0.816497 </N>
20005 // <N ID="1"> 0.666667, -0.666667, 0.333333 </N>
20006 // <N ID="2"> 0.408248, 0.408248, 0.816497 </N>
20007 // <N ID="3"> -0.666667, 0.666667, 0.333333 </N>
20008 // <N ID="4"> 0.408248, -0.408248, -0.816497 </N>
20009 // <N ID="5"> -0.666667, -0.666667, -0.333333 </N>
20010 // <N ID="6"> -0.408248, 0.408248, -0.816497 </N>
20011 // <N ID="7"> 0.666667, 0.666667, -0.333333 </N>
20012 //
20013 // <MAT ID="0">
20014 // <ALPHA> 0.9 </ALPHA>
20015 // <AMB> 0.1, 0.1, 0.1 </AMB>
20016 // <DIFF> 0.2, 0.1, 0.1 </DIFF>
20017 // <EMISS> 0.1, 0.2, 0.1 </EMISS>
20018 // <SHINE> 0.8 </SHINE>
20019 // <SPEC> 0.1, 0.1, 0.2 </SPEC>
20020 // </MAT>
20021 //
20022 // <F>
20023 // <MATREF> 0 </MATREF>
20024 // <FV1><PREF> 0 </PREF><NREF> 0 </NREF></FV1>
20025 // <FV2><PREF> 1 </PREF><NREF> 1 </NREF></FV2>
20026 // <FV3><PREF> 2 </PREF><NREF> 2 </NREF></FV3>
20027 // </F>
20028 // <F>
20029 // <MATREF> 0 </MATREF>
20030 // <FV1><PREF> 0 </PREF><NREF> 0 </NREF></FV1>
20031 // <FV2><PREF> 2 </PREF><NREF> 2 </NREF></FV2>
20032 // <FV3><PREF> 3 </PREF><NREF> 3 </NREF></FV3>
20033 // </F>
20034 // <F>
20035 // <MATREF> 0 </MATREF>
20036 // <FV1><PREF> 4 </PREF><NREF> 4 </NREF></FV1>
20037 // <FV2><PREF> 5 </PREF><NREF> 5 </NREF></FV2>
20038 // <FV3><PREF> 6 </PREF><NREF> 6 </NREF></FV3>
20039 // </F>
20040 // <F>
20041 // <MATREF> 0 </MATREF>
20042 // <FV1><PREF> 4 </PREF><NREF> 4 </NREF></FV1>
20043 // <FV2><PREF> 6 </PREF><NREF> 6 </NREF></FV2>
20044 // <FV3><PREF> 7 </PREF><NREF> 7 </NREF></FV3>
20045 // </F>
20046 // <F>
20047 // <MATREF> 0 </MATREF>
20048 // <FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
20049 // <FV2><PREF> 0 </PREF><NREF> 0 </NREF></FV2>
20050 // <FV3><PREF> 3 </PREF><NREF> 3 </NREF></FV3>
20051 // </F>
20052 // <F>
20053 // <MATREF> 0 </MATREF>
20054 // <FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
20055 // <FV2><PREF> 3 </PREF><NREF> 3 </NREF></FV2>
20056 // <FV3><PREF> 6 </PREF><NREF> 6 </NREF></FV3>
20057 // </F>
20058 // <F>
20059 // <MATREF> 0 </MATREF>
20060 // <FV1><PREF> 1 </PREF><NREF> 1 </NREF></FV1>
20061 // <FV2><PREF> 4 </PREF><NREF> 4 </NREF></FV2>
20062 // <FV3><PREF> 7 </PREF><NREF> 7 </NREF></FV3>
20063 // </F>
20064 // <F>
20065 // <MATREF> 0 </MATREF>
20066 // <FV1><PREF> 1 </PREF><NREF> 1 </NREF></FV1>
20067 // <FV2><PREF> 7 </PREF><NREF> 7 </NREF></FV2>
20068 // <FV3><PREF> 2 </PREF><NREF> 2 </NREF></FV3>
20069 // </F>
20070 // <F>
20071 // <MATREF> 0 </MATREF>
20072 // <FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
20073 // <FV2><PREF> 4 </PREF><NREF> 4 </NREF></FV2>
20074 // <FV3><PREF> 1 </PREF><NREF> 1 </NREF></FV3>
20075 // </F>
20076 // <F>
20077 // <MATREF> 0 </MATREF>
20078 // <FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
20079 // <FV2><PREF> 1 </PREF><NREF> 1 </NREF></FV2>
20080 // <FV3><PREF> 0 </PREF><NREF> 0 </NREF></FV3>
20081 // </F>
20082 // <F>
20083 // <MATREF> 0 </MATREF>
20084 // <FV1><PREF> 3 </PREF><NREF> 3 </NREF></FV1>
20085 // <FV2><PREF> 2 </PREF><NREF> 2 </NREF></FV2>
20086 // <FV3><PREF> 7 </PREF><NREF> 7 </NREF></FV3>
20087 // </F>
20088 // <F>
20089 // <MATREF> 0 </MATREF>
20090 // <FV1><PREF> 3 </PREF><NREF> 3 </NREF></FV1>
20091 // <FV2><PREF> 7 </PREF><NREF> 7 </NREF></FV2>
20092 // <FV3><PREF> 6 </PREF><NREF> 6 </NREF></FV3>
20093 // </F>
20094 // </MESH>
20095 //
20096 // <OBJECT>
20097 // <TRANSFORM>
20098 // <FORWARD> 0, 0, 0 </FORWARD>
20099 // <POSITION> 0, 0, 0 </POSITION>
20100 // <SCALE> 1, 1, 1 </SCALE>
20101 // <UP> 1, 1, 1 </UP>
20102 // </TRANSFORM>
20103 // <MESHREF> 0 </MESHREF>
20104 // </OBJECT>
20105 //
20106 // </WORLD>
20107 //
20108 // Licensing:
20109 //
20110 // This code is distributed under the GNU LGPL license.
20111 //
20112 // Modified:
20113 //
20114 // 17 September 2001
20115 //
20116 // Author:
20117 //
20118 // John Burkardt
20119 //
20120 // Reference:
20121 //
20122 // XGL specification at http://www.xglspec.org/
20123 //
20124 {
20125  int iface;
20126  int ivert;
20127  int j;
20128  float light_ambient_rgb[3];
20129  float light_diffuse_rgb[3];
20130  float light_direction[3];
20131  float light_specular_rgb[3];
20132  int material;
20133  float material_alpha;
20134  float material_amb_rgb[3];
20135  float material_diff_rgb[3];
20136  float material_emiss_rgb[3];
20137  float material_shine;
20138  float material_spec_rgb[3];
20139  int mesh;
20140  int mesh_num = 1;
20141  int object;
20142  float transform_forward[3];
20143  float transform_position[3];
20144  float transform_scale[3];
20145  float transform_up[3];
20146 //
20147 // Make up some placeholder values for now.
20148 //
20149  light_ambient_rgb[0] = 0.2;
20150  light_ambient_rgb[1] = 0.1;
20151  light_ambient_rgb[2] = 0.1;
20152 
20153  light_diffuse_rgb[0] = 0.1;
20154  light_diffuse_rgb[1] = 0.2;
20155  light_diffuse_rgb[2] = 0.1;
20156 
20157  light_direction[0] = 0.0;
20158  light_direction[1] = 0.0;
20159  light_direction[2] = 100.0;
20160 
20161  light_specular_rgb[0] = 0.1;
20162  light_specular_rgb[1] = 0.1;
20163  light_specular_rgb[2] = 0.2;
20164 
20165  material_alpha = 0.9;
20166 
20167  material_amb_rgb[0] = 0.1;
20168  material_amb_rgb[1] = 0.1;
20169  material_amb_rgb[2] = 0.1;
20170 
20171  material_diff_rgb[0] = 0.2;
20172  material_diff_rgb[1] = 0.1;
20173  material_diff_rgb[2] = 0.1;
20174 
20175  material_emiss_rgb[0] = 0.1;
20176  material_emiss_rgb[1] = 0.2;
20177  material_emiss_rgb[2] = 0.1;
20178 
20179  material_shine = 0.8;
20180 
20181  material_spec_rgb[0] = 0.1;
20182  material_spec_rgb[1] = 0.1;
20183  material_spec_rgb[2] = 0.2;
20184 
20185  transform_forward[0] = 0.0;
20186  transform_forward[1] = 0.0;
20187  transform_forward[2] = 0.0;
20188 
20189  transform_position[0] = 0.0;
20190  transform_position[1] = 0.0;
20191  transform_position[2] = 0.0;
20192 
20193  transform_scale[0] = 1.0;
20194  transform_scale[1] = 1.0;
20195  transform_scale[2] = 1.0;
20196 
20197  transform_up[0] = 1.0;
20198  transform_up[1] = 1.0;
20199  transform_up[2] = 1.0;
20200 
20201  object_num = 1;
20202 
20203  text_num = 0;
20204 
20205  fprintf ( fileout, "<WORLD>\n" );
20206  fprintf ( fileout, "\n" );
20207 
20208  text_num = text_num + 2;
20209 
20210  fprintf ( fileout, " <BACKGROUND>\n" );
20211  fprintf ( fileout, " <BACKCOLOR> %f, %f, %f </BACKCOLOR>\n",
20213  fprintf ( fileout, " </BACKGROUND>\n" );
20214  fprintf ( fileout, "\n" );
20215  fprintf ( fileout, " <LIGHTING>\n" );
20216  fprintf ( fileout, " <AMBIENT> %f, %f, %f </AMBIENT>\n",
20217  light_ambient_rgb[0], light_ambient_rgb[1], light_ambient_rgb[2] );
20218  fprintf ( fileout, " <DIRECTIONALLIGHT>\n" );
20219  fprintf ( fileout, " <DIFFUSE> %f, %f, %f </DIFFUSE>\n",
20220  light_diffuse_rgb[0], light_diffuse_rgb[1], light_diffuse_rgb[2] );
20221  fprintf ( fileout, " <DIRECTION> %f, %f, %f </DIRECTION>\n",
20222  light_direction[0], light_direction[1], light_direction[2] );
20223  fprintf ( fileout, " <SPECULAR> %f, %f, %f </SPECULAR>\n",
20224  light_specular_rgb[0], light_specular_rgb[1], light_specular_rgb[2] );
20225  fprintf ( fileout, " </DIRECTIONALLIGHT>\n" );
20226  fprintf ( fileout, " </LIGHTING>\n" );
20227 
20228  text_num = text_num + 12;
20229 
20230  for ( mesh = 0; mesh < mesh_num; mesh++ )
20231  {
20232  fprintf ( fileout, "\n" );
20233  fprintf ( fileout, " <MESH ID = \"%d\">\n", mesh );
20234  fprintf ( fileout, "\n" );
20235  text_num = text_num + 3;
20236 
20237  for ( j = 0; j < cor3_num; j++ )
20238  {
20239  fprintf ( fileout, " <P ID=\"%d\"> %f, %f, %f </P>\n", j,
20240  cor3[0][j], cor3[1][j], cor3[2][j] );
20241  text_num = text_num + 1;
20242  }
20243 
20244  fprintf ( fileout, "\n" );
20245  text_num = text_num + 1;
20246  for ( j = 0; j < cor3_num; j++ )
20247  {
20248  fprintf ( fileout, " <N ID=\"%d\"> %f, %f, %f </N>\n", j,
20249  cor3_normal[0][j], cor3_normal[1][j], cor3_normal[2][j] );
20250  text_num = text_num + 1;
20251  }
20252 
20253  for ( material = 0; material < material_num; material++ )
20254  {
20255  fprintf ( fileout, "\n" );
20256  fprintf ( fileout, " <MAT ID=\"%d\">\n", material );
20257  fprintf ( fileout, " <ALPHA> %f </ALPHA>\n", material_alpha );
20258  fprintf ( fileout, " <AMB> %f, %f, %f </AMB>\n",
20259  material_amb_rgb[0], material_amb_rgb[1], material_amb_rgb[2] );
20260  fprintf ( fileout, " <DIFF> %f, %f, %f </DIFF>\n",
20261  material_diff_rgb[0], material_diff_rgb[1], material_diff_rgb[2] );
20262  fprintf ( fileout, " <EMISS> %f, %f, %f </EMISS>\n",
20263  material_emiss_rgb[0], material_emiss_rgb[1], material_emiss_rgb[2] );
20264  fprintf ( fileout, " <SHINE> %f </SHINE>\n", material_shine );
20265  fprintf ( fileout, " <SPEC> %f, %f, %f </SPEC>\n",
20266  material_spec_rgb[0], material_spec_rgb[1], material_spec_rgb[2] );
20267  fprintf ( fileout, " </MAT>\n" );
20268  text_num = text_num + 9;
20269  }
20270 
20271  fprintf ( fileout, "\n" );
20272  text_num = text_num + 1;
20273 
20274  for ( iface = 0; iface < face_num; iface++ )
20275  {
20276  fprintf ( fileout, " <F>\n" );
20277  fprintf ( fileout, " <MATREF> %d </MATREF>\n", face_material[iface] );
20278  text_num = text_num + 2;
20279  for ( ivert = 0; ivert < face_order[iface]; ivert++ )
20280  {
20281  fprintf ( fileout,
20282  " <FV%d><PREF> %d </PREF><NREF> %d </NREF></FV%d>\n",
20283  ivert+1, face[ivert][iface], face[ivert][iface], ivert+1 );
20284  text_num = text_num + 1;
20285  }
20286  fprintf ( fileout, " </F>\n" );
20287  text_num = text_num + 1;
20288  }
20289 
20290  fprintf ( fileout, " </MESH>\n" );
20291  text_num = text_num + 1;
20292 
20293  }
20294 
20295  fprintf ( fileout, "\n" );
20296  text_num = text_num + 1;
20297 
20298  for ( object = 0; object < object_num; object++ )
20299  {
20300  fprintf ( fileout, " <OBJECT>\n" );
20301  fprintf ( fileout, " <TRANSFORM>\n" );
20302  fprintf ( fileout, " <FORWARD> %f, %f, %f </FORWARD>\n",
20303  transform_forward[0], transform_forward[1], transform_forward[2] );
20304  fprintf ( fileout, " <POSITION> %f, %f, %f </POSITION>\n",
20305  transform_position[0], transform_position[1], transform_position[2] );
20306  fprintf ( fileout, "' <SCALE> %f, %f, %f </SCALE>\n",
20307  transform_scale[0], transform_scale[1], transform_scale[2] );
20308  fprintf ( fileout, " <UP> %f, %f, %f </UP>\n",
20309  transform_up[0], transform_up[1], transform_up[2] );
20310  fprintf ( fileout, " </TRANSFORM>\n" );
20311  mesh = 0;
20312  fprintf ( fileout, " <MESHREF> %d </MESHREF>\n", mesh );
20313  fprintf ( fileout, " </OBJECT>\n" );
20314  text_num = text_num + 9;
20315  }
20316 
20317  fprintf ( fileout, "\n" );
20318  fprintf ( fileout, "</WORLD>\n" );
20319  text_num = text_num + 2;
20320 
20321 //
20322 // Report.
20323 //
20324  cout << "\n";
20325  cout << "XGL_WRITE - Wrote " << text_num << " text lines.\n";
20326 
20327  return 0;
20328 }
int command_line(char **argv)
Definition: ivcon.cpp:2083
void data_check()
Definition: ivcon.cpp:2428
char object_name[81]
Definition: ivcon.cpp:195
int face[ORDER_MAX][FACE_MAX]
Definition: ivcon.cpp:156
unsigned short int tds_read_u_short_int(FILE *filein)
Definition: ivcon.cpp:16511
float face_tex_uv[2][FACE_MAX]
Definition: ivcon.cpp:165
int face_flags[FACE_MAX]
Definition: ivcon.cpp:158
void news()
Definition: ivcon.cpp:10495
unsigned long int tds_read_view_section(FILE *filein, int *views_read)
Definition: ivcon.cpp:16612
int ch_index_last(char *string, char c)
Definition: ivcon.cpp:1790
int ase_read(FILE *filein)
Definition: ivcon.cpp:414
int xgl_write(FILE *fileout)
Definition: ivcon.cpp:19962
unsigned long gmod_read_w32(FILE *filein)
Definition: ivcon.cpp:5581
void edge_null_delete()
Definition: ivcon.cpp:3994
#define G1_SECTION_MODEL_TEXTURE_NAMES
Definition: ivcon.cpp:46
char level_name[LEVEL_MAX][LINE_MAX_LEN]
Definition: ivcon.cpp:175
char fileout_name[81]
Definition: ivcon.cpp:168
int tds_write(FILE *fileout)
Definition: ivcon.cpp:16792
void face_null_delete()
Definition: ivcon.cpp:4358
void tmat_rot_axis(float a[4][4], float b[4][4], float angle, char axis)
Definition: ivcon.cpp:17746
unsigned long int tds_read_obj_section(FILE *filein)
Definition: ivcon.cpp:16017
unsigned long int tds_read_background_section(FILE *filein)
Definition: ivcon.cpp:14748
float s_to_r4(char *s, int *lchar, bool *error)
Definition: ivcon.cpp:12420
unsigned long int tds_read_keyframe_objdes_section(FILE *filein)
Definition: ivcon.cpp:15243
int color_num
Definition: ivcon.cpp:143
unsigned short gmod_read_w16(FILE *filein)
Definition: ivcon.cpp:5550
int smf_read(FILE *filein)
Definition: ivcon.cpp:12868
float cor3[3][COR3_MAX]
Definition: ivcon.cpp:146
void help()
Definition: ivcon.cpp:6053
#define GMOD_MAX_SECTIONS
Definition: ivcon.cpp:48
void tmat_scale(float a[4][4], float b[4][4], float sx, float sy, float sz)
Definition: ivcon.cpp:17925
void tmat_shear(float a[4][4], float b[4][4], char *axis, float s)
Definition: ivcon.cpp:17987
unsigned long int tds_read_unknown_section(FILE *filein)
Definition: ivcon.cpp:16584
int comment_num
Definition: ivcon.cpp:144
#define TEXTURE_MAX
Definition: ivcon.cpp:136
char material_name[MATERIAL_MAX][LINE_MAX_LEN]
Definition: ivcon.cpp:185
int float_write(FILE *fileout, float float_val)
Definition: ivcon.cpp:5061
int pov_write(FILE *fileout)
Definition: ivcon.cpp:11701
int bytes_num
Definition: ivcon.cpp:142
int dxf_write(FILE *fileout)
Definition: ivcon.cpp:3615
int stlb_write(FILE *fileout)
Definition: ivcon.cpp:14340
float gmod_read_float(FILE *filein)
Definition: ivcon.cpp:5502
char mat_name[81]
Definition: ivcon.cpp:189
short int short_int_read(FILE *filein)
Definition: ivcon.cpp:12791
char texture_name[TEXTURE_MAX][LINE_MAX_LEN]
Definition: ivcon.cpp:206
int material_num
Definition: ivcon.cpp:186
int trib_read(FILE *filein)
Definition: ivcon.cpp:18375
int i4_max(int i1, int i2)
Definition: ivcon.cpp:7515
float rgbcolor[3][COLOR_MAX]
Definition: ivcon.cpp:200
char ch_read(FILE *filein)
Definition: ivcon.cpp:1969
unsigned long int tds_read_texmap_section(FILE *filein)
Definition: ivcon.cpp:16438
int txt_write(FILE *fileout)
Definition: ivcon.cpp:18611
int line_prune
Definition: ivcon.cpp:180
char * file_ext(char *file_name)
Definition: ivcon.cpp:4939
int smf_write(FILE *fileout)
Definition: ivcon.cpp:13501
void face_normal_ave()
Definition: ivcon.cpp:4261
int stla_read(FILE *filein)
Definition: ivcon.cpp:13880
#define GMOD_UNUSED_VERTEX
Definition: ivcon.cpp:49
void sort_heap_external(int n, int *indx, int *i, int *j, int isgn)
Definition: ivcon.cpp:13714
int face_object[FACE_MAX]
Definition: ivcon.cpp:162
int obj_write(FILE *fileout)
Definition: ivcon.cpp:11198
int face_order[FACE_MAX]
Definition: ivcon.cpp:163
int stla_write(FILE *fileout)
Definition: ivcon.cpp:14092
int i
Definition: ivcon.cpp:172
int face_subset()
Definition: ivcon.cpp:4619
char ch_cap(char c)
Definition: ivcon.cpp:1709
int face_num
Definition: ivcon.cpp:161
#define COLOR_MAX
Definition: ivcon.cpp:128
unsigned long int tds_read_keyframe_section(FILE *filein, int *views_read)
Definition: ivcon.cpp:15154
#define LINE_MAX_LEN
Definition: ivcon.cpp:131
unsigned long int tds_read_material_section(FILE *filein)
Definition: ivcon.cpp:15678
float float_read(FILE *filein)
Definition: ivcon.cpp:4975
float texture_temp[2][ORDER_MAX *FACE_MAX]
Definition: ivcon.cpp:208
char material_binding[80]
Definition: ivcon.cpp:184
bool gmod_arch_check()
Definition: ivcon.cpp:5100
int object_num
Definition: ivcon.cpp:196
bool ch_eqi(char c1, char c2)
Definition: ivcon.cpp:1749
char anim_name[LINE_MAX_LEN]
Definition: ivcon.cpp:138
int obj_read(FILE *filein)
Definition: ivcon.cpp:10697
void face_reverse_order()
Definition: ivcon.cpp:4526
float vertex_normal[3][ORDER_MAX][FACE_MAX]
Definition: ivcon.cpp:213
int s_len_trim(char *s)
Definition: ivcon.cpp:12183
void face_to_line()
Definition: ivcon.cpp:4776
float cor3_tex_uv[3][COR3_MAX]
Definition: ivcon.cpp:150
int iv_read(FILE *filein)
Definition: ivcon.cpp:8217
void gmod_write_w32(unsigned long Val, FILE *fileout)
Definition: ivcon.cpp:5956
int hrc_write(FILE *fileout)
Definition: ivcon.cpp:7116
void cor3_normal_set()
Definition: ivcon.cpp:2242
int tds_read_name(FILE *filein)
Definition: ivcon.cpp:15968
int i4_modp(int i, int j)
Definition: ivcon.cpp:7593
void tmat_mxm(float a[4][4], float b[4][4], float c[4][4])
Definition: ivcon.cpp:17494
int i4vec_max(int n, int *a)
Definition: ivcon.cpp:10356
int k
Definition: ivcon.cpp:174
void tds_pre_process()
Definition: ivcon.cpp:14468
int off_write(FILE *fileout)
Definition: ivcon.cpp:11598
int hrc_read(FILE *filein)
Definition: ivcon.cpp:6098
int tds_read_long_name(FILE *filein)
Definition: ivcon.cpp:15584
void cor3_range()
Definition: ivcon.cpp:2325
int line_material[LINES_MAX]
Definition: ivcon.cpp:178
int s_to_i4(char *s, int *last, bool *error)
Definition: ivcon.cpp:12231
int line_num
Definition: ivcon.cpp:179
int ch_pad(int *char_index, int *null_index, char *s, int max_string)
Definition: ivcon.cpp:1904
int vla_write(FILE *fileout)
Definition: ivcon.cpp:19522
void data_init()
Definition: ivcon.cpp:2543
int ch_to_digit(char c)
Definition: ivcon.cpp:1998
bool s_to_r4vec(char *s, int n, float rvec[])
Definition: ivcon.cpp:12737
unsigned long int tds_read_spot_section(FILE *filein)
Definition: ivcon.cpp:16537
unsigned long int tds_read_object_section(FILE *filein)
Definition: ivcon.cpp:16279
unsigned long int tds_read_boolean(unsigned char *boolean, FILE *filein)
Definition: ivcon.cpp:14839
unsigned long int tds_read_camera_section(FILE *filein)
Definition: ivcon.cpp:14868
int tds_read(FILE *filein)
Definition: ivcon.cpp:14506
int i4_wrap(int ival, int ilo, int ihi)
Definition: ivcon.cpp:7670
int i4_min(int i1, int i2)
Definition: ivcon.cpp:7554
bool debug
Definition: ivcon.cpp:152
int cor3_num
Definition: ivcon.cpp:149
int line_dex[LINES_MAX]
Definition: ivcon.cpp:177
int list[COR3_MAX]
Definition: ivcon.cpp:182
char input[LINE_MAX_LEN]
Definition: ivcon.cpp:173
int off_read(ifstream &file_in)
Definition: ivcon.cpp:11357
long int long_int_read(FILE *filein)
Definition: ivcon.cpp:10403
int short_int_write(FILE *fileout, short int int_val)
Definition: ivcon.cpp:12825
int tds_write_u_short_int(FILE *fileout, unsigned short int int_val)
Definition: ivcon.cpp:17248
char filein_name[81]
Definition: ivcon.cpp:167
int tria_read(FILE *filein)
Definition: ivcon.cpp:18142
void data_report()
Definition: ivcon.cpp:3122
float face_normal[3][FACE_MAX]
Definition: ivcon.cpp:160
float face_area[FACE_MAX]
Definition: ivcon.cpp:157
unsigned long int tds_read_tex_verts_section(FILE *filein)
Definition: ivcon.cpp:16386
void vertex_to_node_material()
Definition: ivcon.cpp:19294
int gmod_write(FILE *fileout)
Definition: ivcon.cpp:5616
float material_rgba[4][MATERIAL_MAX]
Definition: ivcon.cpp:187
void tmat_rot_vector(float a[4][4], float b[4][4], float angle, float v1, float v2, float v3)
Definition: ivcon.cpp:17839
void tmat_init(float a[4][4])
Definition: ivcon.cpp:17417
bool s_eqi(char *string1, char *string2)
Definition: ivcon.cpp:12106
int tds_write_string(FILE *fileout, char *string)
Definition: ivcon.cpp:17206
int tria_write(FILE *fileout)
Definition: ivcon.cpp:18263
#define DEG_TO_RAD
Definition: ivcon.cpp:52
int ch_write(FILE *fileout, char c)
Definition: ivcon.cpp:2056
int main(int argc, char *argv[])
Definition: ivcon.cpp:363
int gmod_read(FILE *filein)
Definition: ivcon.cpp:5155
float background_rgb[3]
Definition: ivcon.cpp:139
float rgb_to_hue(float r, float g, float b)
Definition: ivcon.cpp:11954
void tmat_mxp(float a[4][4], float x[4], float y[4])
Definition: ivcon.cpp:17563
int byu_write(FILE *fileout)
Definition: ivcon.cpp:1579
unsigned long int tds_read_light_section(FILE *filein)
Definition: ivcon.cpp:15397
int data_write()
Definition: ivcon.cpp:3163
char normal_binding[80]
Definition: ivcon.cpp:192
float transform_matrix[4][4]
Definition: ivcon.cpp:210
void tmat_trans(float a[4][4], float b[4][4], float x, float y, float z)
Definition: ivcon.cpp:18086
#define MATERIAL_MAX
Definition: ivcon.cpp:134
float vertex_rgb[3][ORDER_MAX][FACE_MAX]
Definition: ivcon.cpp:214
void gmod_write_w16(unsigned short Val, FILE *fileout)
Definition: ivcon.cpp:5924
void node_to_vertex_material()
Definition: ivcon.cpp:10653
void face_area_set()
Definition: ivcon.cpp:4100
unsigned long int tds_read_ambient_section(FILE *filein)
Definition: ivcon.cpp:14657
int dxf_read(FILE *filein)
Definition: ivcon.cpp:3364
int bad_num
Definition: ivcon.cpp:140
void vertex_to_face_material()
Definition: ivcon.cpp:19254
int ase_write(FILE *fileout)
Definition: ivcon.cpp:1197
unsigned long int tds_read_edit_section(FILE *filein, int *views_read)
Definition: ivcon.cpp:14956
bool ch_is_space(char c)
Definition: ivcon.cpp:1841
int tec_write(FILE *fileout)
Definition: ivcon.cpp:17291
int text_num
Definition: ivcon.cpp:203
int byu_read(FILE *filein)
Definition: ivcon.cpp:1397
unsigned long int tds_read_vp_section(FILE *filein, int *views_read)
Definition: ivcon.cpp:16690
float float_reverse_bytes(float x)
Definition: ivcon.cpp:5014
int face_print(int iface)
Definition: ivcon.cpp:4445
int stlb_read(FILE *filein)
Definition: ivcon.cpp:14210
int wrl_write(FILE *filout)
Definition: ivcon.cpp:19631
#define LEVEL_MAX
Definition: ivcon.cpp:132
void gmod_write_float(float Val, FILE *fileout)
Definition: ivcon.cpp:5877
char texture_binding[80]
Definition: ivcon.cpp:205
void vertex_normal_set()
Definition: ivcon.cpp:19121
float cor3_normal[3][COR3_MAX]
Definition: ivcon.cpp:148
float origin[3]
Definition: ivcon.cpp:198
int max_order2
Definition: ivcon.cpp:190
int interact()
Definition: ivcon.cpp:7786
void tmat_mxp2(float a[4][4], float x[][3], float y[][3], int n)
Definition: ivcon.cpp:17622
#define G1_SECTION_MODEL_QUADS
Definition: ivcon.cpp:45
void face_to_vertex_material()
Definition: ivcon.cpp:4898
int dup_num
Definition: ivcon.cpp:154
bool data_read()
Definition: ivcon.cpp:2767
float pivot[3]
Definition: ivcon.cpp:199
float vertex_tex_uv[2][ORDER_MAX][FACE_MAX]
Definition: ivcon.cpp:215
int group_num
Definition: ivcon.cpp:170
int cor3_material[COR3_MAX]
Definition: ivcon.cpp:147
void init_program_data()
Definition: ivcon.cpp:7746
#define ORDER_MAX
Definition: ivcon.cpp:135
#define G1_SECTION_MODEL_VERT_ANIMATION
Definition: ivcon.cpp:47
int edge_count()
Definition: ivcon.cpp:3835
#define COR3_MAX
Definition: ivcon.cpp:129
int vla_read(FILE *filein)
Definition: ivcon.cpp:19343
unsigned long int tds_read_u_long_int(FILE *filein)
Definition: ivcon.cpp:15539
int ucd_write(FILE *fileout)
Definition: ivcon.cpp:18950
unsigned long int tds_read_matdef_section(FILE *filein)
Definition: ivcon.cpp:15632
int trib_write(FILE *fileout)
Definition: ivcon.cpp:18492
int rcol_find(float a[][COR3_MAX], int m, int n, float r[])
Definition: ivcon.cpp:11899
bool s_to_i4vec(char *s, int n, int ivec[])
Definition: ivcon.cpp:12363
int iv_write(FILE *fileout)
Definition: ivcon.cpp:9968
int face_smooth[FACE_MAX]
Definition: ivcon.cpp:164
#define ERROR
Definition: ivcon.cpp:44
int face_material[FACE_MAX]
Definition: ivcon.cpp:159
float normal_temp[3][ORDER_MAX *FACE_MAX]
Definition: ivcon.cpp:193
#define LINES_MAX
Definition: ivcon.cpp:133
void hello()
Definition: ivcon.cpp:5990
int long_int_write(FILE *fileout, long int int_val)
Definition: ivcon.cpp:10448
int texture_num
Definition: ivcon.cpp:207
char temp_name[81]
Definition: ivcon.cpp:201
void tmat_mxv(float a[4][4], float x[4], float y[4])
Definition: ivcon.cpp:17686
bool byte_swap
Definition: ivcon.cpp:141
#define FACE_MAX
Definition: ivcon.cpp:130
int vertex_material[ORDER_MAX][FACE_MAX]
Definition: ivcon.cpp:212


ivcon
Author(s): John Burkardt
autogenerated on Mon Feb 28 2022 22:31:01