16708 lines
396 KiB
C
16708 lines
396 KiB
C
/* ivcon.c 24 May 2001 */
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
IVCON converts various 3D graphics files.
|
|
|
|
Acknowledgements:
|
|
|
|
Coding, comments, and advice were supplied by a number of collaborators.
|
|
|
|
John F Flanagan made some corrections to the 3D Studio Max routines.
|
|
|
|
Zik Saleeba (zik@zikzak.net) enhanced the DXF routines, and added the
|
|
Golgotha GMOD routines.
|
|
|
|
Thanks to Susan M. Fisher, University of North Carolina,
|
|
Department of Computer Science, for pointing out a coding error
|
|
in FACE_NULL_DELETE that was overwriting all the data!
|
|
|
|
Modified:
|
|
|
|
04 July 2000
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define FALSE 0
|
|
#define TRUE 1
|
|
|
|
#define ERROR 1
|
|
#define G1_SECTION_MODEL_QUADS 18
|
|
#define G1_SECTION_MODEL_TEXTURE_NAMES 19
|
|
#define G1_SECTION_MODEL_VERT_ANIMATION 20
|
|
#define GMOD_MAX_SECTIONS 32
|
|
#define GMOD_UNUSED_VERTEX 65535
|
|
#define PI 3.141592653589793238462643
|
|
#define SUCCESS 0
|
|
|
|
#define DEG_TO_RAD ( PI / 180.0 )
|
|
#define RAD_TO_DEG ( 180.0 / PI )
|
|
|
|
/******************************************************************************/
|
|
|
|
/* GLOBAL DATA */
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
BACKGROUND_RGB[3], the background color.
|
|
|
|
BYTE_SWAP, byte swapping option.
|
|
|
|
COR3[3][COR3_MAX], the coordinates of nodes.
|
|
|
|
COR3_MATERIAL[COR3_MAX], the index of the material of each node.
|
|
|
|
COR3_MAX, the maximum number of points.
|
|
|
|
COR3_NORMAL[3][COR3_MAX], normal vectors associated with nodes.
|
|
|
|
COR3_NUM, the number of points.
|
|
|
|
COR3_RGB[3][COR3_MAX], RGB colors associated with nodes.
|
|
|
|
COR3_TEX_UV[2][COR3_MAX], texture coordinates associated with nodes.
|
|
|
|
FACE[ORDER_MAX][FACE_MAX] contains the index of the I-th node making up face J.
|
|
|
|
FACE_AREA(FACE_MAX), the area of each face.
|
|
|
|
FACE_MATERIAL[FACE_MAX]; the material of each face.
|
|
|
|
FACE_MAX, the maximum number of faces.
|
|
|
|
FACE_NORMAL[3][FACE_MAX], the face normal vectors.
|
|
|
|
FACE_NUM, the number of faces.
|
|
|
|
FACE_ORDER[FACE_MAX], the number of vertices per face.
|
|
|
|
FACE_TEX_UV[2][FACE_MAX], texture coordinates associated with faces.
|
|
|
|
LINE_DEX[LINES_MAX], node indices, denoting polylines, each terminated by -1.
|
|
|
|
LINE_MATERIAL[LINES_MAX], index into RGBCOLOR for line color.
|
|
|
|
LINES_MAX, the maximum number of line definition items.
|
|
|
|
LINE_NUM, the number of line definition items.
|
|
|
|
LINE_PRUNE, pruning option ( 0 = no pruning, nonzero = pruning).
|
|
|
|
MATERIAL_MAX, the maximum number of materials.
|
|
|
|
MATERIAL_NUM, the number of materials.
|
|
|
|
ORDER_MAX, the maximum number of vertices per face.
|
|
|
|
TEXTURE_MAX, the maximum number of textures.
|
|
|
|
TEXTURE_NAME[TEXTURE_MAX][LINE_MAX_LEN], ...
|
|
|
|
TEXTURE_NUM, the number of textures.
|
|
|
|
TRANSFORM_MATRIX[4][4], the current transformation matrix.
|
|
|
|
VERTEX_MATERIAL[ORDER_MAX][FACE_MAX]; the material of vertices of faces.
|
|
|
|
VERTEX_NORMAL[3][ORDER_MAX][FACE_MAX], normals at vertices of faces.
|
|
|
|
VERTEX_RGB[3][ORDER_MAX][FACE_MAX], colors of vertices of faces.
|
|
|
|
VERTEX_TEX_UV[2][ORDER_MAX][FACE_MAX], texture coordinates of vertices of faces.
|
|
*/
|
|
|
|
#define COLOR_MAX 1000
|
|
#define COR3_MAX 200000
|
|
#define FACE_MAX 200000
|
|
#define LINE_MAX_LEN 256
|
|
#define LEVEL_MAX 10
|
|
#define LINES_MAX 100000
|
|
#define MATERIAL_MAX 100
|
|
#define ORDER_MAX 10
|
|
#define TEXTURE_MAX 100
|
|
|
|
char anim_name[LINE_MAX_LEN];
|
|
float background_rgb[3];
|
|
int bad_num;
|
|
int byte_swap;
|
|
int bytes_num;
|
|
int color_num;
|
|
int comment_num;
|
|
|
|
float cor3[3][COR3_MAX];
|
|
int cor3_material[COR3_MAX];
|
|
float cor3_normal[3][COR3_MAX];
|
|
int cor3_num;
|
|
float cor3_tex_uv[3][COR3_MAX];
|
|
|
|
int debug;
|
|
|
|
int dup_num;
|
|
|
|
int face[ORDER_MAX][FACE_MAX];
|
|
float face_area[FACE_MAX];
|
|
int face_flags[FACE_MAX];
|
|
int face_material[FACE_MAX];
|
|
float face_normal[3][FACE_MAX];
|
|
int face_num;
|
|
int face_object[FACE_MAX];
|
|
int face_order[FACE_MAX];
|
|
int face_smooth[FACE_MAX];
|
|
float face_tex_uv[2][FACE_MAX];
|
|
|
|
char filein_name[1024];
|
|
char fileout_name[1024];
|
|
|
|
int group_num;
|
|
|
|
int i;
|
|
char input[LINE_MAX_LEN];
|
|
int k;
|
|
char level_name[LEVEL_MAX][LINE_MAX_LEN];
|
|
|
|
int line_dex[LINES_MAX];
|
|
int line_material[LINES_MAX];
|
|
int line_num;
|
|
int line_prune;
|
|
|
|
int list[COR3_MAX];
|
|
|
|
char material_binding[80];
|
|
char material_name[MATERIAL_MAX][LINE_MAX_LEN];
|
|
int material_num;
|
|
float material_rgba[4][MATERIAL_MAX];
|
|
|
|
char mat_name[81];
|
|
int max_order2;
|
|
|
|
char normal_binding[80];
|
|
float normal_temp[3][ORDER_MAX*FACE_MAX];
|
|
|
|
char object_name[81];
|
|
int object_num;
|
|
|
|
float origin[3];
|
|
float pivot[3];
|
|
float rgbcolor[3][COLOR_MAX];
|
|
char temp_name[81];
|
|
|
|
int text_num;
|
|
|
|
char texture_binding[80];
|
|
char texture_name[TEXTURE_MAX][LINE_MAX_LEN];
|
|
int texture_num;
|
|
float texture_temp[2][ORDER_MAX*FACE_MAX];
|
|
|
|
float transform_matrix[4][4];
|
|
|
|
int vertex_material[ORDER_MAX][FACE_MAX];
|
|
float vertex_normal[3][ORDER_MAX][FACE_MAX];
|
|
float vertex_rgb[3][ORDER_MAX][FACE_MAX];
|
|
float vertex_tex_uv[2][ORDER_MAX][FACE_MAX];
|
|
|
|
/******************************************************************************/
|
|
|
|
/* FUNCTION PROTOTYPES */
|
|
|
|
/******************************************************************************/
|
|
|
|
int main ( int argc, char **argv );
|
|
int ase_read ( FILE *filein );
|
|
int ase_write ( FILE *fileout );
|
|
int byu_read ( FILE *filein );
|
|
int byu_write ( FILE *fileout );
|
|
int char_index_last ( char* string, char c );
|
|
int char_pad ( int *char_index, int *null_index, char *string,
|
|
int STRING_MAX );
|
|
char char_read ( FILE *filein );
|
|
int char_write ( FILE *fileout, char c );
|
|
int command_line ( char **argv );
|
|
void cor3_normal_set ( void );
|
|
void cor3_range ( void );
|
|
void data_check ( void );
|
|
void data_init ( void );
|
|
int data_read ( void );
|
|
void data_report ( void );
|
|
int data_write ( void );
|
|
int dxf_read ( FILE *filein );
|
|
int dxf_write ( FILE *fileout );
|
|
void edge_null_delete ( void );
|
|
void face_area_set ( void );
|
|
void face_normal_ave ( void );
|
|
void face_null_delete ( void );
|
|
int face_print ( int iface );
|
|
void face_reverse_order ( void );
|
|
int face_subset ( void );
|
|
void face_to_line ( void );
|
|
void face_to_vertex_material ( void );
|
|
char *file_ext ( char *file_name );
|
|
float float_read ( FILE *filein );
|
|
float float_reverse_bytes ( float x );
|
|
int float_write ( FILE *fileout, float float_val );
|
|
int gmod_arch_check ( void );
|
|
int gmod_read ( FILE *filein );
|
|
float gmod_read_float ( FILE *filein );
|
|
unsigned short gmod_read_w16 ( FILE *filein );
|
|
unsigned long gmod_read_w32 ( FILE *filein );
|
|
int gmod_write ( FILE *fileout );
|
|
void gmod_write_float ( float Val, FILE *fileout );
|
|
void gmod_write_w16 ( unsigned short Val, FILE *fileout );
|
|
void gmod_write_w32 ( unsigned long Val, FILE *fileout );
|
|
void hello ( void );
|
|
void help ( void );
|
|
int hrc_read ( FILE *filein );
|
|
int hrc_write ( FILE *fileout );
|
|
void init_program_data ( void );
|
|
int interact ( void );
|
|
int iv_read ( FILE *filein );
|
|
int iv_write ( FILE *fileout );
|
|
int ivec_max ( int n, int *a );
|
|
int leqi ( char* string1, char* string2 );
|
|
long int long_int_read ( FILE *filein );
|
|
int long_int_write ( FILE *fileout, long int int_val );
|
|
void news ( void );
|
|
void node_to_vertex_material ( void );
|
|
int obj_read ( FILE *filein );
|
|
int obj_write ( FILE *fileout );
|
|
int pov_write ( FILE *fileout );
|
|
int rcol_find ( float a[][COR3_MAX], int m, int n, float r[] );
|
|
float rgb_to_hue ( float r, float g, float b );
|
|
short int short_int_read ( FILE *filein );
|
|
int short_int_write ( FILE *fileout, short int int_val );
|
|
int smf_read ( FILE *filein );
|
|
int smf_write ( FILE *fileout );
|
|
int stla_read ( FILE *filein );
|
|
int stla_write ( FILE *fileout );
|
|
int stlb_read ( FILE *filein );
|
|
int stlb_write ( FILE *fileout );
|
|
void tds_pre_process ( void );
|
|
int tds_read ( FILE *filein );
|
|
unsigned long int tds_read_ambient_section ( FILE *filein );
|
|
unsigned long int tds_read_background_section ( FILE *filein );
|
|
unsigned long int tds_read_boolean ( unsigned char *boolean, FILE *filein );
|
|
unsigned long int tds_read_camera_section ( FILE *filein );
|
|
unsigned long int tds_read_edit_section ( FILE *filein, int *views_read );
|
|
unsigned long int tds_read_keyframe_section ( FILE *filein, int *views_read );
|
|
unsigned long int tds_read_keyframe_objdes_section ( FILE *filein );
|
|
unsigned long int tds_read_light_section ( FILE *filein );
|
|
unsigned long int tds_read_u_long_int ( FILE *filein );
|
|
int tds_read_long_name ( FILE *filein );
|
|
unsigned long int tds_read_matdef_section ( FILE *filein );
|
|
unsigned long int tds_read_material_section ( FILE *filein );
|
|
int tds_read_name ( FILE *filein );
|
|
unsigned long int tds_read_obj_section ( FILE *filein );
|
|
unsigned long int tds_read_object_section ( FILE *filein );
|
|
unsigned long int tds_read_tex_verts_section ( FILE *filein );
|
|
unsigned long int tds_read_texmap_section ( FILE *filein );
|
|
unsigned short int tds_read_u_short_int ( FILE *filein );
|
|
unsigned long int tds_read_spot_section ( FILE *filein );
|
|
unsigned long int tds_read_unknown_section ( FILE *filein );
|
|
unsigned long int tds_read_view_section ( FILE *filein, int *views_read );
|
|
unsigned long int tds_read_vp_section ( FILE *filein, int *views_read );
|
|
int tds_write ( FILE *fileout );
|
|
int tds_write_string ( FILE *fileout, char *string );
|
|
int tds_write_u_short_int ( FILE *fileout,
|
|
unsigned short int int_val );
|
|
int tec_write ( FILE *fileout );
|
|
void tmat_init ( float a[4][4] );
|
|
void tmat_mxm ( float a[4][4], float b[4][4], float c[4][4] );
|
|
void tmat_mxp ( float a[4][4], float x[4], float y[4] );
|
|
void tmat_mxp2 ( float a[4][4], float x[][3], float y[][3], int n );
|
|
void tmat_mxv ( float a[4][4], float x[4], float y[4] );
|
|
void tmat_rot_axis ( float a[4][4], float b[4][4], float angle,
|
|
char axis );
|
|
void tmat_rot_vector ( float a[4][4], float b[4][4], float angle,
|
|
float v1, float v2, float v3 );
|
|
void tmat_scale ( float a[4][4], float b[4][4], float sx, float sy,
|
|
float sz );
|
|
void tmat_shear ( float a[4][4], float b[4][4], char *axis,
|
|
float s );
|
|
void tmat_trans ( float a[4][4], float b[4][4], float x, float y,
|
|
float z );
|
|
int tria_read ( FILE *filein );
|
|
int tria_write ( FILE *fileout );
|
|
int trib_read ( FILE *filein );
|
|
int trib_write ( FILE *fileout );
|
|
int txt_write ( FILE *fileout );
|
|
int ucd_write ( FILE *fileout );
|
|
void vertex_normal_set ( void );
|
|
void vertex_to_face_material ( void );
|
|
void vertex_to_node_material ( void );
|
|
int vla_read ( FILE *filein );
|
|
int vla_write ( FILE *fileout );
|
|
int wrl_write ( FILE *filout );
|
|
int xgl_write ( FILE *fileout );
|
|
|
|
/******************************************************************************/
|
|
|
|
int main ( int argc, char **argv )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
MAIN is the main program for converting graphics files.
|
|
|
|
Modified:
|
|
|
|
26 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int result;
|
|
/*
|
|
Initialize the program data.
|
|
*/
|
|
init_program_data ( );
|
|
/*
|
|
If there are at least two command line arguments, call COMMAND_LINE.
|
|
Otherwise call INTERACT and get information from the user.
|
|
*/
|
|
if ( argc >= 2 ) {
|
|
result = command_line ( argv );
|
|
}
|
|
else {
|
|
result = interact ( );
|
|
}
|
|
|
|
return result;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int ase_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
ASE_READ reads an AutoCAD ASE file.
|
|
|
|
Modified:
|
|
|
|
22 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
float bval;
|
|
int count;
|
|
float gval;
|
|
int i;
|
|
int iface;
|
|
int ivert;
|
|
int iword;
|
|
int level;
|
|
char *next;
|
|
int nlbrack;
|
|
int nrbrack;
|
|
int cor3_num_old;
|
|
int face_num_old;
|
|
float rval;
|
|
float temp;
|
|
int width;
|
|
char word[LINE_MAX_LEN];
|
|
char word1[LINE_MAX_LEN];
|
|
char word2[LINE_MAX_LEN];
|
|
char wordm1[LINE_MAX_LEN];
|
|
float x;
|
|
float y;
|
|
float z;
|
|
|
|
level = 0;
|
|
strcpy ( level_name[0], "Top" );
|
|
cor3_num_old = cor3_num;
|
|
face_num_old = face_num;
|
|
nlbrack = 0;
|
|
nrbrack = 0;
|
|
|
|
strcpy ( word, " " );
|
|
strcpy ( wordm1, " " );
|
|
/*
|
|
Read a line of text from the file.
|
|
*/
|
|
|
|
for ( ;; ) {
|
|
|
|
if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
|
|
break;
|
|
}
|
|
|
|
text_num = text_num + 1;
|
|
next = input;
|
|
iword = 0;
|
|
/*
|
|
Read the next word from the line.
|
|
*/
|
|
for ( ;; ) {
|
|
|
|
strcpy ( wordm1, word );
|
|
strcpy ( word, " " );
|
|
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
|
|
if ( count <= 0 ) {
|
|
break;
|
|
}
|
|
|
|
iword = iword + 1;
|
|
|
|
if ( iword == 1 ) {
|
|
strcpy ( word1, word );
|
|
}
|
|
/*
|
|
In case the new word is a bracket, update the bracket count.
|
|
*/
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
|
|
nlbrack = nlbrack + 1;
|
|
level = nlbrack - nrbrack;
|
|
strcpy ( level_name[level], wordm1 );
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
|
|
nrbrack = nrbrack + 1;
|
|
|
|
if ( nlbrack < nrbrack ) {
|
|
|
|
printf ( "\n" );
|
|
printf ( "ASE_READ - Fatal error!\n" );
|
|
printf ( " Extraneous right bracket on line %d\n", text_num );
|
|
printf ( " Currently processing field:\n" );
|
|
printf ( "%s\n", level_name[level] );
|
|
return ERROR;
|
|
}
|
|
|
|
}
|
|
/*
|
|
*3DSMAX_ASCIIEXPORT 200
|
|
*/
|
|
if ( strcmp ( word1, "*3DSMAX_ASCIIEXPORT" ) == 0 ) {
|
|
break;
|
|
}
|
|
/*
|
|
*COMMENT
|
|
*/
|
|
else if ( strcmp ( word1, "*COMMENT" ) == 0 ) {
|
|
break;
|
|
}
|
|
/*
|
|
*GEOMOBJECT
|
|
*/
|
|
else if ( strcmp ( level_name[level], "*GEOMOBJECT" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
/*
|
|
Why don't you read and save this name?
|
|
*/
|
|
else if ( strcmp ( word, "*NODE_NAME" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*NODE_TM" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*MESH" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*PROP_CASTSHADOW" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*PROP_MOTIONBLUR" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*PROP_RECVSHADOW" ) == 0 ) {
|
|
break;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data in GEOMOBJECT, line %d\n", text_num );
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
*MESH
|
|
*/
|
|
else if ( strcmp ( level_name[level], "*MESH" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_CFACELIST" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_CVERTLIST" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_FACE_LIST" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_NORMALS" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_NUMCVERTEX" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_NUMCVFACES" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_NUMFACES" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_NUMTVERTEX" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_NUMTVFACES" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_NUMVERTEX" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_TFACELIST" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_TVERTLIST" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_VERTEX_LIST" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*TIMEVALUE" ) == 0 ) {
|
|
break;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data in MESH, line %d\n", text_num );
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
*MESH_CFACELIST
|
|
*/
|
|
else if ( strcmp ( level_name[level], "*MESH_CFACELIST" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_CFACE" ) == 0 ) {
|
|
break;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data in MESH_CFACE, line %d\n", text_num );
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
*MESH_CVERTLIST
|
|
|
|
Mesh vertex indices must be incremented by COR3_NUM_OLD before being stored
|
|
in the internal array.
|
|
*/
|
|
else if ( strcmp ( level_name[level], "*MESH_CVERTLIST" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_VERTCOL" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%d%n", &i, &width );
|
|
next = next + width;
|
|
|
|
i = i + cor3_num_old;
|
|
|
|
count = sscanf ( next, "%f%n", &rval, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &gval, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &bval, &width );
|
|
next = next + width;
|
|
|
|
if ( material_num < MATERIAL_MAX ) {
|
|
material_rgba[0][material_num] = rval;
|
|
material_rgba[1][material_num] = gval;
|
|
material_rgba[2][material_num] = bval;
|
|
material_rgba[3][material_num] = 1.0;
|
|
}
|
|
|
|
material_num = material_num + 1;
|
|
cor3_material[i] = material_num;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "\n" );
|
|
printf ( "ASE_READ - Warning!\n" );
|
|
printf ( " Bad data in MESH_CVERTLIST, line %d\n", text_num );
|
|
break;
|
|
}
|
|
|
|
}
|
|
/*
|
|
*MESH_FACE_LIST
|
|
This coding assumes a face is always triangular or quadrilateral.
|
|
*/
|
|
else if ( strcmp ( level_name[level], "*MESH_FACE_LIST" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_FACE" ) == 0 ) {
|
|
|
|
if ( face_num < FACE_MAX ) {
|
|
|
|
face_material[face_num] = 0;
|
|
face_order[face_num] = 0;
|
|
|
|
count = sscanf ( next, "%d%n", &i, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%s%n", word2, &width );
|
|
next = next + width;
|
|
count = sscanf ( next, "%s%n", word2, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%d%n", &i, &width );
|
|
next = next + width;
|
|
face[0][face_num] = i + cor3_num_old;
|
|
face_order[face_num] = face_order[face_num] + 1;
|
|
|
|
count = sscanf ( next, "%s%n", word2, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%d%n", &i, &width );
|
|
next = next + width;
|
|
face[1][face_num] = i + cor3_num_old;
|
|
face_order[face_num] = face_order[face_num] + 1;
|
|
|
|
count = sscanf ( next, "%s%n", word2, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%d%n", &i, &width );
|
|
next = next + width;
|
|
face[2][face_num] = i + cor3_num_old;
|
|
face_order[face_num] = face_order[face_num] + 1;
|
|
|
|
count = sscanf ( next, "%s%n", word2, &width );
|
|
next = next + width;
|
|
|
|
if ( strcmp ( word2, "D:" ) == 0 ) {
|
|
count = sscanf ( next, "%d%n", &i, &width );
|
|
next = next + width;
|
|
face[3][face_num] = i + cor3_num_old;
|
|
face_order[face_num] = face_order[face_num] + 1;
|
|
}
|
|
}
|
|
|
|
face_num = face_num + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data in MESH_FACE_LIST, line %d\n", text_num );
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
*MESH_NORMALS
|
|
*/
|
|
else if ( strcmp ( level_name[level], "*MESH_NORMALS" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*MESH_FACENORMAL" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%d%n", &iface, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &x, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &y, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &z, &width );
|
|
next = next + width;
|
|
|
|
iface = iface + face_num_old;
|
|
ivert = 0;
|
|
|
|
face_normal[0][iface] = x;
|
|
face_normal[1][iface] = y;
|
|
face_normal[2][iface] = z;
|
|
|
|
break;
|
|
|
|
}
|
|
else if ( strcmp ( word, "*MESH_VERTEXNORMAL" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%d%n", &i, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &x, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &y, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &z, &width );
|
|
next = next + width;
|
|
|
|
vertex_normal[0][ivert][iface] = x;
|
|
vertex_normal[1][ivert][iface] = y;
|
|
vertex_normal[2][ivert][iface] = z;
|
|
ivert = ivert + 1;
|
|
|
|
break;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data in MESH_NORMALS, line %d\n", text_num );
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
*MESH_TFACELIST
|
|
*/
|
|
else if ( strcmp ( level_name[level], "*MESH_TFACELIST" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word1, "*MESH_TFACE" ) == 0 ) {
|
|
break;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data in MESH_TFACE_LIST, line %d\n", text_num );
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
*MESH_TVERTLIST
|
|
*/
|
|
else if ( strcmp ( level_name[level], "*MESH_TVERTLIST" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word1, "*MESH_TVERT" ) == 0 ) {
|
|
break;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data in MESH_TVERTLIST, line %d\n", text_num );
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
*MESH_VERTEX_LIST
|
|
*/
|
|
else if ( strcmp ( level_name[level], "*MESH_VERTEX_LIST" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
cor3_num_old = cor3_num;
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word1, "*MESH_VERTEX" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%d%n", &i, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &x, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &y, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &z, &width );
|
|
next = next + width;
|
|
|
|
i = i + cor3_num_old;
|
|
if ( cor3_num < i + 1 ) {
|
|
cor3_num = i + 1;
|
|
}
|
|
|
|
if ( i < COR3_MAX ) {
|
|
|
|
cor3[0][i] =
|
|
transform_matrix[0][0] * x
|
|
+ transform_matrix[0][1] * y
|
|
+ transform_matrix[0][2] * z
|
|
+ transform_matrix[0][3];
|
|
|
|
cor3[1][i] =
|
|
transform_matrix[1][0] * x
|
|
+ transform_matrix[1][1] * y
|
|
+ transform_matrix[1][2] * z
|
|
+ transform_matrix[1][3];
|
|
|
|
cor3[2][i] =
|
|
transform_matrix[2][0] * x
|
|
+ transform_matrix[2][1] * y
|
|
+ transform_matrix[2][2] * z
|
|
+ transform_matrix[2][3];
|
|
}
|
|
|
|
break;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data in MESH_VERTEX_LIST, line %d\n", text_num );
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
*NODE_TM
|
|
|
|
Each node should start out with a default transformation matrix.
|
|
*/
|
|
else if ( strcmp ( level_name[level], "*NODE_TM" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
|
|
tmat_init ( transform_matrix );
|
|
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*INHERIT_POS" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*INHERIT_ROT" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*INHERIT_SCL" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*NODE_NAME" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*TM_POS" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*TM_ROTANGLE" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*TM_ROTAXIS" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*TM_ROW0" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%f%n", &temp, &width );
|
|
next = next + width;
|
|
transform_matrix[0][0] = temp;
|
|
|
|
count = sscanf ( next, "%f%n", &temp, &width );
|
|
next = next + width;
|
|
transform_matrix[1][0] = temp;
|
|
|
|
count = sscanf ( next, "%f%n", &temp, &width );
|
|
next = next + width;
|
|
transform_matrix[2][0] = temp;
|
|
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*TM_ROW1" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%f%n", &temp, &width );
|
|
next = next + width;
|
|
transform_matrix[0][1] = temp;
|
|
|
|
count = sscanf ( next, "%f%n", &temp, &width );
|
|
next = next + width;
|
|
transform_matrix[1][1] = temp;
|
|
|
|
count = sscanf ( next, "%f%n", &temp, &width );
|
|
next = next + width;
|
|
transform_matrix[2][1] = temp;
|
|
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*TM_ROW2" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%f%n", &temp, &width );
|
|
next = next + width;
|
|
transform_matrix[0][2] = temp;
|
|
|
|
count = sscanf ( next, "%f%n", &temp, &width );
|
|
next = next + width;
|
|
transform_matrix[1][2] = temp;
|
|
|
|
count = sscanf ( next, "%f%n", &temp, &width );
|
|
next = next + width;
|
|
transform_matrix[2][2] = temp;
|
|
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*TM_ROW3" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%f%n", &temp, &width );
|
|
next = next + width;
|
|
transform_matrix[0][3] = temp;
|
|
|
|
count = sscanf ( next, "%f%n", &temp, &width );
|
|
next = next + width;
|
|
transform_matrix[1][3] = temp;
|
|
|
|
count = sscanf ( next, "%f%n", &temp, &width );
|
|
next = next + width;
|
|
transform_matrix[2][3] = temp;
|
|
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*TM_SCALE" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*TM_SCALEAXIS" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*TM_SCALEAXISANG" ) == 0 ) {
|
|
break;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data in NODE_TM, line %d\n", text_num );
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
*SCENE
|
|
*/
|
|
else if ( strcmp ( level_name[level], "*SCENE" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "*SCENE_AMBIENT_STATIC" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*SCENE_BACKGROUND_STATIC" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*SCENE_FILENAME" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*SCENE_FIRSTFRAME" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*SCENE_FRAMESPEED" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*SCENE_LASTFRAME" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "*SCENE_TICKSPERFRAME" ) == 0 ) {
|
|
break;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data in SCENE, line %d\n", text_num );
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
End of loop reading words from the line.
|
|
*/
|
|
}
|
|
/*
|
|
End of loop reading lines from input file.
|
|
*/
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int ase_write ( FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
ASE_WRITE writes graphics information to an AutoCAD ASE file.
|
|
|
|
Modified:
|
|
|
|
30 September 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
*/
|
|
{
|
|
int i1;
|
|
int i2;
|
|
int i3;
|
|
int i4;
|
|
int iface;
|
|
int ivert;
|
|
int j;
|
|
int text_num;
|
|
|
|
text_num = 0;
|
|
/*
|
|
Write the header.
|
|
*/
|
|
fprintf ( fileout, "*3DSMAX_ASCIIEXPORT 200\n" );
|
|
fprintf ( fileout, "*COMMENT \"%s, created by IVCON.\"\n", fileout_name );
|
|
fprintf ( fileout, "*COMMENT \"Original data in %s\"\n", filein_name );
|
|
|
|
text_num = text_num + 3;
|
|
/*
|
|
Write the scene block.
|
|
*/
|
|
fprintf ( fileout, "*SCENE {\n" );
|
|
fprintf ( fileout, " *SCENE_FILENAME \"\"\n" );
|
|
fprintf ( fileout, " *SCENE_FIRSTFRAME 0\n" );
|
|
fprintf ( fileout, " *SCENE_LASTFRAME 100\n" );
|
|
fprintf ( fileout, " *SCENE_FRAMESPEED 30\n" );
|
|
fprintf ( fileout, " *SCENE_TICKSPERFRAME 160\n" );
|
|
fprintf ( fileout, " *SCENE_BACKGROUND_STATIC 0.0000 0.0000 0.0000\n" );
|
|
fprintf ( fileout, " *SCENE_AMBIENT_STATIC 0.0431 0.0431 0.0431\n" );
|
|
fprintf ( fileout, "}\n" );
|
|
|
|
text_num = text_num + 9;
|
|
/*
|
|
Begin the big geometry block.
|
|
*/
|
|
fprintf ( fileout, "*GEOMOBJECT {\n" );
|
|
fprintf ( fileout, " *NODE_NAME \"%s\"\n", object_name );
|
|
|
|
text_num = text_num + 2;
|
|
/*
|
|
Sub block NODE_TM:
|
|
*/
|
|
fprintf ( fileout, " *NODE_TM {\n" );
|
|
fprintf ( fileout, " *NODE_NAME \"Object01\"\n" );
|
|
fprintf ( fileout, " *INHERIT_POS 0 0 0\n" );
|
|
fprintf ( fileout, " *INHERIT_ROT 0 0 0\n" );
|
|
fprintf ( fileout, " *INHERIT_SCL 0 0 0\n" );
|
|
fprintf ( fileout, " *TM_ROW0 1.0000 0.0000 0.0000\n" );
|
|
fprintf ( fileout, " *TM_ROW1 0.0000 1.0000 0.0000\n" );
|
|
fprintf ( fileout, " *TM_ROW2 0.0000 0.0000 1.0000\n" );
|
|
fprintf ( fileout, " *TM_ROW3 0.0000 0.0000 0.0000\n" );
|
|
fprintf ( fileout, " *TM_POS 0.0000 0.0000 0.0000\n" );
|
|
fprintf ( fileout, " *TM_ROTAXIS 0.0000 0.0000 0.0000\n" );
|
|
fprintf ( fileout, " *TM_ROTANGLE 0.0000\n" );
|
|
fprintf ( fileout, " *TM_SCALE 1.0000 1.0000 1.0000\n" );
|
|
fprintf ( fileout, " *TM_SCALEAXIS 0.0000 0.0000 0.0000\n" );
|
|
fprintf ( fileout, " *TM_SCALEAXISANG 0.0000\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
|
|
text_num = text_num + 16;
|
|
/*
|
|
Sub block MESH:
|
|
Items
|
|
*/
|
|
fprintf ( fileout, " *MESH {\n" );
|
|
fprintf ( fileout, " *TIMEVALUE 0\n" );
|
|
fprintf ( fileout, " *MESH_NUMVERTEX %d\n", cor3_num );
|
|
fprintf ( fileout, " *MESH_NUMFACES %d\n", face_num );
|
|
|
|
text_num = text_num + 4;
|
|
/*
|
|
Sub sub block MESH_VERTEX_LIST
|
|
*/
|
|
fprintf ( fileout, " *MESH_VERTEX_LIST {\n" );
|
|
text_num = text_num + 1;
|
|
|
|
for ( j = 0; j < cor3_num; j++ ) {
|
|
fprintf ( fileout, " *MESH_VERTEX %d %f %f %f\n", j, cor3[0][j],
|
|
cor3[1][j], cor3[2][j] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Sub sub block MESH_FACE_LIST
|
|
Items MESH_FACE
|
|
*/
|
|
fprintf ( fileout, " *MESH_FACE_LIST {\n" );
|
|
text_num = text_num + 1;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
i1 = face[0][iface];
|
|
i2 = face[1][iface];
|
|
i3 = face[2][iface];
|
|
|
|
if ( face_order[iface] == 3 ) {
|
|
fprintf ( fileout, " *MESH_FACE %d: A: %d B: %d C: %d", iface, i1, i2, i3 );
|
|
fprintf ( fileout, " AB: 1 BC: 1 CA: 1 *MESH_SMOOTHING *MESH_MTLID 1\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
else if ( face_order[iface] == 4 ) {
|
|
i4 = face[3][iface];
|
|
fprintf ( fileout, " *MESH_FACE %d: A: %d B: %d C: %d D: %d", iface, i1, i2, i3, i4 );
|
|
fprintf ( fileout, " AB: 1 BC: 1 CD: 1 DA: 1 *MESH_SMOOTHING *MESH_MTLID 1\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
}
|
|
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Item MESH_NUMTVERTEX.
|
|
*/
|
|
fprintf ( fileout, " *MESH_NUMTVERTEX 0\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Item NUMCVERTEX.
|
|
*/
|
|
fprintf ( fileout, " *MESH_NUMCVERTEX 0\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Sub block MESH_NORMALS
|
|
Items MESH_FACENORMAL, MESH_VERTEXNORMAL (repeated)
|
|
*/
|
|
fprintf ( fileout, " *MESH_NORMALS {\n" );
|
|
text_num = text_num + 1;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
fprintf ( fileout, " *MESH_FACENORMAL %d %f %f %f\n",
|
|
iface, face_normal[0][iface], face_normal[1][iface], face_normal[2][iface] );
|
|
text_num = text_num + 1;
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
fprintf ( fileout, " *MESH_VERTEXNORMAL %d %f %f %f\n",
|
|
face[ivert][iface], vertex_normal[0][ivert][iface],
|
|
vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
|
|
text_num = text_num + 1;
|
|
}
|
|
}
|
|
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Close the MESH object.
|
|
*/
|
|
fprintf ( fileout, " }\n" );
|
|
/*
|
|
A few closing parameters.
|
|
*/
|
|
fprintf ( fileout, " *PROP_MOTIONBLUR 0\n" );
|
|
fprintf ( fileout, " *PROP_CASTSHADOW 1\n" );
|
|
fprintf ( fileout, " *PROP_RECVSHADOW 1\n" );
|
|
/*
|
|
Close the GEOM object.
|
|
*/
|
|
fprintf ( fileout, "}\n" );
|
|
|
|
text_num = text_num + 5;
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "ASE_WRITE - Wrote %d text lines;\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
int byu_read ( FILE *filein )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
BYU_READ reads graphics data from a Movie.BYU surface geometry file.
|
|
|
|
Discussion:
|
|
|
|
A Movie.BYU surface geometry file contains 4 groups of data.
|
|
|
|
The first group of data is a single line, containing 4 integers,
|
|
each one left justified in 8 columns. The integers are:
|
|
|
|
PART_NUM, VERTEX_NUM, POLY_NUM, EDGE_NUM,
|
|
|
|
that is, the number of parts or objects, the number of vertices or nodes,
|
|
the number of polygons or faces, and the number of edges.
|
|
|
|
The second group of data is a single line, containing 2 integers,
|
|
each one left justified in 8 columnes. The integers are:
|
|
|
|
POLY1, POLY2,
|
|
|
|
the starting and ending polygon numbers. Presumably, this means
|
|
that the polygons are labeled POLY1, POLY1+1, ..., POLY2, comprising
|
|
a total of POLY_NUM polygons.
|
|
|
|
The third group is the X, Y and Z coordinates of all the vertices.
|
|
These may be written using a FORTRAN format of 6E12.5, which
|
|
crams two sets of (X,Y,Z) data onto each line, with each real value
|
|
written in an exponential format with 5 places after the decimal.
|
|
However, it is generally possible to write the XYZ coordinate data
|
|
for each vertex on a separate line.
|
|
|
|
The fourth group defines the polygons in terms of the vertex indices.
|
|
For each polygon, the vertices that make up the polygon are listed in
|
|
counterclockwise order. The last vertex listed is given with a negative
|
|
sign to indicate the end of the list. All the vertices for all the
|
|
polygons are listed one after the other, using a format that puts
|
|
up to 10 left-justified integers on a line, with each integer occupying
|
|
8 spaces.
|
|
|
|
This code will certainly read a BYU file created by BYU_WRITE, but
|
|
it will not handle more general files. In particular, an object
|
|
can have several parts, the coordinate data can be grouped so
|
|
that there are 2 sets of (x,y,z) data per line, and so on.
|
|
|
|
Example:
|
|
|
|
1 8 6 24
|
|
1 6
|
|
0.00000E+00 0.00000E+00 0.00000E+00
|
|
1.00000E+00 0.00000E+00 0.00000E+00
|
|
1.00000E+00 2.00000E+00 0.00000E+00
|
|
0.00000E+00 2.00000E+00 0.00000E+00
|
|
0.00000E+00 0.00000E+00 1.00000E+00
|
|
1.00000E+00 0.00000E+00 1.00000E+00
|
|
1.00000E+00 2.00000E+00 1.00000E+00
|
|
0.00000E+00 2.00000E+00 1.00000E+00
|
|
4 3 2 -1
|
|
5 6 7 -8
|
|
1 5 8 -4
|
|
4 8 7 -3
|
|
3 7 6 -2
|
|
2 6 5 -1
|
|
|
|
Modified:
|
|
|
|
24 May 2001
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
*/
|
|
{
|
|
int cor3_num_new;
|
|
int count;
|
|
int edge_num;
|
|
int face_num_new;
|
|
int iface;
|
|
int ival;
|
|
int ivert;
|
|
int j;
|
|
char *next;
|
|
int part_num;
|
|
int poly1;
|
|
int poly2;
|
|
int text_num;
|
|
int width;
|
|
float x;
|
|
float y;
|
|
float z;
|
|
|
|
text_num = 0;
|
|
|
|
if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
|
|
return ERROR;
|
|
}
|
|
text_num = text_num + 1;
|
|
|
|
sscanf ( input, "%d %d %d %d", &part_num, &cor3_num_new, &face_num_new,
|
|
&edge_num );
|
|
|
|
if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
|
|
return ERROR;
|
|
}
|
|
text_num = text_num + 1;
|
|
|
|
sscanf ( input, "%d %d", &poly1, &poly2 );
|
|
|
|
for ( j = cor3_num; j < cor3_num + cor3_num_new; j++ ) {
|
|
|
|
if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
|
|
return ERROR;
|
|
}
|
|
text_num = text_num + 1;
|
|
|
|
sscanf ( input, "%f %f %f", &x, &y, &z );
|
|
cor3[0][j] = x;
|
|
cor3[1][j] = y;
|
|
cor3[2][j] = z;
|
|
}
|
|
|
|
for ( iface = face_num; iface < face_num + face_num_new; iface++ ) {
|
|
|
|
if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
|
|
return ERROR;
|
|
}
|
|
text_num = text_num + 1;
|
|
|
|
next = input;
|
|
ivert = 0;
|
|
|
|
for (;;) {
|
|
|
|
count = sscanf ( next, "%d%n", &ival, &width );
|
|
next = next + width;
|
|
|
|
if ( count <= 0 ) {
|
|
return ERROR;
|
|
}
|
|
|
|
if ( ival > 0 ) {
|
|
face[ivert][iface] = ival - 1 + cor3_num;
|
|
}
|
|
else {
|
|
face[ivert][iface] = - ival - 1 - cor3_num;
|
|
break;
|
|
}
|
|
|
|
ivert = ivert + 1;
|
|
|
|
}
|
|
face_order[iface] = ivert + 1;
|
|
}
|
|
|
|
cor3_num = cor3_num + cor3_num_new;
|
|
face_num = face_num + face_num_new;
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "BYU_READ - Read %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
int byu_write ( FILE *fileout )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
BYU_WRITE writes out the graphics data as a Movie.BYU surface geometry file.
|
|
|
|
Discussion:
|
|
|
|
A Movie.BYU surface geometry file contains 4 groups of data.
|
|
|
|
The first group of data is a single line, containing 4 integers,
|
|
each one left justified in 8 columns. The integers are:
|
|
|
|
PART_NUM, VERTEX_NUM, POLY_NUM, EDGE_NUM,
|
|
|
|
that is, the number of parts or objects, the number of vertices or nodes,
|
|
the number of polygons or faces, and the number of edges.
|
|
|
|
The second group of data is a single line, containing 2 integers,
|
|
each one left justified in 8 columnes. The integers are:
|
|
|
|
POLY1, POLY2,
|
|
|
|
the starting and ending polygon numbers. Presumably, this means
|
|
that the polygons are labeled POLY1, POLY1+1, ..., POLY2, comprising
|
|
a total of POLY_NUM polygons.
|
|
|
|
The third group is the X, Y and Z coordinates of all the vertices.
|
|
These may be written using a FORTRAN format of 6E12.5, which
|
|
crams two sets of (X,Y,Z) data onto each line, with each real value
|
|
written in an exponential format with 5 places after the decimal.
|
|
However, it is generally possible to write the XYZ coordinate data
|
|
for each vertex on a separate line.
|
|
|
|
The fourth group defines the polygons in terms of the vertex indices.
|
|
For each polygon, the vertices that make up the polygon are listed in
|
|
counterclockwise order. The last vertex listed is given with a negative
|
|
sign to indicate the end of the list. All the vertices for all the
|
|
polygons are listed one after the other, using a format that puts
|
|
up to 10 left-justified integers on a line, with each integer occupying
|
|
8 spaces.
|
|
|
|
Example:
|
|
|
|
1 8 6 24
|
|
1 6
|
|
0.00000E+00 0.00000E+00 0.00000E+00
|
|
1.00000E+00 0.00000E+00 0.00000E+00
|
|
1.00000E+00 2.00000E+00 0.00000E+00
|
|
0.00000E+00 2.00000E+00 0.00000E+00
|
|
0.00000E+00 0.00000E+00 1.00000E+00
|
|
1.00000E+00 0.00000E+00 1.00000E+00
|
|
1.00000E+00 2.00000E+00 1.00000E+00
|
|
0.00000E+00 2.00000E+00 1.00000E+00
|
|
4 3 2 -1
|
|
5 6 7 -8
|
|
1 5 8 -4
|
|
4 8 7 -3
|
|
3 7 6 -2
|
|
2 6 5 -1
|
|
|
|
Modified:
|
|
|
|
24 May 2001
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int edge_num;
|
|
int iface;
|
|
int ivert;
|
|
int j;
|
|
int jp;
|
|
int part_num;
|
|
int text_num;
|
|
|
|
text_num = 0;
|
|
|
|
edge_num = 0;
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
edge_num = edge_num + face_order[iface];
|
|
}
|
|
|
|
part_num = 1;
|
|
|
|
fprintf ( fileout, "%d %d %d %d\n", part_num, cor3_num, face_num, edge_num );
|
|
text_num = text_num + 1;
|
|
|
|
fprintf ( fileout, "1 %d\n", face_num );
|
|
text_num = text_num + 1;
|
|
|
|
for ( j = 0; j < cor3_num; j++ ) {
|
|
fprintf ( fileout, "%f %f %f\n", cor3[0][j], cor3[1][j], cor3[2][j] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
|
|
jp = face[ivert][iface] + 1;
|
|
if ( ivert == face_order[iface] - 1 ) {
|
|
jp = - jp;
|
|
}
|
|
fprintf ( fileout, "%d ", jp );
|
|
}
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "BYU_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int char_index_last ( char* string, char c )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
CHAR_INDEX_LAST reports the last occurrence of a character in a string.
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int j;
|
|
int nchar;
|
|
|
|
j = -1;
|
|
|
|
nchar = strlen ( string );
|
|
|
|
for ( i = 0; i < nchar; i++ ) {
|
|
if ( string[i] == c ) {
|
|
j = i;
|
|
}
|
|
}
|
|
|
|
return j;
|
|
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int char_pad ( int *char_index, int *null_index, char *string,
|
|
int STRING_MAX )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
CHAR_PAD "pads" a character in a string with a blank on either side.
|
|
|
|
Modified:
|
|
|
|
16 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Parameters:
|
|
|
|
Input/output, int *CHAR_INDEX, the position of the character to be padded.
|
|
On output, this is increased by 1.
|
|
|
|
Input/output, int *NULL_INDEX, the position of the terminating NULL in
|
|
the string. On output, this is increased by 2.
|
|
|
|
Input/output, char STRING[STRING_MAX], the string to be manipulated.
|
|
|
|
Input, int STRING_MAX, the maximum number of characters that can be stored
|
|
in the string.
|
|
|
|
Output, int CHAR_PAD, is SUCCESS if the operation worked, and ERROR otherwise.
|
|
*/
|
|
{
|
|
int i;
|
|
|
|
if ( *char_index < 0 ||
|
|
*char_index >= *null_index ||
|
|
*char_index > STRING_MAX-1 ) {
|
|
return ERROR;
|
|
}
|
|
|
|
if ( (*null_index) + 2 > STRING_MAX-1 ) {
|
|
return ERROR;
|
|
}
|
|
|
|
for ( i = *null_index + 2; i > *char_index + 2; i-- ) {
|
|
string[i] = string[i-2];
|
|
}
|
|
string[*char_index+2] = ' ';
|
|
string[*char_index+1] = string[*char_index];
|
|
string[*char_index] = ' ';
|
|
|
|
*char_index = *char_index + 1;
|
|
*null_index = *null_index + 2;
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
char char_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
CHAR_READ reads one character from a binary file.
|
|
|
|
Modified:
|
|
|
|
24 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
char c;
|
|
|
|
c = ( char ) fgetc ( filein );
|
|
|
|
return c;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int char_write ( FILE *fileout, char c )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
CHAR_WRITE writes one character to a binary file.
|
|
|
|
Modified:
|
|
|
|
24 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
fputc ( c, fileout );
|
|
|
|
return 1;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int command_line ( char **argv )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
|
|
Purpose:
|
|
|
|
COMMAND_LINE carries out a command-line session of file conversion.
|
|
|
|
Discussion:
|
|
|
|
This routine is invoked when the user command is something like
|
|
|
|
ivcon filein_name fileout_name
|
|
|
|
or
|
|
|
|
ivcon -rn filein_name fileout_name
|
|
|
|
where "-rn" signals the "reverse normals" option, or
|
|
|
|
ivcon -rf filein_name fileout_name
|
|
|
|
where "-rf" signals the "reverse faces" option.
|
|
|
|
Modified:
|
|
|
|
28 June 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int iarg;
|
|
int icor3;
|
|
int ierror;
|
|
int iface;
|
|
int ivert;
|
|
int reverse_faces;
|
|
int reverse_normals;
|
|
/*
|
|
Initialize local data.
|
|
*/
|
|
iarg = 0;
|
|
ierror = 0;
|
|
reverse_faces = FALSE;
|
|
reverse_normals = FALSE;
|
|
/*
|
|
Initialize the graphics data.
|
|
*/
|
|
data_init ( );
|
|
/*
|
|
Get the -RN option, -RF option, and the input file name.
|
|
*/
|
|
iarg = iarg + 1;
|
|
strcpy ( filein_name, argv[iarg] );
|
|
|
|
if ( leqi ( filein_name, "-RN" ) == TRUE ) {
|
|
reverse_normals = TRUE;
|
|
printf ( "\n" );
|
|
printf ( "COMMAND_LINE: Reverse_Normals option requested.\n" );
|
|
iarg = iarg + 1;
|
|
strcpy ( filein_name, argv[iarg] );
|
|
}
|
|
|
|
if ( leqi ( filein_name, "-RF" ) == TRUE ) {
|
|
reverse_faces = TRUE;
|
|
printf ( "\n" );
|
|
printf ( "COMMAND_LINE: Reverse_Faces option requested.\n" );
|
|
iarg = iarg + 1;
|
|
strcpy ( filein_name, argv[iarg] );
|
|
}
|
|
/*
|
|
Read the input.
|
|
*/
|
|
ierror = data_read ( );
|
|
|
|
if ( ierror == ERROR ) {
|
|
printf ( "\n" );
|
|
printf ( "COMMAND_LINE - Fatal error!\n" );
|
|
printf ( " Failure while reading input data.\n" );
|
|
return ERROR;
|
|
}
|
|
/*
|
|
Reverse the normal vectors if requested.
|
|
*/
|
|
if ( reverse_normals == TRUE ) {
|
|
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
cor3_normal[i][icor3] = - cor3_normal[i][icor3];
|
|
}
|
|
}
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
face_normal[i][iface] = - face_normal[i][iface];
|
|
}
|
|
}
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
vertex_normal[i][ivert][iface] =
|
|
- vertex_normal[i][ivert][iface];
|
|
}
|
|
}
|
|
}
|
|
printf ( "\n" );
|
|
printf ( "COMMAND_LINE - Note:\n" );
|
|
printf ( " Reversed node, face, and vertex normals.\n" );
|
|
}
|
|
/*
|
|
Reverse the faces if requested.
|
|
*/
|
|
if ( reverse_faces == TRUE ) {
|
|
|
|
face_reverse_order ( );
|
|
|
|
printf ( "\n" );
|
|
printf ( "COMMAND_LINE - Note:\n" );
|
|
printf ( " Reversed the face definitions.\n" );
|
|
}
|
|
/*
|
|
Write the output file.
|
|
*/
|
|
iarg = iarg + 1;
|
|
strcpy ( fileout_name, argv[iarg] );
|
|
|
|
ierror = data_write ( );
|
|
|
|
if ( ierror == ERROR ) {
|
|
printf ( "\n" );
|
|
printf ( "COMMAND_LINE - Fatal error!\n" );
|
|
printf ( " Failure while writing output data.\n" );
|
|
return ERROR;
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
void cor3_normal_set ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
COR3_NORMAL_SET computes node normal vectors.
|
|
|
|
Modified:
|
|
|
|
18 November 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int icor3;
|
|
int iface;
|
|
int ivert;
|
|
int j;
|
|
float norm;
|
|
float temp;
|
|
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
for ( j = 0; j < 3; j++ ) {
|
|
cor3_normal[j][icor3] = 0.0;
|
|
}
|
|
}
|
|
/*
|
|
Add up the normals at all the faces to which the node belongs.
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
|
|
icor3 = face[ivert][iface];
|
|
|
|
for ( j = 0; j < 3; j++ ) {
|
|
cor3_normal[j][icor3] = cor3_normal[j][icor3]
|
|
+ vertex_normal[j][ivert][iface];
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
Renormalize.
|
|
*/
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
|
|
norm = 0.0;
|
|
for ( j = 0; j < 3; j++ ) {
|
|
temp = cor3_normal[j][icor3];
|
|
norm = norm + temp * temp;
|
|
}
|
|
|
|
if ( norm == 0.0 ) {
|
|
norm = 3.0;
|
|
for ( j = 0; j < 3; j++ ) {
|
|
cor3_normal[j][icor3] = 1.0;
|
|
}
|
|
}
|
|
|
|
norm = ( float ) sqrt ( norm );
|
|
|
|
for ( j = 0; j < 3; j++ ) {
|
|
cor3_normal[j][icor3] = cor3_normal[j][icor3] / norm;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
void cor3_range ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
COR3_RANGE computes the coordinate minima and maxima.
|
|
|
|
Modified:
|
|
|
|
31 August 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
float xave;
|
|
float xmax;
|
|
float xmin;
|
|
float yave;
|
|
float ymax;
|
|
float ymin;
|
|
float zave;
|
|
float zmax;
|
|
float zmin;
|
|
|
|
xave = cor3[0][0];
|
|
xmax = cor3[0][0];
|
|
xmin = cor3[0][0];
|
|
|
|
yave = cor3[1][0];
|
|
ymax = cor3[1][0];
|
|
ymin = cor3[1][0];
|
|
|
|
zave = cor3[2][0];
|
|
zmax = cor3[2][0];
|
|
zmin = cor3[2][0];
|
|
|
|
for ( i = 1; i < cor3_num; i++ ) {
|
|
|
|
xave = xave + cor3[0][i];
|
|
if ( cor3[0][i] < xmin ) {
|
|
xmin = cor3[0][i];
|
|
}
|
|
if ( cor3[0][i] > xmax ) {
|
|
xmax = cor3[0][i];
|
|
}
|
|
|
|
yave = yave + cor3[1][i];
|
|
if ( cor3[1][i] < ymin ) {
|
|
ymin = cor3[1][i];
|
|
}
|
|
if ( cor3[1][i] > ymax ) {
|
|
ymax = cor3[1][i];
|
|
}
|
|
|
|
zave = zave + cor3[2][i];
|
|
if ( cor3[2][i] < zmin ) {
|
|
zmin = cor3[2][i];
|
|
}
|
|
if ( cor3[2][i] > zmax ) {
|
|
zmax = cor3[2][i];
|
|
}
|
|
}
|
|
|
|
xave = xave / cor3_num;
|
|
yave = yave / cor3_num;
|
|
zave = zave / cor3_num;
|
|
|
|
printf ( "\n" );
|
|
printf ( "COR3_RANGE - Data range:\n" );
|
|
printf ( "\n" );
|
|
printf ( " Minimum Average Maximum Range\n" );
|
|
printf ( "\n" );
|
|
printf ( "X %f %f %f %f\n", xmin, xave, xmax, xmax-xmin );
|
|
printf ( "Y %f %f %f %f\n", ymin, yave, ymax, ymax-ymin );
|
|
printf ( "Z %f %f %f %f\n", zmin, zave, zmax, zmax-zmin );
|
|
|
|
}
|
|
/******************************************************************************/
|
|
|
|
void data_check ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
DATA_CHECK checks the input data.
|
|
|
|
Modified:
|
|
|
|
18 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int iface;
|
|
int nfix;
|
|
|
|
if ( color_num > COLOR_MAX ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_CHECK - Warning!\n" );
|
|
printf ( " The input data requires %d colors.\n", color_num );
|
|
printf ( " There was only room for %d\n", COLOR_MAX );
|
|
color_num = COLOR_MAX;
|
|
}
|
|
|
|
if ( cor3_num > COR3_MAX ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_CHECK - Warning!\n" );
|
|
printf ( " The input data requires %d points.\n", cor3_num );
|
|
printf ( " There was only room for %d\n", COR3_MAX );
|
|
cor3_num = COR3_MAX;
|
|
}
|
|
|
|
if ( face_num > FACE_MAX ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_CHECK - Warning!\n" );
|
|
printf ( " The input data requires %d faces.\n", face_num );
|
|
printf ( " There was only room for %d\n", FACE_MAX );
|
|
face_num = FACE_MAX;
|
|
}
|
|
|
|
if ( line_num > LINES_MAX ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_CHECK - Warning!\n" );
|
|
printf ( " The input data requires %d line items.\n", line_num );
|
|
printf ( " There was only room for %d.\n", LINES_MAX );
|
|
line_num = LINES_MAX;
|
|
}
|
|
|
|
nfix = 0;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
if ( face_order[iface] > ORDER_MAX ) {
|
|
face_order[iface] = ORDER_MAX;
|
|
nfix = nfix + 1;
|
|
}
|
|
|
|
}
|
|
|
|
if ( nfix > 0 ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_CHECK - Warning!\n" );
|
|
printf ( " Corrected %d faces using more than %d vertices per face.\n",
|
|
nfix, ORDER_MAX );
|
|
}
|
|
|
|
for ( i = 0; i < material_num; i++ ) {
|
|
if ( strcmp ( material_name[i], "" ) == 0 ) {
|
|
strcpy ( material_name[i], "Material_0000" );
|
|
}
|
|
}
|
|
|
|
for ( i = 0; i < texture_num; i++ ) {
|
|
if ( strcmp ( texture_name[i], "" ) == 0 ) {
|
|
strcpy ( texture_name[i], "Texture_0000" );
|
|
}
|
|
}
|
|
|
|
printf ( "\n" );
|
|
printf ( "DATA_CHECK - Data checked.\n" );
|
|
|
|
return;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
void data_init ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
DATA_INIT initializes the internal graphics data.
|
|
|
|
Modified:
|
|
|
|
04 July 2000
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int iface;
|
|
int ivert;
|
|
int j;
|
|
int k;
|
|
|
|
strcpy( anim_name, "" );
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
background_rgb[i] = 0.0;
|
|
}
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
for ( j = 0; j < COR3_MAX; j++ ) {
|
|
cor3[i][j] = 0.0;
|
|
}
|
|
}
|
|
|
|
for ( i = 0; i < COR3_MAX; i++ ) {
|
|
cor3_material[i] = 0;
|
|
}
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
for ( j = 0; j < COR3_MAX; j++ ) {
|
|
cor3_normal[i][j] = 0.0;
|
|
}
|
|
}
|
|
|
|
for ( j = 0; j < COR3_MAX; j++ ) {
|
|
cor3_tex_uv[0][j] = 0.0;
|
|
cor3_tex_uv[1][j] = 0.0;
|
|
}
|
|
|
|
for ( iface = 0; iface < FACE_MAX; iface++ ) {
|
|
for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
|
|
face[ivert][iface] = 0;
|
|
}
|
|
}
|
|
|
|
for ( iface = 0; iface < FACE_MAX; iface++ ) {
|
|
face_flags[iface] = 6;
|
|
}
|
|
|
|
for ( iface = 0; iface < FACE_MAX; iface++ ) {
|
|
face_material[iface] = 0;
|
|
}
|
|
|
|
for ( iface = 0; iface < FACE_MAX; iface++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
face_normal[i][iface] = 0;
|
|
}
|
|
}
|
|
|
|
for ( iface = 0; iface < FACE_MAX; iface++ ) {
|
|
face_object[iface] = -1;
|
|
}
|
|
|
|
for ( iface = 0; iface < FACE_MAX; iface++ ) {
|
|
face_order[iface] = 0;
|
|
}
|
|
|
|
for ( iface = 0; iface < FACE_MAX; iface++ ) {
|
|
face_smooth[iface] = 1;
|
|
}
|
|
|
|
for ( i = 0; i < LINES_MAX; i++ ) {
|
|
line_dex[i] = -1;
|
|
}
|
|
|
|
for ( i = 0; i < LINES_MAX; i++ ) {
|
|
line_material[i] = 0;
|
|
}
|
|
|
|
strcpy ( material_binding, "DEFAULT" );
|
|
|
|
for ( j = 0; j < MATERIAL_MAX; j++ ) {
|
|
strcpy ( material_name[j], "Material_0000" );
|
|
}
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
for ( j = 0; j < MATERIAL_MAX; j++ ) {
|
|
material_rgba[i][j] = 0.0;
|
|
}
|
|
}
|
|
|
|
strcpy ( normal_binding, "DEFAULT" );
|
|
|
|
for ( j = 0; j < ORDER_MAX*FACE_MAX; j++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
normal_temp[i][j] = 0;
|
|
}
|
|
}
|
|
|
|
color_num = 0;
|
|
cor3_num = 0;
|
|
face_num = 0;
|
|
group_num = 0;
|
|
line_num = 0;
|
|
material_num = 0;
|
|
object_num = 0;
|
|
texture_num = 0;
|
|
|
|
strcpy ( object_name, "IVCON" );
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
origin[i] = 0.0;
|
|
}
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
pivot[i] = 0.0;
|
|
}
|
|
|
|
for ( j = 0; j < COLOR_MAX; j++ ) {
|
|
rgbcolor[0][j] = 0.299;
|
|
rgbcolor[1][j] = 0.587;
|
|
rgbcolor[2][j] = 0.114;
|
|
}
|
|
|
|
strcpy ( texture_binding, "DEFAULT" );
|
|
|
|
for ( j = 0; j < TEXTURE_MAX; j++ ) {
|
|
strcpy ( texture_name[j], "Texture_0000" );
|
|
}
|
|
|
|
tmat_init ( transform_matrix );
|
|
|
|
for ( iface = 0; iface < FACE_MAX; iface++ ) {
|
|
for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
|
|
vertex_material[ivert][iface] = 0;
|
|
}
|
|
}
|
|
|
|
for ( iface = 0; iface < FACE_MAX; iface++ ) {
|
|
for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
vertex_normal[i][ivert][iface] = 0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( j = 0; j < 3; j++ ) {
|
|
for ( k = 0; k < FACE_MAX; k++ ) {
|
|
vertex_rgb[0][j][k] = 0.299;
|
|
vertex_rgb[1][j][k] = 0.587;
|
|
vertex_rgb[2][j][k] = 0.114;
|
|
}
|
|
}
|
|
|
|
for ( iface = 0; iface < FACE_MAX; iface++ ) {
|
|
for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
|
|
for ( i = 0; i < 2; i++ ) {
|
|
vertex_tex_uv[i][ivert][iface] = 0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( debug ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_INIT: Graphics data initialized.\n" );
|
|
}
|
|
|
|
return;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int data_read ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
DATA_READ reads a file into internal graphics data.
|
|
|
|
Modified:
|
|
|
|
26 September 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
FILE *filein;
|
|
char *filein_type;
|
|
int icor3;
|
|
int ierror;
|
|
int iface;
|
|
int iline;
|
|
int ivert;
|
|
int ntemp;
|
|
/*
|
|
Retrieve the input file type.
|
|
*/
|
|
filein_type = file_ext ( filein_name );
|
|
|
|
if ( filein_type == NULL ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_READ - Fatal error!\n" );
|
|
printf ( " Could not determine the type of '%s'.\n", filein_name );
|
|
return ERROR;
|
|
}
|
|
else if ( debug ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_READ: Input file has type %s.\n", filein_type );
|
|
}
|
|
/*
|
|
Initialize some data.
|
|
*/
|
|
max_order2 = 0;
|
|
bad_num = 0;
|
|
bytes_num = 0;
|
|
comment_num = 0;
|
|
dup_num = 0;
|
|
text_num = 0;
|
|
/*
|
|
Open the file.
|
|
*/
|
|
if ( leqi ( filein_type, "3DS" ) == TRUE ||
|
|
leqi ( filein_type, "STLB" ) == TRUE ||
|
|
leqi ( filein_type, "TRIB" ) == TRUE ) {
|
|
filein = fopen ( filein_name, "rb" );
|
|
}
|
|
else {
|
|
filein = fopen ( filein_name, "r" );
|
|
}
|
|
|
|
if ( filein == NULL ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_READ - Fatal error!\n" );
|
|
printf ( " Could not open the input file '%s'!\n", filein_name );
|
|
return ERROR;
|
|
}
|
|
/*
|
|
Read the information in the file.
|
|
*/
|
|
if ( leqi ( filein_type, "3DS" ) == TRUE ) {
|
|
|
|
ierror = tds_read ( filein );
|
|
/*
|
|
Cleanup: distribute the node textures to the vertices.
|
|
*/
|
|
if ( ierror == SUCCESS ) {
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
icor3 = face[ivert][iface];
|
|
vertex_tex_uv[0][ivert][iface] = cor3_tex_uv[0][icor3];
|
|
vertex_tex_uv[1][ivert][iface] = cor3_tex_uv[1][icor3];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
else if ( leqi ( filein_type, "ASE" ) == TRUE ) {
|
|
|
|
ierror = ase_read ( filein );
|
|
|
|
if ( ierror == SUCCESS ) {
|
|
|
|
node_to_vertex_material ( );
|
|
|
|
vertex_to_face_material ( );
|
|
|
|
}
|
|
|
|
}
|
|
else if ( leqi ( filein_type, "BYU" ) == TRUE ) {
|
|
|
|
ierror = byu_read ( filein );
|
|
|
|
}
|
|
else if ( leqi ( filein_type, "DXF" ) == TRUE ) {
|
|
|
|
ierror = dxf_read ( filein );
|
|
|
|
}
|
|
else if ( leqi ( filein_type, "GMOD" ) == TRUE ) {
|
|
|
|
ierror = gmod_read ( filein );
|
|
|
|
}
|
|
else if ( leqi ( filein_type, "HRC" ) == TRUE ) {
|
|
|
|
ierror = hrc_read ( filein );
|
|
|
|
}
|
|
else if ( leqi ( filein_type, "IV" ) == TRUE ) {
|
|
|
|
ierror = iv_read ( filein );
|
|
|
|
}
|
|
else if ( leqi ( filein_type, "OBJ" ) == TRUE ) {
|
|
|
|
ierror = obj_read ( filein );
|
|
|
|
}
|
|
else if ( leqi ( filein_type, "SMF" ) == TRUE ) {
|
|
|
|
ierror = smf_read ( filein );
|
|
|
|
}
|
|
else if (
|
|
leqi ( filein_type, "STL" ) == TRUE ||
|
|
leqi ( filein_type, "STLA") == TRUE ) {
|
|
|
|
ierror = stla_read ( filein );
|
|
|
|
if( ierror ) {
|
|
// might be binary
|
|
fclose(filein);
|
|
filein = fopen ( filein_name, "rb" );
|
|
ierror = stlb_read ( filein );
|
|
}
|
|
}
|
|
else if ( leqi ( filein_type, "STLB") == TRUE ) {
|
|
|
|
ierror = stlb_read ( filein );
|
|
|
|
}
|
|
else if (
|
|
leqi ( filein_type, "TRI" ) == TRUE ||
|
|
leqi ( filein_type, "TRIA") == TRUE ) {
|
|
|
|
ierror = tria_read ( filein );
|
|
|
|
}
|
|
else if ( leqi ( filein_type, "TRIB") == TRUE ) {
|
|
|
|
ierror = trib_read ( filein );
|
|
|
|
}
|
|
else if ( leqi ( filein_type, "VLA" ) == TRUE ) {
|
|
|
|
ierror = vla_read ( filein );
|
|
|
|
}
|
|
else {
|
|
printf ( "\n" );
|
|
printf ( "DATA_READ - Fatal error!\n" );
|
|
printf ( " Unacceptable input file type.\n" );
|
|
return ERROR;
|
|
}
|
|
|
|
fclose ( filein );
|
|
|
|
if ( debug ) {
|
|
printf ( "DATA_READ: Finished reading the data file.\n" );
|
|
}
|
|
/*
|
|
Catch errors reported by the various reading routines.
|
|
*/
|
|
if ( ierror == ERROR ) {
|
|
return ierror;
|
|
}
|
|
/*
|
|
Restore the transformation matrix.
|
|
*/
|
|
tmat_init ( transform_matrix );
|
|
/*
|
|
Report on what we read.
|
|
*/
|
|
if ( face_num < FACE_MAX ) {
|
|
ntemp = face_num;
|
|
}
|
|
else {
|
|
ntemp = FACE_MAX;
|
|
}
|
|
|
|
max_order2 = ivec_max ( ntemp, face_order );
|
|
|
|
data_report ( );
|
|
/*
|
|
Warn about any errors that occurred during reading.
|
|
*/
|
|
if ( ierror == ERROR ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_READ - Fatal error!\n" );
|
|
printf ( " An error occurred while reading the input file.\n" );
|
|
return ERROR;
|
|
}
|
|
/*
|
|
Check the data.
|
|
You MUST wait until after this check before doing other computations,
|
|
since COR3_NUM and other variables could be much larger than the legal
|
|
maximums, until corrected by DATA_CHECK.
|
|
*/
|
|
data_check ( );
|
|
/*
|
|
MATERIALS FIXUPS:
|
|
|
|
If there are no materials at all, define one.
|
|
*/
|
|
if ( material_num < 1 ) {
|
|
material_num = 1;
|
|
strcpy ( material_name[0], "Material_0000" );
|
|
material_rgba[0][0] = 0.7;
|
|
material_rgba[1][0] = 0.7;
|
|
material_rgba[2][0] = 0.7;
|
|
material_rgba[3][0] = 1.0;
|
|
}
|
|
/*
|
|
If a node has not been assigned a material, set it to material 0.
|
|
*/
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
if ( cor3_material[icor3] < 0 || cor3_material[icor3] > material_num - 1 ) {
|
|
cor3_material[icor3] = 0;
|
|
}
|
|
}
|
|
/*
|
|
If a vertex has not been assigned a material, set it to material 0.
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
if ( vertex_material[ivert][iface] < 0 || vertex_material[ivert][iface] > material_num - 1 ) {
|
|
vertex_material[ivert][iface] = 0;
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
If a face has not been assigned a material, set it to material 0.
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
if ( face_material[iface] < 0 || face_material[iface] > material_num - 1 ) {
|
|
face_material[iface] = 0;
|
|
}
|
|
}
|
|
/*
|
|
If a line item has not been assigned a material, set it to material 0.
|
|
*/
|
|
for ( iline = 0; iline < line_num; iline++ ) {
|
|
if ( line_dex[iline] == -1 ) {
|
|
line_material[iline] = -1;
|
|
}
|
|
else if ( line_material[iline] < 0 || line_material[iline] > material_num - 1 ) {
|
|
line_material[iline] = 0;
|
|
}
|
|
}
|
|
/*
|
|
Delete edges of zero length.
|
|
*/
|
|
edge_null_delete ( );
|
|
/*
|
|
Compute the area of each face.
|
|
*/
|
|
face_area_set ( );
|
|
/*
|
|
Delete faces with zero area.
|
|
*/
|
|
face_null_delete ( );
|
|
/*
|
|
Recompute zero face-vertex normals from vertex positions.
|
|
*/
|
|
vertex_normal_set ( );
|
|
/*
|
|
Compute the node normals from the vertex normals.
|
|
*/
|
|
cor3_normal_set ( );
|
|
/*
|
|
Recompute zero face normals by averaging face-vertex normals.
|
|
*/
|
|
face_normal_ave ( );
|
|
/*
|
|
Report on the nodal coordinate range.
|
|
*/
|
|
cor3_range ( );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
void data_report ( void )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
DATA_REPORT gives a summary of the contents of the data file.
|
|
|
|
Modified:
|
|
|
|
24 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
printf ( "\n" );
|
|
printf ( "DATA_REPORT - The input file contains:\n" );
|
|
printf ( "\n" );
|
|
printf ( " Bad data items %d\n", bad_num );
|
|
printf ( " Text lines %d\n", text_num );
|
|
printf ( " Text bytes (binary data) %d\n", bytes_num );
|
|
printf ( " Colors %d\n", color_num );
|
|
printf ( " Comments %d\n", comment_num );
|
|
printf ( " Duplicate points %d\n", dup_num );
|
|
printf ( " Faces %d\n", face_num );
|
|
printf ( " Groups %d\n", group_num );
|
|
printf ( " Vertices per face, maximum %d\n", max_order2 );
|
|
printf ( " Line items %d\n", line_num );
|
|
printf ( " Points %d\n", cor3_num );
|
|
printf ( " Objects %d\n", object_num );
|
|
|
|
return;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int data_write ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
DATA_WRITE writes the internal graphics data to a file.
|
|
|
|
Modified:
|
|
|
|
22 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
FILE *fileout;
|
|
char *fileout_type;
|
|
int line_num_save;
|
|
int result;
|
|
|
|
result = SUCCESS;
|
|
/*
|
|
Retrieve the output file type.
|
|
*/
|
|
fileout_type = file_ext ( fileout_name );
|
|
|
|
if ( fileout_type == NULL ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_WRITE - Fatal error!\n" );
|
|
printf ( " Could not determine the output file type.\n" );
|
|
return ERROR;
|
|
}
|
|
/*
|
|
Open the output file.
|
|
*/
|
|
if ( leqi ( fileout_type, "3DS" ) == TRUE ||
|
|
leqi ( fileout_type, "STLB" ) == TRUE ||
|
|
leqi ( fileout_type, "TRIB" ) ) {
|
|
fileout = fopen ( fileout_name, "wb" );
|
|
}
|
|
else {
|
|
fileout = fopen ( fileout_name, "w" );
|
|
}
|
|
|
|
if ( fileout == NULL ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_WRITE - Fatal error!\n" );
|
|
printf ( " Could not open the output file!\n" );
|
|
return ERROR;
|
|
}
|
|
/*
|
|
Write the output file.
|
|
*/
|
|
if ( leqi ( fileout_type, "3DS" ) == TRUE ) {
|
|
|
|
tds_pre_process();
|
|
result = tds_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "ASE" ) == TRUE ) {
|
|
|
|
result = ase_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "BYU" ) == TRUE ) {
|
|
|
|
result = byu_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "DXF" ) == TRUE ) {
|
|
|
|
result = dxf_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "GMOD" ) == TRUE ) {
|
|
|
|
result = gmod_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "HRC" ) == TRUE ) {
|
|
|
|
result = hrc_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "IV" ) == TRUE ) {
|
|
|
|
result = iv_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "OBJ" ) == TRUE ) {
|
|
|
|
result = obj_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "POV" ) == TRUE ) {
|
|
|
|
result = pov_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "SMF" ) == TRUE ) {
|
|
|
|
result = smf_write ( fileout );
|
|
|
|
}
|
|
else if (
|
|
leqi ( fileout_type, "STL" ) == TRUE ||
|
|
leqi ( fileout_type, "STLA" ) == TRUE ) {
|
|
|
|
result = stla_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "STLB" ) == TRUE ) {
|
|
|
|
result = stlb_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "TEC" ) == TRUE ) {
|
|
|
|
result = tec_write ( fileout );
|
|
|
|
}
|
|
else if (
|
|
leqi ( fileout_type, "TRI" ) == TRUE ||
|
|
leqi ( fileout_type, "TRIA" ) == TRUE ) {
|
|
|
|
result = tria_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "TRIB" ) == TRUE ) {
|
|
|
|
result = trib_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "TXT" ) == TRUE ) {
|
|
|
|
result = txt_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "UCD" ) == TRUE ) {
|
|
|
|
result = ucd_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "VLA" ) == TRUE ) {
|
|
|
|
line_num_save = line_num;
|
|
|
|
if ( face_num > 0 ) {
|
|
|
|
printf ( "\n" );
|
|
printf ( "DATA_WRITE - Note:\n" );
|
|
printf ( " Face information will temporarily be converted to\n" );
|
|
printf ( " line information for output to a VLA file.\n" );
|
|
|
|
face_to_line ( );
|
|
|
|
if ( line_num > LINES_MAX ) {
|
|
printf ( "\n" );
|
|
printf ( "DATA_WRITE - Warning:\n" );
|
|
printf ( " Some face information was lost.\n" );
|
|
printf ( " The maximum number of lines is %d.\n", LINES_MAX );
|
|
printf ( " The number of lines needed is %d.\n", line_num );
|
|
line_num = LINES_MAX;
|
|
}
|
|
|
|
}
|
|
|
|
result = vla_write ( fileout );
|
|
|
|
line_num = line_num_save;
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "WRL" ) == TRUE ) {
|
|
|
|
result = wrl_write ( fileout );
|
|
|
|
}
|
|
else if ( leqi ( fileout_type, "XGL" ) == TRUE ) {
|
|
|
|
result = xgl_write ( fileout );
|
|
|
|
}
|
|
else {
|
|
|
|
result = ERROR;
|
|
printf ( "\n" );
|
|
printf ( "DATA_WRITE - Fatal error!\n" );
|
|
printf ( " Unacceptable output file type \"%s\".\n", fileout_type );
|
|
|
|
}
|
|
/*
|
|
Close the output file.
|
|
*/
|
|
fclose ( fileout );
|
|
|
|
if ( result == ERROR ) {
|
|
return ERROR;
|
|
}
|
|
else {
|
|
return SUCCESS;
|
|
}
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int dxf_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
DXF_READ reads an AutoCAD DXF file.
|
|
|
|
Examples:
|
|
|
|
0
|
|
SECTION
|
|
2
|
|
HEADER
|
|
999
|
|
diamond.dxf created by IVREAD.
|
|
999
|
|
Original data in diamond.obj.
|
|
0
|
|
ENDSEC
|
|
0
|
|
SECTION
|
|
2
|
|
TABLES
|
|
0
|
|
ENDSEC
|
|
0
|
|
SECTION
|
|
2
|
|
BLOCKS
|
|
0
|
|
ENDSEC
|
|
0
|
|
SECTION
|
|
2
|
|
ENTITIES
|
|
0
|
|
LINE
|
|
8
|
|
0
|
|
10
|
|
0.00 (X coordinate of beginning of line.)
|
|
20
|
|
0.00 (Y coordinate of beginning of line.)
|
|
30
|
|
0.00 (Z coordinate of beginning of line.)
|
|
11
|
|
1.32 (X coordinate of end of line.)
|
|
21
|
|
1.73 (Y coordinate of end of line.)
|
|
31
|
|
2.25 (Z coordinate of end of line.)
|
|
0
|
|
3DFACE
|
|
8
|
|
Cube
|
|
10
|
|
-0.50 (X coordinate of vertex 1)
|
|
20
|
|
0.50 (Y coordinate of vertex 1)
|
|
30
|
|
1.0 (Z coordinate of vertex 1)
|
|
11
|
|
0.50 (X coordinate of vertex 2)
|
|
21
|
|
0.50 (Y coordinate of vertex 2)
|
|
31
|
|
1.0 (Z coordinate of vertex 2)
|
|
12
|
|
0.50 (X coordinate of vertex 3)
|
|
22
|
|
0.50 (Y coordinate of vertex 3)
|
|
32
|
|
0.00 (Z coordinate of vertex 3)
|
|
0
|
|
ENDSEC
|
|
0
|
|
EOF
|
|
|
|
Modified:
|
|
|
|
23 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int code;
|
|
int count;
|
|
float cvec[3];
|
|
int icor3;
|
|
char input1[LINE_MAX_LEN];
|
|
char input2[LINE_MAX_LEN];
|
|
int ivert;
|
|
float rval;
|
|
int width;
|
|
int linemode;
|
|
int cpos;
|
|
|
|
linemode = 0;
|
|
ivert = 0;
|
|
/*
|
|
Read the next two lines of the file into INPUT1 and INPUT2.
|
|
*/
|
|
|
|
for ( ;; ) {
|
|
|
|
/*
|
|
INPUT1 should contain a single integer, which tells what INPUT2
|
|
will contain.
|
|
*/
|
|
if ( fgets ( input1, LINE_MAX_LEN, filein ) == NULL ) {
|
|
break;
|
|
}
|
|
|
|
text_num = text_num + 1;
|
|
|
|
count = sscanf ( input1, "%d%n", &code, &width );
|
|
if ( count <= 0 ) {
|
|
break;
|
|
}
|
|
/*
|
|
Read the second line, and interpret it according to the code.
|
|
*/
|
|
if ( fgets ( input2, LINE_MAX_LEN, filein ) == NULL ) {
|
|
break;
|
|
}
|
|
|
|
text_num = text_num + 1;
|
|
|
|
if ( code == 0 ) {
|
|
|
|
if ( ivert > 0 ) {
|
|
/* finish off the face */
|
|
face_order[face_num] = ivert;
|
|
face_num = face_num + 1;
|
|
ivert = 0;
|
|
}
|
|
|
|
if ( strncmp( input2, "LINE", 4 ) == 0 ) {
|
|
linemode = 1;
|
|
}
|
|
else if ( strncmp( input2, "3DFACE", 6 ) == 0 ) {
|
|
linemode = 0;
|
|
ivert = 0;
|
|
}
|
|
}
|
|
else {
|
|
|
|
for (cpos = 0; input1[cpos] == ' '; cpos++)
|
|
{};
|
|
|
|
if ( input1[cpos] == '1' || input1[cpos] == '2' || input1[cpos] == '3' ) {
|
|
|
|
count = sscanf ( input2, "%e%n", &rval, &width );
|
|
|
|
switch ( input1[cpos] )
|
|
{
|
|
case '1':
|
|
if ( line_num > 0 ) {
|
|
if ( linemode ) {
|
|
line_dex[line_num] = - 1;
|
|
line_material[line_num] = - 1;
|
|
line_num = line_num + 1;
|
|
}
|
|
}
|
|
cvec[0] = rval;
|
|
break;
|
|
|
|
case '2':
|
|
cvec[1] = rval;
|
|
break;
|
|
|
|
case '3':
|
|
cvec[2] = rval;
|
|
|
|
if ( cor3_num < 1000 ) {
|
|
icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
|
|
}
|
|
else {
|
|
icor3 = -1;
|
|
}
|
|
|
|
if ( icor3 == -1 ) {
|
|
icor3 = cor3_num;
|
|
if ( cor3_num < COR3_MAX ) {
|
|
cor3[0][cor3_num] = cvec[0];
|
|
cor3[1][cor3_num] = cvec[1];
|
|
cor3[2][cor3_num] = cvec[2];
|
|
}
|
|
cor3_num = cor3_num + 1;
|
|
}
|
|
else {
|
|
dup_num = dup_num + 1;
|
|
}
|
|
|
|
if ( linemode ) {
|
|
line_dex[line_num] = icor3;
|
|
line_material[line_num] = 0;
|
|
line_num = line_num + 1;
|
|
}
|
|
else {
|
|
face[ivert][face_num] = icor3;
|
|
ivert = ivert + 1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( line_num > 0 ) {
|
|
if ( linemode ) {
|
|
line_dex[line_num] = - 1;
|
|
line_material[line_num] = - 1;
|
|
line_num = line_num + 1;
|
|
}
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int dxf_write ( FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
DXF_WRITE writes graphics information to an AutoCAD DXF file.
|
|
|
|
Examples:
|
|
|
|
0
|
|
SECTION
|
|
2
|
|
HEADER
|
|
999
|
|
diamond.dxf created by IVREAD.
|
|
999
|
|
Original data in diamond.obj.
|
|
0
|
|
ENDSEC
|
|
0
|
|
SECTION
|
|
2
|
|
TABLES
|
|
0
|
|
ENDSEC
|
|
0
|
|
SECTION
|
|
2
|
|
BLOCKS
|
|
0
|
|
ENDSEC
|
|
0
|
|
SECTION
|
|
2
|
|
ENTITIES
|
|
0
|
|
LINE
|
|
8
|
|
0
|
|
10
|
|
0.00 (X coordinate of beginning of line.)
|
|
20
|
|
0.00 (Y coordinate of beginning of line.)
|
|
30
|
|
0.00 (Z coordinate of beginning of line.)
|
|
11
|
|
1.32 (X coordinate of end of line.)
|
|
21
|
|
1.73 (Y coordinate of end of line.)
|
|
31
|
|
2.25 (Z coordinate of end of line.)
|
|
0
|
|
3DFACE
|
|
8
|
|
Cube
|
|
10
|
|
-0.50 (X coordinate of vertex 1)
|
|
20
|
|
0.50 (Y coordinate of vertex 1)
|
|
30
|
|
1.0 (Z coordinate of vertex 1)
|
|
11
|
|
0.50 (X coordinate of vertex 2)
|
|
21
|
|
0.50 (Y coordinate of vertex 2)
|
|
31
|
|
1.0 (Z coordinate of vertex 2)
|
|
12
|
|
0.50 (X coordinate of vertex 3)
|
|
22
|
|
0.50 (Y coordinate of vertex 3)
|
|
32
|
|
0.00 (Z coordinate of vertex 3)
|
|
0
|
|
ENDSEC
|
|
0
|
|
EOF
|
|
|
|
Modified:
|
|
|
|
16 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int icor3;
|
|
int iline;
|
|
int iface;
|
|
int ivert;
|
|
int jcor3;
|
|
int newline;
|
|
int text_num;
|
|
|
|
/*
|
|
Initialize.
|
|
*/
|
|
text_num = 0;
|
|
|
|
fprintf ( fileout, " 0\n" );
|
|
fprintf ( fileout, "SECTION\n" );
|
|
fprintf ( fileout, " 2\n" );
|
|
fprintf ( fileout, "HEADER\n" );
|
|
fprintf ( fileout, "999\n" );
|
|
fprintf ( fileout, "%s created by IVCON.\n", fileout_name );
|
|
fprintf ( fileout, "999\n" );
|
|
fprintf ( fileout, "Original data in %s.\n", filein_name );
|
|
fprintf ( fileout, " 0\n" );
|
|
fprintf ( fileout, "ENDSEC\n" );
|
|
text_num = text_num + 10;
|
|
|
|
fprintf ( fileout, " 0\n" );
|
|
fprintf ( fileout, "SECTION\n" );
|
|
fprintf ( fileout, " 2\n" );
|
|
fprintf ( fileout, "TABLES\n" );
|
|
fprintf ( fileout, " 0\n" );
|
|
fprintf ( fileout, "ENDSEC\n" );
|
|
text_num = text_num + 6;
|
|
|
|
fprintf ( fileout, " 0\n" );
|
|
fprintf ( fileout, "SECTION\n" );
|
|
fprintf ( fileout, " 2\n" );
|
|
fprintf ( fileout, "BLOCKS\n" );
|
|
fprintf ( fileout, " 0\n" );
|
|
fprintf ( fileout, "ENDSEC\n" );
|
|
text_num = text_num + 6;
|
|
|
|
fprintf ( fileout, " 0\n" );
|
|
fprintf ( fileout, "SECTION\n" );
|
|
fprintf ( fileout, " 2\n" );
|
|
fprintf ( fileout, "ENTITIES\n" );
|
|
text_num = text_num + 4;
|
|
/*
|
|
Handle lines.
|
|
*/
|
|
jcor3 = 0;
|
|
newline = TRUE;
|
|
|
|
for ( iline = 0; iline < line_num; iline++ ) {
|
|
|
|
icor3 = line_dex[iline];
|
|
|
|
if ( icor3 == -1 ) {
|
|
|
|
newline = TRUE;
|
|
}
|
|
else {
|
|
|
|
if ( newline == FALSE ) {
|
|
|
|
fprintf ( fileout, " 0\n" );
|
|
fprintf ( fileout, "LINE\n" );
|
|
fprintf ( fileout, " 8\n" );
|
|
fprintf ( fileout, " 0\n" );
|
|
fprintf ( fileout, " 10\n" );
|
|
fprintf ( fileout, "%f\n", cor3[0][jcor3] );
|
|
fprintf ( fileout, " 20\n" );
|
|
fprintf ( fileout, "%f\n", cor3[1][jcor3] );
|
|
fprintf ( fileout, " 30\n" );
|
|
fprintf ( fileout, "%f\n", cor3[2][jcor3] );
|
|
fprintf ( fileout, " 11\n" );
|
|
fprintf ( fileout, "%f\n", cor3[0][icor3] );
|
|
fprintf ( fileout, " 21\n" );
|
|
fprintf ( fileout, "%f\n", cor3[1][icor3] );
|
|
fprintf ( fileout, " 31\n" );
|
|
fprintf ( fileout, "%f\n", cor3[2][icor3] );
|
|
|
|
text_num = text_num + 16;
|
|
|
|
}
|
|
|
|
jcor3 = icor3;
|
|
newline = FALSE;
|
|
|
|
}
|
|
}
|
|
/*
|
|
Handle faces.
|
|
(If FACE_ORDER is greater than 10, you're sure to have problems here)
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
fprintf ( fileout, " 0\n" );
|
|
fprintf ( fileout, "3DFACE\n" );
|
|
fprintf ( fileout, " 8\n" );
|
|
fprintf ( fileout, " Cube\n" );
|
|
text_num = text_num + 4;
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
|
|
icor3 = face[ivert][iface];
|
|
|
|
fprintf ( fileout, "1%d\n", ivert );
|
|
fprintf ( fileout, "%f\n", cor3[0][icor3] );
|
|
fprintf ( fileout, "2%d\n", ivert );
|
|
fprintf ( fileout, "%f\n", cor3[1][icor3] );
|
|
fprintf ( fileout, "3%d\n", ivert );
|
|
fprintf ( fileout, "%f\n", cor3[2][icor3] );
|
|
|
|
text_num = text_num + 6;
|
|
}
|
|
}
|
|
|
|
fprintf ( fileout, " 0\n" );
|
|
fprintf ( fileout, "ENDSEC\n" );
|
|
fprintf ( fileout, " 0\n" );
|
|
fprintf ( fileout, "EOF\n" );
|
|
text_num = text_num + 4;
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "DXF_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
void edge_null_delete ( void )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
EDGE_NULL_DELETE deletes face edges with zero length.
|
|
|
|
Modified:
|
|
|
|
16 July 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
float distsq;
|
|
int face2[ORDER_MAX];
|
|
int face_order2;
|
|
int iface;
|
|
int inode;
|
|
int ivert;
|
|
int j;
|
|
int jnode;
|
|
int jvert;
|
|
int edge_num;
|
|
int edge_num_del;
|
|
float vertex_normal2[3][ORDER_MAX];
|
|
float x;
|
|
float y;
|
|
float z;
|
|
|
|
edge_num = 0;
|
|
edge_num_del = 0;
|
|
/*
|
|
Consider each face.
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
/*
|
|
Consider each pair of consecutive vertices.
|
|
*/
|
|
face_order2 = 0;
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
|
|
edge_num = edge_num + 1;
|
|
|
|
jvert = ivert + 1;
|
|
if ( jvert >= face_order[iface] ) {
|
|
jvert = 0;
|
|
}
|
|
|
|
inode = face[ivert][iface];
|
|
jnode = face[jvert][iface];
|
|
|
|
|
|
x = cor3[0][inode] - cor3[0][jnode];
|
|
y = cor3[1][inode] - cor3[1][jnode];
|
|
z = cor3[2][inode] - cor3[2][jnode];
|
|
|
|
distsq = x * x + y * y + z * z;
|
|
|
|
if ( distsq != 0.0 ) {
|
|
face2[face_order2] = face[ivert][iface];
|
|
vertex_normal2[0][face_order2] = vertex_normal[0][ivert][iface];
|
|
vertex_normal2[1][face_order2] = vertex_normal[1][ivert][iface];
|
|
vertex_normal2[2][face_order2] = vertex_normal[2][ivert][iface];
|
|
face_order2 = face_order2 + 1;
|
|
}
|
|
else {
|
|
edge_num_del = edge_num_del + 1;
|
|
}
|
|
|
|
}
|
|
|
|
face_order[iface] = face_order2;
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
face[ivert][iface] = face2[ivert];
|
|
for ( j = 0; j < 3; j++ ) {
|
|
vertex_normal[j][ivert][iface] = vertex_normal2[j][ivert];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
printf ( "\n" );
|
|
printf ( "EDGE_NULL_DELETE:\n" );
|
|
printf ( " There are a total of %d edges.\n", edge_num );
|
|
printf ( " Of these, %d were of zero length, and deleted.\n", edge_num_del );
|
|
|
|
return;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
void face_area_set ( void )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
FACE_AREA_SET computes the area of the faces.
|
|
|
|
Formula:
|
|
|
|
The area is the sum of the areas of the triangles formed by
|
|
node N with consecutive pairs of nodes.
|
|
|
|
Reference:
|
|
|
|
Adrian Bowyer and John Woodwark,
|
|
A Programmer's Geometry,
|
|
Butterworths, 1983.
|
|
|
|
Modified:
|
|
|
|
17 July 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
float alpha;
|
|
float area_max;
|
|
float area_min;
|
|
float area_tri;
|
|
float base;
|
|
float dot;
|
|
float height;
|
|
int i;
|
|
int i1;
|
|
int i2;
|
|
int i3;
|
|
int iface;
|
|
int face_num_del;
|
|
float tol;
|
|
float x;
|
|
float x1;
|
|
float x2;
|
|
float x3;
|
|
float y;
|
|
float y1;
|
|
float y2;
|
|
float y3;
|
|
float z;
|
|
float z1;
|
|
float z2;
|
|
float z3;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
face_area[iface] = 0.0;
|
|
|
|
for ( i = 0; i < face_order[iface]-2; i++ ) {
|
|
|
|
i1 = face[i][iface];
|
|
i2 = face[i+1][iface];
|
|
i3 = face[i+2][iface];
|
|
|
|
x1 = cor3[0][i1];
|
|
y1 = cor3[1][i1];
|
|
z1 = cor3[2][i1];
|
|
|
|
x2 = cor3[0][i2];
|
|
y2 = cor3[1][i2];
|
|
z2 = cor3[2][i2];
|
|
|
|
x3 = cor3[0][i3];
|
|
y3 = cor3[1][i3];
|
|
z3 = cor3[2][i3];
|
|
/*
|
|
Find the projection of (P3-P1) onto (P2-P1).
|
|
*/
|
|
dot =
|
|
( x2 - x1 ) * ( x3 - x1 ) +
|
|
( y2 - y1 ) * ( y3 - y1 ) +
|
|
( z2 - z1 ) * ( z3 - z1 );
|
|
|
|
base = sqrt (
|
|
( x2 - x1 ) * ( x2 - x1 )
|
|
+ ( y2 - y1 ) * ( y2 - y1 )
|
|
+ ( z2 - z1 ) * ( z2 - z1 ) );
|
|
/*
|
|
The height of the triangle is the length of (P3-P1) after its
|
|
projection onto (P2-P1) has been subtracted.
|
|
*/
|
|
if ( base == 0.0 ) {
|
|
height = 0.0;
|
|
}
|
|
else {
|
|
|
|
alpha = dot / ( base * base );
|
|
|
|
x = x3 - x1 - alpha * ( x2 - x1 );
|
|
y = y3 - y1 - alpha * ( y2 - y1 );
|
|
z = z3 - z1 - alpha * ( z2 - z1 );
|
|
|
|
height = sqrt ( x * x + y * y + z * z );
|
|
|
|
}
|
|
|
|
area_tri = 0.5 * base * height;
|
|
|
|
face_area[iface] = face_area[iface] + area_tri;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
area_min = face_area[0];
|
|
area_max = face_area[0];
|
|
|
|
for ( iface = 1; iface < face_num; iface++ ) {
|
|
if ( area_min > face_area[iface] ) {
|
|
area_min = face_area[iface];
|
|
}
|
|
if ( area_max < face_area[iface] ) {
|
|
area_max = face_area[iface];
|
|
}
|
|
}
|
|
|
|
printf ( "\n" );
|
|
printf ( "FACE_AREA_SET:\n" );
|
|
printf ( " Minimum face area is %f\n", area_min );
|
|
printf ( " Maximum face area is %f\n", area_max );
|
|
|
|
tol = area_max / 10000.0;
|
|
|
|
if ( area_min < tol ) {
|
|
|
|
face_num_del = 0;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
if ( face_area[iface] < tol ) {
|
|
face_order[iface] = 0;
|
|
face_num_del = face_num_del + 1;
|
|
}
|
|
}
|
|
|
|
printf ( " Marked %d tiny faces for deletion.\n", face_num_del );
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
void face_normal_ave ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
FACE_NORMAL_AVE sets face normals as average of face vertex normals.
|
|
|
|
Modified:
|
|
|
|
09 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int iface;
|
|
int ivert;
|
|
int nfix;
|
|
float norm;
|
|
float x;
|
|
float y;
|
|
float z;
|
|
|
|
if ( face_num <= 0 ) {
|
|
return;
|
|
}
|
|
|
|
nfix = 0;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
/*
|
|
Check the norm of the current normal vector.
|
|
*/
|
|
x = face_normal[0][iface];
|
|
y = face_normal[1][iface];
|
|
z = face_normal[2][iface];
|
|
norm = ( float ) sqrt ( x * x + y * y + z * z );
|
|
|
|
if ( norm == 0.0 ) {
|
|
|
|
nfix = nfix + 1;
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
face_normal[i][iface] = 0.0;
|
|
}
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
face_normal[i][iface] = face_normal[i][iface] +
|
|
vertex_normal[i][ivert][iface];
|
|
}
|
|
}
|
|
|
|
x = face_normal[0][iface];
|
|
y = face_normal[1][iface];
|
|
z = face_normal[2][iface];
|
|
norm = ( float ) sqrt ( x * x + y * y + z * z );
|
|
|
|
if ( norm == 0.0 ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
face_normal[i][iface] = ( float ) ( 1.0 / sqrt ( 3.0 ) );
|
|
}
|
|
}
|
|
else {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
face_normal[i][iface] = face_normal[i][iface] / norm;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( nfix > 0 ) {
|
|
printf ( "\n" );
|
|
printf ( "FACE_NORMAL_AVE: Recomputed %d face normals\n", nfix );
|
|
printf ( " by averaging face vertex normals.\n" );
|
|
}
|
|
return;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
void face_null_delete ( void )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
FACE_NULL_DELETE deletes faces of order less than 3.
|
|
|
|
Comments:
|
|
|
|
Thanks to Susan M. Fisher, University of North Carolina,
|
|
Department of Computer Science, for pointing out a coding error
|
|
in FACE_NULL_DELETE that was overwriting all the data!
|
|
|
|
Modified:
|
|
|
|
30 November 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int iface;
|
|
int ivert;
|
|
int j;
|
|
int face_num2;
|
|
/*
|
|
FACE_NUM2 is the number of faces we'll keep.
|
|
*/
|
|
face_num2 = 0;
|
|
/*
|
|
Check every face.
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
/*
|
|
Keep it only if it has order 3 or more.
|
|
*/
|
|
if ( face_order[iface] >= 3 ) {
|
|
/*
|
|
We don't have to slide data down in the array until
|
|
NUMFACE2 and IFACE get out of synch, that is, after
|
|
we've discarded at least one face.
|
|
*/
|
|
if ( face_num2 != iface ) {
|
|
|
|
face_area[face_num2] = face_area[iface];
|
|
face_material[face_num2] = face_material[iface];
|
|
face_order[face_num2] = face_order[iface];
|
|
for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
|
|
face[ivert][face_num2] = face[ivert][iface];
|
|
vertex_material[ivert][face_num2] = vertex_material[ivert][iface];
|
|
for ( j = 0; j < 3; j++ ) {
|
|
vertex_normal[j][ivert][face_num2] = vertex_normal[j][ivert][iface];
|
|
}
|
|
}
|
|
|
|
}
|
|
/*
|
|
Update the count only after we've used the un-incremented value
|
|
as a pointer.
|
|
*/
|
|
face_num2 = face_num2 + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf ( "\n" );
|
|
printf ( "FACE_NULL_DELETE\n" );
|
|
printf ( " There are a total of %d faces.\n", face_num );
|
|
printf ( " Of these, %d passed the order test.\n", face_num2 );
|
|
|
|
face_num = face_num2;
|
|
|
|
return;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int face_print ( int iface )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
FACE_PRINT prints out information about a face.
|
|
|
|
Modified:
|
|
|
|
31 August 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int ivert;
|
|
int j;
|
|
int k;
|
|
|
|
if ( iface < 0 || iface > face_num-1 ) {
|
|
printf ( "\n" );
|
|
printf ( "FACE_PRINT - Fatal error!\n" );
|
|
printf ( " Face indices must be between 1 and %d\n", face_num );
|
|
printf ( " But your requested value was %d\n", iface );
|
|
return ERROR;
|
|
}
|
|
|
|
printf ( "\n" );
|
|
printf ( "FACE_PRINT\n" );
|
|
printf ( " Information about face %d\n", iface );
|
|
printf ( "\n" );
|
|
printf ( " Number of vertices is %d\n", face_order[iface] );
|
|
printf ( "\n" );
|
|
printf ( " Vertex list:\n" );
|
|
printf ( " Vertex #, Node #, Material #, X, Y, Z:\n" );
|
|
printf ( "\n" );
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
j = face[ivert][iface];
|
|
k = vertex_material[ivert][iface];
|
|
printf ( " %d %d %d %f %f %f\n", ivert, j, k, cor3[0][j], cor3[1][j],
|
|
cor3[2][j] );
|
|
}
|
|
|
|
printf ( "\n" );
|
|
printf ( " Face normal vector:\n" );
|
|
printf ( "\n" );
|
|
printf ( " %f %f %f\n", face_normal[0][iface], face_normal[1][iface],
|
|
face_normal[2][iface] );
|
|
|
|
printf ( "\n" );
|
|
printf ( " Vertex face normals:\n" );
|
|
printf ( "\n" );
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
printf ( " %d %f %f %f\n", ivert, vertex_normal[0][ivert][iface],
|
|
vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
|
|
}
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
/**********************************************************************/
|
|
|
|
void face_reverse_order ( void )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
FACE_REVERSE_ORDER reverses the order of the nodes in each face.
|
|
|
|
Discussion:
|
|
|
|
Reversing the order of the nodes requires that the normal vectors
|
|
be reversed as well, so this routine will automatically reverse
|
|
the normals associated with nodes, vertices and faces.
|
|
|
|
Modified:
|
|
|
|
28 June 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int iface;
|
|
int itemp;
|
|
int ivert;
|
|
int j;
|
|
int m;
|
|
float temp;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
m = face_order[iface];
|
|
|
|
for ( ivert = 0; ivert < ( m / 2 ); ivert++ ) {
|
|
|
|
itemp = face[ivert][iface];
|
|
face[ivert][iface] = face[m-1-ivert][iface];
|
|
face[m-1-ivert][iface] = itemp;
|
|
|
|
itemp = vertex_material[ivert][iface];
|
|
vertex_material[ivert][iface] = vertex_material[m-1-ivert][iface];
|
|
vertex_material[m-1-ivert][iface] = itemp;
|
|
|
|
for ( j = 0; j < 3; j++ ) {
|
|
temp = vertex_normal[j][ivert][iface];
|
|
vertex_normal[j][ivert][iface] = vertex_normal[j][m-1-ivert][iface];
|
|
vertex_normal[j][m-1-ivert][iface] = temp;
|
|
}
|
|
|
|
for ( j = 0; j < 2; j++ ) {
|
|
temp = vertex_tex_uv[j][ivert][iface];
|
|
vertex_tex_uv[j][ivert][iface] = vertex_tex_uv[j][m-1-ivert][iface];
|
|
vertex_tex_uv[j][m-1-ivert][iface] = temp;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for ( i = 0; i < cor3_num; i++ ) {
|
|
for ( j = 0; j < 3; j++ ) {
|
|
cor3_normal[j][i] = - cor3_normal[j][i];
|
|
}
|
|
}
|
|
|
|
for ( i = 0; i < face_num; i++ ) {
|
|
for ( j = 0; j < 3; j++ ) {
|
|
face_normal[j][i] = - face_normal[j][i];
|
|
}
|
|
}
|
|
|
|
printf ( "\n" );
|
|
printf ( "FACE_REVERSE_ORDER\n" );
|
|
printf ( " Each list of nodes defining a face\n" );
|
|
printf ( " has been reversed; related information,\n" );
|
|
printf ( " including normal vectors, was also updated.\n" );
|
|
|
|
return;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
int face_subset ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
FACE_SUBSET selects a subset of the current faces as the new object.
|
|
|
|
Warning:
|
|
|
|
The original graphic object is overwritten by the new one.
|
|
|
|
Modified:
|
|
|
|
12 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
*/
|
|
{
|
|
int i;
|
|
int iface;
|
|
int iface1;
|
|
int iface2;
|
|
int inc;
|
|
int ivert;
|
|
int j;
|
|
int k;
|
|
int cor3_num2;
|
|
|
|
line_num = 0;
|
|
/*
|
|
Get the first and last faces to save, IFACE1 and IFACE2.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "Enter lowest face number to save between 0 and %d:\n", face_num-1 );
|
|
scanf ( "%d", &iface1 );
|
|
if ( iface1 < 0 || iface1 > face_num - 1 ) {
|
|
printf ( "Illegal choice!\n" );
|
|
return ERROR;
|
|
}
|
|
|
|
printf ( "\n" );
|
|
printf ( "Enter highest face number to save between %d and %d:\n",
|
|
iface1, face_num-1 );
|
|
scanf ( "%d", &iface2 );
|
|
if ( iface2 < iface1 || iface2 > face_num - 1 ) {
|
|
printf ( "Illegal choice!\n" );
|
|
return ERROR;
|
|
}
|
|
|
|
inc = iface1;
|
|
/*
|
|
"Slide" the data for the saved faces down the face arrays.
|
|
*/
|
|
for ( iface = 0; iface < iface2 + 1 - iface1; iface++ ) {
|
|
face_order[iface] = face_order[iface+inc];
|
|
for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
|
|
face[ivert][iface] = face[ivert][iface+inc];
|
|
vertex_material[ivert][iface] = vertex_material[ivert][iface+inc];
|
|
for ( i = 0; i < 3; i++ ) {
|
|
vertex_normal[i][ivert][iface] =
|
|
vertex_normal[i][ivert][iface+inc];
|
|
vertex_rgb[i][ivert][iface] = vertex_rgb[i][ivert][iface+inc];
|
|
}
|
|
}
|
|
for ( i = 0; i < 3; i++ ) {
|
|
face_normal[i][iface] = face_normal[i][iface+inc];
|
|
}
|
|
}
|
|
/*
|
|
Now reset the number of faces.
|
|
*/
|
|
face_num = iface2 + 1 - iface1;
|
|
/*
|
|
Now, for each point I, set LIST(I) = J if point I is the J-th
|
|
point we are going to save, and 0 otherwise. Then J will be
|
|
the new label of point I.
|
|
*/
|
|
for ( i = 0; i < cor3_num; i++ ) {
|
|
list[i] = -1;
|
|
}
|
|
|
|
cor3_num2 = 0;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ){
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ){
|
|
j = face[ivert][iface];
|
|
if ( list[j] == -1 ) {
|
|
cor3_num2 = cor3_num2 + 1;
|
|
list[j] = cor3_num2;
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
Now make the nonzero list entries rise in order, so that
|
|
we can compress the COR3 data in a minute.
|
|
*/
|
|
cor3_num2 = 0;
|
|
|
|
for ( i = 0; i < cor3_num; i++ ) {
|
|
if ( list[i] != -1 ) {
|
|
list[i] = cor3_num2;
|
|
cor3_num2 = cor3_num2 + 1;
|
|
}
|
|
}
|
|
/*
|
|
Relabel the FACE array with the new node indices.
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ){
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ){
|
|
j = face[ivert][iface];
|
|
face[ivert][iface] = list[j];
|
|
}
|
|
}
|
|
/*
|
|
Rebuild the COR3 array by sliding data down.
|
|
*/
|
|
for ( i = 0; i < cor3_num; i++ ){
|
|
k = list[i];
|
|
if ( k != -1 ) {
|
|
for ( j = 0; j < 3; j++ ) {
|
|
cor3[j][k] = cor3[j][i];
|
|
}
|
|
}
|
|
}
|
|
|
|
cor3_num = cor3_num2;
|
|
|
|
return SUCCESS;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
void face_to_line ( void )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
FACE_TO_LINE converts face information to line information.
|
|
|
|
Discussion:
|
|
|
|
In some cases, the graphic information represented by polygonal faces
|
|
must be converted to a representation based solely on line segments.
|
|
This is particularly true if a VLA file is being written.
|
|
|
|
Modified:
|
|
|
|
26 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int icor3;
|
|
int iface;
|
|
int ivert;
|
|
int jcor3;
|
|
int jvert;
|
|
/*
|
|
Case 0:
|
|
No line pruning.
|
|
*/
|
|
if ( line_prune == 0 ) {
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
|
|
icor3 = face[ivert][iface];
|
|
|
|
line_num = line_num + 1;
|
|
if ( line_num <= LINES_MAX ) {
|
|
line_dex[line_num] = icor3;
|
|
line_material[line_num] = vertex_material[ivert][iface];
|
|
}
|
|
}
|
|
|
|
ivert = 0;
|
|
icor3 = face[ivert][iface];
|
|
|
|
line_num = line_num + 1;
|
|
if ( line_num <= LINES_MAX ) {
|
|
line_dex[line_num] = icor3;
|
|
line_material[line_num] = vertex_material[ivert][iface];
|
|
}
|
|
|
|
line_num = line_num + 1;
|
|
if ( line_num <= LINES_MAX ) {
|
|
line_dex[line_num] = -1;
|
|
line_material[line_num] = -1;
|
|
}
|
|
}
|
|
|
|
}
|
|
/*
|
|
Case 2:
|
|
Simple-minded line pruning.
|
|
Only draw line (I,J) if I < J.
|
|
*/
|
|
else {
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
|
|
icor3 = face[ivert][iface];
|
|
|
|
if ( ivert + 1 < face_order[iface] ) {
|
|
jvert = ivert + 1;
|
|
}
|
|
else {
|
|
jvert = 0;
|
|
}
|
|
|
|
jcor3 = face[jvert][iface];
|
|
|
|
if ( icor3 < jcor3 ) {
|
|
|
|
if ( line_num + 3 < LINES_MAX ) {
|
|
|
|
line_num = line_num + 1;
|
|
line_dex[line_num] = icor3;
|
|
line_material[line_num] = vertex_material[ivert][iface];
|
|
|
|
line_num = line_num + 1;
|
|
line_dex[line_num] = jcor3;
|
|
line_material[line_num] = vertex_material[jvert][iface];
|
|
|
|
line_num = line_num + 1;
|
|
line_dex[line_num] = -1;
|
|
line_material[line_num] = -1;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
void face_to_vertex_material ( void )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
FACE_TO_VERTEX_MAT extends face material definitions to vertices.
|
|
|
|
Discussion:
|
|
|
|
Assuming material indices are defined for all the faces, this
|
|
routine assigns to each vertex of a face the material of that face.
|
|
|
|
Modified:
|
|
|
|
22 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int iface;
|
|
int ivert;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
vertex_material[ivert][iface] = face_material[iface];
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
char *file_ext ( char *file_name )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
FILE_EXT picks out the extension in a file name.
|
|
|
|
Modified:
|
|
|
|
21 July 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
|
|
i = char_index_last ( file_name, '.' );
|
|
|
|
if ( i == -1 ) {
|
|
return NULL;
|
|
}
|
|
else {
|
|
return file_name + i + 1;
|
|
}
|
|
}
|
|
/******************************************************************************/
|
|
|
|
float float_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
FLOAT_READ reads 1 float from a binary file.
|
|
|
|
Modified:
|
|
|
|
24 May 1999
|
|
*/
|
|
{
|
|
float rval;
|
|
float temp;
|
|
|
|
fread ( &temp, sizeof ( float ), 1, filein );
|
|
|
|
if ( byte_swap == TRUE ) {
|
|
rval = float_reverse_bytes ( temp );
|
|
}
|
|
else {
|
|
rval = temp;
|
|
}
|
|
|
|
return rval;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
float float_reverse_bytes ( float x )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
FLOAT_REVERSE_BYTES reverses the four bytes in a float.
|
|
|
|
Modified:
|
|
|
|
24 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Parameters:
|
|
|
|
X, a float whose bytes are to be reversed.
|
|
|
|
FLOAT_REVERSE_BYTES, a float with bytes in reverse order from those in X.
|
|
*/
|
|
{
|
|
char c;
|
|
union {
|
|
float yfloat;
|
|
char ychar[4];
|
|
} y;
|
|
|
|
y.yfloat = x;
|
|
|
|
c = y.ychar[0];
|
|
y.ychar[0] = y.ychar[3];
|
|
y.ychar[3] = c;
|
|
|
|
c = y.ychar[1];
|
|
y.ychar[1] = y.ychar[2];
|
|
y.ychar[2] = c;
|
|
|
|
return ( y.yfloat );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int float_write ( FILE *fileout, float float_val )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
FLOAT_WRITE writes 1 float to a binary file.
|
|
|
|
Modified:
|
|
|
|
23 September 1998
|
|
*/
|
|
{
|
|
int nbyte = sizeof ( float );
|
|
float temp;
|
|
|
|
if ( byte_swap == TRUE ) {
|
|
temp = float_reverse_bytes ( float_val );
|
|
}
|
|
else {
|
|
temp = float_val;
|
|
}
|
|
|
|
fwrite ( &temp, nbyte, 1, fileout );
|
|
|
|
return nbyte;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int gmod_arch_check ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
GMOD_ARCH_CHECK inquires into some features of the computer architecture.
|
|
|
|
Modified:
|
|
|
|
19 May 1999
|
|
|
|
Author:
|
|
|
|
Zik Saleeba (zik@zikzak.net)
|
|
*/
|
|
{
|
|
static unsigned char one[4];
|
|
int temp;
|
|
|
|
temp = sizeof ( float );
|
|
if ( temp != 4 ) {
|
|
return FALSE;
|
|
}
|
|
|
|
*(float *)one = 1.0;
|
|
|
|
if (one[0] == 0 && one[1] == 0 && one[2] == 128 && one[3] == 63) {
|
|
/* little endian IEEE floats */
|
|
return TRUE;
|
|
}
|
|
|
|
if (one[0] == 63 && one[1] == 128 && one[2] == 0 && one[3] == 0) {
|
|
/* big endian IEEE floats */
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int gmod_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
GMOD_READ reads a golgotha GMOD file.
|
|
|
|
Modified:
|
|
|
|
19 May 1999
|
|
|
|
Author:
|
|
|
|
Zik Saleeba (zik@zikzak.net)
|
|
*/
|
|
|
|
/*
|
|
golgotha GMOD file format:
|
|
|
|
|
|
FILE HEADER
|
|
|
|
w32 magic number f9 fa 63 1e
|
|
w32 number of sections
|
|
[ number of sections
|
|
w32 section id
|
|
w32 section offset
|
|
]
|
|
|
|
|
|
TEXTURE NAME SECTION - section id = 0x13 (19)
|
|
|
|
w16 number of faces
|
|
[ number of faces
|
|
w16 texture name length
|
|
[ texture name length
|
|
w8 texture name character
|
|
]
|
|
]
|
|
|
|
|
|
|
|
MODEL QUADS SECTION - section id = 0x12 (18)
|
|
|
|
w16 number of faces
|
|
[ number of faces
|
|
[ four vertices
|
|
w16 vertex index
|
|
float xpos (0.0-1.0)
|
|
float ypos (0.0-1.0)
|
|
]
|
|
float scale
|
|
w16 flags
|
|
float xnormal (normal should be normalised)
|
|
float ynormal
|
|
float znormal
|
|
]
|
|
|
|
|
|
VERTEX ARRAY SECTION - section id = 0x14 (20)
|
|
|
|
w16 number of vertices
|
|
w16 number of animations
|
|
w16 length of animation name
|
|
[ length of animation name
|
|
w8 animation name character
|
|
]
|
|
w16 number of frames in animation
|
|
[ number of frames in animation
|
|
[ number of vertices
|
|
float xpos
|
|
float ypos
|
|
float zpos
|
|
float xnormal
|
|
float ynormal
|
|
float znormal
|
|
]
|
|
]
|
|
*/
|
|
{
|
|
unsigned char MagicNumber[4];
|
|
unsigned long int NumSections;
|
|
int SectionCount;
|
|
unsigned long int SectionID[GMOD_MAX_SECTIONS];
|
|
unsigned long int SectionOffset[GMOD_MAX_SECTIONS];
|
|
|
|
unsigned short NumAnimations;
|
|
unsigned short NumFrames;
|
|
unsigned short FaceCount;
|
|
unsigned short TextureCount;
|
|
int VertexCount;
|
|
|
|
float Scale;
|
|
unsigned short Flags;
|
|
unsigned short TextureNameLen;
|
|
unsigned short AnimationNameLen;
|
|
int Order;
|
|
int MaxCor = 0;
|
|
|
|
/*
|
|
* check if we can handle this architecture
|
|
*/
|
|
|
|
if (!gmod_arch_check()) {
|
|
printf("GMOD_READ - This architecture not supported.\n");
|
|
return ERROR;
|
|
}
|
|
|
|
/*
|
|
* read the file header
|
|
*/
|
|
|
|
/* read the magic number */
|
|
fread(MagicNumber, 1, 4, filein);
|
|
if (MagicNumber[0] != 0xf9 ||
|
|
MagicNumber[1] != 0xfa ||
|
|
MagicNumber[2] != 0x63 ||
|
|
MagicNumber[3] != 0x1e) {
|
|
printf("GMOD_READ - Bad magic number on GMOD file.\n");
|
|
return ERROR;
|
|
}
|
|
|
|
NumSections = gmod_read_w32(filein);
|
|
if (NumSections >= GMOD_MAX_SECTIONS) {
|
|
printf("GMOD_READ - Too many sections (%ld) in GMOD file - please increase static limit GMOD_MAX_SECTIONS\n", NumSections);
|
|
return ERROR;
|
|
}
|
|
|
|
/*
|
|
Read the sections.
|
|
*/
|
|
|
|
for ( SectionCount = 0; SectionCount < ( int ) NumSections; SectionCount++ ) {
|
|
SectionID[SectionCount] = gmod_read_w32(filein);
|
|
SectionOffset[SectionCount] = gmod_read_w32(filein);
|
|
}
|
|
/*
|
|
Read each successive section.
|
|
*/
|
|
for ( SectionCount = 0; SectionCount < ( int ) NumSections; SectionCount++ ) {
|
|
/*
|
|
Go to the start of the section.
|
|
*/
|
|
fseek ( filein, ( long int ) SectionOffset[SectionCount], SEEK_SET );
|
|
/*
|
|
What type of section is it?
|
|
*/
|
|
switch (SectionID[SectionCount]) {
|
|
|
|
/*
|
|
Model section.
|
|
*/
|
|
case G1_SECTION_MODEL_QUADS:
|
|
/*
|
|
Get the number of faces.
|
|
*/
|
|
face_num = gmod_read_w16 ( filein );
|
|
|
|
if (face_num > FACE_MAX) {
|
|
printf("GMOD_READ - Too many faces (%d) in GMOD file - please increase static limit FACE_MAX.\n", face_num);
|
|
return ERROR;
|
|
}
|
|
/*
|
|
Get the information on each face.
|
|
*/
|
|
for ( FaceCount = 0; FaceCount < ( unsigned short ) face_num; FaceCount++ ) {
|
|
|
|
Order = 0;
|
|
for ( VertexCount = 0; VertexCount < 4; VertexCount++ ) {
|
|
|
|
/* read the vertex index */
|
|
|
|
face[VertexCount][FaceCount] = gmod_read_w16(filein);
|
|
|
|
if (face[VertexCount][FaceCount] != GMOD_UNUSED_VERTEX) {
|
|
Order = VertexCount+1;
|
|
if (MaxCor < face[VertexCount][FaceCount])
|
|
MaxCor = face[VertexCount][FaceCount];
|
|
}
|
|
|
|
/* read the texture position */
|
|
|
|
vertex_tex_uv[0][VertexCount][FaceCount] = gmod_read_float(filein);
|
|
vertex_tex_uv[1][VertexCount][FaceCount] = gmod_read_float(filein);
|
|
}
|
|
|
|
/* scale and flags */
|
|
|
|
fread(&Scale, sizeof(Scale), 1, filein);
|
|
Flags = gmod_read_w16(filein);
|
|
|
|
if ( debug ) {
|
|
printf ( "Flags = %d\n", Flags );
|
|
}
|
|
|
|
/* normal vector */
|
|
|
|
face_normal[0][FaceCount] = gmod_read_float(filein);
|
|
face_normal[1][FaceCount] = gmod_read_float(filein);
|
|
face_normal[2][FaceCount] = gmod_read_float(filein);
|
|
|
|
/* the order is the number of used vertices */
|
|
|
|
face_order[FaceCount] = Order;
|
|
}
|
|
break;
|
|
|
|
|
|
/*
|
|
Texture name section.
|
|
*/
|
|
|
|
case G1_SECTION_MODEL_TEXTURE_NAMES:
|
|
|
|
/* get the number of textures */
|
|
|
|
texture_num = gmod_read_w16(filein);
|
|
if (texture_num > TEXTURE_MAX) {
|
|
printf ( "GMOD_READ - Too many texture maps (%d) in GMOD file.\n", texture_num );
|
|
printf ( " Increase static limit TEXTURE_MAX.\n" );
|
|
return ERROR;
|
|
}
|
|
face_num = texture_num;
|
|
|
|
for (TextureCount = 0; TextureCount < ( unsigned short ) texture_num;
|
|
TextureCount++) {
|
|
|
|
/* read the texture name */
|
|
|
|
TextureNameLen = gmod_read_w16(filein);
|
|
fread ( texture_name[TextureCount], sizeof(char), TextureNameLen, filein);
|
|
texture_name[TextureCount][TextureNameLen] = '\0';
|
|
}
|
|
break;
|
|
|
|
|
|
/*
|
|
* vertex section
|
|
*/
|
|
|
|
case G1_SECTION_MODEL_VERT_ANIMATION:
|
|
|
|
/* get the number of vertices */
|
|
|
|
cor3_num = gmod_read_w16(filein);
|
|
if (cor3_num > COR3_MAX) {
|
|
printf("GMOD_READ - Too many vertices (%d) in GMOD file - please increase static limit COR3_MAX.\n", cor3_num);
|
|
return ERROR;
|
|
}
|
|
|
|
/*
|
|
Get the number of animations.
|
|
*/
|
|
|
|
NumAnimations = gmod_read_w16(filein);
|
|
|
|
if (NumAnimations > 1) {
|
|
printf ( "GMOD_READ - Fatal error!\n" );
|
|
printf ( " GMOD files can only handle one animation.\n" );
|
|
printf ( " This file contains %d.\n", NumAnimations );
|
|
return ERROR;
|
|
}
|
|
|
|
/* read the animation name */
|
|
AnimationNameLen = gmod_read_w16(filein);
|
|
fread ( anim_name, sizeof(char), AnimationNameLen, filein);
|
|
anim_name[AnimationNameLen] = '\0';
|
|
|
|
/* get the number of frames of animation */
|
|
NumFrames = gmod_read_w16(filein);
|
|
if (NumFrames > 1)
|
|
printf("GMOD_READ - Too many frames of animation (%d) in GMOD file - will only use 1.\n", NumFrames);
|
|
|
|
/* go through all the vertices, reading each one */
|
|
for (VertexCount = 0; VertexCount < cor3_num; VertexCount++) {
|
|
|
|
/* read the vertex */
|
|
cor3[0][VertexCount] = gmod_read_float(filein);
|
|
cor3[1][VertexCount] = gmod_read_float(filein);
|
|
cor3[2][VertexCount] = gmod_read_float(filein);
|
|
|
|
/* read the normal */
|
|
cor3_normal[0][VertexCount] = gmod_read_float(filein);
|
|
cor3_normal[1][VertexCount] = gmod_read_float(filein);
|
|
cor3_normal[2][VertexCount] = gmod_read_float(filein);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Set some other stray info.
|
|
*/
|
|
line_num = 0;
|
|
|
|
/*
|
|
Check for sanity.
|
|
*/
|
|
if ( MaxCor >= cor3_num ) {
|
|
printf ( "GMOD_READ - Maximum coordinate index (%d)\n", MaxCor );
|
|
printf ( " exceeded number of coordinates (%d) in GMOD file.\n", cor3_num );
|
|
return ERROR;
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
float gmod_read_float ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
GMOD_READ_FLOAT reads a float from a Golgotha GMOD file.
|
|
|
|
Modified:
|
|
|
|
19 May 1999
|
|
|
|
Author:
|
|
|
|
Zik Saleeba (zik@zikzak.net)
|
|
*/
|
|
{
|
|
int endian = 1;
|
|
unsigned char *out_pos;
|
|
int i;
|
|
float Val;
|
|
|
|
if (*(char *)&endian == 1) {
|
|
/* we're little-endian, which is native for GMOD floats */
|
|
fread(&Val, sizeof(Val), 1, filein);
|
|
}
|
|
else {
|
|
/* we're big-endian, flip `em */
|
|
out_pos = (unsigned char *)&Val;
|
|
for ( i = sizeof(Val)-1; i >= 0; i-- ) {
|
|
*(out_pos+i) = fgetc(filein);
|
|
}
|
|
}
|
|
|
|
return Val;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned short gmod_read_w16 ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
GMOD_READ_W16 reads a 16 bit word from a Golgotha GMOD file.
|
|
|
|
Modified:
|
|
|
|
19 May 1999
|
|
|
|
Author:
|
|
|
|
Zik Saleeba (zik@zikzak.net)
|
|
*/
|
|
{
|
|
unsigned char Byte1;
|
|
unsigned char Byte2;
|
|
|
|
Byte1 = fgetc ( filein );
|
|
Byte2 = fgetc ( filein );
|
|
|
|
return Byte1 | (((unsigned short)Byte2) << 8);
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long gmod_read_w32 ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
GMOD_READ_W32 reads a 32 bit word from a Golgotha GMOD file.
|
|
|
|
Modified:
|
|
|
|
19 May 1999
|
|
|
|
Author:
|
|
|
|
Zik Saleeba (zik@zikzak.net)
|
|
*/
|
|
{
|
|
unsigned char Byte1, Byte2, Byte3, Byte4;
|
|
|
|
Byte1 = fgetc(filein);
|
|
Byte2 = fgetc(filein);
|
|
Byte3 = fgetc(filein);
|
|
Byte4 = fgetc(filein);
|
|
|
|
return Byte1 |
|
|
(((unsigned long)Byte2) << 8) |
|
|
(((unsigned long)Byte3) << 16) |
|
|
(((unsigned long)Byte4) << 24);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
int gmod_write ( FILE *fileout ) {
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
GMOD_WRITE writes a Golgotha GMOD file.
|
|
|
|
Modified:
|
|
|
|
19 May 1999
|
|
|
|
Author:
|
|
|
|
Zik Saleeba (zik@zikzak.net)
|
|
*/
|
|
static unsigned char MagicNumber[4] = { 0xf9, 0xfa, 0x63, 0x1e };
|
|
unsigned long NumSections;
|
|
unsigned long SectionHeaderPos;
|
|
unsigned long TextureNameSectionPos;
|
|
unsigned long ModelSectionPos;
|
|
unsigned long VertexSectionPos;
|
|
|
|
int VertexCount;
|
|
int FaceCount;
|
|
int TextureCount;
|
|
unsigned long SectionCount;
|
|
float Scale;
|
|
float Min[3];
|
|
float Max[3];
|
|
int CorNumber;
|
|
int DimensionCount;
|
|
float MaxWidth;
|
|
/*
|
|
Check if we can handle this architecture.
|
|
*/
|
|
|
|
if ( !gmod_arch_check() ) {
|
|
printf("GMOD_WRITE - This architecture not supported.\n");
|
|
return ERROR;
|
|
}
|
|
|
|
/*
|
|
Write the file header.
|
|
*/
|
|
|
|
/*
|
|
Write the magic number.
|
|
*/
|
|
fwrite ( MagicNumber, sizeof(char), 4, fileout );
|
|
|
|
/*
|
|
Write the number of sections.
|
|
*/
|
|
NumSections = 3;
|
|
gmod_write_w32 ( NumSections, fileout );
|
|
|
|
/*
|
|
Write a dummy section header which we'll overwrite later.
|
|
*/
|
|
SectionHeaderPos = ftell ( fileout );
|
|
for (SectionCount = 0; SectionCount < NumSections; SectionCount++) {
|
|
gmod_write_w32 ( 0, fileout );
|
|
gmod_write_w32 ( 0, fileout );
|
|
}
|
|
/*
|
|
Texture name section.
|
|
*/
|
|
|
|
/*
|
|
Take note of where we are in the file.
|
|
*/
|
|
TextureNameSectionPos = ftell ( fileout );
|
|
|
|
/*
|
|
Write the number of textures.
|
|
*/
|
|
|
|
gmod_write_w16 ( ( unsigned short ) face_num, fileout );
|
|
/*
|
|
Write the texture names.
|
|
*/
|
|
for ( TextureCount = 0; TextureCount < face_num; TextureCount++ ) {
|
|
|
|
gmod_write_w16 ( ( unsigned short ) strlen ( texture_name[TextureCount] ),
|
|
fileout );
|
|
|
|
fwrite ( texture_name[TextureCount], strlen ( texture_name[TextureCount] ),
|
|
1, fileout );
|
|
}
|
|
|
|
/*
|
|
Model section.
|
|
*/
|
|
|
|
/*
|
|
Take note of where we are in the file.
|
|
*/
|
|
|
|
ModelSectionPos = ftell(fileout);
|
|
|
|
/*
|
|
Write the number of faces.
|
|
*/
|
|
|
|
gmod_write_w16 ( ( unsigned short ) face_num, fileout );
|
|
|
|
/*
|
|
Write the information on each face.
|
|
*/
|
|
|
|
for ( FaceCount = 0; FaceCount < face_num; FaceCount++ ) {
|
|
|
|
for (VertexCount = 0; VertexCount < ((face_order[FaceCount] < 4) ? face_order[FaceCount] : 4); VertexCount++) {
|
|
|
|
/*
|
|
Write the vertex index.
|
|
*/
|
|
gmod_write_w16 ( ( unsigned short ) face[VertexCount][FaceCount], fileout );
|
|
|
|
/*
|
|
Write the texture position.
|
|
*/
|
|
|
|
gmod_write_float ( vertex_tex_uv[0][VertexCount][FaceCount], fileout );
|
|
gmod_write_float ( vertex_tex_uv[1][VertexCount][FaceCount], fileout );
|
|
}
|
|
|
|
/*
|
|
Write any extra vertices which are unused.
|
|
*/
|
|
|
|
for ( ; VertexCount < 4; VertexCount++ ) {
|
|
|
|
/*
|
|
Write the vertex index.
|
|
*/
|
|
gmod_write_w16 ( GMOD_UNUSED_VERTEX, fileout );
|
|
/*
|
|
Write the texture position.
|
|
*/
|
|
gmod_write_float ( vertex_tex_uv[0][VertexCount][FaceCount], fileout );
|
|
|
|
gmod_write_float ( vertex_tex_uv[1][VertexCount][FaceCount], fileout );
|
|
}
|
|
|
|
/*
|
|
Scale and flags.
|
|
*/
|
|
|
|
/*
|
|
Find the bounding box.
|
|
*/
|
|
|
|
for ( DimensionCount = 0; DimensionCount < 3; DimensionCount++ ) {
|
|
|
|
CorNumber = face[0][FaceCount];
|
|
Min[DimensionCount] = cor3[DimensionCount][CorNumber];
|
|
Max[DimensionCount] = cor3[DimensionCount][CorNumber];
|
|
|
|
for (VertexCount = 1; VertexCount < ((face_order[FaceCount] < 4) ? face_order[FaceCount] : 4); VertexCount++) {
|
|
|
|
CorNumber = face[VertexCount][FaceCount];
|
|
|
|
if (Min[DimensionCount] > cor3[DimensionCount][CorNumber])
|
|
Min[DimensionCount] = cor3[DimensionCount][CorNumber];
|
|
|
|
if (Max[DimensionCount] < cor3[DimensionCount][CorNumber])
|
|
Max[DimensionCount] = cor3[DimensionCount][CorNumber];
|
|
}
|
|
}
|
|
|
|
/*
|
|
The scale is the "width" of the face for mipmapping -
|
|
I just take the maximum bounding box dimension.
|
|
*/
|
|
MaxWidth = Max[0] - Min[0];
|
|
for ( DimensionCount = 1; DimensionCount < 3; DimensionCount++ ) {
|
|
|
|
if ( MaxWidth < Max[DimensionCount] - Min[DimensionCount] )
|
|
MaxWidth = Max[DimensionCount] - Min[DimensionCount];
|
|
}
|
|
|
|
Scale = MaxWidth;
|
|
fwrite ( &Scale, sizeof(Scale), 1, fileout );
|
|
|
|
/*
|
|
Flags are just nothing.
|
|
*/
|
|
gmod_write_w16 ( 0, fileout );
|
|
/*
|
|
Normal vector.
|
|
*/
|
|
gmod_write_float ( face_normal[0][FaceCount], fileout );
|
|
gmod_write_float ( face_normal[1][FaceCount], fileout );
|
|
gmod_write_float ( face_normal[2][FaceCount], fileout );
|
|
}
|
|
|
|
/*
|
|
Vertex section.
|
|
*/
|
|
|
|
/*
|
|
Take note of where we are in the file.
|
|
*/
|
|
|
|
VertexSectionPos = ftell ( fileout );
|
|
|
|
/*
|
|
Write the number of vertices.
|
|
*/
|
|
|
|
gmod_write_w16 ( ( unsigned short ) cor3_num, fileout );
|
|
|
|
/*
|
|
Write the number of animations.
|
|
*/
|
|
|
|
gmod_write_w16 ( 1, fileout );
|
|
|
|
/*
|
|
Write the animation name.
|
|
*/
|
|
|
|
gmod_write_w16 ( 0, fileout );
|
|
|
|
/*
|
|
Write the number of frames of animation.
|
|
*/
|
|
|
|
gmod_write_w16 ( 1, fileout );
|
|
|
|
/*
|
|
Go through all the vertices, writing each one.
|
|
*/
|
|
|
|
for ( VertexCount = 0; VertexCount < cor3_num; VertexCount++ ) {
|
|
|
|
/*
|
|
Write the vertex.
|
|
*/
|
|
gmod_write_float ( cor3[0][VertexCount], fileout );
|
|
gmod_write_float ( cor3[1][VertexCount], fileout );
|
|
gmod_write_float ( cor3[2][VertexCount], fileout );
|
|
|
|
/*
|
|
Write the normal.
|
|
*/
|
|
gmod_write_float ( cor3_normal[0][VertexCount], fileout );
|
|
gmod_write_float ( cor3_normal[1][VertexCount], fileout );
|
|
gmod_write_float ( cor3_normal[2][VertexCount], fileout );
|
|
}
|
|
/*
|
|
Now rewrite the section header.
|
|
*/
|
|
|
|
/*
|
|
Go back to the section header.
|
|
*/
|
|
fseek ( fileout, ( long int ) SectionHeaderPos, SEEK_SET );
|
|
|
|
/*
|
|
Write the texture name section header.
|
|
*/
|
|
gmod_write_w32 ( G1_SECTION_MODEL_TEXTURE_NAMES, fileout );
|
|
gmod_write_w32 ( TextureNameSectionPos, fileout );
|
|
|
|
/*
|
|
Write the model section header.
|
|
*/
|
|
gmod_write_w32 ( G1_SECTION_MODEL_QUADS, fileout );
|
|
gmod_write_w32 ( ModelSectionPos, fileout );
|
|
|
|
/*
|
|
Write the vertex section header.
|
|
*/
|
|
gmod_write_w32 ( G1_SECTION_MODEL_VERT_ANIMATION, fileout );
|
|
gmod_write_w32 ( VertexSectionPos, fileout );
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
void gmod_write_float ( float Val, FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
GMOD_WRITE_FLOAT writes a float to a Golgotha GMOD file.
|
|
|
|
Modified:
|
|
|
|
19 May 1999
|
|
|
|
Author:
|
|
|
|
Zik Saleeba (zik@zikzak.net)
|
|
*/
|
|
{
|
|
int endian = 1;
|
|
unsigned char *out_pos;
|
|
int i;
|
|
|
|
if (*(char *)&endian == 1) {
|
|
/* we're little-endian, which is native for GMOD floats */
|
|
fwrite ( &Val, sizeof(Val), 1, fileout );
|
|
}
|
|
else {
|
|
/* we're big-endian, flip `em */
|
|
out_pos = (unsigned char *)&Val;
|
|
for ( i = sizeof(Val)-1; i >= 0; i-- ) {
|
|
fputc(*(out_pos+i), fileout);
|
|
}
|
|
}
|
|
}
|
|
/******************************************************************************/
|
|
|
|
void gmod_write_w16 ( unsigned short Val, FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
GMOD_WRITE_W16 writes a 16 bit word to a Golgotha GMOD file.
|
|
|
|
Modified:
|
|
|
|
13 September 2000
|
|
|
|
Author:
|
|
|
|
Zik Saleeba (zik@zikzak.net)
|
|
*/
|
|
{
|
|
unsigned char OutByte[2];
|
|
|
|
OutByte[0] = (unsigned char)(Val & 0xff);
|
|
OutByte[1] = (unsigned char)(Val >> 8);
|
|
|
|
fwrite ( OutByte, sizeof(unsigned char), 2, fileout );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
void gmod_write_w32 ( unsigned long Val, FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
GMOD_WRITE writes a 32 bit word to a Golgotha GMOD file.
|
|
|
|
Modified:
|
|
|
|
19 May 1999
|
|
|
|
Author:
|
|
|
|
Zik Saleeba (zik@zikzak.net)
|
|
*/
|
|
{
|
|
unsigned char OutByte[4];
|
|
|
|
OutByte[0] = (unsigned char)(Val & 0xff);
|
|
OutByte[1] = (unsigned char)((Val >> 8) & 0xff);
|
|
OutByte[2] = (unsigned char)((Val >> 16) & 0xff);
|
|
OutByte[3] = (unsigned char)((Val >> 24) & 0xff);
|
|
|
|
fwrite ( OutByte, sizeof(unsigned char), 4, fileout );
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
void hello ( void )
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
Purpose:
|
|
|
|
HELLO prints an explanatory header message.
|
|
|
|
Modified:
|
|
|
|
04 July 2000
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
printf ( "\n" );
|
|
printf ( "Hello: This is IVCON,\n" );
|
|
printf ( " for 3D graphics file conversion.\n" );
|
|
printf ( "\n" );
|
|
printf ( " \".3ds\" 3D Studio Max binary;\n" );
|
|
printf ( " \".ase\" 3D Studio Max ASCII export;\n" );
|
|
printf ( " \".byu\" Movie.BYU surface geometry;\n" );
|
|
printf ( " \".dxf\" DXF;\n" );
|
|
printf ( " \".gmod\" Golgotha model;\n" );
|
|
printf ( " \".hrc\" SoftImage hierarchy;\n" );
|
|
printf ( " \".iv\" SGI Open Inventor;\n" );
|
|
printf ( " \".obj\" WaveFront Advanced Visualizer;\n" );
|
|
printf ( " \".pov\" Persistence of Vision (output only);\n" );
|
|
printf ( " \".smf\" Michael Garland's format;\n" );
|
|
printf ( " \".stl\" ASCII StereoLithography;\n" );
|
|
printf ( " \".stla\" ASCII StereoLithography;\n" );
|
|
printf ( " \".stlb\" Binary StereoLithography;\n" );
|
|
printf ( " \".tec\" TECPLOT (output only);\n" );
|
|
printf ( " \".tri\" [Greg Hood ASCII triangle format];\n" );
|
|
printf ( " \".tria\" [Greg Hood ASCII triangle format];\n" );
|
|
printf ( " \".trib\" [Greg Hood binary triangle format];\n" );
|
|
printf ( " \".txt\" Text (output only);\n" );
|
|
printf ( " \".ucd\" AVS UCD file(output only);\n" );
|
|
printf ( " \".vla\" VLA;\n" );
|
|
printf ( " \".wrl\" VRML (Virtual Reality Modeling Language) (output only).\n" );
|
|
printf ( " \".xgl\" XML/OpenGL format (output only);\n" );
|
|
printf ( "\n" );
|
|
printf ( " Current limits include:\n" );
|
|
printf ( " %d faces;\n", FACE_MAX );
|
|
printf ( " %d line items;\n", LINES_MAX );
|
|
printf ( " %d points;\n", COR3_MAX );
|
|
printf ( " %d face order;\n", ORDER_MAX );
|
|
printf ( " %d materials;\n", MATERIAL_MAX);
|
|
printf ( " %d textures.\n", TEXTURE_MAX );
|
|
printf ( "\n" );
|
|
printf ( " Last modification: 04 July 2000.\n" );
|
|
printf ( "\n" );
|
|
printf ( " Send problem reports to burkardt@psc.edu.\n" );
|
|
|
|
return;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
void help ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
HELP prints a list of the interactive commands.
|
|
|
|
Modified:
|
|
|
|
26 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
printf ( "\n" );
|
|
printf ( "Commands:\n" );
|
|
printf ( "\n" );
|
|
printf ( "< file Read data from input file;\n" );
|
|
printf ( "<< file Append data in input file to current data;\n" );
|
|
printf ( "> file Write output file;\n" );
|
|
printf ( "B Switch the binary file byte-swapping mode;\n" );
|
|
printf ( "D Switch the debugging mode;\n" );
|
|
printf ( "F Print information about one face;\n" );
|
|
printf ( "H Print this help list;\n" );
|
|
printf ( "I Info, print out recent changes;\n" );
|
|
printf ( "LINES Convert face information to lines;\n" );
|
|
printf ( "N Recompute normal vectors;\n" );
|
|
printf ( "P Set LINE_PRUNE option.\n" );
|
|
printf ( "Q Quit;\n" );
|
|
printf ( "R Reverse the normal vectors.\n" );
|
|
printf ( "S Select face subset (NOT WORKING).\n" );
|
|
printf ( "T Transform the data.\n" );
|
|
printf ( "W Reverse the face node ordering.\n" );
|
|
|
|
return;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int hrc_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
HRC_READ reads graphics information from a SoftImage HRC file.
|
|
|
|
Examples:
|
|
|
|
HRCH: Softimage 4D Creative Environment v3.00
|
|
|
|
|
|
model
|
|
{
|
|
name "cube_10x10"
|
|
scaling 1.000 1.000 1.000
|
|
rotation 0.000 0.000 0.000
|
|
translation 0.000 0.000 0.000
|
|
|
|
mesh
|
|
{
|
|
flag ( PROCESS )
|
|
discontinuity 60.000
|
|
|
|
vertices 8
|
|
{
|
|
[0] position -5.000 -5.000 -5.000
|
|
[1] position -5.000 -5.000 5.000
|
|
[2] position -5.000 5.000 -5.000
|
|
[3] position -5.000 5.000 5.000
|
|
[4] position 5.000 -5.000 -5.000
|
|
[5] position 5.000 -5.000 5.000
|
|
[6] position 5.000 5.000 -5.000
|
|
[7] position 5.000 5.000 5.000
|
|
}
|
|
|
|
polygons 6
|
|
{
|
|
[0] nodes 4
|
|
{
|
|
[0] vertex 0
|
|
normal -1.000 0.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[1] vertex 1
|
|
normal -1.000 0.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[2] vertex 3
|
|
normal -1.000 0.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[3] vertex 2
|
|
normal -1.000 0.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
}
|
|
material 0
|
|
[1] nodes 4
|
|
{
|
|
[0] vertex 1
|
|
normal 0.000 0.000 1.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[1] vertex 5
|
|
|
|
...etc.....
|
|
|
|
[5] nodes 4
|
|
{
|
|
[0] vertex 2
|
|
normal 0.000 1.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[1] vertex 3
|
|
normal 0.000 1.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[2] vertex 7
|
|
normal 0.000 1.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[3] vertex 6
|
|
normal 0.000 1.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
}
|
|
material 0
|
|
}
|
|
|
|
edges 12
|
|
{
|
|
[1] vertices 3 2
|
|
[2] vertices 2 0
|
|
[3] vertices 0 1
|
|
[4] vertices 1 3
|
|
[5] vertices 7 3
|
|
[6] vertices 1 5
|
|
[7] vertices 5 7
|
|
[8] vertices 6 7
|
|
[9] vertices 5 4
|
|
[10] vertices 4 6
|
|
[11] vertices 2 6
|
|
[12] vertices 4 0
|
|
}
|
|
}
|
|
|
|
material [0]
|
|
{
|
|
name "kazoo"
|
|
type PHONG
|
|
ambient 0.0 1.0 0.0
|
|
diffuse 1.0 0.0 0.0
|
|
specular 0.0 0.0 1.0
|
|
exponent 50.0
|
|
reflectivity 0.0
|
|
transparency 0.0
|
|
refracIndex 1.0
|
|
glow 0
|
|
coc 0.0
|
|
}
|
|
|
|
texture [0]
|
|
{
|
|
name "/usr/users/foss/HOUSE/PICTURES/mellon"
|
|
glbname "t2d1"
|
|
anim STATIC
|
|
method XY
|
|
repeat 1 1
|
|
scaling 1.000 1.000
|
|
offset 0.000 0.000
|
|
pixelInterp
|
|
effect INTENSITY
|
|
blending 1.000
|
|
ambient 0.977
|
|
diffuse 1.000
|
|
specular 0.966
|
|
reflect 0.000
|
|
transp 0.000
|
|
roughness 0.000
|
|
reflMap 1.000
|
|
rotation 0.000
|
|
txtsup_rot 0.000 0.000 0.000
|
|
txtsup_trans 0.000 0.000 0.000
|
|
txtsup_scal 1.000 1.000 1.000
|
|
}
|
|
}
|
|
|
|
Modified:
|
|
|
|
25 June 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
float b;
|
|
int count;
|
|
float g;
|
|
int i;
|
|
int icor3;
|
|
int ivert;
|
|
int iword;
|
|
int jval;
|
|
int level;
|
|
char *next;
|
|
int nlbrack;
|
|
int nrbrack;
|
|
int cor3_num_old;
|
|
float r;
|
|
float t;
|
|
float temp[3];
|
|
int width;
|
|
char word[LINE_MAX_LEN];
|
|
char word1[LINE_MAX_LEN];
|
|
char word2[LINE_MAX_LEN];
|
|
char wordm1[LINE_MAX_LEN];
|
|
float x;
|
|
float y;
|
|
float z;
|
|
|
|
level = 0;
|
|
strcpy ( level_name[0], "Top" );
|
|
nlbrack = 0;
|
|
nrbrack = 0;
|
|
cor3_num_old = cor3_num;
|
|
strcpy ( word, " " );
|
|
strcpy ( wordm1, " " );
|
|
/*
|
|
Read a line of text from the file.
|
|
*/
|
|
for ( ;; ) {
|
|
|
|
if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
|
|
break;
|
|
}
|
|
|
|
text_num = text_num + 1;
|
|
next = input;
|
|
iword = 0;
|
|
/*
|
|
Read a word from the line.
|
|
*/
|
|
for ( ;; ) {
|
|
|
|
strcpy ( wordm1, word );
|
|
|
|
count = sscanf ( next, "%s%n", word2, &width );
|
|
next = next + width;
|
|
|
|
if ( count <= 0 ) {
|
|
break;
|
|
}
|
|
|
|
strcpy ( word, word2 );
|
|
|
|
iword = iword + 1;
|
|
|
|
if ( iword == 1 ) {
|
|
strcpy ( word1, word );
|
|
}
|
|
/*
|
|
The first line of the file must be the header.
|
|
*/
|
|
if ( text_num == 1 ) {
|
|
|
|
if ( strcmp ( word1, "HRCH:" ) != 0 ) {
|
|
printf ( "\n" );
|
|
printf ( "HRC_READ - Fatal error!\n" );
|
|
printf ( " The input file has a bad header.\n" );
|
|
return ERROR;
|
|
}
|
|
else {
|
|
comment_num = comment_num + 1;
|
|
}
|
|
break;
|
|
}
|
|
/*
|
|
If the word is a curly bracket, count it.
|
|
*/
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
nlbrack = nlbrack + 1;
|
|
level = nlbrack - nrbrack;
|
|
strcpy ( level_name[level], wordm1 );
|
|
if ( debug ) {
|
|
printf ( "New level: %s\n", level_name[level] );
|
|
}
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
nrbrack = nrbrack + 1;
|
|
|
|
if ( nlbrack < nrbrack ) {
|
|
printf ( "\n" );
|
|
printf ( "HRC_READ - Fatal error!\n" );
|
|
printf ( " Extraneous right bracket on line %d.\n", text_num );
|
|
printf ( " Currently processing field %s\n.", level_name[level] );
|
|
return ERROR;
|
|
}
|
|
}
|
|
/*
|
|
CONTROLPOINTS
|
|
*/
|
|
if ( strcmp ( level_name[level], "controlpoints" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
|
|
if ( line_num < LINES_MAX ) {
|
|
line_dex[line_num] = -1;
|
|
line_material[line_num] = 0;
|
|
}
|
|
line_num = line_num + 1;
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( word[0] == '[' ) {
|
|
}
|
|
else if ( strcmp ( word, "position" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%f%n", &x, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &y, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &z, &width );
|
|
next = next + width;
|
|
|
|
temp[0] = x;
|
|
temp[1] = y;
|
|
temp[2] = z;
|
|
|
|
if ( cor3_num < 1000 ) {
|
|
icor3 = rcol_find ( cor3, 3, cor3_num, temp );
|
|
}
|
|
else {
|
|
icor3 = -1;
|
|
}
|
|
|
|
if ( icor3 == -1 ) {
|
|
|
|
icor3 = cor3_num;
|
|
if ( cor3_num < COR3_MAX ) {
|
|
cor3[0][cor3_num] = x;
|
|
cor3[1][cor3_num] = y;
|
|
cor3[2][cor3_num] = z;
|
|
}
|
|
cor3_num = cor3_num + 1;
|
|
|
|
}
|
|
else {
|
|
dup_num = dup_num + 1;
|
|
}
|
|
|
|
if ( line_num < LINES_MAX ) {
|
|
line_dex[line_num] = icor3;
|
|
line_material[line_num] = 0;
|
|
}
|
|
line_num = line_num + 1;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "CONTROLPOINTS: Bad data %s\n", word );
|
|
return ERROR;
|
|
}
|
|
|
|
}
|
|
/*
|
|
EDGES
|
|
*/
|
|
else if ( strcmp ( level_name[level], "edges" ) == 0 ) {
|
|
|
|
if ( strcmp( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( word[0] == '[' ) {
|
|
}
|
|
else if ( strcmp ( word, "vertices" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%d%n", &jval, &width );
|
|
next = next + width;
|
|
|
|
if ( line_num < LINES_MAX ) {
|
|
line_dex[line_num] = jval + cor3_num_old;
|
|
line_material[line_num] = 0;
|
|
}
|
|
line_num = line_num + 1;
|
|
|
|
count = sscanf ( next, "%d%n", &jval, &width );
|
|
next = next + width;
|
|
|
|
if ( line_num < LINES_MAX ) {
|
|
line_dex[line_num] = jval + cor3_num_old;
|
|
line_material[line_num] = 0;
|
|
}
|
|
line_num = line_num + 1;
|
|
|
|
if ( line_num < LINES_MAX ) {
|
|
line_dex[line_num] = -1;
|
|
line_material[line_num] = -1;
|
|
}
|
|
line_num = line_num + 1;
|
|
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "EDGES: Bad data %s\n", word );
|
|
return ERROR;
|
|
}
|
|
|
|
}
|
|
/*
|
|
MATERIAL
|
|
*/
|
|
else if ( strcmp ( level_name[level], "material" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
material_num = material_num + 1;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( word[0] == '[' ) {
|
|
}
|
|
else if ( strcmp ( word, "ambient" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "coc" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "diffuse" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%f%n", &r, &width );
|
|
next = next + width;
|
|
material_rgba[0][material_num-1] = r;
|
|
|
|
count = sscanf ( next, "%f%n", &g, &width );
|
|
next = next + width;
|
|
material_rgba[0][material_num-1] = g;
|
|
|
|
count = sscanf ( next, "%f%n", &b, &width );
|
|
next = next + width;
|
|
material_rgba[0][material_num-1] = b;
|
|
|
|
}
|
|
else if ( strcmp ( word, "exponent" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "glow" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "name" ) == 0 ) {
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
strcpy ( material_name[material_num-1], word );
|
|
}
|
|
else if ( strcmp ( word, "reflectivity" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "refracindex" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "specular" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "transparency" ) == 0 ) {
|
|
count = sscanf ( next, "%f%n", &t, &width );
|
|
next = next + width;
|
|
material_rgba[3][material_num-1] = 1.0 - t;
|
|
}
|
|
else if ( strcmp ( word, "type" ) == 0 ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "MATERIAL: Bad data %s\n", word );
|
|
return ERROR;
|
|
}
|
|
}
|
|
/*
|
|
MESH
|
|
*/
|
|
else if ( strcmp ( level_name[level], "mesh" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( strcmp ( word, "discontinuity" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "edges" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "flag" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "polygons" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "vertices" ) == 0 ) {
|
|
break;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "MESH: Bad data %s\n", word );
|
|
return ERROR;
|
|
}
|
|
|
|
}
|
|
/*
|
|
MODEL
|
|
*/
|
|
else if ( strcmp ( level_name[level], "model" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( strcmp ( word, "material" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "mesh" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "name" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "patch" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "rotation" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "scaling" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "spline" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "translation" ) == 0 ) {
|
|
break;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "MODEL: Bad data %s\n", word );
|
|
return ERROR;
|
|
}
|
|
|
|
}
|
|
/*
|
|
NODES
|
|
*/
|
|
else if ( strcmp ( level_name[level], "nodes" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
ivert = 0;
|
|
face_order[face_num] = 0;
|
|
face_num = face_num + 1;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( word[0] == '[' ) {
|
|
}
|
|
else if ( strcmp ( word, "normal" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%f%n", &x, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &y, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &z, &width );
|
|
next = next + width;
|
|
|
|
if ( ivert < ORDER_MAX && face_num < FACE_MAX ) {
|
|
vertex_normal[0][ivert-1][face_num-1] = x;
|
|
vertex_normal[1][ivert-1][face_num-1] = y;
|
|
vertex_normal[2][ivert-1][face_num-1] = z;
|
|
}
|
|
|
|
}
|
|
else if ( strcmp ( word, "uvTexture" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%f%n", &x, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &y, &width );
|
|
next = next + width;
|
|
|
|
if ( ivert < ORDER_MAX && face_num < FACE_MAX ) {
|
|
vertex_tex_uv[0][ivert-1][face_num-1] = x;
|
|
vertex_tex_uv[1][ivert-1][face_num-1] = y;
|
|
}
|
|
}
|
|
else if ( strcmp ( word, "vertex" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%d%n", &jval, &width );
|
|
next = next + width;
|
|
|
|
if ( ivert < ORDER_MAX && face_num < FACE_MAX ) {
|
|
face_order[face_num-1] = face_order[face_num-1] + 1;
|
|
face[ivert][face_num-1] = jval;
|
|
}
|
|
ivert = ivert + 1;
|
|
|
|
}
|
|
/*
|
|
Right now, we don't do anything with the vertexColor information.
|
|
*/
|
|
else if ( strcmp ( word, "vertexColor" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%d%n", &jval, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%d%n", &jval, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%d%n", &jval, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%d%n", &jval, &width );
|
|
next = next + width;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "NODES: Bad data %s\n", word );
|
|
return ERROR;
|
|
}
|
|
|
|
}
|
|
/*
|
|
PATCH
|
|
I don't know what to do with this yet.
|
|
*/
|
|
else if ( strcmp ( level_name[level], "patch" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( strcmp ( word, "approx_type" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "controlpoints" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "curv_u" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "curv_v" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "recmin" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "recmax" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "recursion" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "spacial" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "taggedpoints" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "ucurve" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "ustep" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "utension" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "utype" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "vclose" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "vcurve" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "viewdep" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "vpoint" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "vstep" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "vtension" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "vtype" ) == 0 ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "PATCH: Bad data %s\n", word );
|
|
return ERROR;
|
|
}
|
|
}
|
|
/*
|
|
POLYGONS
|
|
*/
|
|
else if ( strcmp ( level_name[level], "polygons" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( word[0] == '[' ) {
|
|
}
|
|
else if ( strcmp ( word, "material" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%d%n", &jval, &width );
|
|
next = next + width;
|
|
|
|
for ( ivert = 0; ivert < ORDER_MAX; ivert++ ) {
|
|
vertex_material[ivert][face_num-1] = jval;
|
|
}
|
|
|
|
}
|
|
else if ( strcmp ( word, "nodes" ) == 0 ) {
|
|
count = sscanf ( next, "%s%n", word2, &width );
|
|
next = next + width;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "POLYGONS: Bad data %s\n", word );
|
|
return ERROR;
|
|
}
|
|
|
|
}
|
|
/*
|
|
SPLINE
|
|
*/
|
|
else if ( strcmp ( level_name[level], "spline" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( strcmp ( word, "controlpoints" ) == 0 ) {
|
|
break;
|
|
}
|
|
/*
|
|
WHY DON'T YOU READ IN THE OBJECT NAME HERE?
|
|
*/
|
|
else if ( strcmp ( word, "name" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "nbKeys" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "step" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "tension" ) == 0 ) {
|
|
break;
|
|
}
|
|
else if ( strcmp ( word, "type" ) == 0 ) {
|
|
break;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "SPLINE: Bad data %s\n", word );
|
|
return ERROR;
|
|
}
|
|
|
|
}
|
|
/*
|
|
TAGGEDPOINTS
|
|
*/
|
|
else if ( strcmp ( level_name[level], "taggedpoints" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( word[0] == '[' ) {
|
|
}
|
|
else if ( strcmp ( word, "tagged" ) == 0 ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "TAGGEDPOINTS: Bad data %s\n", word );
|
|
return ERROR;
|
|
}
|
|
|
|
}
|
|
/*
|
|
TEXTURE
|
|
*/
|
|
else if ( strcmp ( level_name[level], "texture" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
texture_num = texture_num + 1;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( word[0] == '[' ) {
|
|
}
|
|
else if ( strcmp ( word, "ambient" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "anim" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "blending" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "diffuse" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "effect" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "glbname" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "method" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "name" ) == 0 ) {
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
strcpy ( texture_name[texture_num-1], word );
|
|
}
|
|
else if ( strcmp ( word, "offset" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "pixelinterp" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "reflect" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "reflmap" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "repeat" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "rotation" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "roughness" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "scaling" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "specular" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "transp" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "txtsup_rot" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "txtsup_scal" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "txtsup_trans" ) == 0 ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "TEXTURE: Bad data %s\n", word );
|
|
return ERROR;
|
|
}
|
|
}
|
|
/*
|
|
VERTICES
|
|
*/
|
|
else if ( strcmp ( level_name[level], "vertices" ) == 0 ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( word[0] == '[' ) {
|
|
}
|
|
else if ( strcmp ( word, "position" ) == 0 ) {
|
|
|
|
count = sscanf ( next, "%f%n", &x, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &y, &width );
|
|
next = next + width;
|
|
|
|
count = sscanf ( next, "%f%n", &z, &width );
|
|
next = next + width;
|
|
|
|
if ( cor3_num < COR3_MAX ) {
|
|
cor3[0][cor3_num] = x;
|
|
cor3[1][cor3_num] = y;
|
|
cor3[2][cor3_num] = z;
|
|
}
|
|
cor3_num = cor3_num + 1;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "VERTICES: Bad data %s\n", word );
|
|
return ERROR;
|
|
}
|
|
}
|
|
/*
|
|
Any other word:
|
|
*/
|
|
else {
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
End of information in file.
|
|
|
|
Check the "materials" defining a line.
|
|
|
|
If COORDINDEX is -1, so should be the MATERIALINDEX.
|
|
If COORDINDEX is not -1, then the MATERIALINDEX shouldn"t be either.
|
|
*/
|
|
for ( i = 0; i < line_num; i++ ) {
|
|
|
|
if ( line_dex[i] == -1 ) {
|
|
line_material[i] = -1;
|
|
}
|
|
else if ( line_material[i] == -1 ) {
|
|
line_material[i] = 0;
|
|
}
|
|
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int hrc_write ( FILE* fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
HRC_WRITE writes graphics data to an HRC SoftImage file.
|
|
|
|
Examples:
|
|
|
|
HRCH: Softimage 4D Creative Environment v3.00
|
|
|
|
|
|
model
|
|
{
|
|
name "cube_10x10"
|
|
scaling 1.000 1.000 1.000
|
|
rotation 0.000 0.000 0.000
|
|
translation 0.000 0.000 0.000
|
|
|
|
mesh
|
|
{
|
|
flag ( PROCESS )
|
|
discontinuity 60.000
|
|
|
|
vertices 8
|
|
{
|
|
[0] position -5.000 -5.000 -5.000
|
|
[1] position -5.000 -5.000 5.000
|
|
[2] position -5.000 5.000 -5.000
|
|
[3] position -5.000 5.000 5.000
|
|
[4] position 5.000 -5.000 -5.000
|
|
[5] position 5.000 -5.000 5.000
|
|
[6] position 5.000 5.000 -5.000
|
|
[7] position 5.000 5.000 5.000
|
|
}
|
|
|
|
polygons 6
|
|
{
|
|
[0] nodes 4
|
|
{
|
|
[0] vertex 0
|
|
normal -1.000 0.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[1] vertex 1
|
|
normal -1.000 0.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[2] vertex 3
|
|
normal -1.000 0.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[3] vertex 2
|
|
normal -1.000 0.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
}
|
|
material 0
|
|
[1] nodes 4
|
|
{
|
|
[0] vertex 1
|
|
normal 0.000 0.000 1.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[1] vertex 5
|
|
|
|
...etc.....
|
|
|
|
[5] nodes 4
|
|
{
|
|
[0] vertex 2
|
|
normal 0.000 1.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[1] vertex 3
|
|
normal 0.000 1.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[2] vertex 7
|
|
normal 0.000 1.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
[3] vertex 6
|
|
normal 0.000 1.000 0.000
|
|
uvTexture 0.000 0.000
|
|
vertexColor 255 178 178 178
|
|
}
|
|
material 0
|
|
}
|
|
|
|
edges 12
|
|
{
|
|
[1] vertices 3 2
|
|
[2] vertices 2 0
|
|
[3] vertices 0 1
|
|
[4] vertices 1 3
|
|
[5] vertices 7 3
|
|
[6] vertices 1 5
|
|
[7] vertices 5 7
|
|
[8] vertices 6 7
|
|
[9] vertices 5 4
|
|
[10] vertices 4 6
|
|
[11] vertices 2 6
|
|
[12] vertices 4 0
|
|
}
|
|
}
|
|
|
|
material [0]
|
|
{
|
|
name "kazoo"
|
|
type PHONG
|
|
ambient 0.0 1.0 0.0
|
|
diffuse 1.0 0.0 0.0
|
|
specular 0.0 0.0 1.0
|
|
exponent 50.0
|
|
reflectivity 0.0
|
|
transparency 0.0
|
|
refracIndex 1.0
|
|
glow 0
|
|
coc 0.0
|
|
}
|
|
|
|
texture [0]
|
|
{
|
|
name "/usr/users/foss/HOUSE/PICTURES/mellon"
|
|
glbname "t2d1"
|
|
anim STATIC
|
|
method XY
|
|
repeat 1 1
|
|
scaling 1.000 1.000
|
|
offset 0.000 0.000
|
|
pixelInterp
|
|
effect INTENSITY
|
|
blending 1.000
|
|
ambient 0.977
|
|
diffuse 1.000
|
|
specular 0.966
|
|
reflect 0.000
|
|
transp 0.000
|
|
roughness 0.000
|
|
reflMap 1.000
|
|
rotation 0.000
|
|
txtsup_rot 0.000 0.000 0.000
|
|
txtsup_trans 0.000 0.000 0.000
|
|
txtsup_scal 1.000 1.000 1.000
|
|
}
|
|
}
|
|
|
|
Modified:
|
|
|
|
25 June 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
*/
|
|
{
|
|
int iface;
|
|
int ivert;
|
|
int j;
|
|
int jhi;
|
|
int jlo;
|
|
int jrel;
|
|
int k;
|
|
int npts;
|
|
int nseg;
|
|
int text_num;
|
|
|
|
nseg = 0;
|
|
text_num = 0;
|
|
|
|
fprintf ( fileout, "HRCH: Softimage 4D Creative Environment v3.00\n" );
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
fprintf ( fileout, "model\n" );
|
|
fprintf ( fileout, "{\n" );
|
|
fprintf ( fileout, " name \"%s\"\n", object_name );
|
|
fprintf ( fileout, " scaling 1.000 1.000 1.000\n" );
|
|
fprintf ( fileout, " rotation 0.000 0.000 0.000\n" );
|
|
fprintf ( fileout, " translation 0.000 0.000 0.000\n" );
|
|
text_num = text_num + 6;
|
|
|
|
if ( face_num > 0 ) {
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " mesh\n" );
|
|
fprintf ( fileout, " {\n" );
|
|
fprintf ( fileout, " flag ( PROCESS )\n" );
|
|
fprintf ( fileout, " discontinuity 60.000\n" );
|
|
text_num = text_num + 5;
|
|
/*
|
|
Point coordinates.
|
|
*/
|
|
if ( cor3_num > 0 ) {
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " vertices %d\n", cor3_num );
|
|
fprintf ( fileout, " {\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( j = 0; j < cor3_num; j++ ) {
|
|
|
|
fprintf ( fileout, " [%d] position %f %f %f\n", j, cor3[0][j],
|
|
cor3[1][j], cor3[2][j] );
|
|
text_num = text_num + 1;
|
|
}
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
/*
|
|
Faces.
|
|
*/
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " polygons %d\n", face_num );
|
|
fprintf ( fileout, " {\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
fprintf ( fileout, " [%d] nodes %d\n", iface, face_order[iface] );
|
|
fprintf ( fileout, " {\n" );
|
|
text_num = text_num + 2;
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
|
|
fprintf ( fileout, " [%d] vertex %d\n", ivert, face[ivert][iface] );
|
|
fprintf ( fileout, " normal %f %f %f\n",
|
|
vertex_normal[0][ivert][iface],
|
|
vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
|
|
fprintf ( fileout, " uvTexture %f %f\n",
|
|
vertex_tex_uv[0][ivert][iface], vertex_tex_uv[1][ivert][iface] );
|
|
fprintf ( fileout, " vertexColor 255 178 178 178\n" );
|
|
text_num = text_num + 4;
|
|
}
|
|
fprintf ( fileout, " }\n" );
|
|
fprintf ( fileout, " material %d\n", face_material[iface] );
|
|
text_num = text_num + 2;
|
|
}
|
|
fprintf ( fileout, " }\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 2;
|
|
}
|
|
/*
|
|
IndexedLineSet.
|
|
*/
|
|
if ( line_num > 0 ) {
|
|
|
|
nseg = 0;
|
|
|
|
jhi = -1;
|
|
|
|
for ( ;; ) {
|
|
|
|
jlo = jhi + 1;
|
|
/*
|
|
Look for the next index JLO that is not -1.
|
|
*/
|
|
while ( jlo < line_num ) {
|
|
if ( line_dex[jlo] != -1 ) {
|
|
break;
|
|
}
|
|
jlo = jlo + 1;
|
|
}
|
|
|
|
if ( jlo >= line_num ) {
|
|
break;
|
|
}
|
|
/*
|
|
Look for the highest following index JHI that is not -1.
|
|
*/
|
|
jhi = jlo + 1;
|
|
|
|
while ( jhi < line_num ) {
|
|
if ( line_dex[jhi] == -1 ) {
|
|
break;
|
|
}
|
|
jhi = jhi + 1;
|
|
}
|
|
|
|
jhi = jhi - 1;
|
|
/*
|
|
Our next line segment involves LINE_DEX indices JLO through JHI.
|
|
*/
|
|
nseg = nseg + 1;
|
|
npts = jhi + 1 - jlo;
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " spline\n" );
|
|
fprintf ( fileout, " {\n" );
|
|
fprintf ( fileout, " name \"spl%d\"\n", nseg );
|
|
fprintf ( fileout, " type LINEAR\n" );
|
|
fprintf ( fileout, " nbKeys %d\n", npts );
|
|
fprintf ( fileout, " tension 0.000\n" );
|
|
fprintf ( fileout, " step 1\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 9;
|
|
|
|
fprintf ( fileout, " controlpoints\n" );
|
|
fprintf ( fileout, " {\n" );
|
|
text_num = text_num + 2;
|
|
|
|
for ( j = jlo; j <= jhi; j++ ) {
|
|
jrel = j - jlo;
|
|
k = line_dex[j];
|
|
fprintf ( fileout, " [%d] position %f %f %f\n", jrel,
|
|
cor3[0][k], cor3[1][k], cor3[2][k] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, " }\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 2;
|
|
}
|
|
}
|
|
/*
|
|
MATERIALS
|
|
*/
|
|
for ( i = 0; i < material_num; i++ ) {
|
|
|
|
fprintf ( fileout, " material [%d]\n", i );
|
|
fprintf ( fileout, " {\n" );
|
|
fprintf ( fileout, " name \"%s\"\n", material_name[i] );
|
|
fprintf ( fileout, " type PHONG\n" );
|
|
fprintf ( fileout, " ambient %f %f %f\n", material_rgba[0][i],
|
|
material_rgba[1][i], material_rgba[2][i] );
|
|
fprintf ( fileout, " diffuse %f %f %f\n", material_rgba[0][i],
|
|
material_rgba[1][i], material_rgba[2][i] );
|
|
fprintf ( fileout, " specular %f %f %f\n", material_rgba[0][i],
|
|
material_rgba[1][i], material_rgba[2][i] );
|
|
fprintf ( fileout, " exponent 50.0\n" );
|
|
fprintf ( fileout, " reflectivity 0.0\n" );
|
|
fprintf ( fileout, " transparency %f\n", 1.0 - material_rgba[3][i] );
|
|
fprintf ( fileout, " refracIndex 1.0\n" );
|
|
fprintf ( fileout, " glow 0\n" );
|
|
fprintf ( fileout, " coc 0.0\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
|
|
text_num = text_num + 14;
|
|
|
|
}
|
|
/*
|
|
TEXTURES
|
|
*/
|
|
for ( i = 0; i < texture_num; i++ ) {
|
|
|
|
fprintf ( fileout, " texture [%d]\n", i );
|
|
fprintf ( fileout, " {\n" );
|
|
fprintf ( fileout, " name \"%s\"\n", texture_name[i] );
|
|
fprintf ( fileout, " glbname \"t2d1\"\n" );
|
|
fprintf ( fileout, " anim STATIC\n" );
|
|
fprintf ( fileout, " method XY\n" );
|
|
fprintf ( fileout, " repeat 1 1\n" );
|
|
fprintf ( fileout, " scaling 1.000 1.000\n" );
|
|
fprintf ( fileout, " offset 0.000 0.000\n" );
|
|
fprintf ( fileout, " pixelInterp\n" );
|
|
fprintf ( fileout, " effect INTENSITY\n" );
|
|
fprintf ( fileout, " blending 1.000\n" );
|
|
fprintf ( fileout, " ambient 0.977\n" );
|
|
fprintf ( fileout, " diffuse 1.000\n" );
|
|
fprintf ( fileout, " specular 0.966\n" );
|
|
fprintf ( fileout, " reflect 0.000\n" );
|
|
fprintf ( fileout, " transp 0.000\n" );
|
|
fprintf ( fileout, " roughness 0.000\n" );
|
|
fprintf ( fileout, " reflMap 1.000\n" );
|
|
fprintf ( fileout, " rotation 0.000\n" );
|
|
fprintf ( fileout, " txtsup_rot 0.000 0.000 0.000\n" );
|
|
fprintf ( fileout, " txtsup_trans 0.000 0.000 0.000\n" );
|
|
fprintf ( fileout, " txtsup_scal 1.000 1.000 1.000\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
|
|
text_num = text_num + 25;
|
|
|
|
}
|
|
fprintf ( fileout, "}\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "HRC_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
void init_program_data ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
INIT_PROGRAM_DATA initializes the internal program data.
|
|
|
|
Modified:
|
|
|
|
26 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
byte_swap = FALSE;
|
|
debug = 0;
|
|
line_prune = 1;
|
|
color_num = 0;
|
|
cor3_num = 0;
|
|
face_num = 0;
|
|
line_num = 0;
|
|
|
|
if ( debug ) {
|
|
printf ( "\n" );
|
|
printf ( "INIT_PROGRAM_DATA: Program data initialized.\n" );
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int interact ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
INTERACT carries on an interactive session with the user.
|
|
|
|
Modified:
|
|
|
|
22 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int icor3;
|
|
int ierror;
|
|
int iface;
|
|
int itemp;
|
|
int ivert;
|
|
int j;
|
|
int jvert;
|
|
int m;
|
|
char *next;
|
|
float temp;
|
|
float x;
|
|
float y;
|
|
float z;
|
|
|
|
strcpy ( filein_name, "NO_IN_NAME" );
|
|
strcpy ( fileout_name, "NO_OUT_NAME" );
|
|
|
|
/*
|
|
Say hello.
|
|
*/
|
|
hello ( );
|
|
/*
|
|
Get the next user command.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "Enter command (H for help)\n" );
|
|
|
|
while ( fgets ( input, LINE_MAX_LEN, stdin ) != NULL ) {
|
|
/*
|
|
Advance to the first nonspace character in INPUT.
|
|
*/
|
|
for ( next = input; *next != '\0' && isspace(*next); next++ ) {
|
|
}
|
|
/*
|
|
Skip blank lines and comments.
|
|
*/
|
|
if ( *next == '\0' ) {
|
|
continue;
|
|
}
|
|
/*
|
|
Command: << FILENAME
|
|
Append new data to current graphics information.
|
|
*/
|
|
if ( *next == '<' && *(next+1) == '<' ) {
|
|
|
|
next = next + 2;
|
|
sscanf ( next, "%s", filein_name );
|
|
|
|
ierror = data_read ( );
|
|
|
|
if ( ierror == ERROR ) {
|
|
printf ( "\n" );
|
|
printf ( "INTERACT - Fatal error!\n" );
|
|
printf ( " DATA_READ failed to read input data.\n" );
|
|
}
|
|
}
|
|
/*
|
|
Command: < FILENAME
|
|
*/
|
|
else if ( *next == '<' ) {
|
|
|
|
next = next + 1;
|
|
sscanf ( next, "%s", filein_name );
|
|
|
|
data_init ( );
|
|
|
|
ierror = data_read ( );
|
|
|
|
if ( ierror == ERROR ) {
|
|
printf ( "\n" );
|
|
printf ( "INTERACT - Fatal error!\n" );
|
|
printf ( " DATA_READ failed to read input data.\n" );
|
|
}
|
|
}
|
|
/*
|
|
Command: > FILENAME
|
|
*/
|
|
else if ( *next == '>' ) {
|
|
|
|
next = next + 1;
|
|
sscanf ( next, "%s", fileout_name );
|
|
|
|
ierror = data_write ( );
|
|
|
|
if ( ierror == ERROR ) {
|
|
printf ( "\n" );
|
|
printf ( "INTERACT - Fatal error!\n" );
|
|
printf ( " OUTPUT_DATA failed to write output data.\n" );
|
|
}
|
|
|
|
}
|
|
/*
|
|
B: Switch byte swapping option.
|
|
*/
|
|
else if ( *next == 'B' || *next == 'b' ) {
|
|
|
|
if ( byte_swap == TRUE ) {
|
|
byte_swap = FALSE;
|
|
printf ( "Byte_swapping reset to FALSE.\n" );
|
|
}
|
|
else {
|
|
byte_swap = TRUE;
|
|
printf ( "Byte_swapping reset to TRUE.\n" );
|
|
}
|
|
|
|
}
|
|
/*
|
|
D: Switch debug option.
|
|
*/
|
|
else if ( *next == 'D' || *next == 'd' ) {
|
|
if ( debug ) {
|
|
debug = 0;
|
|
printf ( "Debug reset to FALSE.\n" );
|
|
}
|
|
else {
|
|
debug = 1;
|
|
printf ( "Debug reset to TRUE.\n" );
|
|
}
|
|
}
|
|
/*
|
|
F: Check a face.
|
|
*/
|
|
else if ( *next == 'f' || *next == 'F' ) {
|
|
printf ( "\n" );
|
|
printf ( " Enter a face index between 0 and %d:", face_num-1 );
|
|
scanf ( "%d", &iface );
|
|
face_print ( iface );
|
|
}
|
|
/*
|
|
H: Help
|
|
*/
|
|
else if ( *next == 'h' || *next == 'H' ) {
|
|
help ( );
|
|
}
|
|
/*
|
|
I: Print change information.
|
|
*/
|
|
else if ( *next == 'i' || *next == 'I') {
|
|
news ( );
|
|
}
|
|
/*
|
|
LINES:
|
|
Convert face information to lines.
|
|
*/
|
|
else if ( *next == 'l' || *next == 'L') {
|
|
|
|
if ( face_num > 0 ) {
|
|
|
|
printf ( "\n" );
|
|
printf ( "INTERACT - Note:\n" );
|
|
printf ( " Face information will be converted\n" );
|
|
printf ( " to line information.\n" );
|
|
|
|
face_to_line ( );
|
|
|
|
if ( line_num > LINES_MAX ) {
|
|
|
|
printf ( "\n" );
|
|
printf ( "INTERACT - Note:\n" );
|
|
printf ( " Some face information was lost.\n" );
|
|
printf ( " The maximum number of lines is %d,\n", LINES_MAX );
|
|
printf ( " but we would need at least %d.\n", line_num );
|
|
|
|
line_num = LINES_MAX;
|
|
|
|
}
|
|
|
|
face_num = 0;
|
|
}
|
|
else {
|
|
|
|
printf ( "\n" );
|
|
printf ( "INTERACT - Note:\n" );
|
|
printf ( " There were no faces to convert.\n" );
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
N: Recompute normal vectors.
|
|
*/
|
|
else if ( *next == 'n' || *next == 'N') {
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
face_normal[i][iface] = 0.0;
|
|
}
|
|
}
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
vertex_normal[i][ivert][iface] = 0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
vertex_normal_set ( );
|
|
|
|
cor3_normal_set ( );
|
|
|
|
face_normal_ave ( );
|
|
}
|
|
/*
|
|
P: Line pruning optiont
|
|
*/
|
|
else if ( *next == 'p' || *next == 'P' ) {
|
|
|
|
printf ( "\n" );
|
|
printf ( "INTERACT - SET LINE PRUNING OPTION.\n" );
|
|
printf ( "\n" );
|
|
printf ( " LINE_PRUNE = 0 means no line pruning.\n" );
|
|
printf ( " nonzero means line pruning.\n" );
|
|
printf ( "\n" );
|
|
printf ( " Current value is LINE_PRUNE = %d.\n", line_prune );
|
|
printf ( "\n" );
|
|
printf ( " Enter new value for LINE_PRUNE.\n" );
|
|
|
|
if ( fgets ( input, LINE_MAX_LEN, stdin ) == NULL ) {
|
|
printf ( " ??? Error trying to read input.\n" );
|
|
}
|
|
else {
|
|
sscanf ( input, "%d", &line_prune );
|
|
printf ( " New value is LINE_PRUNE = %d.\n", line_prune );
|
|
}
|
|
}
|
|
/*
|
|
Q: Quit
|
|
*/
|
|
else if ( *next == 'q' || *next == 'Q' ) {
|
|
printf ( "\n" );
|
|
printf ( "INTERACT - Normal end of execution.\n" );
|
|
return SUCCESS;
|
|
}
|
|
/*
|
|
R: Reverse normal vectors.
|
|
*/
|
|
else if ( *next == 'r' || *next == 'R' ) {
|
|
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
cor3_normal[i][icor3] = - cor3_normal[i][icor3];
|
|
}
|
|
}
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
face_normal[i][iface] = - face_normal[i][iface];
|
|
}
|
|
}
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
vertex_normal[i][ivert][iface] =
|
|
- vertex_normal[i][ivert][iface];
|
|
}
|
|
}
|
|
}
|
|
printf ( "\n" );
|
|
printf ( "INTERACT - Note:\n" );
|
|
printf ( " Reversed node, face and vertex normals.\n" );
|
|
}
|
|
/*
|
|
S: Select a few faces, discard the rest.
|
|
*/
|
|
else if ( *next == 's' || *next == 'S' ) {
|
|
face_subset ( );
|
|
}
|
|
/*
|
|
T: Transform the data.
|
|
*/
|
|
else if ( *next == 't' || *next == 'T' ) {
|
|
|
|
printf ( "\n" );
|
|
printf ( "For now, we only offer point scaling.\n" );
|
|
printf ( "Enter X, Y, Z scale factors:\n" );
|
|
|
|
scanf ( "%f %f %f", &x, &y, &z );
|
|
|
|
for ( j = 0; j < cor3_num; j++ ) {
|
|
cor3[0][j] = x * cor3[0][j];
|
|
cor3[1][j] = y * cor3[1][j];
|
|
cor3[2][j] = z * cor3[2][j];
|
|
}
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
face_normal[i][iface] = 0.0;
|
|
}
|
|
}
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
vertex_normal[i][ivert][iface] = 0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
vertex_normal_set ( );
|
|
|
|
cor3_normal_set ( );
|
|
|
|
face_normal_ave ( );
|
|
}
|
|
/*
|
|
U: Renumber faces, count objects:
|
|
*/
|
|
else if ( *next == 'u' || *next == 'U' ) {
|
|
}
|
|
/*
|
|
V: Convert polygons to triangles:
|
|
*/
|
|
else if ( *next == 'v' || *next == 'V' ) {
|
|
}
|
|
/*
|
|
W: Reverse the face node ordering.
|
|
*/
|
|
else if ( *next == 'w' || *next == 'W' ) {
|
|
|
|
if ( face_num > 0 ) {
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
m = face_order[iface];
|
|
|
|
for ( ivert = 0; ivert < m/2; ivert++ ) {
|
|
|
|
jvert = m - ivert - 1;
|
|
|
|
itemp = face[ivert][iface];
|
|
face[ivert][iface] = face[jvert][iface];
|
|
face[jvert][iface] = itemp;
|
|
|
|
itemp = vertex_material[ivert][iface];
|
|
vertex_material[ivert][iface] = vertex_material[jvert][iface];
|
|
vertex_material[jvert][iface] = itemp;
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
temp = vertex_normal[i][ivert][iface];
|
|
vertex_normal[i][ivert][iface] =
|
|
vertex_normal[i][jvert][iface];
|
|
vertex_normal[i][jvert][iface] = temp;
|
|
}
|
|
}
|
|
}
|
|
printf ( "\n" );
|
|
printf ( "INTERACT - Note:\n" );
|
|
printf ( " Reversed face node ordering.\n" );
|
|
}
|
|
}
|
|
/*
|
|
Command: ???
|
|
*/
|
|
else {
|
|
printf ( "\n" );
|
|
printf ( "INTERACT: Warning!\n" );
|
|
printf ( " Your command was not recognized.\n" );
|
|
}
|
|
|
|
printf ( "\n" );
|
|
printf ( "Enter command (H for help)\n" );
|
|
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int iv_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
IV_READ reads graphics information from an Inventor file.
|
|
|
|
Example:
|
|
|
|
#Inventor V2.0 ascii
|
|
|
|
Separator {
|
|
Info {
|
|
string "Inventor file generated by IVCON.
|
|
Original data in file cube.iv."
|
|
}
|
|
Separator {
|
|
LightModel {
|
|
model PHONG
|
|
}
|
|
MatrixTransform { matrix
|
|
0.9 0.0 0.0 0.0
|
|
0.0 -0.9 0.0 0.0
|
|
0.0 0.0 -1.5 0.0
|
|
0.0 0.0 0.0 1.0
|
|
}
|
|
Material {
|
|
ambientColor 0.2 0.2 0.2
|
|
diffuseColor [
|
|
0.8 0.8 0.8,
|
|
0.7 0.1 0.1,
|
|
0.1 0.8 0.2,
|
|
]
|
|
emissiveColor 0.0 0.0 0.0
|
|
specularColor 0.0 0.0 0.0
|
|
shininess 0.2
|
|
transparency [
|
|
0.0, 0.5, 1.0,
|
|
]
|
|
}
|
|
Texture2 {
|
|
filename "fred.rgb"
|
|
wrapS REPEAT
|
|
wrapT REPEAT
|
|
model MODULATE
|
|
blendColor 0.0 0.0 0.0
|
|
}
|
|
|
|
MaterialBinding {
|
|
value PER_VERTEX_INDEXED
|
|
}
|
|
NormalBinding {
|
|
value PER_VERTEX_INDEXED
|
|
}
|
|
TextureCoordinateBinding {
|
|
value PER_VERTEX_INDEXED
|
|
}
|
|
|
|
ShapeHints {
|
|
vertexOrdering COUNTERCLOCKWISE
|
|
shapeType UNKNOWN_SHAPE_TYPE
|
|
faceType CONVEX
|
|
creaseAngle 6.28319
|
|
}
|
|
|
|
Coordinate3 {
|
|
point [
|
|
8.59816 5.55317 -3.05561,
|
|
8.59816 2.49756 0.000000E+00,
|
|
...etc...
|
|
2.48695 2.49756 -3.05561,
|
|
]
|
|
}
|
|
|
|
Normal {
|
|
vector [
|
|
0.71 0.71 0.0,
|
|
...etc...
|
|
0.32 0.32 0.41,
|
|
]
|
|
}
|
|
|
|
TextureCoordinate2 {
|
|
point [
|
|
0.0 1.0,
|
|
0.1, 0.8,
|
|
...etc...
|
|
0.4 0.7,
|
|
]
|
|
}
|
|
|
|
IndexedLineSet {
|
|
coordIndex [
|
|
0, 1, 2, -1,
|
|
3, 4, 5, -1,
|
|
7, 8, 9, -1,
|
|
...etc...
|
|
189, 190, 191, -1,
|
|
]
|
|
materialIndex [
|
|
0, 0, 0, -1,
|
|
1, 1, 1, -1,
|
|
2, 2, 2, -1,
|
|
...etc...
|
|
64, 64, 64, -1,
|
|
]
|
|
}
|
|
|
|
IndexedFaceSet {
|
|
coordIndex [
|
|
0, 1, 2, -1,
|
|
3, 4, 5, -1,
|
|
7, 8, 9, -1,
|
|
...etc...
|
|
189, 190, 191, -1,
|
|
]
|
|
materialIndex [
|
|
0, 0, 0, -1,
|
|
1, 1, 1, -1,
|
|
2, 2, 2, -1,
|
|
...etc...
|
|
64, 64, 64, -1,
|
|
]
|
|
normalIndex [
|
|
0, 0, 0, -1,
|
|
1, 1, 1, -1,
|
|
2, 2, 2, -1,
|
|
...etc...
|
|
64, 64, 64, -1,
|
|
]
|
|
textureCoordIndex [
|
|
0, 0, 0, -1,
|
|
1, 1, 1, -1,
|
|
2, 2, 2, -1,
|
|
...etc...
|
|
64, 64, 64, -1,
|
|
]
|
|
}
|
|
|
|
IndexedTriangleStripSet {
|
|
vertexProperty VertexProperty {
|
|
vertex [ x y z,
|
|
...
|
|
x y z ]
|
|
normal [ x y z,
|
|
...
|
|
x y z ]
|
|
materialBinding OVERALL
|
|
normalBinding PER_VERTEX_INDEXED
|
|
}
|
|
coordIndex [
|
|
i, j, k, l, m, -1,
|
|
n, o, p, q, r, s, t, u, -1,
|
|
v, w, x, -1
|
|
..., -1 ]
|
|
normalIndex -1
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
Modified:
|
|
|
|
01 July 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
char c;
|
|
int count;
|
|
int i;
|
|
int icol;
|
|
int icolor;
|
|
int icface;
|
|
int inormface;
|
|
int iface_num;
|
|
int irow;
|
|
int iuv;
|
|
int ivert;
|
|
int iword;
|
|
int ix;
|
|
int ixyz;
|
|
int iy;
|
|
int iz;
|
|
int j;
|
|
int jval;
|
|
int level;
|
|
char *next;
|
|
int nlbrack;
|
|
int nrbrack;
|
|
int nu;
|
|
int null_index;
|
|
int cor3_num_old;
|
|
int line_num2;
|
|
int face_num2;
|
|
int normal_num_temp;
|
|
int text_numure_temp;
|
|
int nv;
|
|
int result;
|
|
float rval;
|
|
int width;
|
|
char word[LINE_MAX_LEN];
|
|
char word1[LINE_MAX_LEN];
|
|
char wordm1[LINE_MAX_LEN];
|
|
float xvec[3];
|
|
|
|
icface = 0;
|
|
icol = -1;
|
|
inormface = 0;
|
|
iface_num = face_num;
|
|
irow = 0;
|
|
ix = 0;
|
|
ixyz = 0;
|
|
iy = 0;
|
|
iz = 0;
|
|
jval = 0;
|
|
level = 0;
|
|
strcpy ( level_name[0], "Top" );
|
|
nlbrack = 0;
|
|
nrbrack = 0;
|
|
nu = 0;
|
|
cor3_num_old = cor3_num;
|
|
face_num2 = face_num;
|
|
line_num2 = line_num;
|
|
normal_num_temp = 0;
|
|
text_numure_temp = 0;
|
|
nv = 0;
|
|
rval = 0.0;
|
|
strcpy ( word, " " );
|
|
strcpy ( wordm1, " " );
|
|
/*
|
|
Read the next line of text from the input file.
|
|
*/
|
|
for ( ;; ) {
|
|
|
|
if ( fgets ( input, LINE_MAX_LEN, filein ) == NULL ) {
|
|
break;
|
|
}
|
|
|
|
text_num = text_num + 1;
|
|
next = input;
|
|
iword = 0;
|
|
/*
|
|
Remove all commas from the line, so we can use SSCANF to read
|
|
numeric items.
|
|
*/
|
|
i = 0;
|
|
while ( input[i] != '\0' ) {
|
|
if ( input[i] == ',' ) {
|
|
input[i] = ' ';
|
|
}
|
|
i++;
|
|
}
|
|
/*
|
|
Force brackets and braces to be buffered by spaces.
|
|
*/
|
|
i = 0;
|
|
while ( input[i] != '\0' ) {
|
|
i++;
|
|
}
|
|
null_index = i;
|
|
|
|
i = 0;
|
|
while ( input[i] != '\0' && i < LINE_MAX_LEN ) {
|
|
|
|
if ( input[i] == '[' || input[i] == ']' ||
|
|
input[i] == '{' || input[i] == '}' ) {
|
|
|
|
result = char_pad ( &i, &null_index, input, LINE_MAX_LEN );
|
|
if ( result == ERROR ) {
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
i++;
|
|
}
|
|
}
|
|
/*
|
|
Read a word from the line.
|
|
*/
|
|
for ( ;; ) {
|
|
|
|
strcpy ( wordm1, word );
|
|
strcpy ( word, " " );
|
|
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
|
|
if ( count <= 0 ) {
|
|
break;
|
|
}
|
|
|
|
iword = iword + 1;
|
|
|
|
if ( iword == 1 ) {
|
|
strcpy ( word1, word );
|
|
}
|
|
/*
|
|
The first line of the file must be the header.
|
|
*/
|
|
if ( text_num == 1 ) {
|
|
|
|
if ( leqi ( word1, "#Inventor" ) != TRUE ) {
|
|
printf ( "\n" );
|
|
printf ( "IV_READ - Fatal error!\n" );
|
|
printf ( " The input file has a bad header.\n" );
|
|
return ERROR;
|
|
}
|
|
else {
|
|
comment_num = comment_num + 1;
|
|
}
|
|
break;
|
|
}
|
|
/*
|
|
A comment begins anywhere with '#'.
|
|
Skip the rest of the line.
|
|
*/
|
|
if ( word[1] == '#' ) {
|
|
comment_num = comment_num + 1;
|
|
break;
|
|
}
|
|
/*
|
|
If the word is a curly or square bracket, count it.
|
|
If the word is a left bracket, the previous word is the name of a node.
|
|
*/
|
|
if ( strcmp ( word, "{" ) == 0 || strcmp ( word, "[" ) == 0 ) {
|
|
nlbrack = nlbrack + 1;
|
|
level = nlbrack - nrbrack;
|
|
strcpy ( level_name[level], wordm1 );
|
|
if ( debug ) {
|
|
printf ( "Begin level: %s\n", wordm1 );
|
|
}
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 || strcmp ( word, "]" ) == 0 ) {
|
|
nrbrack = nrbrack + 1;
|
|
|
|
if ( nlbrack < nrbrack ) {
|
|
printf ( "\n" );
|
|
printf ( "IV_READ - Fatal error!\n" );
|
|
printf ( " Extraneous right bracket on line %d.\n", text_num );
|
|
printf ( " Currently processing field %s\n.", level_name[level] );
|
|
return ERROR;
|
|
}
|
|
}
|
|
/*
|
|
BASECOLOR
|
|
*/
|
|
if ( leqi ( level_name[level], "BASECOLOR" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "RGB" ) == TRUE ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
/*
|
|
COORDINATE3
|
|
*/
|
|
else if ( leqi ( level_name[level], "COORDINATE3" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "POINT" ) == TRUE ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "COORDINATE3: Bad data %s\n", word );
|
|
}
|
|
}
|
|
/*
|
|
COORDINATE4
|
|
*/
|
|
else if ( leqi ( level_name[level], "COORDINATE4" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "POINT" ) == TRUE ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "COORDINATE4: Bad data %s\n", word );
|
|
}
|
|
}
|
|
/*
|
|
COORDINDEX
|
|
*/
|
|
else if ( leqi ( level_name[level], "COORDINDEX" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
ivert = 0;
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
/*
|
|
(indexedlineset) COORDINDEX
|
|
*/
|
|
else if ( leqi ( level_name[level-1], "INDEXEDLINESET" ) == TRUE ) {
|
|
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
if ( jval < -1 ) {
|
|
bad_num = bad_num + 1;
|
|
}
|
|
else {
|
|
if ( line_num < LINES_MAX ) {
|
|
if ( jval != -1 ) {
|
|
jval = jval + cor3_num_old;
|
|
}
|
|
line_dex[line_num] = jval;
|
|
}
|
|
line_num = line_num + 1;
|
|
}
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
}
|
|
}
|
|
/*
|
|
(indexedfaceset) COORDINDEX
|
|
Warning: If the list of indices is not terminated with a final -1, then
|
|
the last face won't get counted.
|
|
*/
|
|
else if ( leqi ( level_name[level-1], "INDEXEDFACESET" ) == TRUE ) {
|
|
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
if ( jval == -1 ) {
|
|
ivert = 0;
|
|
face_num = face_num + 1;
|
|
}
|
|
else {
|
|
if ( ivert == 0 ) {
|
|
if ( face_num < FACE_MAX ) {
|
|
face_order[face_num] = 0;
|
|
}
|
|
}
|
|
if ( face_num < FACE_MAX ) {
|
|
face_order[face_num] = face_order[face_num] + 1;
|
|
face[ivert][face_num] = jval + cor3_num_old;
|
|
ivert = ivert + 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
(indexednurbssurface) COORDINDEX
|
|
*/
|
|
else if ( leqi ( level_name[level-1], "INDEXEDNURBSSURFACE" ) == TRUE ) {
|
|
}
|
|
/*
|
|
(indexedtrianglestripset) COORDINDEX
|
|
|
|
First three coordinate indices I1, I2, I3 define a triangle.
|
|
Next triangle is defined by I2, I3, I4 (actually, I4, I3, I2
|
|
to stay with same counterclockwise sense).
|
|
Next triangle is defined by I3, I4, I5 ( do not need to reverse
|
|
odd numbered triangles) and so on.
|
|
List is terminated with -1.
|
|
*/
|
|
else if ( leqi ( level_name[level-1], "INDEXEDTRIANGLESTRIPSET" ) == TRUE ) {
|
|
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
if ( jval == -1 ) {
|
|
ivert = 0;
|
|
}
|
|
else {
|
|
|
|
ix = iy;
|
|
iy = iz;
|
|
iz = jval + cor3_num_old;
|
|
|
|
if ( ivert == 0 ) {
|
|
if ( face_num < FACE_MAX ) {
|
|
face[ivert][face_num] = jval + cor3_num_old;
|
|
face_order[face_num] = 3;
|
|
}
|
|
}
|
|
else if ( ivert == 1 ) {
|
|
if ( face_num < FACE_MAX ) {
|
|
face[ivert][face_num] = jval + cor3_num_old;
|
|
}
|
|
}
|
|
else if ( ivert == 2 ) {
|
|
if ( face_num < FACE_MAX ) {
|
|
face[ivert][face_num] = jval + cor3_num_old;
|
|
}
|
|
face_num = face_num + 1;
|
|
}
|
|
else {
|
|
|
|
if ( face_num < FACE_MAX ) {
|
|
face_order[face_num] = 3;
|
|
if ( ( ivert % 2 ) == 0 ) {
|
|
face[0][face_num] = ix;
|
|
face[1][face_num] = iy;
|
|
face[2][face_num] = iz;
|
|
}
|
|
else {
|
|
face[0][face_num] = iz;
|
|
face[1][face_num] = iy;
|
|
face[2][face_num] = ix;
|
|
}
|
|
}
|
|
face_num = face_num + 1;
|
|
}
|
|
ivert = ivert + 1;
|
|
/*
|
|
Very very tentative guess as to how indices into the normal
|
|
vector array are set up...
|
|
*/
|
|
if ( face_num < FACE_MAX && ivert > 2 ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
face_normal[i][face_num] = normal_temp[i][ix];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
INDEXEDFACESET
|
|
*/
|
|
else if ( leqi ( level_name[level], "INDEXEDFACESET" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "COORDINDEX" ) == TRUE ) {
|
|
ivert = 0;
|
|
}
|
|
else if ( leqi ( word, "MATERIALINDEX" ) == TRUE ) {
|
|
}
|
|
else if ( leqi ( word, "NORMALINDEX" ) == TRUE ) {
|
|
}
|
|
else if ( leqi ( word, "TEXTURECOORDINDEX" ) == TRUE ) {
|
|
if ( texture_num <= 0 ) {
|
|
texture_num = 1;
|
|
strcpy ( texture_name[0], "Texture_0000" );
|
|
}
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
/*
|
|
INDEXEDLINESET
|
|
*/
|
|
else if ( leqi ( level_name[level], "INDEXEDLINESET" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "COORDINDEX" ) == TRUE ) {
|
|
}
|
|
else if ( leqi ( word, "MATERIALINDEX" ) == TRUE ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
/*
|
|
INDEXEDNURBSSURFACE
|
|
*/
|
|
else if ( leqi ( level_name[level], "INDEXEDNURBSSURFACE" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "NUMUCONTROLPOINTS") == TRUE ) {
|
|
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
nu = jval;
|
|
if ( debug ) {
|
|
printf ( "NU = %d\n", nu );
|
|
}
|
|
}
|
|
else {
|
|
nu = 0;
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
else if ( leqi ( word, "NUMVCONTROLPOINTS" ) == TRUE ) {
|
|
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
nv = jval;
|
|
if ( debug ) {
|
|
printf ( "NV = %d\n", nv );
|
|
}
|
|
}
|
|
else {
|
|
nv = 0;
|
|
bad_num = bad_num + 1;
|
|
}
|
|
}
|
|
else if ( leqi ( word, "COORDINDEX" ) == TRUE ) {
|
|
}
|
|
else if ( leqi ( word, "UKNOTVECTOR" ) == TRUE ) {
|
|
}
|
|
else if ( leqi ( word, "VKNOTVECTOR" ) == TRUE ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
/*
|
|
INDEXEDTRIANGLESTRIPSET
|
|
*/
|
|
else if ( leqi ( level_name[level], "INDEXEDTRIANGLESTRIPSET" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "VERTEXPROPERTY" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
}
|
|
else if ( leqi ( word, "COORDINDEX" ) == TRUE ) {
|
|
ivert = 0;
|
|
}
|
|
else if ( leqi ( word, "NORMALINDEX" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
/*
|
|
INFO
|
|
*/
|
|
else if ( leqi ( level_name[level], "INFO" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "STRING" ) == TRUE ) {
|
|
}
|
|
else if ( strcmp ( word, "\"" ) == 0 ) {
|
|
}
|
|
else {
|
|
}
|
|
}
|
|
/*
|
|
LIGHTMODEL
|
|
Read, but ignore.
|
|
*/
|
|
else if ( leqi ( level_name[level], "LIGHTMODEL" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "model" ) == TRUE ) {
|
|
}
|
|
else {
|
|
}
|
|
}
|
|
/*
|
|
MATERIAL
|
|
Read, but ignore.
|
|
*/
|
|
else if ( leqi ( level_name[level],"MATERIAL" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "AMBIENTCOLOR" ) == TRUE ) {
|
|
}
|
|
else if ( leqi ( word, "EMISSIVECOLOR" ) == TRUE ) {
|
|
}
|
|
else if ( leqi ( word, "DIFFUSECOLOR" ) == TRUE ) {
|
|
}
|
|
else if ( leqi ( word, "SHININESS" ) == TRUE ) {
|
|
}
|
|
else if ( leqi ( word, "SPECULARCOLOR" ) == TRUE ) {
|
|
}
|
|
else if ( leqi ( word, "TRANSPARENCY" ) == TRUE ) {
|
|
}
|
|
else {
|
|
}
|
|
}
|
|
/*
|
|
MATERIALBINDING
|
|
Read, but ignore
|
|
*/
|
|
else if ( leqi ( level_name[level], "MATERIALBINDING" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "VALUE" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", material_binding, &width );
|
|
next = next + width;
|
|
}
|
|
else {
|
|
count = sscanf ( next, "%f%n", &rval, &width );
|
|
next = next + width;
|
|
|
|
if ( count > 0 ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
MATERIALINDEX
|
|
*/
|
|
else if ( leqi ( level_name[level], "MATERIALINDEX" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
ivert = 0;
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
/*
|
|
(indexedfaceset) MATERIALINDEX
|
|
*/
|
|
else if ( leqi ( level_name[level-1], "INDEXEDFACESET" ) == TRUE ) {
|
|
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
if ( jval == -1 ) {
|
|
ivert = 0;
|
|
face_num2 = face_num2 + 1;
|
|
}
|
|
else {
|
|
|
|
if ( face_num2 < FACE_MAX ) {
|
|
if ( jval != -1 ) {
|
|
jval = jval + cor3_num_old;
|
|
}
|
|
vertex_material[ivert][face_num2] = jval;
|
|
ivert = ivert + 1;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
/*
|
|
(indexedlineset) MATERIALINDEX
|
|
*/
|
|
else if ( leqi ( level_name[level-1], "INDEXEDLINESET" ) == TRUE ) {
|
|
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
if ( line_num2 < LINES_MAX ) {
|
|
if ( jval != -1 ) {
|
|
jval = jval + cor3_num_old;
|
|
}
|
|
line_material[line_num2] = jval;
|
|
line_num2 = line_num2 + 1;
|
|
}
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
else {
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
MATRIXTRANSFORM.
|
|
*/
|
|
else if ( leqi ( level_name[level], "MATRIXTRANSFORM" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "MATRIX" ) == TRUE ) {
|
|
icol = -1;
|
|
irow = 0;
|
|
}
|
|
else {
|
|
|
|
count = sscanf ( word, "%f%n", &rval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
icol = icol + 1;
|
|
if ( icol > 3 ) {
|
|
icol = 0;
|
|
irow = irow + 1;
|
|
if ( irow > 3 ) {
|
|
irow = 0;
|
|
}
|
|
}
|
|
|
|
transform_matrix[irow][icol] = rval;
|
|
}
|
|
|
|
}
|
|
}
|
|
/*
|
|
NORMAL
|
|
The field "VECTOR" may be followed by three numbers,
|
|
(handled here), or by a square bracket, and sets of three numbers.
|
|
*/
|
|
else if ( leqi ( level_name[level], "NORMAL" ) == TRUE ) {
|
|
/*
|
|
(vertexproperty) NORMAL
|
|
*/
|
|
if ( leqi ( level_name[level-1], "VERTEXPROPERTY" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
ixyz = 0;
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else {
|
|
|
|
count = sscanf ( word, "%f%n", &rval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
if ( inormface < FACE_MAX ) {
|
|
face_normal[ixyz][inormface] = rval;
|
|
}
|
|
|
|
ixyz = ixyz + 1;
|
|
if ( ixyz > 2 ) {
|
|
ixyz = 0;
|
|
inormface = inormface + 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
(anythingelse) NORMAL
|
|
*/
|
|
else {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
ixyz = 0;
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "VECTOR" ) == TRUE ) {
|
|
}
|
|
else {
|
|
|
|
count = sscanf ( word, "%f%n", &rval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
/* COMMENTED OUT
|
|
|
|
if ( nfnorm < FACE_MAX ) {
|
|
normal[ixyz][nfnorm] = rval;
|
|
}
|
|
|
|
*/
|
|
ixyz = ixyz + 1;
|
|
if ( ixyz > 2 ) {
|
|
ixyz = 0;
|
|
}
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
NORMALBINDING
|
|
Read, but ignore
|
|
*/
|
|
else if ( leqi ( level_name[level], "NORMALBINDING" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "VALUE" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", normal_binding, &width );
|
|
next = next + width;
|
|
}
|
|
else {
|
|
count = sscanf ( word, "%f%n", &rval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
NORMALINDEX
|
|
*/
|
|
else if ( leqi ( level_name[level], "NORMALINDEX" ) == TRUE ) {
|
|
/*
|
|
(indexedtrianglestripset) NORMALINDEX
|
|
*/
|
|
if ( leqi ( level_name[level-1], "INDEXEDTRIANGLESTRIPSET" ) == TRUE ) {
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "[" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
}
|
|
}
|
|
/*
|
|
(anythingelse) NORMALINDEX
|
|
*/
|
|
else {
|
|
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
ivert = 0;
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else {
|
|
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
if ( jval == -1 ) {
|
|
ivert = 0;
|
|
iface_num = iface_num + 1;
|
|
}
|
|
else {
|
|
if ( iface_num < FACE_MAX ) {
|
|
for ( i = 0; i < 3; i++ ){
|
|
vertex_normal[i][ivert][iface_num] = normal_temp[i][jval];
|
|
}
|
|
ivert = ivert + 1;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
(coordinate3) POINT
|
|
*/
|
|
else if ( leqi ( level_name[level], "POINT" ) == TRUE ) {
|
|
|
|
if ( leqi ( level_name[level-1], "COORDINATE3" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
ixyz = 0;
|
|
cor3_num_old = cor3_num;
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else {
|
|
|
|
count = sscanf ( word, "%f%n", &rval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
if ( cor3_num < COR3_MAX ) {
|
|
xvec[ixyz] = rval;
|
|
}
|
|
|
|
ixyz = ixyz + 1;
|
|
|
|
if ( ixyz == 3 ) {
|
|
|
|
ixyz = 0;
|
|
|
|
tmat_mxp ( transform_matrix, xvec, xvec );
|
|
|
|
cor3[0][cor3_num] = xvec[0];
|
|
cor3[1][cor3_num] = xvec[1];
|
|
cor3[2][cor3_num] = xvec[2];
|
|
|
|
cor3_num = cor3_num + 1;
|
|
|
|
continue;
|
|
}
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
(texturecoodinate2) POINT
|
|
*/
|
|
else if ( leqi ( level_name[level-1], "TEXTURECOORDINATE2" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
iuv = 0;
|
|
text_numure_temp = 0;
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else {
|
|
|
|
count = sscanf ( word, "%f%n", &rval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
texture_temp[iuv][text_numure_temp] = rval;
|
|
|
|
iuv = iuv + 1;
|
|
if ( iuv == 2 ) {
|
|
iuv = 0;
|
|
text_numure_temp = text_numure_temp + 1;
|
|
}
|
|
}
|
|
else {
|
|
printf ( "TextureCoordinate2 { Point [: Bad data\n" );
|
|
bad_num = bad_num + 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
RGB
|
|
*/
|
|
else if ( leqi ( level_name[level],"RGB" ) == TRUE ) {
|
|
/*
|
|
(basecolor) RGB
|
|
*/
|
|
if ( leqi ( level_name[level-1], "BASECOLOR" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
icolor = 0;
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else {
|
|
|
|
count = sscanf ( word, "%f%n", &rval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
rgbcolor[icolor][color_num] = rval;
|
|
icolor = icolor + 1;
|
|
|
|
if ( icolor == 3 ) {
|
|
icolor = 0;
|
|
color_num = color_num + 1;
|
|
}
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
(anythingelse RGB)
|
|
*/
|
|
else {
|
|
|
|
printf ( "HALSBAND DES TODES!\n" );
|
|
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
icolor = 0;
|
|
ivert = 0;
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else {
|
|
|
|
count = sscanf ( word, "%f%n", &rval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
if ( icface < FACE_MAX ) {
|
|
|
|
vertex_rgb[icolor][ivert][icface] = rval;
|
|
|
|
icolor = icolor + 1;
|
|
if ( icolor == 3 ) {
|
|
icolor = 0;
|
|
color_num = color_num + 1;
|
|
ivert = ivert + 1;
|
|
if ( ivert == face_order[icface] ) {
|
|
ivert = 0;
|
|
icface = icface + 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
/*
|
|
SEPARATOR
|
|
*/
|
|
else if ( leqi ( level_name[level], "SEPARATOR" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else {
|
|
}
|
|
}
|
|
/*
|
|
SHAPEHINTS
|
|
Read, but ignore.
|
|
*/
|
|
else if ( leqi ( level_name[level], "SHAPEHINTS" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "CREASEANGLE" ) == TRUE ) {
|
|
|
|
count = sscanf ( next, "%f%n", &rval, &width );
|
|
next = next + width;
|
|
|
|
if ( count <= 0 ) {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
else if ( leqi ( word, "FACETYPE" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
}
|
|
else if ( leqi ( word, "SHAPETYPE" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
}
|
|
else if ( leqi ( word, "VERTEXORDERING" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
/*
|
|
TEXTURE2
|
|
*/
|
|
else if ( leqi ( level_name[level], "TEXTURE2" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
texture_num = texture_num + 1;
|
|
}
|
|
else if ( leqi ( word, "BLENDCOLOR" ) == TRUE ) {
|
|
}
|
|
/*
|
|
NEED TO REMOVE QUOTES SURROUNDING TEXTURE NAME.
|
|
*/
|
|
else if ( leqi ( word, "FILENAME" ) == TRUE ) {
|
|
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
|
|
strcpy ( texture_name[texture_num], word );
|
|
|
|
i = 0;
|
|
j = 0;
|
|
do {
|
|
c = texture_name[texture_num][i];
|
|
i = i + 1;
|
|
if ( c != '"' ) {
|
|
texture_name[texture_num][j] = c;
|
|
j = j + 1;
|
|
}
|
|
} while ( c != '\0' );
|
|
|
|
}
|
|
else if ( leqi ( word, "IMAGE" ) == TRUE ) {
|
|
}
|
|
else if ( leqi ( word, "MODEL" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
}
|
|
else if ( leqi ( word, "WRAPS" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
}
|
|
else if ( leqi ( word, "WRAPT" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
}
|
|
else {
|
|
}
|
|
}
|
|
/*
|
|
TEXTURECOORDINATE2
|
|
*/
|
|
else if ( leqi ( level_name[level], "TEXTURECOORDINATE2" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "POINT" ) == TRUE ) {
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "TEXTURECOORDINATE2: Bad data %s\n", word );
|
|
}
|
|
}
|
|
/*
|
|
TEXTURECOORDINATEBINDING
|
|
*/
|
|
else if ( leqi ( level_name[level], "TEXTURECOORDINATEBINDING" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "VALUE" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", texture_binding, &width );
|
|
next = next + width;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
/*
|
|
TEXTURECOORDINDEX
|
|
*/
|
|
else if ( leqi ( level_name[level], "TEXTURECOORDINDEX" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
ivert = 0;
|
|
iface_num = 0;
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else {
|
|
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
if ( jval == - 1 ) {
|
|
ivert = 0;
|
|
}
|
|
else {
|
|
|
|
if ( iface_num < FACE_MAX ) {
|
|
vertex_tex_uv[0][ivert][iface_num] = texture_temp[0][jval];
|
|
vertex_tex_uv[1][ivert][iface_num] = texture_temp[1][jval];
|
|
}
|
|
|
|
ivert = ivert + 1;
|
|
|
|
if ( ivert == face_order[iface_num] ) {
|
|
ivert = 0;
|
|
iface_num = iface_num + 1;
|
|
}
|
|
}
|
|
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
|
|
}
|
|
}
|
|
/*
|
|
UKNOTVECTOR
|
|
*/
|
|
else if ( leqi ( level_name[level], "UKNOTVECTOR" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
else {
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
}
|
|
}
|
|
/*
|
|
VECTOR
|
|
*/
|
|
else if ( leqi ( level_name[level], "VECTOR" ) == TRUE ) {
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
/*
|
|
(normal) VECTOR
|
|
*/
|
|
else if ( leqi ( level_name[level-1], "NORMAL" ) == TRUE ) {
|
|
|
|
count = sscanf ( word, "%f%n", &rval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
if ( normal_num_temp < ORDER_MAX * FACE_MAX ) {
|
|
normal_temp[ixyz][normal_num_temp] = rval;
|
|
ixyz = ixyz + 1;
|
|
if ( ixyz == 3 ) {
|
|
ixyz = 0;
|
|
normal_num_temp = normal_num_temp + 1;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "NORMAL VECTOR: bad data %s\n", word );
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
(vertexproperty) VERTEX
|
|
*/
|
|
else if ( leqi ( level_name[level], "VERTEX" ) == TRUE ) {
|
|
|
|
if ( leqi ( level_name[level-1], "VERTEXPROPERTY" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
ixyz = 0;
|
|
cor3_num_old = cor3_num;
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else {
|
|
count = sscanf ( word, "%f%n", &rval, &width );
|
|
|
|
if ( count > 0 ) {
|
|
|
|
if ( cor3_num < COR3_MAX ) {
|
|
cor3[ixyz][cor3_num] = rval;
|
|
}
|
|
ixyz = ixyz + 1;
|
|
if ( ixyz == 3 ) {
|
|
ixyz = 0;
|
|
cor3_num = cor3_num + 1;
|
|
}
|
|
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
(indexedtrianglestripset) VERTEXPROPERTY
|
|
*/
|
|
else if ( leqi ( level_name[level], "VERTEXPROPERTY" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "{" ) == 0 ) {
|
|
}
|
|
else if ( strcmp ( word, "}" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
}
|
|
else if ( leqi ( word, "VERTEX" ) == TRUE ) {
|
|
}
|
|
else if ( leqi ( word, "NORMAL" ) == TRUE ) {
|
|
ixyz = 0;
|
|
}
|
|
else if ( leqi ( word, "MATERIALBINDING" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
}
|
|
else if ( leqi ( word, "NORMALBINDING" ) == TRUE ) {
|
|
count = sscanf ( next, "%s%n", word, &width );
|
|
next = next + width;
|
|
}
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
printf ( "Bad data %s\n", word );
|
|
}
|
|
}
|
|
/*
|
|
VKNOTVECTOR
|
|
*/
|
|
else if ( leqi ( level_name[level], "VKNOTVECTOR" ) == TRUE ) {
|
|
|
|
if ( strcmp ( word, "[" ) == 0 ) {
|
|
continue;
|
|
}
|
|
else if ( strcmp ( word, "]" ) == 0 ) {
|
|
level = nlbrack - nrbrack;
|
|
continue;
|
|
}
|
|
else {
|
|
count = sscanf ( word, "%d%n", &jval, &width );
|
|
}
|
|
}
|
|
/*
|
|
Any other word:
|
|
*/
|
|
else {
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
Reset the transformation matrix to the identity,
|
|
because, presumably, we've applied it by now.
|
|
*/
|
|
tmat_init ( transform_matrix );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int iv_write ( FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
IV_WRITE writes graphics information to an Inventor file.
|
|
|
|
Modified:
|
|
|
|
29 June 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int icor3;
|
|
int iface;
|
|
int itemp;
|
|
int ivert;
|
|
int j;
|
|
int length;
|
|
int text_num;
|
|
|
|
text_num = 0;
|
|
|
|
fprintf ( fileout, "#Inventor V2.0 ascii\n" );
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "Separator {\n" );
|
|
fprintf ( fileout, " Info {\n" );
|
|
fprintf ( fileout, " string \"%s generated by IVCON.\"\n", fileout_name );
|
|
fprintf ( fileout, " string \"Original data in file %s.\"\n", filein_name );
|
|
fprintf ( fileout, " }\n" );
|
|
fprintf ( fileout, " Separator {\n" );
|
|
text_num = text_num + 8;
|
|
/*
|
|
LightModel:
|
|
|
|
BASE_COLOR ignores light sources, and uses only diffuse color
|
|
and transparency. Even without normal vector information,
|
|
the object will show up. However, you won't get shadow
|
|
and lighting effects.
|
|
|
|
PHONG uses the Phong lighting model, accounting for light sources
|
|
and surface orientation. This is the default. I believe
|
|
you need accurate normal vector information in order for this
|
|
option to produce nice pictures.
|
|
|
|
DEPTH ignores light sources, and calculates lighting based on
|
|
the location of the object within the near and far planes
|
|
of the current camera's view volume.
|
|
*/
|
|
fprintf ( fileout, " LightModel {\n" );
|
|
fprintf ( fileout, " model PHONG\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 3;
|
|
/*
|
|
Transformation matrix.
|
|
*/
|
|
fprintf ( fileout, " MatrixTransform { matrix\n" );
|
|
fprintf ( fileout, " %f %f %f %f\n", transform_matrix[0][0],
|
|
transform_matrix[0][1], transform_matrix[0][2], transform_matrix[0][3] );
|
|
fprintf ( fileout, " %f %f %f %f\n", transform_matrix[1][0],
|
|
transform_matrix[1][1], transform_matrix[1][2], transform_matrix[1][3] );
|
|
fprintf ( fileout, " %f %f %f %f\n", transform_matrix[2][0],
|
|
transform_matrix[2][1], transform_matrix[2][2], transform_matrix[2][3] );
|
|
fprintf ( fileout, " %f %f %f %f\n", transform_matrix[3][0],
|
|
transform_matrix[3][1], transform_matrix[3][2], transform_matrix[3][3] );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 6;
|
|
/*
|
|
Material.
|
|
*/
|
|
fprintf ( fileout, " Material {\n" );
|
|
fprintf ( fileout, " ambientColor 0.2 0.2 0.2\n" );
|
|
fprintf ( fileout, " diffuseColor 0.8 0.8 0.8\n" );
|
|
fprintf ( fileout, " emissiveColor 0.0 0.0 0.0\n" );
|
|
fprintf ( fileout, " specularColor 0.0 0.0 0.0\n" );
|
|
fprintf ( fileout, " shininess 0.2\n" );
|
|
fprintf ( fileout, " transparency 0.0\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 8;
|
|
/*
|
|
MaterialBinding
|
|
*/
|
|
fprintf ( fileout, " MaterialBinding {\n" );
|
|
fprintf ( fileout, " value PER_VERTEX_INDEXED\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 3;
|
|
/*
|
|
NormalBinding
|
|
|
|
PER_VERTEX promises that we will write a list of normal vectors
|
|
in a particular order, namely, the normal vectors for the vertices
|
|
of the first face, then the second face, and so on.
|
|
|
|
PER_VERTEX_INDEXED promises that we will write a list of normal vectors,
|
|
and then, as part of the IndexedFaceSet, we will give a list of
|
|
indices referencing this normal vector list.
|
|
*/
|
|
fprintf ( fileout, " NormalBinding {\n" );
|
|
fprintf ( fileout, " value PER_VERTEX_INDEXED\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 3;
|
|
/*
|
|
Texture2.
|
|
|
|
FLAW: We can only handle on texture right now.
|
|
*/
|
|
if ( texture_num > 0 ) {
|
|
fprintf ( fileout, " Texture2 {\n" );
|
|
fprintf ( fileout, " filename \"%s\"\n", texture_name[0] );
|
|
fprintf ( fileout, " wrapS REPEAT\n" );
|
|
fprintf ( fileout, " wrapT REPEAT\n" );
|
|
fprintf ( fileout, " model MODULATE\n" );
|
|
fprintf ( fileout, " blendColor 0.0 0.0 0.0\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 7;
|
|
}
|
|
/*
|
|
TextureCoordinateBinding
|
|
*/
|
|
fprintf ( fileout, " TextureCoordinateBinding {\n" );
|
|
fprintf ( fileout, " value PER_VERTEX_INDEXED\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 3;
|
|
/*
|
|
ShapeHints
|
|
*/
|
|
fprintf ( fileout, " ShapeHints {\n" );
|
|
fprintf ( fileout, " vertexOrdering COUNTERCLOCKWISE\n" );
|
|
fprintf ( fileout, " shapeType UNKNOWN_SHAPE_TYPE\n" );
|
|
fprintf ( fileout, " faceType CONVEX\n" );
|
|
fprintf ( fileout, " creaseAngle 6.28319\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 6;
|
|
/*
|
|
Point coordinates.
|
|
*/
|
|
fprintf ( fileout, " Coordinate3 {\n" );
|
|
fprintf ( fileout, " point [\n" );
|
|
text_num = text_num + 2;
|
|
|
|
for ( j = 0; j < cor3_num; j++ ) {
|
|
fprintf ( fileout, " %f %f %f,\n", cor3[0][j], cor3[1][j], cor3[2][j] );
|
|
text_num = text_num + 1;
|
|
}
|
|
fprintf ( fileout, " ]\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 2;
|
|
/*
|
|
Texture coordinates.
|
|
*/
|
|
fprintf ( fileout, " TextureCoordinate2 {\n" );
|
|
fprintf ( fileout, " point [\n" );
|
|
text_num = text_num + 2;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
fprintf ( fileout, " %f %f,\n", vertex_tex_uv[0][ivert][iface],
|
|
vertex_tex_uv[1][ivert][iface] );
|
|
text_num = text_num + 1;
|
|
}
|
|
}
|
|
fprintf ( fileout, " ]\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 2;
|
|
/*
|
|
BaseColor.
|
|
*/
|
|
if ( color_num > 0 ) {
|
|
|
|
fprintf ( fileout, " BaseColor {\n" );
|
|
fprintf ( fileout, " rgb [\n" );
|
|
text_num = text_num + 2;
|
|
|
|
for ( j = 0; j < color_num; j++ ) {
|
|
fprintf ( fileout, " %f %f %f,\n", rgbcolor[0][j], rgbcolor[1][j],
|
|
rgbcolor[2][j] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 2;
|
|
}
|
|
/*
|
|
Normal vectors.
|
|
Use the normal vectors associated with nodes.
|
|
*/
|
|
if ( face_num > 0 ) {
|
|
|
|
fprintf ( fileout, " Normal { \n" );
|
|
fprintf ( fileout, " vector [\n" );
|
|
text_num = text_num + 2;
|
|
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
fprintf ( fileout, " %f %f %f,\n",
|
|
cor3_normal[0][icor3],
|
|
cor3_normal[1][icor3],
|
|
cor3_normal[2][icor3] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 2;
|
|
}
|
|
/*
|
|
IndexedLineSet
|
|
*/
|
|
if ( line_num > 0 ) {
|
|
|
|
fprintf ( fileout, " IndexedLineSet {\n" );
|
|
/*
|
|
IndexedLineSet coordIndex
|
|
*/
|
|
fprintf ( fileout, " coordIndex [\n" );
|
|
text_num = text_num + 2;
|
|
|
|
length = 0;
|
|
|
|
for ( j = 0; j < line_num; j++ ) {
|
|
|
|
if ( length == 0 ) {
|
|
fprintf ( fileout, " " );
|
|
}
|
|
|
|
fprintf ( fileout, " %d,", line_dex[j] );
|
|
length = length + 1;
|
|
|
|
if ( line_dex[j] == -1 || length >= 10 || j == line_num-1 ) {
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
length = 0;
|
|
}
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
IndexedLineSet materialIndex.
|
|
*/
|
|
fprintf ( fileout, " materialIndex [\n" );
|
|
text_num = text_num + 1;
|
|
|
|
length = 0;
|
|
|
|
for ( j = 0; j < line_num; j++ ) {
|
|
|
|
if ( length == 0 ) {
|
|
fprintf ( fileout, " " );
|
|
}
|
|
|
|
fprintf ( fileout, " %d,", line_material[j] );
|
|
length = length + 1;
|
|
|
|
if ( line_material[j] == -1 || length >= 10 || j == line_num-1 ) {
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
length = 0;
|
|
}
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 2;
|
|
}
|
|
/*
|
|
IndexedFaceSet.
|
|
*/
|
|
if ( face_num > 0 ) {
|
|
|
|
fprintf ( fileout, " IndexedFaceSet {\n" );
|
|
fprintf ( fileout, " coordIndex [\n" );
|
|
text_num = text_num + 2;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
fprintf ( fileout, " " );
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
fprintf ( fileout, " %d,", face[ivert][iface] );
|
|
}
|
|
fprintf ( fileout, " -1,\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
IndexedFaceSet normalIndex
|
|
*/
|
|
fprintf ( fileout, " normalIndex [\n" );
|
|
text_num = text_num + 1;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
fprintf ( fileout, " " );
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
fprintf ( fileout, " %d,", face[ivert][iface] );
|
|
}
|
|
fprintf ( fileout, " -1,\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
fprintf ( fileout, " ]\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
IndexedFaceSet materialIndex
|
|
*/
|
|
fprintf ( fileout, " materialIndex [\n" );
|
|
text_num = text_num + 1;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
fprintf ( fileout, " " );
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
fprintf ( fileout, " %d,", vertex_material[ivert][iface] );
|
|
}
|
|
fprintf ( fileout, " -1,\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
IndexedFaceSet textureCoordIndex
|
|
*/
|
|
fprintf ( fileout, " textureCoordIndex [\n" );
|
|
text_num = text_num + 1;
|
|
|
|
itemp = 0;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
fprintf ( fileout, " " );
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
fprintf ( fileout, " %d,", itemp );
|
|
itemp = itemp + 1;
|
|
}
|
|
fprintf ( fileout, " -1,\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 2;
|
|
}
|
|
/*
|
|
Close up the Separator nodes.
|
|
*/
|
|
fprintf ( fileout, " }\n" );
|
|
fprintf ( fileout, "}\n" );
|
|
text_num = text_num + 2;
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "IV_WRITE - Wrote %d text lines;\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int ivec_max ( int n, int *a )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
IVEC_MAX returns the maximum element in an integer array.
|
|
|
|
Modified:
|
|
|
|
09 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int *ia;
|
|
int imax;
|
|
|
|
if ( n <= 0 ) {
|
|
imax = 0;
|
|
}
|
|
else {
|
|
ia = a;
|
|
imax = *ia;
|
|
for ( i = 1; i < n; i++ ) {
|
|
ia = ia + 1;
|
|
if ( imax < *ia ) {
|
|
imax = *ia;
|
|
}
|
|
}
|
|
}
|
|
return imax;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int leqi ( char* string1, char* string2 )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
LEQI compares two strings for equality, disregarding case.
|
|
|
|
Modified:
|
|
|
|
15 September 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int nchar;
|
|
int nchar1;
|
|
int nchar2;
|
|
|
|
nchar1 = strlen ( string1 );
|
|
nchar2 = strlen ( string2 );
|
|
|
|
if ( nchar1 < nchar2 ) {
|
|
nchar = nchar1;
|
|
}
|
|
else {
|
|
nchar = nchar2;
|
|
}
|
|
/*
|
|
The strings are not equal if they differ over their common length.
|
|
*/
|
|
for ( i = 0; i < nchar; i++ ) {
|
|
|
|
if ( toupper ( string1[i] ) != toupper ( string2[i] ) ) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
/*
|
|
The strings are not equal if the longer one includes nonblanks
|
|
in the tail.
|
|
*/
|
|
if ( nchar1 > nchar ) {
|
|
for ( i = nchar; i < nchar1; i++ ) {
|
|
if ( string1[i] != ' ' ) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
else if ( nchar2 > nchar ) {
|
|
for ( i = nchar; i < nchar2; i++ ) {
|
|
if ( string2[i] != ' ' ) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
long int long_int_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
LONG_INT_READ reads a long int from a binary file.
|
|
|
|
Modified:
|
|
|
|
24 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
union {
|
|
long int yint;
|
|
char ychar[4];
|
|
} y;
|
|
|
|
if ( byte_swap == TRUE ) {
|
|
y.ychar[3] = fgetc ( filein );
|
|
y.ychar[2] = fgetc ( filein );
|
|
y.ychar[1] = fgetc ( filein );
|
|
y.ychar[0] = fgetc ( filein );
|
|
}
|
|
else {
|
|
y.ychar[0] = fgetc ( filein );
|
|
y.ychar[1] = fgetc ( filein );
|
|
y.ychar[2] = fgetc ( filein );
|
|
y.ychar[3] = fgetc ( filein );
|
|
}
|
|
|
|
return y.yint;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int long_int_write ( FILE *fileout, long int int_val )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
LONG_INT_WRITE writes a long int to a binary file.
|
|
|
|
Modified:
|
|
|
|
14 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
union {
|
|
long int yint;
|
|
char ychar[4];
|
|
} y;
|
|
|
|
y.yint = int_val;
|
|
|
|
if ( byte_swap == TRUE ) {
|
|
fputc ( y.ychar[3], fileout );
|
|
fputc ( y.ychar[2], fileout );
|
|
fputc ( y.ychar[1], fileout );
|
|
fputc ( y.ychar[0], fileout );
|
|
}
|
|
else {
|
|
fputc ( y.ychar[0], fileout );
|
|
fputc ( y.ychar[1], fileout );
|
|
fputc ( y.ychar[2], fileout );
|
|
fputc ( y.ychar[3], fileout );
|
|
}
|
|
|
|
return 4;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
void news ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
NEWS reports the program change history.
|
|
|
|
Modified:
|
|
|
|
26 September 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
printf ( "\n" );
|
|
printf ( "Recent changes:\n" );
|
|
printf ( "\n" );
|
|
printf ( " 04 July 2000\n" );
|
|
printf ( " Added preliminary XGL_WRITE.\n" );
|
|
printf ( " 26 September 1999\n" );
|
|
printf ( " After ASE_READ, call NODE_TO_VERTEX_MAT and VERTEX_TO_FACE_MATERIAL.\n" );
|
|
printf ( " 27 July 1999\n" );
|
|
printf ( " Corrected TMAT_ROT_VECTOR.\n" );
|
|
printf ( " 17 July 1999\n" );
|
|
printf ( " Added null edge and face deletion.\n" );
|
|
printf ( " Corrected a string problem in SMF_READ.\n" );
|
|
printf ( " 03 July 1999\n" );
|
|
printf ( " Fixed a problem with BINDING variables in SMF_READ.\n" );
|
|
printf ( " 02 July 1999\n" );
|
|
printf ( " Added limited texture support in 3DS/IV.\n" );
|
|
printf ( " 26 June 1999\n" );
|
|
printf ( " BYU_READ added.\n" );
|
|
printf ( " 25 June 1999\n" );
|
|
printf ( " BYU_WRITE added.\n" );
|
|
printf ( " 22 June 1999\n" );
|
|
printf ( " TRIB_READ added.\n" );
|
|
printf ( " 16 June 1999\n" );
|
|
printf ( " TRIB_WRITE Greg Hood binary triangle output routine added.\n" );
|
|
printf ( " 10 June 1999\n" );
|
|
printf ( " TRIA_WRITE Greg Hood ASCII triangle output routine added.\n" );
|
|
printf ( " 09 June 1999\n" );
|
|
printf ( " TEC_WRITE TECPLOT output routine added.\n" );
|
|
printf ( " IV_READ and IV_WRITE use TRANSFORM_MATRIX now.\n" );
|
|
printf ( " 26 May 1999\n" );
|
|
printf ( " LINE_PRUNE option added for VLA_WRITE.\n" );
|
|
printf ( " 24 May 1999\n" );
|
|
printf ( " Added << command to append new graphics data to old.\n" );
|
|
printf ( " Stuck in first draft STLB_READ/STLB_WRITE routines.\n" );
|
|
printf ( " STLA_WRITE and STLB_WRITE automatically decompose \n" );
|
|
printf ( " non-triangular faces before writing.\n" );
|
|
printf ( " 23 May 1999\n" );
|
|
printf ( " Stuck in first draft WRL_WRITE routine.\n" );
|
|
printf ( " 22 May 1999\n" );
|
|
printf ( " Faces converted to lines before calling VLA_WRITE.\n" );
|
|
printf ( " Added UCD_WRITE.\n" );
|
|
printf ( " Added MATERIAL/PATCH/TAGGEDPOINTS fields in HRC_READ.\n" );
|
|
printf ( " 17 May 1999\n" );
|
|
printf ( " Updated SMF_WRITE, SMF_READ to match code in IVREAD.\n" );
|
|
printf ( " Added transformation matrix routines.\n" );
|
|
printf ( " 16 May 1999\n" );
|
|
printf ( " Zik Saleeba improved DXF support to handle polygons.\n" );
|
|
printf ( " 15 April 1999\n" );
|
|
printf ( " Zik Saleeba added Golgotha GMOD file format support.\n" );
|
|
printf ( " 03 December 1998\n" );
|
|
printf ( " Set up simple hooks in TDS_READ_MATERIAL_SECTION.\n" );
|
|
printf ( " 02 December 1998\n" );
|
|
printf ( " Set up simple hooks for texture map names.\n" );
|
|
printf ( " 19 November 1998\n" );
|
|
printf ( " IV_WRITE uses PER_VERTEX normal binding.\n" );
|
|
printf ( " 18 November 1998\n" );
|
|
printf ( " Added node normals.\n" );
|
|
printf ( " Finally added the -RN option.\n" );
|
|
printf ( " 17 November 1998\n" );
|
|
printf ( " Added face node ordering reversal option.\n" );
|
|
printf ( " 20 October 1998\n" );
|
|
printf ( " Added DATA_REPORT.\n" );
|
|
printf ( " 19 October 1998\n" );
|
|
printf ( " SMF_READ and SMF_WRITE added.\n" );
|
|
printf ( " 16 October 1998\n" );
|
|
printf ( " Fixing a bug in IV_READ that chokes on ]} and other\n" );
|
|
printf ( " cases where brackets aren't properly spaced.\n" );
|
|
printf ( " 11 October 1998\n" );
|
|
printf ( " Added face subset selection option S.\n" );
|
|
printf ( " 09 October 1998\n" );
|
|
printf ( " Reworking normal vector treatments.\n" );
|
|
printf ( " Synchronizing IVREAD and IVCON.\n" );
|
|
printf ( " POV_WRITE added.\n" );
|
|
printf ( " 02 October 1998\n" );
|
|
printf ( " IVCON reproduces BOX.3DS and CONE.3DS exactly.\n" );
|
|
printf ( " 30 September 1998\n" );
|
|
printf ( " IVCON compiled on the PC.\n" );
|
|
printf ( " Interactive BYTE_SWAP option added for binary files.\n" );
|
|
printf ( " 25 September 1998\n" );
|
|
printf ( " OBJECT_NAME made available to store object name.\n" );
|
|
printf ( " 23 September 1998\n" );
|
|
printf ( " 3DS binary files can be written.\n" );
|
|
printf ( " 15 September 1998\n" );
|
|
printf ( " 3DS binary files can be read.\n" );
|
|
printf ( " 01 September 1998\n" );
|
|
printf ( " COR3_RANGE, FACE_NORMAL_AVE added.\n" );
|
|
printf ( " Major modifications to normal vectors.\n" );
|
|
printf ( " 24 August 1998\n" );
|
|
printf ( " HRC_READ added.\n" );
|
|
printf ( " 21 August 1998\n" );
|
|
printf ( " TXT_WRITE improved.\n" );
|
|
printf ( " 20 August 1998\n" );
|
|
printf ( " HRC_WRITE can output lines as linear splines.\n" );
|
|
printf ( " 19 August 1998\n" );
|
|
printf ( " Automatic normal computation for OBJ files.\n" );
|
|
printf ( " Added normal vector computation.\n" );
|
|
printf ( " HRC_WRITE is working.\n" );
|
|
printf ( " 18 August 1998\n" );
|
|
printf ( " IV_READ/IV_WRITE handle BASECOLOR RGB properly now.\n" );
|
|
printf ( " Improved treatment of face materials and normals.\n" );
|
|
printf ( " 17 August 1998\n" );
|
|
printf ( " ORDER_MAX increased to 35.\n" );
|
|
printf ( " FACE_PRINT routine added.\n" );
|
|
printf ( " INIT_DATA routine added.\n" );
|
|
printf ( " 14 August 1998\n" );
|
|
printf ( " IV_READ is working.\n" );
|
|
printf ( " 13 August 1998\n" );
|
|
printf ( " ASE_WRITE is working.\n" );
|
|
printf ( " IV_WRITE is working.\n" );
|
|
printf ( " 12 August 1998\n" );
|
|
printf ( " ASE_READ is working.\n" );
|
|
printf ( " 10 August 1998\n" );
|
|
printf ( " DXF_WRITE is working.\n" );
|
|
printf ( " DXF_READ is working.\n" );
|
|
printf ( " 27 July 1998\n" );
|
|
printf ( " Interactive mode is working.\n" );
|
|
printf ( " OBJ_READ is working.\n" );
|
|
printf ( " 25 July 1998\n" );
|
|
printf ( " OBJ_WRITE is working.\n" );
|
|
printf ( " 24 July 1998\n" );
|
|
printf ( " DATA_CHECK checks the input data.\n" );
|
|
printf ( " VLA_READ is working.\n" );
|
|
printf ( " VLA_WRITE is working.\n" );
|
|
printf ( " 23 July 1998\n" );
|
|
printf ( " STL_WRITE is working.\n" );
|
|
printf ( " 22 July 1998\n" );
|
|
printf ( " STL_READ is working.\n" );
|
|
printf ( " TXT_WRITE is working.\n" );
|
|
}
|
|
/**********************************************************************/
|
|
|
|
void node_to_vertex_material ( void )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
NODE_TO_VERTEX_MAT extends node material definitions to vertices.
|
|
|
|
Discussion:
|
|
|
|
A NODE is a point in space.
|
|
A VERTEX is a node as used in a particular face.
|
|
One node may be used as a vertex in several faces, or none.
|
|
|
|
Modified:
|
|
|
|
22 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int iface;
|
|
int ivert;
|
|
int node;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
node = face[ivert][iface];
|
|
vertex_material[ivert][iface] = cor3_material[node];
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int obj_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
OBJ_READ reads a Wavefront OBJ file.
|
|
|
|
Example:
|
|
|
|
# magnolia.obj
|
|
|
|
mtllib ./vp.mtl
|
|
|
|
g
|
|
v -3.269770 -39.572201 0.876128
|
|
v -3.263720 -39.507999 2.160890
|
|
...
|
|
v 0.000000 -9.988540 0.000000
|
|
g stem
|
|
s 1
|
|
usemtl brownskn
|
|
f 8 9 11 10
|
|
f 12 13 15 14
|
|
...
|
|
f 788 806 774
|
|
|
|
Modified:
|
|
|
|
20 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int count;
|
|
int i;
|
|
int ivert;
|
|
char *next;
|
|
char *next2;
|
|
char *next3;
|
|
int node;
|
|
int vertex_normal_num;
|
|
float r1;
|
|
float r2;
|
|
float r3;
|
|
char token[LINE_MAX_LEN];
|
|
char token2[LINE_MAX_LEN];
|
|
int width;
|
|
/*
|
|
Initialize.
|
|
*/
|
|
vertex_normal_num = 0;
|
|
/*
|
|
Read the next line of the file into INPUT.
|
|
*/
|
|
while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL ) {
|
|
|
|
text_num = text_num + 1;
|
|
/*
|
|
Advance to the first nonspace character in INPUT.
|
|
*/
|
|
for ( next = input; *next != '\0' && isspace(*next); next++ ) {
|
|
}
|
|
/*
|
|
Skip blank lines and comments.
|
|
*/
|
|
|
|
if ( *next == '\0' ) {
|
|
continue;
|
|
}
|
|
|
|
if ( *next == '#' || *next == '$' ) {
|
|
comment_num = comment_num + 1;
|
|
continue;
|
|
}
|
|
/*
|
|
Extract the first word in this line.
|
|
*/
|
|
sscanf ( next, "%s%n", token, &width );
|
|
/*
|
|
Set NEXT to point to just after this token.
|
|
*/
|
|
|
|
next = next + width;
|
|
/*
|
|
BEVEL
|
|
Bevel interpolation.
|
|
*/
|
|
if ( leqi ( token, "BEVEL" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
BMAT
|
|
Basis matrix.
|
|
*/
|
|
else if ( leqi ( token, "BMAT" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
C_INTERP
|
|
Color interpolation.
|
|
*/
|
|
else if ( leqi ( token, "C_INTERP" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
CON
|
|
Connectivity between free form surfaces.
|
|
*/
|
|
else if ( leqi ( token, "CON" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
CSTYPE
|
|
Curve or surface type.
|
|
*/
|
|
else if ( leqi ( token, "CSTYPE" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
CTECH
|
|
Curve approximation technique.
|
|
*/
|
|
else if ( leqi ( token, "CTECH" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
CURV
|
|
Curve.
|
|
*/
|
|
else if ( leqi ( token, "CURV" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
CURV2
|
|
2D curve.
|
|
*/
|
|
else if ( leqi ( token, "CURV2" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
D_INTERP
|
|
Dissolve interpolation.
|
|
*/
|
|
else if ( leqi ( token, "D_INTERP" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
DEG
|
|
Degree.
|
|
*/
|
|
else if ( leqi ( token, "DEG" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
END
|
|
End statement.
|
|
*/
|
|
else if ( leqi ( token, "END" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
F V1 V2 V3
|
|
or
|
|
F V1/VT1/VN1 V2/VT2/VN2 ...
|
|
or
|
|
F V1//VN1 V2//VN2 ...
|
|
|
|
Face.
|
|
A face is defined by the vertices.
|
|
Optionally, slashes may be used to include the texture vertex
|
|
and vertex normal indices.
|
|
|
|
OBJ line node indices are 1 based rather than 0 based.
|
|
So we have to decrement them before loading them into FACE.
|
|
*/
|
|
|
|
else if ( leqi ( token, "F" ) == TRUE ) {
|
|
|
|
ivert = 0;
|
|
face_order[face_num] = 0;
|
|
/*
|
|
Read each item in the F definition as a token, and then
|
|
take it apart.
|
|
*/
|
|
for ( ;; ) {
|
|
|
|
count = sscanf ( next, "%s%n", token2, &width );
|
|
next = next + width;
|
|
|
|
if ( count != 1 ) {
|
|
break;
|
|
}
|
|
|
|
count = sscanf ( token2, "%d%n", &node, &width );
|
|
next2 = token2 + width;
|
|
|
|
if ( count != 1 ) {
|
|
break;
|
|
}
|
|
|
|
if ( ivert < ORDER_MAX && face_num < FACE_MAX ) {
|
|
face[ivert][face_num] = node-1;
|
|
vertex_material[ivert][face_num] = 0;
|
|
face_order[face_num] = face_order[face_num] + 1;
|
|
}
|
|
/*
|
|
If there's a slash, skip to the next slash, and extract the
|
|
index of the normal vector.
|
|
*/
|
|
if ( *next2 == '/' ) {
|
|
|
|
for ( next3 = next2 + 1; next3 < token2 + LINE_MAX_LEN; next3++ ) {
|
|
|
|
if ( *next3 == '/' ) {
|
|
next3 = next3 + 1;
|
|
count = sscanf ( next3, "%d%n", &node, &width );
|
|
|
|
node = node - 1;
|
|
if ( 0 <= node && node < vertex_normal_num ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
vertex_normal[i][ivert][face_num] = normal_temp[i][node];
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
ivert = ivert + 1;
|
|
}
|
|
face_num = face_num + 1;
|
|
}
|
|
|
|
/*
|
|
G
|
|
Group name.
|
|
*/
|
|
|
|
else if ( leqi ( token, "G" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
HOLE
|
|
Inner trimming hole.
|
|
*/
|
|
else if ( leqi ( token, "HOLE" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
L
|
|
I believe OBJ line node indices are 1 based rather than 0 based.
|
|
So we have to decrement them before loading them into LINE_DEX.
|
|
*/
|
|
|
|
else if ( leqi ( token, "L" ) == TRUE ) {
|
|
|
|
for ( ;; ) {
|
|
|
|
count = sscanf ( next, "%d%n", &node, &width );
|
|
next = next + width;
|
|
|
|
if ( count != 1 ) {
|
|
break;
|
|
}
|
|
|
|
if ( line_num < LINES_MAX ) {
|
|
line_dex[line_num] = node-1;
|
|
line_material[line_num] = 0;
|
|
}
|
|
line_num = line_num + 1;
|
|
|
|
}
|
|
|
|
if ( line_num < LINES_MAX ) {
|
|
line_dex[line_num] = -1;
|
|
line_material[line_num] = -1;
|
|
}
|
|
line_num = line_num + 1;
|
|
|
|
}
|
|
|
|
/*
|
|
LOD
|
|
Level of detail.
|
|
*/
|
|
else if ( leqi ( token, "LOD" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
MG
|
|
Merging group.
|
|
*/
|
|
else if ( leqi ( token, "MG" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
MTLLIB
|
|
Material library.
|
|
*/
|
|
|
|
else if ( leqi ( token, "MTLLIB" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
O
|
|
Object name.
|
|
*/
|
|
else if ( leqi ( token, "O" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
P
|
|
Point.
|
|
*/
|
|
else if ( leqi ( token, "P" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
PARM
|
|
Parameter values.
|
|
*/
|
|
else if ( leqi ( token, "PARM" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
S
|
|
Smoothing group
|
|
*/
|
|
else if ( leqi ( token, "S" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
SCRV
|
|
Special curve.
|
|
*/
|
|
else if ( leqi ( token, "SCRV" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
SHADOW_OBJ
|
|
Shadow casting.
|
|
*/
|
|
else if ( leqi ( token, "SHADOW_OBJ" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
SP
|
|
Special point.
|
|
*/
|
|
else if ( leqi ( token, "SP" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
STECH
|
|
Surface approximation technique.
|
|
*/
|
|
else if ( leqi ( token, "STECH" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
STEP
|
|
Stepsize.
|
|
*/
|
|
else if ( leqi ( token, "CURV" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
SURF
|
|
Surface.
|
|
*/
|
|
else if ( leqi ( token, "SURF" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
TRACE_OBJ
|
|
Ray tracing.
|
|
*/
|
|
else if ( leqi ( token, "TRACE_OBJ" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
TRIM
|
|
Outer trimming loop.
|
|
*/
|
|
else if ( leqi ( token, "TRIM" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
USEMTL
|
|
Material name.
|
|
*/
|
|
else if ( leqi ( token, "USEMTL" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
V X Y Z W
|
|
Geometric vertex.
|
|
W is optional, a weight for rational curves and surfaces.
|
|
The default for W is 1.
|
|
*/
|
|
|
|
else if ( leqi ( token, "V" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
|
|
|
|
if ( cor3_num < COR3_MAX ) {
|
|
cor3[0][cor3_num] = r1;
|
|
cor3[1][cor3_num] = r2;
|
|
cor3[2][cor3_num] = r3;
|
|
}
|
|
|
|
cor3_num = cor3_num + 1;
|
|
|
|
}
|
|
/*
|
|
VN
|
|
Vertex normals.
|
|
*/
|
|
|
|
else if ( leqi ( token, "VN" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
|
|
|
|
if ( vertex_normal_num < ORDER_MAX * FACE_MAX ) {
|
|
normal_temp[0][vertex_normal_num] = r1;
|
|
normal_temp[1][vertex_normal_num] = r2;
|
|
normal_temp[2][vertex_normal_num] = r3;
|
|
}
|
|
|
|
vertex_normal_num = vertex_normal_num + 1;
|
|
|
|
}
|
|
/*
|
|
VT
|
|
Vertex texture.
|
|
*/
|
|
else if ( leqi ( token, "VT" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
VP
|
|
Parameter space vertices.
|
|
*/
|
|
else if ( leqi ( token, "VP" ) == TRUE ) {
|
|
continue;
|
|
}
|
|
/*
|
|
Unrecognized
|
|
*/
|
|
else {
|
|
bad_num = bad_num + 1;
|
|
}
|
|
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int obj_write ( FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
OBJ_WRITE writes a Wavefront OBJ file.
|
|
|
|
Example:
|
|
|
|
# magnolia.obj
|
|
|
|
mtllib ./vp.mtl
|
|
|
|
g
|
|
v -3.269770 -39.572201 0.876128
|
|
v -3.263720 -39.507999 2.160890
|
|
...
|
|
v 0.000000 -9.988540 0.000000
|
|
g stem
|
|
s 1
|
|
usemtl brownskn
|
|
f 8 9 11 10
|
|
f 12 13 15 14
|
|
...
|
|
f 788 806 774
|
|
|
|
Modified:
|
|
|
|
01 September 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int iface;
|
|
int indexvn;
|
|
int ivert;
|
|
int k;
|
|
int new;
|
|
int text_num;
|
|
float w;
|
|
/*
|
|
Initialize.
|
|
*/
|
|
text_num = 0;
|
|
w = 1.0;
|
|
|
|
fprintf ( fileout, "# %s created by IVCON.\n", fileout_name );
|
|
fprintf ( fileout, "# Original data in %s.\n", filein_name );
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "g %s\n", object_name );
|
|
fprintf ( fileout, "\n" );
|
|
|
|
text_num = text_num + 5;
|
|
/*
|
|
V: vertex coordinates.
|
|
*/
|
|
for ( i = 0; i < cor3_num; i++ ) {
|
|
fprintf ( fileout, "v %f %f %f\n",
|
|
cor3[0][i], cor3[1][i], cor3[2][i]);
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
/*
|
|
VN: Vertex face normal vectors.
|
|
*/
|
|
if ( face_num > 0 ) {
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
|
|
fprintf ( fileout, "vn %f %f %f\n", vertex_normal[0][ivert][iface],
|
|
vertex_normal[1][ivert][iface], vertex_normal[2][ivert][iface] );
|
|
text_num = text_num + 1;
|
|
}
|
|
}
|
|
/*
|
|
F: faces.
|
|
*/
|
|
if ( face_num > 0 ) {
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
indexvn = 0;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
fprintf ( fileout, "f" );
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
indexvn = indexvn + 1;
|
|
fprintf ( fileout, " %d//%d", face[ivert][iface]+1, indexvn );
|
|
}
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
/*
|
|
L: lines.
|
|
*/
|
|
if ( line_num > 0 ) {
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
new = TRUE;
|
|
|
|
for ( i = 0; i < line_num; i++ ) {
|
|
|
|
k = line_dex[i];
|
|
|
|
if ( k == -1 ) {
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
new = TRUE;
|
|
}
|
|
else {
|
|
if ( new == TRUE ) {
|
|
fprintf ( fileout, "l" );
|
|
new = FALSE;
|
|
}
|
|
fprintf ( fileout, " %d", k+1 );
|
|
}
|
|
|
|
}
|
|
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "OBJ_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int pov_write ( FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
POV_WRITE writes graphics information to a POV file.
|
|
|
|
Example:
|
|
|
|
// cone.pov created by IVCON.
|
|
// Original data in cone.iv
|
|
|
|
#version 3.0
|
|
#include "colors.inc"
|
|
#include "shapes.inc"
|
|
global_settings { assumed_gamma 2.2 }
|
|
|
|
camera {
|
|
right < 4/3, 0, 0>
|
|
up < 0, 1, 0 >
|
|
sky < 0, 1, 0 >
|
|
angle 20
|
|
location < 0, 0, -300 >
|
|
look_at < 0, 0, 0>
|
|
}
|
|
|
|
light_source { < 20, 50, -100 > color White }
|
|
|
|
background { color SkyBlue }
|
|
|
|
#declare RedText = texture {
|
|
pigment { color rgb < 0.8, 0.2, 0.2> }
|
|
finish { ambient 0.2 diffuse 0.5 }
|
|
}
|
|
|
|
#declare BlueText = texture {
|
|
pigment { color rgb < 0.2, 0.2, 0.8> }
|
|
finish { ambient 0.2 diffuse 0.5 }
|
|
}
|
|
mesh {
|
|
smooth_triangle {
|
|
< 0.29, -0.29, 0.0>, < 0.0, 0.0, -1.0 >,
|
|
< 38.85, 10.03, 0.0>, < 0.0, 0.0, -1.0 >,
|
|
< 40.21, -0.29, 0.0>, < 0.0, 0.0, -1.0 >
|
|
texture { RedText } }
|
|
...
|
|
smooth_triangle {
|
|
< 0.29, -0.29, 70.4142 >, < 0.0, 0.0, 1.0 >,
|
|
< 8.56, -2.51, 70.4142 >, < 0.0, 0.0, 1.0 >,
|
|
< 8.85, -0.29, 70.4142 >, < 0.0, 0.0, 1.0 >
|
|
texture { BlueText } }
|
|
}
|
|
|
|
Modified:
|
|
|
|
08 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int j;
|
|
int jj;
|
|
int jlo;
|
|
int k;
|
|
int text_num;
|
|
|
|
text_num = 0;
|
|
fprintf ( fileout, "// %s created by IVCON.\n", fileout_name );
|
|
fprintf ( fileout, "// Original data in %s.\n", filein_name );
|
|
text_num = text_num + 2;
|
|
/*
|
|
Initial declarations.
|
|
*/
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "#version 3.0\n" );
|
|
fprintf ( fileout, "#include \"colors.inc\"\n" );
|
|
fprintf ( fileout, "#include \"shapes.inc\"\n" );
|
|
fprintf ( fileout, "global_settings { assumed_gamma 2.2 }\n" );
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "camera {\n" );
|
|
fprintf ( fileout, " right < 4/3, 0, 0>\n" );
|
|
fprintf ( fileout, " up < 0, 1, 0 >\n" );
|
|
fprintf ( fileout, " sky < 0, 1, 0 >\n" );
|
|
fprintf ( fileout, " angle 20\n" );
|
|
fprintf ( fileout, " location < 0, 0, -300 >\n" );
|
|
fprintf ( fileout, " look_at < 0, 0, 0>\n" );
|
|
fprintf ( fileout, "}\n" );
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "light_source { < 20, 50, -100 > color White }\n" );
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "background { color SkyBlue }\n" );
|
|
|
|
text_num = text_num + 15;
|
|
/*
|
|
Declare RGB textures.
|
|
*/
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "#declare RedText = texture {\n" );
|
|
fprintf ( fileout, " pigment { color rgb < 0.8, 0.2, 0.2> }\n" );
|
|
fprintf ( fileout, " finish { ambient 0.2 diffuse 0.5 }\n" );
|
|
fprintf ( fileout, "}\n" );
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "#declare GreenText = texture {\n" );
|
|
fprintf ( fileout, " pigment { color rgb < 0.2, 0.8, 0.2> }\n" );
|
|
fprintf ( fileout, " finish { ambient 0.2 diffuse 0.5 }\n" );
|
|
fprintf ( fileout, "}\n" );
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "#declare BlueText = texture {\n" );
|
|
fprintf ( fileout, " pigment { color rgb < 0.2, 0.2, 0.8> }\n" );
|
|
fprintf ( fileout, " finish { ambient 0.2 diffuse 0.5 }\n" );
|
|
fprintf ( fileout, "}\n" );
|
|
/*
|
|
Write one big object.
|
|
*/
|
|
fprintf ( fileout, "mesh {\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Do the next face.
|
|
*/
|
|
for ( i = 0; i < face_num; i++ ) {
|
|
/*
|
|
Break the face up into triangles, anchored at node 1.
|
|
*/
|
|
for ( jlo = 0; jlo < face_order[i] - 2; jlo++ ) {
|
|
fprintf ( fileout, " smooth_triangle {\n" );
|
|
text_num = text_num + 1;
|
|
|
|
for ( j = jlo; j < jlo + 3; j++ ) {
|
|
|
|
if ( j == jlo ) {
|
|
jj = 0;
|
|
}
|
|
else {
|
|
jj = j;
|
|
}
|
|
|
|
k = face[jj][i];
|
|
|
|
fprintf ( fileout, "<%f, %f, %f>, <%f, %f, %f>",
|
|
cor3[0][k], cor3[1][k], cor3[2][k],
|
|
vertex_normal[0][jj][i],
|
|
vertex_normal[1][jj][i],
|
|
vertex_normal[2][jj][i] );
|
|
|
|
if ( j < jlo + 2 ) {
|
|
fprintf ( fileout, ",\n" );
|
|
}
|
|
else {
|
|
fprintf ( fileout, "\n" );
|
|
}
|
|
text_num = text_num + 1;
|
|
|
|
}
|
|
|
|
if (i%6 == 1 ) {
|
|
fprintf ( fileout, "texture { RedText } }\n" );
|
|
}
|
|
else if ( i%2 == 0 ) {
|
|
fprintf ( fileout, "texture { BlueText } }\n" );
|
|
}
|
|
else {
|
|
fprintf ( fileout, "texture { GreenText } }\n" );
|
|
}
|
|
text_num = text_num + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf ( fileout, "}\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "POV_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int rcol_find ( float a[][COR3_MAX], int m, int n, float r[] )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
RCOL_FIND finds if a vector occurs in a table.
|
|
|
|
Comment:
|
|
|
|
Explicitly forcing the second dimension to be COR3_MAX is a kludge.
|
|
I have to figure out how to do this as pointer references.
|
|
|
|
Also, since the array is not sorted, this routine should not be carelessly
|
|
called repeatedly for really big values of N, because you'll waste a
|
|
lot of time.
|
|
|
|
Modified:
|
|
|
|
27 April 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int icol;
|
|
int j;
|
|
|
|
icol = -1;
|
|
|
|
for ( j = 0; j < n; j++ ) {
|
|
for ( i = 0; i < m; i++ ) {
|
|
if ( a[i][j] != r[i] ) {
|
|
break;
|
|
}
|
|
if ( i == m-1 ) {
|
|
return j;
|
|
}
|
|
}
|
|
}
|
|
|
|
return icol;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
float rgb_to_hue ( float r, float g, float b )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
RGB_TO_HUE converts (R,G,B) colors to a hue value between 0 and 1.
|
|
|
|
Discussion:
|
|
|
|
The hue computed here should be the same as the H value computed
|
|
for HLS and HSV, except that it ranges from 0 to 1 instead of
|
|
0 to 360.
|
|
|
|
A monochromatic color ( white, black, or a shade of gray) does not
|
|
have a hue. This routine will return a special value of H = -1
|
|
for such cases.
|
|
|
|
Examples:
|
|
|
|
Color R G B H
|
|
|
|
red 1.0 0.0 0.0 0.00
|
|
yellow 1.0 1.0 0.0 0.16
|
|
green 0.0 1.0 0.0 0.33
|
|
cyan 0.0 1.0 1.0 0.50
|
|
blue 0.0 0.0 1.0 0.67
|
|
magenta 1.0 0.0 1.0 0.83
|
|
|
|
black 0.0 0.0 0.0 -1.00
|
|
gray 0.5 0.5 0.5 -1.00
|
|
white 1.0 1.0 1.0 -1.00
|
|
|
|
Modified:
|
|
|
|
22 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Parameters:
|
|
|
|
Input, float R, G, B, the red, green and blue values of the color.
|
|
These values should be between 0 and 1.
|
|
|
|
Output, float RGB_TO_HUE, the corresponding hue of the color, or -1.0 if
|
|
the color is monochromatic.
|
|
*/
|
|
{
|
|
float h;
|
|
float rgbmax;
|
|
float rgbmin;
|
|
/*
|
|
Make sure the colors are between 0 and 1.
|
|
*/
|
|
if ( r < 0.0 ) {
|
|
r = 0.0;
|
|
}
|
|
else if ( r > 1.0 ) {
|
|
r = 1.0;
|
|
}
|
|
|
|
if ( g < 0.0 ) {
|
|
g = 0.0;
|
|
}
|
|
else if ( g > 1.0 ) {
|
|
g = 1.0;
|
|
}
|
|
|
|
if ( b < 0.0 ) {
|
|
b = 0.0;
|
|
}
|
|
else if ( b > 1.0 ) {
|
|
b = 1.0;
|
|
}
|
|
/*
|
|
Compute the minimum and maximum of R, G and B.
|
|
*/
|
|
rgbmax = r;
|
|
if ( g > rgbmax ) {
|
|
rgbmax = g;
|
|
}
|
|
if ( b > rgbmax ) {
|
|
rgbmax = b;
|
|
}
|
|
|
|
rgbmin = r;
|
|
if ( g < rgbmin ) {
|
|
rgbmin = g;
|
|
}
|
|
if ( b < rgbmin ) {
|
|
rgbmin = b;
|
|
}
|
|
/*
|
|
If RGBMAX = RGBMIN, { the color has no hue.
|
|
*/
|
|
if ( rgbmax == rgbmin ) {
|
|
h = - 1.0;
|
|
}
|
|
/*
|
|
Otherwise, we need to determine the dominant color.
|
|
*/
|
|
else {
|
|
|
|
if ( r == rgbmax ) {
|
|
h = ( g - b ) / ( rgbmax - rgbmin );
|
|
}
|
|
else if ( g == rgbmax ) {
|
|
h = 2.0 + ( b - r ) / ( rgbmax - rgbmin );
|
|
}
|
|
else if ( b == rgbmax ) {
|
|
h = 4.0 + ( r - g ) / ( rgbmax - rgbmin );
|
|
}
|
|
|
|
h = h / 6.0;
|
|
/*
|
|
Make sure H lies between 0 and 1.0.
|
|
*/
|
|
if ( h < 0.0 ) {
|
|
h = h + 1.0;
|
|
}
|
|
else if ( h > 1.0 ) {
|
|
h = h - 1.0;
|
|
}
|
|
|
|
}
|
|
|
|
return h;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
short int short_int_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
Purpose:
|
|
|
|
SHORT_INT_READ reads a short int from a binary file.
|
|
|
|
Modified:
|
|
|
|
14 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
unsigned char c1;
|
|
unsigned char c2;
|
|
short int ival;
|
|
|
|
c1 = fgetc ( filein );
|
|
c2 = fgetc ( filein );
|
|
|
|
ival = c1 | ( c2 << 8 );
|
|
|
|
return ival;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int short_int_write ( FILE *fileout, short int short_int_val )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
SHORT_INT_WRITE writes a short int to a binary file.
|
|
|
|
Modified:
|
|
|
|
14 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
union {
|
|
short int yint;
|
|
char ychar[2];
|
|
} y;
|
|
|
|
y.yint = short_int_val;
|
|
|
|
if ( byte_swap == TRUE ) {
|
|
fputc ( y.ychar[1], fileout );
|
|
fputc ( y.ychar[0], fileout );
|
|
}
|
|
else {
|
|
fputc ( y.ychar[0], fileout );
|
|
fputc ( y.ychar[1], fileout );
|
|
}
|
|
|
|
return 2;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int smf_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
SMF_READ reads an SMF file.
|
|
|
|
Example:
|
|
|
|
#SMF2.0
|
|
# cube_face.smf
|
|
# This example demonstrates how an RGB color can be assigned to
|
|
# each face of an object.
|
|
#
|
|
# First, define the geometry of the cube.
|
|
#
|
|
v 0.0 0.0 0.0
|
|
v 1.0 0.0 0.0
|
|
v 0.0 1.0 0.0
|
|
v 1.0 1.0 0.0
|
|
v 0.0 0.0 1.0
|
|
v 1.0 0.0 1.0
|
|
v 0.0 1.0 1.0
|
|
v 1.0 1.0 1.0
|
|
f 1 4 2
|
|
f 1 3 4
|
|
f 5 6 8
|
|
f 5 8 7
|
|
f 1 2 6
|
|
f 1 6 5
|
|
f 2 4 8
|
|
f 2 8 6
|
|
f 4 3 7
|
|
f 4 7 8
|
|
f 3 1 5
|
|
f 3 5 7
|
|
#
|
|
# Colors will be bound 1 per face.
|
|
#
|
|
bind c face
|
|
c 1.0 0.0 0.0
|
|
c 1.0 0.0 0.0
|
|
c 0.0 1.0 0.0
|
|
c 0.0 1.0 0.0
|
|
c 0.0 0.0 1.0
|
|
c 0.0 0.0 1.0
|
|
c 1.0 1.0 0.0
|
|
c 1.0 1.0 0.0
|
|
c 0.0 1.0 1.0
|
|
c 0.0 1.0 1.0
|
|
c 1.0 0.0 1.0
|
|
c 1.0 0.0 1.0
|
|
#
|
|
# Normal vectors will be bound 1 per face.
|
|
#
|
|
bind n face
|
|
n 0.0 0.0 -1.0
|
|
n 0.0 0.0 -1.0
|
|
n 0.0 0.0 1.0
|
|
n 0.0 0.0 1.0
|
|
n 0.0 -1.0 0.0
|
|
n 0.0 -1.0 0.0
|
|
n 1.0 0.0 0.0
|
|
n 1.0 0.0 0.0
|
|
n 0.0 1.0 0.0
|
|
n 0.0 1.0 0.0
|
|
n -1.0 0.0 0.0
|
|
n -1.0 0.0 0.0
|
|
#
|
|
# Texture coordinate pairs will be bound 1 per face.
|
|
#
|
|
bind r face
|
|
r 0.0 0.0
|
|
r 0.0 0.1
|
|
r 0.0 0.2
|
|
r 0.0 0.3
|
|
r 0.1 0.0
|
|
r 0.1 0.1
|
|
r 0.1 0.2
|
|
r 0.1 0.3
|
|
r 0.2 0.0
|
|
r 0.2 0.1
|
|
r 0.2 0.2
|
|
r 0.2 0.3
|
|
|
|
Modified:
|
|
|
|
03 July 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
float angle;
|
|
char axis;
|
|
float b;
|
|
char cnr[LINE_MAX_LEN];
|
|
int count;
|
|
float dx;
|
|
float dy;
|
|
int face_count;
|
|
float g;
|
|
int icor3_normal;
|
|
int icor3_tex_uv;
|
|
int iface_normal;
|
|
int iface_tex_uv;
|
|
int imat;
|
|
int ivert;
|
|
int level;
|
|
char *next;
|
|
int node;
|
|
int node_count;
|
|
float r;
|
|
float r1;
|
|
float r2;
|
|
float r3;
|
|
float rgba[4];
|
|
char *string;
|
|
float sx;
|
|
float sy;
|
|
float sz;
|
|
char token[LINE_MAX_LEN];
|
|
char token2[LINE_MAX_LEN];
|
|
char type[LINE_MAX_LEN];
|
|
float u;
|
|
float v;
|
|
int vertex_base;
|
|
int vertex_correction;
|
|
int width;
|
|
float x;
|
|
float xvec[3];
|
|
float y;
|
|
float z;
|
|
|
|
face_count = 0;
|
|
icor3_normal = 0;
|
|
icor3_tex_uv = 0;
|
|
iface_normal = 0;
|
|
iface_tex_uv = 0;
|
|
level = 0;
|
|
node_count = 0;
|
|
vertex_base = 0;
|
|
vertex_correction = 0;
|
|
/*
|
|
Read the next line of the file into INPUT.
|
|
*/
|
|
while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL ) {
|
|
|
|
text_num = text_num + 1;
|
|
|
|
if ( debug ) {
|
|
printf ( "SMF_READ: DEBUG: Reading line #%d\n", text_num );
|
|
}
|
|
/*
|
|
Advance to the first nonspace character in INPUT.
|
|
*/
|
|
for ( next = input; *next != '\0' && isspace(*next); next++ ) {
|
|
}
|
|
/*
|
|
Skip blank lines.
|
|
*/
|
|
|
|
if ( *next == '\0' ) {
|
|
continue;
|
|
}
|
|
/*
|
|
Skip comment lines.
|
|
*/
|
|
if ( *next == '#' || *next == '$' ) {
|
|
comment_num = comment_num + 1;
|
|
continue;
|
|
}
|
|
/*
|
|
Extract the first word in this line.
|
|
*/
|
|
sscanf ( next, "%s%n", token, &width );
|
|
/*
|
|
Set NEXT to point to just after this token.
|
|
*/
|
|
next = next + width;
|
|
/*
|
|
BEGIN
|
|
Reset the transformation matrix to identity.
|
|
Node numbering starts at zero again. (Really, this is level based)
|
|
(Really should define a new transformation matrix, and concatenate.)
|
|
(Also, might need to keep track of level.)
|
|
*/
|
|
if ( leqi ( token, "BEGIN" ) == TRUE ) {
|
|
|
|
level = level + 1;
|
|
|
|
vertex_base = cor3_num;
|
|
group_num = group_num + 1;
|
|
tmat_init ( transform_matrix );
|
|
|
|
}
|
|
/*
|
|
BIND [c|n|r] [vertex|face]
|
|
Specify the binding for RGB color, Normal, or Texture.
|
|
Options are "vertex" or "face"
|
|
*/
|
|
else if ( leqi ( token, "BIND" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%s%n", cnr, &width );
|
|
next = next + width;
|
|
|
|
if ( debug ) {
|
|
printf ( "CNR = %s\n", cnr );
|
|
}
|
|
|
|
sscanf ( next, "%s%n", type, &width );
|
|
next = next + width;
|
|
|
|
if ( debug ) {
|
|
printf ( "TYPE = %s\n", type );
|
|
}
|
|
|
|
if ( leqi ( cnr, "C" ) == TRUE ) {
|
|
|
|
if ( leqi ( type, "VERTEX" ) == TRUE ) {
|
|
strcpy ( material_binding, "PER_VERTEX" );
|
|
}
|
|
else if ( leqi ( type, "FACE" ) == TRUE ) {
|
|
strcpy ( material_binding, "PER_FACE" );
|
|
}
|
|
|
|
}
|
|
else if ( leqi ( cnr, "N" ) == TRUE ) {
|
|
|
|
if ( leqi ( type, "VERTEX" ) == TRUE ) {
|
|
strcpy ( normal_binding, "PER_VERTEX" );
|
|
}
|
|
else if ( leqi ( type, "FACE" ) == TRUE ) {
|
|
strcpy ( normal_binding, "PER_FACE" );
|
|
}
|
|
|
|
}
|
|
else if ( leqi ( cnr, "R" ) == TRUE ) {
|
|
|
|
if ( leqi ( type, "VERTEX" ) == TRUE ) {
|
|
strcpy ( texture_binding, "PER_VERTEX" );
|
|
}
|
|
else if ( leqi ( type, "FACE" ) == TRUE ) {
|
|
strcpy ( texture_binding, "PER_FACE" );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
C <r> <g> <b>
|
|
Specify an RGB color, with R, G, B between 0.0 and 1.0.
|
|
*/
|
|
else if ( leqi ( token, "C" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%f%n", &r, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%f%n", &g, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%f%n", &b, &width );
|
|
next = next + width;
|
|
/*
|
|
Set up a temporary material (R,G,B,1.0).
|
|
Add the material to the material database, or find the index of
|
|
a matching material already in.
|
|
Assign the material of the node or face to this index.
|
|
*/
|
|
rgba[0] = r;
|
|
rgba[1] = g;
|
|
rgba[2] = b;
|
|
rgba[3] = 1.0;
|
|
|
|
if ( material_num < MATERIAL_MAX ) {
|
|
|
|
for ( k = 0; k < 4; k++ ) {
|
|
material_rgba[k][material_num] = rgba[k];
|
|
}
|
|
|
|
imat = material_num;
|
|
material_num = material_num + 1;
|
|
|
|
}
|
|
else {
|
|
|
|
imat = 0;
|
|
|
|
}
|
|
|
|
if ( leqi ( material_binding, "PER_FACE" ) == TRUE ) {
|
|
|
|
face_count = face_count + 1;
|
|
face_material[face_count] = imat;
|
|
|
|
}
|
|
else if ( leqi ( material_binding, "PER_VERTEX" ) == TRUE ) {
|
|
|
|
node_count = node_count + 1;
|
|
cor3_material[node_count] = imat;
|
|
|
|
}
|
|
else {
|
|
|
|
printf ( "\n" );
|
|
printf ( "SMF_READ - Fatal error!\n" );
|
|
printf ( " Material binding undefined!\n" );
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
END
|
|
Drop down a level.
|
|
*/
|
|
else if ( leqi ( token, "END" ) == TRUE ) {
|
|
|
|
level = level - 1;
|
|
|
|
if ( level < 0 ) {
|
|
printf ( "\n" );
|
|
printf ( "SMF_READ - Fatal error!\n" );
|
|
printf ( " More END statements than BEGINs!\n" );
|
|
return ERROR;
|
|
}
|
|
}
|
|
/*
|
|
F V1 V2 V3
|
|
|
|
Face.
|
|
A face is defined by the vertices.
|
|
Node indices are 1 based rather than 0 based.
|
|
So we have to decrement them before loading them into FACE.
|
|
Note that vertex indices start back at 0 each time a BEGIN is entered.
|
|
The strategy here won't handle nested BEGIN's, just one at a time.
|
|
*/
|
|
|
|
else if ( leqi ( token, "F" ) == TRUE ) {
|
|
|
|
ivert = 0;
|
|
face_order[face_num] = 0;
|
|
/*
|
|
Read each item in the F definition as a token, and then
|
|
take it apart.
|
|
*/
|
|
for ( ;; ) {
|
|
|
|
count = sscanf ( next, "%s%n", token2, &width );
|
|
next = next + width;
|
|
|
|
if ( count != 1 ) {
|
|
break;
|
|
}
|
|
|
|
count = sscanf ( token2, "%d%n", &node, &width );
|
|
|
|
if ( count != 1 ) {
|
|
break;
|
|
}
|
|
|
|
if ( ivert < ORDER_MAX && face_num < FACE_MAX ) {
|
|
face[ivert][face_num] = node - 1 + vertex_base;
|
|
vertex_material[ivert][face_num] = 0;
|
|
face_order[face_num] = face_order[face_num] + 1;
|
|
}
|
|
ivert = ivert + 1;
|
|
}
|
|
face_num = face_num + 1;
|
|
}
|
|
/*
|
|
N <x> <y> <z>
|
|
Specify a normal vector.
|
|
*/
|
|
else if ( leqi ( token, "N" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%f%n", &x, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%f%n", &y, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%f%n", &z, &width );
|
|
next = next + width;
|
|
|
|
if ( leqi ( normal_binding, "PER_FACE" ) == TRUE ) {
|
|
|
|
face_normal[0][iface_normal] = x;
|
|
face_normal[1][iface_normal] = y;
|
|
face_normal[2][iface_normal] = z;
|
|
|
|
iface_normal = iface_normal + 1;
|
|
|
|
}
|
|
else if ( leqi ( normal_binding, "PER_VERTEX" ) == TRUE ) {
|
|
|
|
cor3_normal[0][icor3_normal] = x;
|
|
cor3_normal[1][icor3_normal] = y;
|
|
cor3_normal[2][icor3_normal] = z;
|
|
|
|
icor3_normal = icor3_normal + 1;
|
|
|
|
}
|
|
else {
|
|
|
|
printf ( "\n" );
|
|
printf ( "SMF_READ - Fatal error!\n" );
|
|
printf ( " Normal binding undefined!\n" );
|
|
return ERROR;
|
|
|
|
}
|
|
}
|
|
/*
|
|
R <u> <v>
|
|
Specify a texture coordinate.
|
|
*/
|
|
else if ( leqi ( token, "R" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%f%n", &u, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%f%n", &v, &width );
|
|
next = next + width;
|
|
|
|
if ( leqi ( texture_binding, "PER_FACE" ) == TRUE ) {
|
|
|
|
face_tex_uv[0][iface_tex_uv] = u;
|
|
face_tex_uv[1][iface_tex_uv] = v;
|
|
|
|
icor3_tex_uv = icor3_tex_uv + 1;
|
|
|
|
}
|
|
else if ( leqi ( texture_binding, "PER_VERTEX" ) == TRUE ) {
|
|
|
|
cor3_tex_uv[0][icor3_tex_uv] = u;
|
|
cor3_tex_uv[1][icor3_tex_uv] = v;
|
|
|
|
icor3_tex_uv = icor3_tex_uv + 1;
|
|
}
|
|
else {
|
|
printf ( "\n" );
|
|
printf ( "SMF_READ - Fatal error!\n" );
|
|
printf ( " Texture binding undefined!\n" );
|
|
return ERROR;
|
|
}
|
|
|
|
}
|
|
/*
|
|
ROT [x|y|z] <theta>
|
|
*/
|
|
else if ( leqi ( token, "ROT" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%c%n", &axis, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%f%n", &angle, &width );
|
|
next = next + width;
|
|
|
|
tmat_rot_axis ( transform_matrix, transform_matrix, angle, axis );
|
|
|
|
}
|
|
/*
|
|
SCALE <sx> <sy> <sz>
|
|
*/
|
|
else if ( leqi ( token, "SCALE" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%f%n", &sx, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%f%n", &sy, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%f%n", &sz, &width );
|
|
next = next + width;
|
|
|
|
tmat_scale ( transform_matrix, transform_matrix, sx, sy, sz );
|
|
}
|
|
/*
|
|
SET VERTEX_CORRECTION <i>
|
|
Specify increment to add to vertex indices in file.
|
|
*/
|
|
else if ( leqi ( token, "SET" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%s%n", cnr, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%d%n", &vertex_correction, &width );
|
|
next = next + width;
|
|
|
|
}
|
|
/*
|
|
T_SCALE <dx> <dy>
|
|
Specify a scaling to texture coordinates.
|
|
*/
|
|
else if ( leqi ( token, "T_SCALE" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%f%n", &dx, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%f%n", &dy, &width );
|
|
next = next + width;
|
|
|
|
}
|
|
/*
|
|
T_TRANS <dx> <dy>
|
|
Specify a translation to texture coordinates.
|
|
*/
|
|
else if ( leqi ( token, "T_TRANS" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%f%n", &dx, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%f%n", &dy, &width );
|
|
next = next + width;
|
|
|
|
}
|
|
/*
|
|
TEX <filename>
|
|
Specify a filename containing the texture.
|
|
(ANY CHANCE THIS IS RIGHT?)
|
|
*/
|
|
else if ( leqi ( token, "TEX" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%s%n", string, &width );
|
|
|
|
for ( i = 0; i < LINE_MAX_LEN; i++ ) {
|
|
texture_name[texture_num][i] = string[i];
|
|
if ( string[i] == '\0' ) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
texture_num = texture_num + 1;
|
|
|
|
}
|
|
/*
|
|
TRANS <dx> <dy> <dz>
|
|
*/
|
|
else if ( leqi ( token, "TRANS" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%f%n", &x, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%f%n", &y, &width );
|
|
next = next + width;
|
|
|
|
sscanf ( next, "%f%n", &z, &width );
|
|
next = next + width;
|
|
|
|
tmat_trans ( transform_matrix, transform_matrix, x, y, z );
|
|
}
|
|
/*
|
|
V X Y Z
|
|
Geometric vertex.
|
|
*/
|
|
else if ( leqi ( token, "V" ) == TRUE ) {
|
|
|
|
sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
|
|
|
|
xvec[0] = r1;
|
|
xvec[1] = r2;
|
|
xvec[2] = r3;
|
|
/*
|
|
Apply current transformation matrix.
|
|
Right now, we can only handle one matrix, not a stack of
|
|
matrices representing nested BEGIN/END's.
|
|
*/
|
|
tmat_mxp ( transform_matrix, xvec, xvec );
|
|
|
|
if ( cor3_num < COR3_MAX ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
cor3[i][cor3_num] = xvec[i];
|
|
}
|
|
}
|
|
|
|
cor3_num = cor3_num + 1;
|
|
|
|
}
|
|
/*
|
|
Unrecognized keyword.
|
|
*/
|
|
else {
|
|
|
|
bad_num = bad_num + 1;
|
|
|
|
if ( bad_num <= 10 ) {
|
|
printf ( "\n" );
|
|
printf ( "SMF_READ: Bad data on line %d.\n", text_num );
|
|
}
|
|
}
|
|
|
|
}
|
|
/*
|
|
Extend the material definition
|
|
* from the face to the vertices and nodes, or
|
|
* from the vertices to the faces and nodes.
|
|
*/
|
|
if ( strcmp ( material_binding, "PER_FACE" ) == 0 ) {
|
|
|
|
face_to_vertex_material ( );
|
|
|
|
vertex_to_node_material ( );
|
|
|
|
}
|
|
else if ( strcmp ( material_binding, "PER_VERTEX" ) == 0 ) {
|
|
|
|
node_to_vertex_material ( );
|
|
|
|
vertex_to_face_material ( );
|
|
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int smf_write ( FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
SMF_WRITE writes graphics information to an SMF file.
|
|
|
|
Example:
|
|
|
|
#SMF2.0
|
|
# cube_face.smf
|
|
# This example demonstrates how an RGB color can be assigned to
|
|
# each face of an object.
|
|
#
|
|
# First, define the geometry of the cube.
|
|
#
|
|
v 0.0 0.0 0.0
|
|
v 1.0 0.0 0.0
|
|
v 0.0 1.0 0.0
|
|
v 1.0 1.0 0.0
|
|
v 0.0 0.0 1.0
|
|
v 1.0 0.0 1.0
|
|
v 0.0 1.0 1.0
|
|
v 1.0 1.0 1.0
|
|
f 1 4 2
|
|
f 1 3 4
|
|
f 5 6 8
|
|
f 5 8 7
|
|
f 1 2 6
|
|
f 1 6 5
|
|
f 2 4 8
|
|
f 2 8 6
|
|
f 4 3 7
|
|
f 4 7 8
|
|
f 3 1 5
|
|
f 3 5 7
|
|
#
|
|
# Colors will be bound 1 per face.
|
|
#
|
|
bind c face
|
|
c 1.0 0.0 0.0
|
|
c 1.0 0.0 0.0
|
|
c 0.0 1.0 0.0
|
|
c 0.0 1.0 0.0
|
|
c 0.0 0.0 1.0
|
|
c 0.0 0.0 1.0
|
|
c 1.0 1.0 0.0
|
|
c 1.0 1.0 0.0
|
|
c 0.0 1.0 1.0
|
|
c 0.0 1.0 1.0
|
|
c 1.0 0.0 1.0
|
|
c 1.0 0.0 1.0
|
|
#
|
|
# Normal vectors will be bound 1 per face.
|
|
#
|
|
bind n face
|
|
n 0.0 0.0 -1.0
|
|
n 0.0 0.0 -1.0
|
|
n 0.0 0.0 1.0
|
|
n 0.0 0.0 1.0
|
|
n 0.0 -1.0 0.0
|
|
n 0.0 -1.0 0.0
|
|
n 1.0 0.0 0.0
|
|
n 1.0 0.0 0.0
|
|
n 0.0 1.0 0.0
|
|
n 0.0 1.0 0.0
|
|
n -1.0 0.0 0.0
|
|
n -1.0 0.0 0.0
|
|
#
|
|
# Texture coordinate pairs will be bound 1 per face.
|
|
#
|
|
bind r face
|
|
r 0.0 0.0
|
|
r 0.0 0.1
|
|
r 0.0 0.2
|
|
r 0.0 0.3
|
|
r 0.1 0.0
|
|
r 0.1 0.1
|
|
r 0.1 0.2
|
|
r 0.1 0.3
|
|
r 0.2 0.0
|
|
r 0.2 0.1
|
|
r 0.2 0.2
|
|
r 0.2 0.3
|
|
|
|
Modified:
|
|
|
|
05 July 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int icor3;
|
|
int iface;
|
|
int imat;
|
|
int ivert;
|
|
int text_num;
|
|
/*
|
|
Initialize.
|
|
*/
|
|
text_num = 0;
|
|
|
|
fprintf ( fileout, "#$SMF 2.0\n" );
|
|
fprintf ( fileout, "#$vertices %d\n", cor3_num );
|
|
fprintf ( fileout, "#$faces %d\n", face_num );
|
|
fprintf ( fileout, "#\n" );
|
|
fprintf ( fileout, "# %s created by IVCON.\n", fileout_name );
|
|
fprintf ( fileout, "# Original data in %s.\n", filein_name );
|
|
fprintf ( fileout, "#\n" );
|
|
|
|
text_num = text_num + 7;
|
|
/*
|
|
V: vertex coordinates.
|
|
*/
|
|
for ( i = 0; i < cor3_num; i++ ) {
|
|
fprintf ( fileout, "v %f %f %f\n",
|
|
cor3[0][i], cor3[1][i], cor3[2][i] );
|
|
text_num = text_num + 1;
|
|
}
|
|
/*
|
|
F: faces.
|
|
*/
|
|
if ( face_num > 0 ) {
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
fprintf ( fileout, "f" );
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
fprintf ( fileout, " %d", face[ivert][iface]+1 );
|
|
}
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
/*
|
|
Material binding.
|
|
*/
|
|
fprintf ( fileout, "bind c vertex\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Material RGB values at each node.
|
|
*/
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
|
|
imat = cor3_material[icor3];
|
|
|
|
fprintf ( fileout, "c %f %f %f\n", material_rgba[0][imat],
|
|
material_rgba[1][imat], material_rgba[2][imat] );
|
|
|
|
text_num = text_num + 1;
|
|
}
|
|
/*
|
|
Normal binding.
|
|
*/
|
|
fprintf ( fileout, "bind n vertex\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Normal vector at each node.
|
|
*/
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
|
|
fprintf ( fileout, "n %f %f %f\n", cor3_normal[0][icor3],
|
|
cor3_normal[1][icor3], cor3_normal[2][icor3] );
|
|
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
if ( texture_num > 0 ) {
|
|
/*
|
|
Texture filename.
|
|
*/
|
|
fprintf ( fileout, "tex %s\n", texture_name[0] );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Texture binding.
|
|
*/
|
|
fprintf ( fileout, "bind r vertex\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Texture coordinates at each node.
|
|
*/
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
fprintf ( fileout, "r %f %f\n", cor3_tex_uv[0][icor3],
|
|
cor3_tex_uv[1][icor3] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
}
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "SMF_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int stla_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
STLA_READ reads an ASCII STL (stereolithography) file.
|
|
|
|
Examples:
|
|
|
|
solid MYSOLID
|
|
facet normal 0.4 0.4 0.2
|
|
outerloop
|
|
vertex 1.0 2.1 3.2
|
|
vertex 2.1 3.7 4.5
|
|
vertex 3.1 4.5 6.7
|
|
endloop
|
|
endfacet
|
|
...
|
|
facet normal 0.2 0.2 0.4
|
|
outerloop
|
|
vertex 2.0 2.3 3.4
|
|
vertex 3.1 3.2 6.5
|
|
vertex 4.1 5.5 9.0
|
|
endloop
|
|
endfacet
|
|
endsolid MYSOLID
|
|
|
|
Modified:
|
|
|
|
20 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int count;
|
|
int i;
|
|
int icor3;
|
|
int ivert;
|
|
char *next;
|
|
float r1;
|
|
float r2;
|
|
float r3;
|
|
float r4;
|
|
float temp[3];
|
|
char token[LINE_MAX_LEN];
|
|
int width;
|
|
/*
|
|
Read the next line of the file into INPUT.
|
|
*/
|
|
while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL ) {
|
|
|
|
text_num = text_num + 1;
|
|
/*
|
|
Advance to the first nonspace character in INPUT.
|
|
*/
|
|
for ( next = input; *next != '\0' && isspace(*next); next++ ) {
|
|
}
|
|
/*
|
|
Skip blank lines and comments.
|
|
*/
|
|
if ( *next == '\0' || *next == '#' || *next == '!' || *next == '$' ) {
|
|
continue;
|
|
}
|
|
/*
|
|
Extract the first word in this line.
|
|
*/
|
|
sscanf ( next, "%s%n", token, &width );
|
|
/*
|
|
Set NEXT to point to just after this token.
|
|
*/
|
|
next = next + width;
|
|
/*
|
|
FACET
|
|
*/
|
|
if ( leqi ( token, "facet" ) == TRUE ) {
|
|
/*
|
|
Get the XYZ coordinates of the normal vector to the face.
|
|
*/
|
|
sscanf ( next, "%*s %e %e %e", &r1, &r2, &r3 );
|
|
|
|
if ( face_num < FACE_MAX ) {
|
|
face_normal[0][face_num] = r1;
|
|
face_normal[1][face_num] = r2;
|
|
face_normal[2][face_num] = r3;
|
|
}
|
|
|
|
fgets ( input, LINE_MAX_LEN, filein );
|
|
text_num = text_num + 1;
|
|
|
|
ivert = 0;
|
|
|
|
for ( ;; ) {
|
|
|
|
fgets ( input, LINE_MAX_LEN, filein );
|
|
text_num = text_num + 1;
|
|
|
|
count = sscanf ( input, "%*s %e %e %e", &r1, &r2, &r3 );
|
|
|
|
if ( count != 3 ) {
|
|
break;
|
|
}
|
|
|
|
temp[0] = r1;
|
|
temp[1] = r2;
|
|
temp[2] = r3;
|
|
|
|
if ( cor3_num < 1000 ) {
|
|
icor3 = rcol_find ( cor3, 3, cor3_num, temp );
|
|
}
|
|
else {
|
|
icor3 = -1;
|
|
}
|
|
|
|
if ( icor3 == -1 ) {
|
|
|
|
icor3 = cor3_num;
|
|
|
|
if ( cor3_num < COR3_MAX ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
cor3[i][cor3_num] = temp[i];
|
|
}
|
|
}
|
|
cor3_num = cor3_num + 1;
|
|
}
|
|
else {
|
|
dup_num = dup_num + 1;
|
|
}
|
|
|
|
if ( ivert < ORDER_MAX && face_num < FACE_MAX ) {
|
|
face[ivert][face_num] = icor3;
|
|
vertex_material[ivert][face_num] = 0;
|
|
for ( i = 0; i < 3; i++ ) {
|
|
vertex_normal[i][ivert][face_num] = face_normal[i][face_num];
|
|
}
|
|
}
|
|
|
|
ivert = ivert + 1;
|
|
}
|
|
|
|
fgets ( input, LINE_MAX_LEN, filein );
|
|
text_num = text_num + 1;
|
|
|
|
if ( face_num < FACE_MAX ) {
|
|
face_order[face_num] = ivert;
|
|
}
|
|
|
|
face_num = face_num + 1;
|
|
|
|
}
|
|
/*
|
|
COLOR
|
|
*/
|
|
|
|
else if ( leqi ( token, "color" ) == TRUE ) {
|
|
sscanf ( next, "%*s %f %f %f %f", &r1, &r2, &r3, &r4 );
|
|
}
|
|
/*
|
|
SOLID
|
|
*/
|
|
else if ( leqi ( token, "solid" ) == TRUE ) {
|
|
object_num = object_num + 1;
|
|
}
|
|
/*
|
|
ENDSOLID
|
|
*/
|
|
else if ( leqi ( token, "endsolid" ) == TRUE ) {
|
|
}
|
|
/*
|
|
Unexpected or unrecognized.
|
|
*/
|
|
else {
|
|
printf ( "\n" );
|
|
printf ( "STLA_READ - Fatal error!\n" );
|
|
printf ( " Unrecognized first word on line.\n" );
|
|
return ERROR;
|
|
}
|
|
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int stla_write ( FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
STLA_WRITE writes an ASCII STL (stereolithography) file.
|
|
|
|
Examples:
|
|
|
|
solid MYSOLID
|
|
facet normal 0.4 0.4 0.2
|
|
outerloop
|
|
vertex 1.0 2.1 3.2
|
|
vertex 2.1 3.7 4.5
|
|
vertex 3.1 4.5 6.7
|
|
endloop
|
|
endfacet
|
|
...
|
|
facet normal 0.2 0.2 0.4
|
|
outerloop
|
|
vertex 2.0 2.3 3.4
|
|
vertex 3.1 3.2 6.5
|
|
vertex 4.1 5.5 9.0
|
|
endloop
|
|
endfacet
|
|
endsolid
|
|
|
|
Discussion:
|
|
|
|
The polygons in an STL file should only be triangular. This routine
|
|
will try to automatically decompose higher-order polygonal faces into
|
|
suitable triangles, without actually modifying the internal graphics
|
|
data.
|
|
|
|
Modified:
|
|
|
|
01 September 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int icor3;
|
|
int iface;
|
|
int jvert;
|
|
int face_num2;
|
|
int text_num;
|
|
/*
|
|
Initialize.
|
|
*/
|
|
text_num = 0;
|
|
face_num2 = 0;
|
|
|
|
fprintf ( fileout, "solid MYSOLID created by IVCON, original data in %s\n",
|
|
filein_name );
|
|
|
|
text_num = text_num + 1;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
for ( jvert = 2; jvert < face_order[iface]; jvert++ ) {
|
|
|
|
face_num2 = face_num2 + 1;
|
|
|
|
fprintf ( fileout, " facet normal %f %f %f\n",
|
|
face_normal[0][iface], face_normal[1][iface], face_normal[2][iface] );
|
|
|
|
fprintf ( fileout, " outer loop\n" );
|
|
|
|
icor3 = face[0][iface];
|
|
fprintf ( fileout, " vertex %f %f %f\n",
|
|
cor3[0][icor3], cor3[1][icor3], cor3[2][icor3] );
|
|
|
|
icor3 = face[jvert-1][iface];
|
|
fprintf ( fileout, " vertex %f %f %f\n",
|
|
cor3[0][icor3], cor3[1][icor3], cor3[2][icor3] );
|
|
|
|
icor3 = face[jvert][iface];
|
|
fprintf ( fileout, " vertex %f %f %f\n",
|
|
cor3[0][icor3], cor3[1][icor3], cor3[2][icor3] );
|
|
|
|
fprintf ( fileout, " endloop\n" );
|
|
fprintf ( fileout, " endfacet\n" );
|
|
text_num = text_num + 7;
|
|
}
|
|
}
|
|
|
|
fprintf ( fileout, "endsolid MYSOLID\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "STLA_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
if ( face_num != face_num2 ) {
|
|
printf ( " Number of faces in original data was %d.\n", face_num );
|
|
printf ( " Number of triangular faces in decomposed data is %d.\n",
|
|
face_num2 );
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int stlb_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
STLB_READ reads a binary STL (stereolithography) file.
|
|
|
|
Example:
|
|
|
|
80 byte string = header containing nothing in particular
|
|
|
|
4 byte int = number of faces
|
|
|
|
For each face:
|
|
|
|
3 4-byte floats = components of normal vector to face;
|
|
3 4-byte floats = coordinates of first node;
|
|
3 4-byte floats = coordinates of second node;
|
|
3 4-byte floats = coordinates of third and final node;
|
|
2-byte int = attribute, whose value is 0.
|
|
|
|
Modified:
|
|
|
|
24 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
short int attribute = 0;
|
|
char c;
|
|
float cvec[3];
|
|
int icor3;
|
|
int i;
|
|
int iface;
|
|
int ivert;
|
|
/*
|
|
80 byte Header.
|
|
*/
|
|
for ( i = 0; i < 80; i++ ) {
|
|
c = char_read ( filein );
|
|
if ( debug ) {
|
|
printf ( "%d\n", c );
|
|
}
|
|
bytes_num = bytes_num + 1;
|
|
}
|
|
/*
|
|
Number of faces.
|
|
*/
|
|
face_num = long_int_read ( filein );
|
|
bytes_num = bytes_num + 4;
|
|
/*
|
|
For each (triangular) face,
|
|
components of normal vector,
|
|
coordinates of three vertices,
|
|
2 byte "attribute".
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
face_order[iface] = 3;
|
|
face_material[iface] = 0;
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
face_normal[i][iface] = float_read ( filein );
|
|
bytes_num = bytes_num + 4;
|
|
}
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
cvec[i] = float_read ( filein );
|
|
bytes_num = bytes_num + 4;
|
|
}
|
|
|
|
if ( cor3_num < 1000 ) {
|
|
icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
|
|
}
|
|
else {
|
|
icor3 = -1;
|
|
}
|
|
|
|
if ( icor3 == -1 ) {
|
|
icor3 = cor3_num;
|
|
if ( cor3_num < COR3_MAX ) {
|
|
cor3[0][cor3_num] = cvec[0];
|
|
cor3[1][cor3_num] = cvec[1];
|
|
cor3[2][cor3_num] = cvec[2];
|
|
}
|
|
cor3_num = cor3_num + 1;
|
|
}
|
|
else {
|
|
dup_num = dup_num + 1;
|
|
}
|
|
|
|
face[ivert][iface] = icor3;
|
|
|
|
}
|
|
attribute = short_int_read ( filein );
|
|
if ( debug ) {
|
|
printf ( "ATTRIBUTE = %d\n", attribute );
|
|
}
|
|
bytes_num = bytes_num + 2;
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int stlb_write ( FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
STLB_WRITE writes a binary STL (stereolithography) file.
|
|
|
|
Example:
|
|
|
|
80 byte string = header containing nothing in particular
|
|
|
|
4 byte int = number of faces
|
|
|
|
For each face:
|
|
|
|
3 4-byte floats = components of normal vector to face;
|
|
3 4-byte floats = coordinates of first node;
|
|
3 4-byte floats = coordinates of second node;
|
|
3 4-byte floats = coordinates of third and final node;
|
|
2-byte int = attribute, whose value is 0.
|
|
|
|
Discussion:
|
|
|
|
The polygons in an STL file should only be triangular. This routine
|
|
will try to automatically decompose higher-order polygonal faces into
|
|
suitable triangles, without actually modifying the internal graphics
|
|
data.
|
|
|
|
Modified:
|
|
|
|
24 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
short int attribute = 0;
|
|
char c;
|
|
int i;
|
|
int icor3;
|
|
int iface;
|
|
int jvert;
|
|
int face_num2;
|
|
/*
|
|
80 byte Header.
|
|
*/
|
|
for ( i = 0; i < 80; i++ ) {
|
|
c = ' ';
|
|
bytes_num = bytes_num + char_write ( fileout, c );
|
|
}
|
|
/*
|
|
Number of faces.
|
|
*/
|
|
face_num2 = 0;
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
face_num2 = face_num2 + face_order[iface] - 2;
|
|
}
|
|
|
|
bytes_num = bytes_num + long_int_write ( fileout, face_num2 );
|
|
/*
|
|
For each (triangular) face,
|
|
components of normal vector,
|
|
coordinates of three vertices,
|
|
2 byte "attribute".
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
for ( jvert = 2; jvert < face_order[iface]; jvert++ ) {
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
bytes_num = bytes_num + float_write ( fileout, face_normal[i][iface] );
|
|
}
|
|
|
|
icor3 = face[0][iface];
|
|
for ( i = 0; i < 3; i++ ) {
|
|
bytes_num = bytes_num + float_write ( fileout, cor3[i][icor3] );
|
|
}
|
|
|
|
icor3 = face[jvert-1][iface];
|
|
for ( i = 0; i < 3; i++ ) {
|
|
bytes_num = bytes_num + float_write ( fileout, cor3[i][icor3] );
|
|
}
|
|
|
|
icor3 = face[jvert][iface];
|
|
for ( i = 0; i < 3; i++ ) {
|
|
bytes_num = bytes_num + float_write ( fileout, cor3[i][icor3] );
|
|
}
|
|
|
|
bytes_num = bytes_num + short_int_write ( fileout, attribute );
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "STLB_WRITE - Wrote %d bytes.\n", bytes_num );
|
|
|
|
if ( face_num != face_num2 ) {
|
|
printf ( " Number of faces in original data was %d.\n", face_num );
|
|
printf ( " Number of triangular faces in decomposed data is %d.\n",
|
|
face_num2 );
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
void tds_pre_process ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TDS_PRE_PROCESS divides the monolithic object into acceptably small pieces.
|
|
|
|
Note:
|
|
|
|
The 3DS binary format allows an unsigned short int for the number of
|
|
points, and number of faces in an object. This limits such quantities
|
|
to 65535. We have at least one interesting object with more faces
|
|
than that. So we need to tag faces and nodes somehow.
|
|
|
|
Modified:
|
|
|
|
14 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
/* static unsigned short int BIG = 60000; */
|
|
|
|
return;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int tds_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TDS_READ reads a 3D Studio MAX binary 3DS file.
|
|
|
|
Modified:
|
|
|
|
20 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
unsigned long int chunk_begin;
|
|
unsigned long int chunk_end;
|
|
unsigned long int chunk_length;
|
|
unsigned long int chunk_length2;
|
|
unsigned long int position;
|
|
unsigned short int temp_int;
|
|
int version;
|
|
int views_read;
|
|
/*
|
|
Initialize.
|
|
*/
|
|
views_read = 0;
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
|
|
if ( temp_int == 0x4d4d ) {
|
|
|
|
if ( debug ) {
|
|
printf ( "TDS_READ: DEBUG: Read magic number %0X.\n", temp_int );
|
|
}
|
|
/*
|
|
Move to 28 bytes from the beginning of the file.
|
|
*/
|
|
position = 28;
|
|
fseek ( filein, ( long ) position, SEEK_SET );
|
|
version = fgetc ( filein );
|
|
|
|
if ( version < 3 ) {
|
|
printf ( "\n" );
|
|
printf ( "TDS_READ - Fatal error!\n" );
|
|
printf ( " This routine can only read 3DS version 3 or later.\n" );
|
|
printf ( " The input file is version %d.\n" ,version );
|
|
return ERROR;
|
|
}
|
|
|
|
if ( debug ) {
|
|
printf ( "TDS_READ: DEBUG: Version number is %d.\n", version );
|
|
}
|
|
/*
|
|
Move to 2 bytes from the beginning of the file.
|
|
Set CURRENT_POINTER to the first byte of the chunk.
|
|
Set CHUNK_LENGTH to the number of bytes in the chunk.
|
|
*/
|
|
chunk_begin = 0;
|
|
position = 2;
|
|
fseek ( filein, ( long ) position, SEEK_SET );
|
|
|
|
chunk_length = tds_read_u_long_int ( filein );
|
|
position = 6;
|
|
|
|
chunk_end = chunk_begin + chunk_length;
|
|
|
|
if ( debug ) {
|
|
printf ( "TDS_READ:\n" );
|
|
printf ( " Chunk begin = %lu.\n", chunk_begin );
|
|
printf ( " Chunk length = %lu.\n", chunk_length );
|
|
printf ( " Chunk end = %lu.\n", chunk_end );
|
|
}
|
|
|
|
while ( position + 2 < chunk_end ) {
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
position = position + 2;
|
|
|
|
if ( debug ) {
|
|
printf ( "TDS_READ: Short int = %0X, position = %lu.\n", temp_int, position );
|
|
}
|
|
|
|
if ( temp_int == 0x0002 ) {
|
|
if ( debug ) {
|
|
printf ( "TDS_READ: Read_Initial_Section:\n" );
|
|
}
|
|
chunk_length2 = tds_read_u_long_int ( filein );
|
|
position = position + 4;
|
|
position = position - 6 + chunk_length2;
|
|
fseek ( filein, ( long ) position, SEEK_SET );
|
|
}
|
|
else if ( temp_int == 0x3d3d ) {
|
|
if ( debug ) {
|
|
printf ( "TDS_READ: Read_Edit_Section:\n" );
|
|
}
|
|
position = position - 2;
|
|
position = position + tds_read_edit_section ( filein, &views_read );
|
|
}
|
|
else if ( temp_int == 0xb000 ) {
|
|
if ( debug ) {
|
|
printf ( "TDS_READ: Read_Keyframe_Section:\n" );
|
|
}
|
|
|
|
position = position - 2;
|
|
position = position + tds_read_keyframe_section ( filein, &views_read );
|
|
}
|
|
else {
|
|
printf ( "\n" );
|
|
printf ( "TDS_READ - Fatal error!\n" );
|
|
printf ( " Unexpected input, position = %lu.\n", position );
|
|
printf ( " TEMP_INT = %hux\n", temp_int );
|
|
return ERROR;
|
|
}
|
|
}
|
|
position = chunk_begin + chunk_length;
|
|
fseek ( filein, ( long ) position, SEEK_SET );
|
|
}
|
|
else {
|
|
printf ( "\n" );
|
|
printf ( "TDS_READ - Fatal error!\n" );
|
|
printf ( " Could not find the main section tag.\n" );
|
|
return ERROR;
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_ambient_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
{
|
|
unsigned long int current_pointer;
|
|
unsigned char end_found = FALSE;
|
|
int i;
|
|
long int pointer;
|
|
float rgb_val[3];
|
|
unsigned short int temp_int;
|
|
unsigned long int temp_pointer;
|
|
unsigned long int teller;
|
|
unsigned char true_c_val[3];
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
teller = 6;
|
|
|
|
while ( end_found == FALSE ) {
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
teller = teller + 2;
|
|
|
|
switch ( temp_int ) {
|
|
case 0x0010:
|
|
if ( debug ) {
|
|
printf ( " COLOR_F color definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
for ( i = 0; i < 3; i++ ) {
|
|
rgb_val[i] = float_read ( filein );
|
|
}
|
|
if ( debug ) {
|
|
printf ( "RGB_VAL = %f %f %f\n", rgb_val[0], rgb_val[1], rgb_val[2] );
|
|
}
|
|
teller = teller + 3 * sizeof ( float );
|
|
break;
|
|
case 0x0011:
|
|
if ( debug ) {
|
|
printf ( " COLOR_24 24 bit color definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
true_c_val[i] = fgetc ( filein );
|
|
}
|
|
if ( debug ) {
|
|
printf ( "TRUE_C_VAL = %d %d %d\n", true_c_val[0], true_c_val[1],
|
|
true_c_val[2] );
|
|
}
|
|
teller = teller + 3;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( teller >= temp_pointer ) {
|
|
end_found = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
pointer = ( long ) ( current_pointer + temp_pointer );
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_background_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
{
|
|
unsigned long int current_pointer;
|
|
unsigned char end_found = FALSE;
|
|
int i;
|
|
long int pointer;
|
|
float rgb_val[3];
|
|
unsigned short int temp_int;
|
|
unsigned long int temp_pointer;
|
|
unsigned long int teller;
|
|
unsigned char true_c_val[3];
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
teller = 6;
|
|
|
|
while ( end_found == FALSE ) {
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
teller = teller + 2;
|
|
|
|
switch ( temp_int ) {
|
|
case 0x0010:
|
|
if ( debug ) {
|
|
printf ( " COLOR_F RGB color definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
for ( i = 0; i < 3; i++ ) {
|
|
rgb_val[i] = float_read ( filein );
|
|
}
|
|
if ( debug ) {
|
|
printf ( "RGB_VAL = %f %f %f\n", rgb_val[0], rgb_val[1], rgb_val[2] );
|
|
}
|
|
teller = teller + 3 * sizeof ( float );
|
|
break;
|
|
case 0x0011:
|
|
if ( debug ) {
|
|
printf ( " COLOR_24 24 bit color definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
true_c_val[i] = fgetc ( filein );
|
|
}
|
|
if ( debug ) {
|
|
printf ( "TRUE_C_VAL = %d %d %d\n", true_c_val[0], true_c_val[1],
|
|
true_c_val[2] );
|
|
}
|
|
teller = teller + 3;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( teller >= temp_pointer ) {
|
|
end_found = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
pointer = ( long ) ( current_pointer + temp_pointer );
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_boolean ( unsigned char *boolean, FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
{
|
|
unsigned long current_pointer;
|
|
long int pointer;
|
|
unsigned long temp_pointer;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
|
|
*boolean = fgetc ( filein );
|
|
|
|
pointer = ( long ) ( current_pointer + temp_pointer );
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_camera_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
float camera_eye[3];
|
|
float camera_focus[3];
|
|
unsigned long int current_pointer;
|
|
float lens;
|
|
long int pointer;
|
|
float rotation;
|
|
unsigned long int temp_pointer;
|
|
unsigned short int u_short_int_val;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
|
|
camera_eye[0] = float_read ( filein );
|
|
camera_eye[1] = float_read ( filein );
|
|
camera_eye[2] = float_read ( filein );
|
|
|
|
camera_focus[0] = float_read ( filein );
|
|
camera_focus[1] = float_read ( filein );
|
|
camera_focus[2] = float_read ( filein );
|
|
|
|
rotation = float_read ( filein );
|
|
lens = float_read ( filein );
|
|
|
|
if ( debug ) {
|
|
printf ( " Found camera viewpoint at XYZ = %f %f %f.\n",
|
|
camera_eye[0], camera_eye[1], camera_eye[2] );
|
|
printf ( " Found camera focus coordinates at XYZ = %f %f %f.\n",
|
|
camera_focus[0], camera_focus[1], camera_focus[2] );
|
|
printf ( " Rotation of camera is: %f.\n", rotation );
|
|
printf ( " Lens in used camera is: %f mm.\n", lens );
|
|
}
|
|
|
|
if ( ( temp_pointer-38 ) > 0 ) {
|
|
|
|
if ( debug ) {
|
|
printf ( " Found extra camera sections.\n" );
|
|
}
|
|
|
|
u_short_int_val = tds_read_u_short_int ( filein );
|
|
|
|
if ( u_short_int_val == 0x4710 ) {
|
|
if ( debug ) {
|
|
printf ( " CAM_SEE_CONE.\n" );
|
|
}
|
|
tds_read_unknown_section ( filein );
|
|
}
|
|
|
|
u_short_int_val = tds_read_u_short_int ( filein );
|
|
|
|
if ( u_short_int_val == 0x4720 ) {
|
|
if ( debug ) {
|
|
printf ( " CAM_RANGES.\n" );
|
|
}
|
|
tds_read_unknown_section ( filein );
|
|
}
|
|
|
|
}
|
|
|
|
pointer = ( long ) ( current_pointer + temp_pointer );
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_edit_section ( FILE *filein, int *views_read )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Modified:
|
|
|
|
18 September 1998
|
|
*/
|
|
{
|
|
unsigned long int chunk_length;
|
|
unsigned long int current_pointer;
|
|
unsigned char end_found = FALSE;
|
|
long int pointer;
|
|
unsigned long int teller;
|
|
unsigned short int temp_int;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
chunk_length = tds_read_u_long_int ( filein );
|
|
teller = 6;
|
|
|
|
while ( end_found == FALSE ) {
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
teller = teller + 2;
|
|
|
|
if ( debug ) {
|
|
printf ( " TDS_READ_EDIT_SECTION processing tag %0X\n", temp_int );
|
|
}
|
|
|
|
switch ( temp_int ) {
|
|
case 0x1100:
|
|
if ( debug ) {
|
|
printf ( " BIT_MAP section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x1201:
|
|
if ( debug ) {
|
|
printf ( " USE_SOLID_BGND section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x1300:
|
|
if ( debug ) {
|
|
printf ( " V_GRADIENT section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x1400:
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x1420:
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x1450:
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x1500:
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x2200:
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x2201:
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x2210:
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x2300:
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x2302:
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x3000:
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x2100:
|
|
if ( debug ) {
|
|
printf ( " AMBIENT_LIGHT section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_ambient_section ( filein );
|
|
break;
|
|
case 0x1200:
|
|
if ( debug ) {
|
|
printf ( " SOLID_BGND section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_background_section ( filein );
|
|
break;
|
|
case 0x0100:
|
|
if ( debug ) {
|
|
printf ( " MASTER_SCALE section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x3d3e:
|
|
if ( debug ) {
|
|
printf ( " MESH_VERSION section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xafff:
|
|
if ( debug ) {
|
|
printf ( " MAT_ENTRY section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_material_section ( filein );
|
|
break;
|
|
case 0x4000:
|
|
if ( debug ) {
|
|
printf ( " NAMED_OBJECT section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_object_section ( filein );
|
|
break;
|
|
case 0x7001:
|
|
if ( debug ) {
|
|
printf ( " VIEWPORT_LAYOUT section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_view_section ( filein, views_read );
|
|
break;
|
|
case 0x7012:
|
|
if ( debug ) {
|
|
printf ( " VIEWPORT_DATA_3 section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x7011:
|
|
if ( debug ) {
|
|
printf ( " VIEWPORT_DATA section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x7020:
|
|
if ( debug ) {
|
|
printf ( " VIEWPORT_SIZE section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
default:
|
|
if ( debug ) {
|
|
printf ( " Junk.\n" );
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( teller >= chunk_length ) {
|
|
end_found = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
pointer = ( long ) ( current_pointer + chunk_length );
|
|
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( chunk_length );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_keyframe_section ( FILE *filein, int *views_read )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
unsigned long int current_pointer;
|
|
unsigned char end_found = FALSE;
|
|
long int pointer;
|
|
unsigned short int temp_int;
|
|
unsigned long int temp_pointer;
|
|
unsigned long int teller;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
teller = 6;
|
|
|
|
while ( end_found == FALSE ) {
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
teller = teller + 2;
|
|
|
|
switch ( temp_int ) {
|
|
case 0x7001:
|
|
if ( debug ) {
|
|
printf ( " VIEWPORT_LAYOUT main definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_view_section ( filein, views_read );
|
|
break;
|
|
case 0xb008:
|
|
if ( debug ) {
|
|
printf ( " KFSEG frames section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xb002:
|
|
if ( debug ) {
|
|
printf ( " OBJECT_NODE_TAG object description section tag of %0X\n",
|
|
temp_int);
|
|
}
|
|
teller = teller + tds_read_keyframe_objdes_section ( filein );
|
|
break;
|
|
case 0xb009:
|
|
if ( debug ) {
|
|
printf ( " KFCURTIME section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xb00a:
|
|
if ( debug ) {
|
|
printf ( " KFHDR section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( teller >= temp_pointer ) {
|
|
end_found = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
pointer = ( long ) ( current_pointer + temp_pointer );
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_keyframe_objdes_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Modified:
|
|
|
|
21 September 1998
|
|
*/
|
|
{
|
|
unsigned long int chunk_size;
|
|
unsigned long int current_pointer;
|
|
unsigned char end_found = FALSE;
|
|
long int pointer;
|
|
unsigned short int temp_int;
|
|
unsigned long int temp_pointer;
|
|
unsigned long int teller;
|
|
unsigned long int u_long_int_val;
|
|
unsigned short int u_short_int_val;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
teller = 6;
|
|
|
|
while ( end_found == FALSE ) {
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
teller = teller + 2;
|
|
|
|
switch ( temp_int ) {
|
|
case 0xb011:
|
|
if ( debug ) {
|
|
printf ( " INSTANCE_NAME section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xb010:
|
|
if ( debug ) {
|
|
printf ( " NODE_HDR section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xb020:
|
|
if ( debug ) {
|
|
printf ( " POS_TRACK_TAG section tag of %0X\n", temp_int );
|
|
}
|
|
chunk_size = tds_read_u_long_int ( filein );
|
|
if ( debug ) {
|
|
printf ( " chunk_size = %d\n", chunk_size );
|
|
}
|
|
u_short_int_val = tds_read_u_short_int ( filein );
|
|
u_short_int_val = tds_read_u_short_int ( filein );
|
|
u_short_int_val = tds_read_u_short_int ( filein );
|
|
u_short_int_val = tds_read_u_short_int ( filein );
|
|
u_short_int_val = tds_read_u_short_int ( filein );
|
|
u_short_int_val = tds_read_u_short_int ( filein );
|
|
u_short_int_val = tds_read_u_short_int ( filein );
|
|
u_short_int_val = tds_read_u_short_int ( filein );
|
|
u_long_int_val = tds_read_u_long_int ( filein );
|
|
if ( debug ) {
|
|
printf ( "u_short_int_val = %d\n", u_short_int_val );
|
|
printf ( "u_long_int_val = %d\n", u_long_int_val );
|
|
}
|
|
origin[0] = float_read ( filein );
|
|
origin[1] = float_read ( filein );
|
|
origin[2] = float_read ( filein );
|
|
teller = teller + 32;
|
|
break;
|
|
case 0xb013:
|
|
if ( debug ) {
|
|
printf ( " PIVOT section tag of %0X\n", temp_int );
|
|
}
|
|
chunk_size = tds_read_u_long_int ( filein );
|
|
pivot[0] = float_read ( filein );
|
|
pivot[1] = float_read ( filein );
|
|
pivot[2] = float_read ( filein );
|
|
teller = teller + 12;
|
|
break;
|
|
case 0xb014:
|
|
if ( debug ) {
|
|
printf ( " BOUNDBOX section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xb015:
|
|
if ( debug ) {
|
|
printf ( " MORPH_SMOOTH section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xb021:
|
|
if ( debug ) {
|
|
printf ( " ROT_TRACK_TAG section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xb022:
|
|
if ( debug ) {
|
|
printf ( " SCL_TRACK_TAG section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xb030:
|
|
if ( debug ) {
|
|
printf ( " NODE_ID section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( teller >= temp_pointer ) {
|
|
end_found = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
pointer = ( long ) ( current_pointer+temp_pointer );
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_light_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
unsigned char boolean;
|
|
unsigned long int current_pointer;
|
|
unsigned char end_found = FALSE;
|
|
int i;
|
|
float light_coors[3];
|
|
long int pointer;
|
|
float rgb_val[3];
|
|
unsigned long int teller;
|
|
unsigned short int temp_int;
|
|
unsigned long int temp_pointer;
|
|
unsigned char true_c_val[3];
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
teller = 6;
|
|
|
|
light_coors[0] = float_read ( filein );
|
|
light_coors[1] = float_read ( filein );
|
|
light_coors[2] = float_read ( filein );
|
|
|
|
teller = teller + 3 * 4;
|
|
|
|
if ( debug ) {
|
|
printf ( " Found light at coordinates XYZ = %f %f %f.\n",
|
|
light_coors[0], light_coors[1], light_coors[2] );
|
|
}
|
|
|
|
while ( end_found == FALSE ) {
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
teller = teller + 2;
|
|
|
|
switch ( temp_int ) {
|
|
case 0x0010:
|
|
if ( debug ) {
|
|
printf ( " COLOR_F RGB color definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
for ( i = 0; i < 3; i++ ) {
|
|
rgb_val[i] = float_read ( filein );
|
|
}
|
|
if ( debug ) {
|
|
printf ( " RGB_VAL value set to %f %f %f\n", rgb_val[0],
|
|
rgb_val[1], rgb_val[2] );
|
|
}
|
|
teller = teller + 3 * sizeof ( float );
|
|
break;
|
|
case 0x0011:
|
|
if ( debug ) {
|
|
printf ( " COLOR_24 24 bit color definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
true_c_val[i] = fgetc ( filein );
|
|
}
|
|
if ( debug ) {
|
|
printf ( " TRUE_C_VAL value set to %d %d %d\n", true_c_val[0],
|
|
true_c_val[1], true_c_val[2] );
|
|
}
|
|
teller = teller + 3;
|
|
break;
|
|
case 0x4620:
|
|
if ( debug ) {
|
|
printf ( " DL_OFF section: %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_boolean ( &boolean, filein );
|
|
if ( debug ) {
|
|
if ( boolean == TRUE ) {
|
|
printf ( " Light is on\n" );
|
|
}
|
|
else {
|
|
printf ( " Light is off\n" );
|
|
}
|
|
}
|
|
break;
|
|
case 0x4610:
|
|
if ( debug ) {
|
|
printf ( " DL_SPOTLIGHT section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_spot_section ( filein );
|
|
break;
|
|
case 0x465a:
|
|
if ( debug ) {
|
|
printf ( " DL_OUTER_RANGE section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( teller >= temp_pointer ) {
|
|
end_found = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
pointer = ( long ) ( current_pointer + temp_pointer );
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long int tds_read_u_long_int ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Modified:
|
|
|
|
01 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
union {
|
|
unsigned long int yint;
|
|
char ychar[4];
|
|
} y;
|
|
|
|
if ( byte_swap == TRUE ) {
|
|
y.ychar[3] = fgetc ( filein );
|
|
y.ychar[2] = fgetc ( filein );
|
|
y.ychar[1] = fgetc ( filein );
|
|
y.ychar[0] = fgetc ( filein );
|
|
}
|
|
else {
|
|
y.ychar[0] = fgetc ( filein );
|
|
y.ychar[1] = fgetc ( filein );
|
|
y.ychar[2] = fgetc ( filein );
|
|
y.ychar[3] = fgetc ( filein );
|
|
}
|
|
|
|
return y.yint;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int tds_read_long_name ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
unsigned char letter;
|
|
unsigned int teller;
|
|
|
|
teller = 0;
|
|
letter = fgetc ( filein );
|
|
/*
|
|
Could be a dummy object.
|
|
*/
|
|
if ( letter == 0 ) {
|
|
strcpy ( temp_name, "Default_name" );
|
|
return -1;
|
|
}
|
|
|
|
temp_name[teller] = letter;
|
|
teller = teller + 1;
|
|
|
|
do {
|
|
letter = fgetc ( filein );
|
|
temp_name[teller] = letter;
|
|
teller = teller + 1;
|
|
} while ( letter != 0 );
|
|
|
|
temp_name[teller-1] = 0;
|
|
|
|
if ( debug ) {
|
|
printf ( " tds_read_long_name found name: %s.\n", temp_name );
|
|
}
|
|
|
|
return teller;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_matdef_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
unsigned long int current_pointer;
|
|
long int pointer;
|
|
int teller;
|
|
unsigned long int temp_pointer;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
|
|
teller = tds_read_long_name ( filein );
|
|
|
|
if ( teller == -1 ) {
|
|
if ( debug ) {
|
|
printf ( " No material name found.\n" );
|
|
}
|
|
}
|
|
else {
|
|
strcpy ( mat_name, temp_name );
|
|
if ( debug ) {
|
|
printf ( " Material name %s.\n", mat_name );
|
|
}
|
|
}
|
|
|
|
pointer = ( long ) ( current_pointer + temp_pointer );
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_material_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
unsigned long int current_pointer;
|
|
unsigned char end_found = FALSE;
|
|
long int pointer;
|
|
unsigned short int temp_int;
|
|
unsigned long int temp_pointer;
|
|
unsigned long int teller;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
teller = 6;
|
|
|
|
while ( end_found == FALSE ) {
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
teller = teller + 2;
|
|
|
|
switch ( temp_int ) {
|
|
|
|
case 0xa000:
|
|
if ( debug ) {
|
|
printf ( " MAT_NAME definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_matdef_section ( filein );
|
|
break;
|
|
case 0xa010:
|
|
if ( debug ) {
|
|
printf ( " MAT_AMBIENT definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa020:
|
|
if ( debug ) {
|
|
printf ( " MAT_DIFFUSE definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa030:
|
|
if ( debug ) {
|
|
printf ( " MAT_SPECULAR definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa040:
|
|
if ( debug ) {
|
|
printf ( " MAT_SHININESS definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa041:
|
|
if ( debug ) {
|
|
printf ( " MAT_SHIN2PCT definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa042:
|
|
if ( debug ) {
|
|
printf ( " MAT_SHIN3PCT definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa050:
|
|
if ( debug ) {
|
|
printf ( " MAT_TRANSPARENCY definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa052:
|
|
if ( debug ) {
|
|
printf ( " MAT_XPFALL definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa053:
|
|
if ( debug ) {
|
|
printf ( " MAT_REFBLUR definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa080:
|
|
if ( debug ) {
|
|
printf ( " MAT_SELF_ILLUM definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa081:
|
|
if ( debug ) {
|
|
printf ( " MAT_TWO_SIDE definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa082:
|
|
if ( debug ) {
|
|
printf ( " MAT_DECAL definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa083:
|
|
if ( debug ) {
|
|
printf ( " MAT_ADDITIVE definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa084:
|
|
if ( debug ) {
|
|
printf ( " MAT_SELF_ILPCT definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa085:
|
|
if ( debug ) {
|
|
printf ( " MAT_WIRE definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa086:
|
|
if ( debug ) {
|
|
printf ( " MAT_SUPERSMP definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa087:
|
|
if ( debug ) {
|
|
printf ( " MAT_WIRESIZE definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa088:
|
|
if ( debug ) {
|
|
printf ( " MAT_FACEMAP definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa08a:
|
|
if ( debug ) {
|
|
printf ( " MAT_XPFALLIN definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa08c:
|
|
if ( debug ) {
|
|
printf ( " MAT_PHONGSOFT definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa08e:
|
|
if ( debug ) {
|
|
printf ( " MAT_WIREABS definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa100:
|
|
if ( debug ) {
|
|
printf ( " MAT_SHADING definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa200:
|
|
if ( debug ) {
|
|
printf ( " MAT_TEXMAP definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_texmap_section ( filein );
|
|
/*
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
*/
|
|
break;
|
|
case 0xa204:
|
|
if ( debug ) {
|
|
printf ( " MAT_SPECMAP definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa210:
|
|
if ( debug ) {
|
|
printf ( " MAT_OPACMAP definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa220:
|
|
if ( debug ) {
|
|
printf ( " MAT_REFLMAP definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa230:
|
|
if ( debug ) {
|
|
printf ( " MAT_BUMPMAP definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0xa353:
|
|
if ( debug ) {
|
|
printf ( " MAT_MAP_TEXBLUR definition section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
default:
|
|
if ( debug ) {
|
|
printf ( " Junk section tag of %0X\n", temp_int );
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( teller >= temp_pointer ) {
|
|
end_found = TRUE;
|
|
}
|
|
|
|
}
|
|
pointer = ( long ) ( current_pointer + temp_pointer );
|
|
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int tds_read_name ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
unsigned char letter;
|
|
unsigned int teller;
|
|
|
|
teller = 0;
|
|
letter = fgetc ( filein );
|
|
/*
|
|
Could be a dummy object.
|
|
*/
|
|
|
|
if ( letter == 0 ) {
|
|
strcpy ( temp_name, "Default name" );
|
|
return (-1);
|
|
}
|
|
|
|
temp_name[teller] = letter;
|
|
teller = teller + 1;
|
|
|
|
do {
|
|
letter = fgetc ( filein );
|
|
temp_name[teller] = letter;
|
|
teller = teller + 1;
|
|
} while ( ( letter != 0 ) && ( teller < 12 ) );
|
|
|
|
temp_name[teller-1] = 0;
|
|
|
|
if ( debug ) {
|
|
printf ( " tds_read_name found name: %s.\n", temp_name );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_obj_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Comments:
|
|
|
|
Thanks to John F Flanagan for some suggested corrections.
|
|
|
|
Modified:
|
|
|
|
30 June 2001
|
|
*/
|
|
{
|
|
unsigned short int b;
|
|
unsigned long int chunk_size;
|
|
unsigned short int color_index;
|
|
unsigned long int current_pointer;
|
|
unsigned char end_found = FALSE;
|
|
unsigned short int g;
|
|
int i;
|
|
int j;
|
|
int cor3_num_base;
|
|
int cor3_num_inc;
|
|
int face_num_inc;
|
|
long int pointer;
|
|
unsigned short int r;
|
|
unsigned short int temp_int;
|
|
unsigned long int temp_pointer;
|
|
unsigned long int temp_pointer2;
|
|
unsigned long int teller;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
teller = 6;
|
|
cor3_num_base = cor3_num;
|
|
|
|
while ( end_found == FALSE ) {
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
teller = teller + 2;
|
|
|
|
switch ( temp_int ) {
|
|
|
|
case 0x4000:
|
|
if ( debug ) {
|
|
printf ( " NAMED_OBJECT section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
|
|
case 0x4100:
|
|
if ( debug ) {
|
|
printf ( " N_TRI_OBJECT section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
|
|
case 0x4110:
|
|
|
|
if ( debug ) {
|
|
printf ( " POINT_ARRAY section tag of %0X\n", temp_int );
|
|
}
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer2 = tds_read_u_long_int ( filein );
|
|
cor3_num_inc = ( int ) tds_read_u_short_int ( filein );
|
|
|
|
for ( i = cor3_num; i < cor3_num + cor3_num_inc; i++ ) {
|
|
cor3[0][i] = float_read ( filein );
|
|
cor3[1][i] = float_read ( filein );
|
|
cor3[2][i] = float_read ( filein );
|
|
}
|
|
|
|
cor3_num = cor3_num + cor3_num_inc;
|
|
teller = teller + temp_pointer2;
|
|
break;
|
|
|
|
case 0x4111:
|
|
if ( debug ) {
|
|
printf ( " POINT_FLAG_ARRAY faces (2) section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
|
|
case 0x4120:
|
|
|
|
if ( debug ) {
|
|
printf ( " FACE_ARRAY section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
|
|
temp_pointer2 = tds_read_u_long_int ( filein );
|
|
face_num_inc = ( int ) tds_read_u_short_int ( filein );
|
|
|
|
for ( i = face_num; i < face_num + face_num_inc; i++ ) {
|
|
face[0][i] = tds_read_u_short_int ( filein ) + cor3_num_base;
|
|
face[1][i] = tds_read_u_short_int ( filein ) + cor3_num_base;
|
|
face[2][i] = tds_read_u_short_int ( filein ) + cor3_num_base;
|
|
face_order[i] = 3;
|
|
face_flags[i] = tds_read_u_short_int ( filein );
|
|
/*
|
|
Color is given per face, and as 24 bit RGB data packed in one word.
|
|
Extract RGB from the word, and assign R / 255 to each vertex.
|
|
|
|
Just a guess, JVB, 30 June 2001.
|
|
*/
|
|
temp_int = face_flags[i] & 0x000F;
|
|
r = ( temp_int & 0x0004 ) >> 2;
|
|
g = ( temp_int & 0x0002 ) >> 1;
|
|
b = ( temp_int & 0x0001 );
|
|
|
|
for ( j = 0; j < 3; j++ ) {
|
|
vertex_rgb[0][j][i] = ( float ) r / 255.0;
|
|
vertex_rgb[1][j][i] = ( float ) g / 255.0;
|
|
vertex_rgb[2][j][i] = ( float ) b / 255.0;
|
|
}
|
|
|
|
}
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
if ( temp_int == 0x4150 ) {
|
|
for ( i = face_num; i < face_num + face_num_inc; i++ ) {
|
|
face_smooth[i] = ( int ) tds_read_u_long_int ( filein )
|
|
+ cor3_num_base;
|
|
}
|
|
}
|
|
face_num = face_num + face_num_inc;
|
|
teller = ftell ( filein );
|
|
break;
|
|
|
|
case 0x4130:
|
|
if ( debug ) {
|
|
printf ( " MSH_MAT_GROUP section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
|
|
case 0x4140:
|
|
if ( debug ) {
|
|
printf ( " TEX_VERTS section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_tex_verts_section ( filein );
|
|
break;
|
|
|
|
case 0x4150:
|
|
if ( debug ) {
|
|
printf ( " SMOOTH_GROUP section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
|
|
case 0x4160:
|
|
|
|
if ( debug ) {
|
|
printf ( " MESH_MATRIX section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
|
|
tds_read_u_long_int ( filein );
|
|
|
|
for ( j = 0; j < 4; j++ ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
transform_matrix[j][i] = float_read ( filein );
|
|
}
|
|
}
|
|
transform_matrix[0][3] = 0.0;
|
|
transform_matrix[1][3] = 0.0;
|
|
transform_matrix[2][3] = 0.0;
|
|
transform_matrix[3][3] = 0.0;
|
|
|
|
teller = teller + 12 * sizeof ( float );
|
|
break;
|
|
|
|
case 0x4165:
|
|
|
|
if ( debug ) {
|
|
printf ( " MESH_COLOR section tag of %0X\n", temp_int );
|
|
}
|
|
|
|
chunk_size = tds_read_u_long_int ( filein );
|
|
|
|
if ( chunk_size == 7 ) {
|
|
color_index = fgetc ( filein );
|
|
teller = teller + 5;
|
|
}
|
|
else {
|
|
color_index = tds_read_u_short_int ( filein );
|
|
teller = teller + 6;
|
|
}
|
|
if ( debug ) {
|
|
printf ( " Color index set to %d\n", color_index );
|
|
}
|
|
break;
|
|
|
|
case 0x4170:
|
|
if ( debug ) {
|
|
printf ( " MESH_TEXTURE_INFO section tag of %0X\n",
|
|
temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
|
|
default:
|
|
if ( debug ) {
|
|
printf ( " JUNK section tag of %0X\n", temp_int );
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( teller >= temp_pointer ) {
|
|
end_found = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
pointer = ( long int ) ( current_pointer + temp_pointer );
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_object_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
unsigned char end_found = FALSE;
|
|
unsigned long int current_pointer;
|
|
int int_val;
|
|
long int pointer;
|
|
unsigned short int temp_int;
|
|
unsigned long int temp_pointer;
|
|
unsigned long int teller;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
teller = 6;
|
|
/*
|
|
Why don't you read and save the name here?
|
|
*/
|
|
int_val = tds_read_name ( filein );
|
|
|
|
if ( int_val == -1 ) {
|
|
if ( debug ) {
|
|
printf ( " Dummy Object found\n" );
|
|
}
|
|
}
|
|
else {
|
|
strcpy ( object_name, temp_name );
|
|
}
|
|
|
|
while ( end_found == FALSE ) {
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
teller = teller + 2;
|
|
|
|
switch ( temp_int ) {
|
|
case 0x4700:
|
|
if ( debug ) {
|
|
printf ( " N_CAMERA section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_camera_section ( filein );
|
|
break;
|
|
case 0x4600:
|
|
if ( debug ) {
|
|
printf ( " N_DIRECT_LIGHT section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_light_section ( filein );
|
|
break;
|
|
case 0x4100:
|
|
if ( debug ) {
|
|
printf ( " OBJ_TRIMESH section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_obj_section ( filein );
|
|
break;
|
|
case 0x4010:
|
|
if ( debug ) {
|
|
printf ( " OBJ_HIDDEN section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x4012:
|
|
if ( debug ) {
|
|
printf ( " OBJ_DOESNT_CAST section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( teller >= temp_pointer ) {
|
|
end_found = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
pointer = ( long ) ( current_pointer + temp_pointer );
|
|
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long int tds_read_tex_verts_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TDS_READ_TEX_VERTS_SECTION reads the texture vertex data.
|
|
|
|
Discussion:
|
|
|
|
The texture vertex data seems to be associated with nodes. This routine
|
|
distributes that data to vertices (nodes as they make up a particular
|
|
face).
|
|
|
|
Modified:
|
|
|
|
02 July 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
unsigned long int current_pointer;
|
|
int icor3;
|
|
long int pointer;
|
|
unsigned long int temp_pointer;
|
|
unsigned short int n2;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
|
|
pointer = ( long int ) ( current_pointer + temp_pointer );
|
|
|
|
n2 = tds_read_u_short_int ( filein );
|
|
|
|
for ( icor3 = 0; icor3 < n2; icor3++ ) {
|
|
cor3_tex_uv[0][icor3] = float_read ( filein );
|
|
cor3_tex_uv[1][icor3] = float_read ( filein );
|
|
}
|
|
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_texmap_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TDS_READ_TEXMAP_SECTION tries to get the TEXMAP name from the TEXMAP section.
|
|
|
|
Warning:
|
|
|
|
The code has room for lots of textures. In this routine, we behave as
|
|
though there were only one, and we stick its name in the first name slot.
|
|
|
|
Modified:
|
|
|
|
30 June 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
unsigned long int current_pointer;
|
|
long int pointer;
|
|
int teller;
|
|
unsigned long int temp_pointer;
|
|
|
|
texture_num = texture_num + 1;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
|
|
tds_read_u_short_int ( filein );
|
|
tds_read_u_short_int ( filein );
|
|
tds_read_u_short_int ( filein );
|
|
tds_read_u_short_int ( filein );
|
|
|
|
/*
|
|
This next short int should equal A300.
|
|
*/
|
|
tds_read_u_short_int ( filein );
|
|
tds_read_u_long_int ( filein );
|
|
/*
|
|
Now read the TEXMAP file name.
|
|
*/
|
|
teller = tds_read_long_name ( filein );
|
|
|
|
if ( teller == -1 ) {
|
|
if ( debug ) {
|
|
printf ( " No TEXMAP name found.\n" );
|
|
}
|
|
}
|
|
else {
|
|
strcpy ( texture_name[0], temp_name );
|
|
if ( debug ) {
|
|
printf ( " TEXMAP name %s.\n", texture_name[0] );
|
|
}
|
|
}
|
|
|
|
pointer = ( long ) ( current_pointer + temp_pointer );
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned short int tds_read_u_short_int ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
unsigned char c1;
|
|
unsigned char c2;
|
|
short int ival;
|
|
|
|
c1 = fgetc ( filein );
|
|
c2 = fgetc ( filein );
|
|
|
|
ival = c1 | ( c2 << 8 );
|
|
|
|
return ival;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_spot_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
unsigned long int current_pointer;
|
|
float falloff;
|
|
float hotspot;
|
|
long int pointer;
|
|
float target[4];
|
|
unsigned long int temp_pointer;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
|
|
target[0] = float_read ( filein );
|
|
target[1] = float_read ( filein );
|
|
target[2] = float_read ( filein );
|
|
hotspot = float_read ( filein );
|
|
falloff = float_read ( filein );
|
|
|
|
if ( debug ) {
|
|
printf ( " The target of the spot is XYZ = %f %f %f.\n",
|
|
target[0], target[1], target[2] );
|
|
printf ( " The hotspot of this light is %f.\n", hotspot );
|
|
printf ( " The falloff of this light is %f.\n", falloff );
|
|
}
|
|
|
|
pointer = ( long ) ( current_pointer + temp_pointer );
|
|
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long int tds_read_unknown_section ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
unsigned long int current_pointer;
|
|
long int pointer;
|
|
unsigned long int temp_pointer;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
|
|
pointer = ( long int ) ( current_pointer + temp_pointer );
|
|
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_view_section ( FILE *filein, int *views_read )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
unsigned long int current_pointer;
|
|
unsigned char end_found = FALSE;
|
|
long int pointer;
|
|
unsigned short int temp_int;
|
|
unsigned long int temp_pointer;
|
|
unsigned long int teller;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
teller = 6;
|
|
|
|
while ( end_found == FALSE ) {
|
|
|
|
temp_int = tds_read_u_short_int ( filein );
|
|
teller = teller + 2;
|
|
|
|
switch ( temp_int ) {
|
|
case 0x7012:
|
|
if ( debug ) {
|
|
printf ( " VIEWPORT_DATA_3 section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_vp_section ( filein, views_read );
|
|
break;
|
|
case 0x7011:
|
|
if ( debug ) {
|
|
printf ( " VIEWPORT_DATA section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_unknown_section ( filein );
|
|
break;
|
|
case 0x7020:
|
|
if ( debug ) {
|
|
printf ( " VIEWPORT_SIZE section tag of %0X\n", temp_int );
|
|
}
|
|
teller = teller + tds_read_vp_section ( filein, views_read );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( teller >= temp_pointer ) {
|
|
end_found = TRUE;
|
|
}
|
|
|
|
if ( *views_read > 3 ) {
|
|
end_found = TRUE;
|
|
}
|
|
}
|
|
|
|
pointer = ( long int ) ( current_pointer + temp_pointer );
|
|
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
unsigned long tds_read_vp_section ( FILE *filein, int *views_read )
|
|
|
|
/******************************************************************************/
|
|
{
|
|
unsigned int attribs;
|
|
unsigned long int current_pointer;
|
|
int i;
|
|
int int_val;
|
|
long int pointer;
|
|
unsigned int port;
|
|
unsigned long int temp_pointer;
|
|
char *viewports[11] = {
|
|
"Bogus",
|
|
"Top",
|
|
"Bottom",
|
|
"Left",
|
|
"Right",
|
|
"Front",
|
|
"Back",
|
|
"User",
|
|
"Camera",
|
|
"Light",
|
|
"Disabled"
|
|
};
|
|
|
|
*views_read = *views_read + 1;
|
|
|
|
current_pointer = ftell ( filein ) - 2;
|
|
temp_pointer = tds_read_u_long_int ( filein );
|
|
|
|
attribs = tds_read_u_short_int ( filein );
|
|
|
|
if ( attribs == 3 ) {
|
|
if ( debug ) {
|
|
printf ( "<Snap> active in viewport.\n" );
|
|
}
|
|
}
|
|
|
|
if ( attribs == 5 ) {
|
|
if ( debug ) {
|
|
printf ( "<Grid> active in viewport.\n" );
|
|
}
|
|
}
|
|
/*
|
|
Read 5 INTS to get to the viewport information.
|
|
*/
|
|
for ( i = 1; i < 6; i++ ) {
|
|
tds_read_u_short_int ( filein );
|
|
}
|
|
|
|
port = tds_read_u_short_int ( filein );
|
|
/*
|
|
Find camera section.
|
|
*/
|
|
if ( ( port == 0xffff ) || ( port == 0 ) ) {
|
|
|
|
for ( i = 0; i < 12; i++ ) {
|
|
tds_read_u_short_int ( filein );
|
|
}
|
|
|
|
int_val = tds_read_name (filein );
|
|
|
|
if ( int_val == -1 ) {
|
|
if ( debug ) {
|
|
printf ( " No Camera name found\n" );
|
|
}
|
|
}
|
|
|
|
port = 0x0008;
|
|
}
|
|
|
|
if ( debug ) {
|
|
printf ( "Reading [%s] information with tag:%d\n", viewports[port], port );
|
|
}
|
|
|
|
pointer = ( long int ) ( current_pointer + temp_pointer );
|
|
|
|
fseek ( filein, pointer, SEEK_SET );
|
|
|
|
return ( temp_pointer );
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int tds_write ( FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TDS_WRITE writes graphics information to a 3D Studio Max 3DS file.
|
|
|
|
Modified:
|
|
|
|
14 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
*/
|
|
{
|
|
float float_val;
|
|
int i;
|
|
int icor3;
|
|
int iface;
|
|
int j;
|
|
long int l0002;
|
|
long int l0100;
|
|
long int l3d3d;
|
|
long int l3d3e;
|
|
long int l4000;
|
|
long int l4100;
|
|
long int l4110;
|
|
long int l4120;
|
|
long int l4150;
|
|
long int l4160;
|
|
long int l4d4d;
|
|
long int lb000;
|
|
long int lb002;
|
|
long int lb00a;
|
|
long int lb008;
|
|
long int lb009;
|
|
long int lb010;
|
|
long int lb013;
|
|
long int lb020;
|
|
long int lb021;
|
|
long int lb022;
|
|
long int lb030;
|
|
long int long_int_val;
|
|
int name_length;
|
|
short int short_int_val;
|
|
unsigned short int u_short_int_val;
|
|
|
|
bytes_num = 0;
|
|
name_length = strlen ( object_name );
|
|
|
|
l0002 = 10;
|
|
|
|
l4150 = 2 + 4 + face_num * 4;
|
|
l4120 = 2 + 4 + 2 + 4 * face_num * 2 + l4150;
|
|
l4160 = 2 + 4 + 4 * 12;
|
|
l4110 = 2 + 4 + 2 + cor3_num * 3 * 4;
|
|
l4100 = 2 + 4 + l4110 + l4160 + l4120;
|
|
l4000 = 2 + 4 + ( name_length + 1 ) + l4100;
|
|
l0100 = 2 + 4 + 4;
|
|
l3d3e = 2 + 4 + 4;
|
|
l3d3d = 2 + 4 + l3d3e + l0100 + l4000;
|
|
|
|
lb022 = 2 + 4 + 32;
|
|
lb021 = 2 + 4 + 9 * 4;
|
|
lb020 = 2 + 4 + 8 * 4;
|
|
lb013 = 2 + 4 + 6 * 2;
|
|
lb010 = 2 + 4 + ( name_length + 1 ) + 3 * 2;
|
|
lb030 = 2 + 4 + 2;
|
|
lb002 = 2 + 4 + lb030 + lb010 + lb013 + lb020 + lb021 + lb022;
|
|
lb009 = 2 + 4 + 4;
|
|
lb008 = 2 + 4 + 2 * 4;
|
|
lb00a = 2 + 4 + 2 + 9 + 2 * 2;
|
|
lb000 = 2 + 4 + lb00a + lb008 + lb009 + lb002;
|
|
|
|
l4d4d = 2 + 4 + l0002 + l3d3d + lb000;
|
|
/*
|
|
M3DMAGIC begin.
|
|
tag, size.
|
|
*/
|
|
short_int_val = ( short ) 0x4d4d;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, l4d4d );
|
|
/*
|
|
M3D_VERSION begin.
|
|
tag, size, version.
|
|
*/
|
|
short_int_val = ( short ) 0x0002;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, l0002 );
|
|
long_int_val = 3;
|
|
bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
|
|
/*
|
|
M3D_VERSION end.
|
|
MDATA begin.
|
|
tag, size.
|
|
*/
|
|
short_int_val = ( short ) 0x3d3d;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, l3d3d );
|
|
/*
|
|
MESH_VERSION begin.
|
|
tag, size, version.
|
|
*/
|
|
short_int_val = ( short ) 0x3d3e;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, l3d3e );
|
|
long_int_val = 3;
|
|
bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
|
|
/*
|
|
MESH_VERSION end.
|
|
MASTER_SCALE begin.
|
|
tag, size, scale.
|
|
*/
|
|
short_int_val = ( short ) 0x0100;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, l0100 );
|
|
float_val = 1.0;
|
|
bytes_num = bytes_num + float_write ( fileout, float_val );
|
|
/*
|
|
MASTER_SCALE end.
|
|
NAMED_OBJECT begin.
|
|
tag, size, name.
|
|
*/
|
|
short_int_val = ( short ) 0x4000;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, l4000 );
|
|
bytes_num = bytes_num + tds_write_string ( fileout, object_name );
|
|
/*
|
|
N_TRI_OBJECT begin.
|
|
tag, size.
|
|
*/
|
|
short_int_val = ( short ) 0x4100;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, l4100 );
|
|
/*
|
|
POINT_ARRAY begin.
|
|
tag, size, number of points, coordinates of points.
|
|
Warning! number of points could exceed a short!
|
|
*/
|
|
short_int_val = ( short ) 0x4110;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, l4110 );
|
|
|
|
u_short_int_val = ( unsigned short ) cor3_num;
|
|
bytes_num = bytes_num + tds_write_u_short_int ( fileout, u_short_int_val );
|
|
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
for ( j = 0; j < 3; j++ ) {
|
|
bytes_num = bytes_num + float_write ( fileout, cor3[j][icor3] );
|
|
}
|
|
}
|
|
/*
|
|
POINT_ARRAY end.
|
|
MESH_MATRIX begin.
|
|
tag, size, 4 by 3 matrix.
|
|
*/
|
|
short_int_val = ( short ) 0x4160;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, l4160 );
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
for ( j = 0; j < 3; j++ ) {
|
|
float_val = transform_matrix[i][j];
|
|
bytes_num = bytes_num + float_write ( fileout, float_val );
|
|
}
|
|
}
|
|
/*
|
|
MESH_MATRIX end.
|
|
FACE_ARRAY begin.
|
|
tag, size, number of faces, nodes per face.
|
|
Warning: number of faces could exceed a short!
|
|
*/
|
|
short_int_val = ( short ) 0x4120;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, l4120 );
|
|
|
|
u_short_int_val = ( unsigned short ) face_num;
|
|
bytes_num = bytes_num + tds_write_u_short_int ( fileout, u_short_int_val );
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( j = 0; j < 3; j++ ) {
|
|
short_int_val = face[j][iface];
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
}
|
|
short_int_val = face_flags[iface];
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
}
|
|
/*
|
|
SMOOTH_GROUP begin.
|
|
tag, size, group for each face.
|
|
*/
|
|
short_int_val = ( short ) 0x4150;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, l4150 );
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
long_int_val = face_smooth[iface];
|
|
bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
|
|
}
|
|
/*
|
|
SMOOTH_GROUP end.
|
|
FACE_ARRAY end.
|
|
N_TRI_OBJECT end.
|
|
NAMED_OBJECT end.
|
|
MDATA end.
|
|
KFDATA begin.
|
|
*/
|
|
short_int_val = ( short ) 0xb000;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, lb000 );
|
|
/*
|
|
KFHDR begin.
|
|
tag, size, revision, filename, animlen.
|
|
*/
|
|
short_int_val = ( short ) 0xb00a;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, lb00a );
|
|
short_int_val = 5;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + tds_write_string ( fileout, "MAXSCENE" );
|
|
short_int_val = 100;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
/*
|
|
KFHDR end.
|
|
KFSEG begin.
|
|
tag, size, start, end.
|
|
*/
|
|
short_int_val = ( short ) 0xb008;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, lb008 );
|
|
long_int_val = 0;
|
|
bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
|
|
long_int_val = 100;
|
|
bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
|
|
/*
|
|
KFSEG end.
|
|
KFCURTIME begin.
|
|
tag, size, current_frame.
|
|
*/
|
|
short_int_val = ( short ) 0xb009;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, lb009 );
|
|
long_int_val = 0;
|
|
bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
|
|
/*
|
|
KFCURTIME end.
|
|
OBJECT_NODE_TAG begin.
|
|
tag, size.
|
|
*/
|
|
short_int_val = ( short ) 0xb002;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, lb002 );
|
|
/*
|
|
NODE_ID begin.
|
|
tag, size, id.
|
|
*/
|
|
short_int_val = ( short ) 0xb030;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, lb030 );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
/*
|
|
NODE_ID end.
|
|
NODE_HDR begin.
|
|
tag, size, object_name, flag1, flag2, hierarchy.
|
|
*/
|
|
short_int_val = ( short ) 0xb010;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, lb010 );
|
|
bytes_num = bytes_num + tds_write_string ( fileout, object_name );
|
|
short_int_val = 16384;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = -1;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
/*
|
|
NODE_HDR end.
|
|
PIVOT begin.
|
|
tag, size, pivot_x, pivot_y, pivot_z.
|
|
*/
|
|
short_int_val = ( short ) 0xb013;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, lb013 );
|
|
for ( i = 0; i < 3; i++ ) {
|
|
float_val = pivot[i];
|
|
bytes_num = bytes_num + float_write ( fileout, float_val );
|
|
}
|
|
/*
|
|
PIVOT end.
|
|
POS_TRACK_TAG begin.
|
|
tag, size, flag, i1, i2, i3, i4, i5, i6, frame, l1, pos_x, pos_y, pos_z.
|
|
*/
|
|
short_int_val = ( short ) 0xb020;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, lb020 );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 1;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
long_int_val = 0;
|
|
bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
|
|
for ( i = 0; i < 3; i++ ) {
|
|
float_val = origin[i];
|
|
bytes_num = bytes_num + float_write ( fileout, float_val );
|
|
}
|
|
/*
|
|
POS_TRACK_TAG end.
|
|
ROT_TRACK_TAG begin.
|
|
tag, size, i1, i2, i3, i4, i5, i6, i7, i8, l1, rad, axis_x, axis_y, axis_z.
|
|
*/
|
|
short_int_val = ( short ) 0xb021;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, lb021 );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 1;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
long_int_val = 0;
|
|
bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
|
|
float_val = 0.0;
|
|
bytes_num = bytes_num + float_write ( fileout, float_val );
|
|
bytes_num = bytes_num + float_write ( fileout, float_val );
|
|
bytes_num = bytes_num + float_write ( fileout, float_val );
|
|
bytes_num = bytes_num + float_write ( fileout, float_val );
|
|
/*
|
|
ROT_TRACK_TAG end.
|
|
SCL_TRACK_TAG begin.
|
|
tag, size, i1, i2, i3, i4, i5, i6, i7, i8, l1, scale_x, scale_y, scale_z.
|
|
*/
|
|
short_int_val = ( short ) 0xb022;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
bytes_num = bytes_num + long_int_write ( fileout, lb022 );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 1;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
short_int_val = 0;
|
|
bytes_num = bytes_num + short_int_write ( fileout, short_int_val );
|
|
long_int_val = 0;
|
|
bytes_num = bytes_num + long_int_write ( fileout, long_int_val );
|
|
float_val = 1.0;
|
|
bytes_num = bytes_num + float_write ( fileout, float_val );
|
|
bytes_num = bytes_num + float_write ( fileout, float_val );
|
|
bytes_num = bytes_num + float_write ( fileout, float_val );
|
|
/*
|
|
SCL_TRACK_TAG end.
|
|
OBJECT_NODE_TAG end.
|
|
KFDATA end.
|
|
M3DMAGIC end.
|
|
*/
|
|
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "TDS_WRITE wrote %d bytes.\n", bytes_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int tds_write_string ( FILE *fileout, char *string )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Modified:
|
|
|
|
23 September 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
char *c;
|
|
int nchar;
|
|
|
|
nchar = 0;
|
|
|
|
for ( c = string; nchar < 12; c++ ) {
|
|
|
|
fputc ( *c, fileout );
|
|
nchar = nchar + 1;
|
|
|
|
if ( *c == 0 ) {
|
|
return nchar;
|
|
}
|
|
|
|
}
|
|
|
|
return nchar;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int tds_write_u_short_int ( FILE *fileout, unsigned short int short_int_val )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Modified:
|
|
|
|
14 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
union {
|
|
unsigned short int yint;
|
|
char ychar[2];
|
|
} y;
|
|
|
|
y.yint = short_int_val;
|
|
|
|
if ( byte_swap == TRUE ) {
|
|
fputc ( y.ychar[1], fileout );
|
|
fputc ( y.ychar[0], fileout );
|
|
}
|
|
else {
|
|
fputc ( y.ychar[0], fileout );
|
|
fputc ( y.ychar[1], fileout );
|
|
}
|
|
|
|
return 2;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
int tec_write ( FILE *fileout )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TEC_WRITE writes graphics information to a TECPLOT file.
|
|
|
|
Discussion:
|
|
|
|
The file format used is appropriate for 3D finite element surface
|
|
zone data. Polygons are decomposed into triangles where necessary.
|
|
|
|
Example:
|
|
|
|
TITLE = "cube.tec created by IVCON."
|
|
VARIABLES = "X", "Y", "Z", "R", "G", "B"
|
|
ZONE T="TRIANGLES", N=8, E=12, F=FEPOINT, ET=TRIANGLE
|
|
0.0 0.0 0.0 0.0 0.0 0.0
|
|
1.0 0.0 0.0 1.0 0.0 0.0
|
|
1.0 1.0 0.0 1.0 1.0 0.0
|
|
0.0 1.0 0.0 0.0 1.0 0.0
|
|
0.0 0.0 1.0 0.0 0.0 1.0
|
|
1.0 0.0 1.0 1.0 0.0 1.0
|
|
1.0 1.0 1.0 1.0 1.0 1.0
|
|
0.0 1.0 1.0 0.0 1.0 1.0
|
|
1 4 2
|
|
2 4 3
|
|
1 5 8
|
|
1 2 5
|
|
2 6 5
|
|
2 3 6
|
|
3 7 6
|
|
3 4 7
|
|
4 8 7
|
|
4 1 8
|
|
5 6 8
|
|
6 7 8
|
|
|
|
Modified:
|
|
|
|
09 June 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
float b;
|
|
int face2[3];
|
|
float g;
|
|
int icor3;
|
|
int iface;
|
|
int imat;
|
|
int j;
|
|
int face_num2;
|
|
int text_num;
|
|
float r;
|
|
/*
|
|
Determine the number of triangular faces.
|
|
*/
|
|
face_num2 = 0;
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( j = 0; j < face_order[iface] - 2; j++ ) {
|
|
face_num2 = face_num2 + 1;
|
|
}
|
|
}
|
|
|
|
text_num = 0;
|
|
|
|
fprintf ( fileout, "\"%s created by IVCON.\"\n", fileout_name );
|
|
fprintf ( fileout, "VARIABLES = \"X\", \"Y\", \"Z\", \"R\", \"G\", \"B\"\n" );
|
|
fprintf ( fileout,
|
|
"ZONE T=\"TRIANGLES\", N=%d, E=%d, F=FEPOINT, ET=TRIANGLE\n",
|
|
cor3_num, face_num2 );
|
|
|
|
text_num = text_num + 3;
|
|
/*
|
|
Write out X, Y, Z, R, G, B per node.
|
|
*/
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
imat = cor3_material[icor3];
|
|
r = material_rgba[0][imat];
|
|
g = material_rgba[1][imat];
|
|
b = material_rgba[2][imat];
|
|
fprintf ( fileout, "%f %f %f %f %f %f\n", cor3[0][icor3], cor3[1][icor3],
|
|
cor3[2][icor3], r, g, b );
|
|
text_num = text_num + 1;
|
|
}
|
|
/*
|
|
Do the next face.
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
/*
|
|
Break the face up into triangles, anchored at node 1.
|
|
*/
|
|
for ( j = 0; j < face_order[iface] - 2; j++ ) {
|
|
|
|
face2[0] = face[ 0][iface] + 1;
|
|
face2[1] = face[j+1][iface] + 1;
|
|
face2[2] = face[j+2][iface] + 1;
|
|
|
|
fprintf ( fileout, "%d %d %d\n", face2[0], face2[1], face2[2] );
|
|
text_num = text_num + 1;
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "TEC_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*********************************************************************/
|
|
|
|
void tmat_init ( float a[4][4] )
|
|
|
|
/*********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TMAT_INIT initializes the geometric transformation matrix.
|
|
|
|
Definition:
|
|
|
|
The geometric transformation matrix can be thought of as a 4 by 4
|
|
matrix "A" having components:
|
|
|
|
r11 r12 r13 t1
|
|
r21 r22 r23 t2
|
|
r31 r32 r33 t3
|
|
0 0 0 1
|
|
|
|
This matrix encodes the rotations, scalings and translations that
|
|
are applied to graphical objects.
|
|
|
|
A point P = (x,y,z) is rewritten in "homogeneous coordinates" as
|
|
PH = (x,y,z,1). Then to apply the transformations encoded in A to
|
|
the point P, we simply compute A * PH.
|
|
|
|
Individual transformations, such as a scaling, can be represented
|
|
by simple versions of the transformation matrix. If the matrix
|
|
A represents the current set of transformations, and we wish to
|
|
apply a new transformation B, { the original points are
|
|
transformed twice: B * ( A * PH ). The new transformation B can
|
|
be combined with the original one A, to give a single matrix C that
|
|
encodes both transformations: C = B * A.
|
|
|
|
Modified:
|
|
|
|
19 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Reference:
|
|
|
|
Foley, van Dam, Feiner, Hughes,
|
|
Computer Graphics, Principles and Practice,
|
|
Addison Wesley, Second Edition, 1990.
|
|
|
|
Parameters:
|
|
|
|
Input, float A[4][4], the geometric transformation matrix.
|
|
*/
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
for ( j = 0; j < 4; j++ ) {
|
|
if ( i == j ) {
|
|
a[i][j] = 1.0;
|
|
}
|
|
else {
|
|
a[i][j] = 0.0;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
/*********************************************************************/
|
|
|
|
void tmat_mxm ( float a[4][4], float b[4][4], float c[4][4] )
|
|
|
|
/*********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TMAT_MXM multiplies two geometric transformation matrices.
|
|
|
|
Note:
|
|
|
|
The product is accumulated in a temporary array, and { assigned
|
|
to the result. Therefore, it is legal for any two, or all three,
|
|
of the arguments to share memory.
|
|
|
|
Modified:
|
|
|
|
19 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Reference:
|
|
|
|
Foley, van Dam, Feiner, Hughes,
|
|
Computer Graphics, Principles and Practice,
|
|
Addison Wesley, Second Edition, 1990.
|
|
|
|
Parameters:
|
|
|
|
Input, float A[4][4], the first geometric transformation matrix.
|
|
|
|
Input, float B[4][4], the second geometric transformation matrix.
|
|
|
|
Output, float C[4][4], the product A * B.
|
|
*/
|
|
{
|
|
float d[4][4];
|
|
int i;
|
|
int j;
|
|
int k;
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
for ( k = 0; k < 4; k++ ) {
|
|
d[i][k] = 0.0;
|
|
for ( j = 0; j < 4; j++ ) {
|
|
d[i][k] = d[i][k] + a[i][j] * b[j][k];
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
for ( j = 0; j < 4; j++ ) {
|
|
c[i][j] = d[i][j];
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
/*********************************************************************/
|
|
|
|
void tmat_mxp ( float a[4][4], float x[4], float y[4] )
|
|
|
|
/*********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TMAT_MXP multiplies a geometric transformation matrix times a point.
|
|
|
|
Modified:
|
|
|
|
19 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Reference:
|
|
|
|
Foley, van Dam, Feiner, Hughes,
|
|
Computer Graphics, Principles and Practice,
|
|
Addison Wesley, Second Edition, 1990.
|
|
|
|
Parameters:
|
|
|
|
Input, float A[4][4], the geometric transformation matrix.
|
|
|
|
Input, float X[4], the point to be multiplied. The fourth component
|
|
of X is implicitly assigned the value of 1.
|
|
|
|
Output, float Y[4], the result of A*X. The product is accumulated in
|
|
a temporary vector, and { assigned to the result. Therefore, it
|
|
is legal for X and Y to share memory.
|
|
*/
|
|
{
|
|
int i;
|
|
int j;
|
|
float z[4];
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
z[i] = a[i][3];
|
|
for ( j = 0; j < 3; j++ ) {
|
|
z[i] = z[i] + a[i][j] * x[j];
|
|
}
|
|
}
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
y[i] = z[i];
|
|
}
|
|
return;
|
|
}
|
|
/*********************************************************************/
|
|
|
|
void tmat_mxp2 ( float a[4][4], float x[][3], float y[][3], int n )
|
|
|
|
/*********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TMAT_MXP2 multiplies a geometric transformation matrix times N points.
|
|
|
|
Modified:
|
|
|
|
20 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Reference:
|
|
|
|
Foley, van Dam, Feiner, Hughes,
|
|
Computer Graphics, Principles and Practice,
|
|
Addison Wesley, Second Edition, 1990.
|
|
|
|
Parameters:
|
|
|
|
Input, float A[4][4], the geometric transformation matrix.
|
|
|
|
Input, float X[N][3], the points to be multiplied.
|
|
|
|
Output, float Y[N][3], the transformed points. Each product is
|
|
accumulated in a temporary vector, and { assigned to the
|
|
result. Therefore, it is legal for X and Y to share memory.
|
|
|
|
*/
|
|
{
|
|
int i;
|
|
int j;
|
|
int k;
|
|
float z[4];
|
|
|
|
for ( k = 0; k < n; k++ ) {
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
z[i] = a[i][3];
|
|
for ( j = 0; j < 3; j++ ) {
|
|
z[i] = z[i] + a[i][j] * x[k][j];
|
|
}
|
|
}
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
y[k][i] = z[i];
|
|
}
|
|
|
|
}
|
|
return;
|
|
}
|
|
/*********************************************************************/
|
|
|
|
void tmat_mxv ( float a[4][4], float x[4], float y[4] )
|
|
|
|
/*********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TMAT_MXV multiplies a geometric transformation matrix times a vector.
|
|
|
|
Modified:
|
|
|
|
12 August 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Reference:
|
|
|
|
Foley, van Dam, Feiner, Hughes,
|
|
Computer Graphics, Principles and Practice,
|
|
Addison Wesley, Second Edition, 1990.
|
|
|
|
Parameters:
|
|
|
|
Input, float A[4][4], the geometric transformation matrix.
|
|
|
|
Input, float X[3], the vector to be multiplied. The fourth component
|
|
of X is implicitly assigned the value of 1.
|
|
|
|
Output, float Y[3], the result of A*X. The product is accumulated in
|
|
a temporary vector, and assigned to the result. Therefore, it
|
|
is legal for X and Y to share memory.
|
|
*/
|
|
{
|
|
int i;
|
|
int j;
|
|
float z[4];
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
z[i] = 0.0;
|
|
for ( j = 0; j < 3; j++ ) {
|
|
z[i] = z[i] + a[i][j] * x[j];
|
|
}
|
|
z[i] = z[i] + a[i][3];
|
|
}
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
y[i] = z[i];
|
|
}
|
|
return;
|
|
}
|
|
/*********************************************************************/
|
|
|
|
void tmat_rot_axis ( float a[4][4], float b[4][4], float angle,
|
|
char axis )
|
|
|
|
/*********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TMAT_ROT_AXIS applies an axis rotation to the geometric transformation matrix.
|
|
|
|
Modified:
|
|
|
|
19 April 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Reference:
|
|
|
|
Foley, van Dam, Feiner, Hughes,
|
|
Computer Graphics, Principles and Practice,
|
|
Addison Wesley, Second Edition, 1990.
|
|
|
|
Parameters:
|
|
|
|
Input, float A[4][4], the current geometric transformation matrix.
|
|
|
|
Output, float B[4][4], the modified geometric transformation matrix.
|
|
A and B may share the same memory.
|
|
|
|
Input, float ANGLE, the angle, in degrees, of the rotation.
|
|
|
|
Input, character AXIS, is 'X', 'Y' or 'Z', specifying the coordinate
|
|
axis about which the rotation occurs.
|
|
*/
|
|
{
|
|
float c[4][4];
|
|
float d[4][4];
|
|
int i;
|
|
int j;
|
|
float theta;
|
|
|
|
theta = angle * DEG_TO_RAD;
|
|
|
|
tmat_init ( c );
|
|
|
|
if ( axis == 'X' || axis == 'x' ) {
|
|
c[1][1] = cos ( theta );
|
|
c[1][2] = - sin ( theta );
|
|
c[2][1] = sin ( theta );
|
|
c[2][2] = cos ( theta );
|
|
}
|
|
else if ( axis == 'Y' || axis == 'y' ) {
|
|
c[0][0] = cos ( theta );
|
|
c[0][2] = sin ( theta );
|
|
c[2][0] = - sin ( theta );
|
|
c[2][2] = cos ( theta );
|
|
}
|
|
else if ( axis == 'Z' || axis == 'z' ) {
|
|
c[0][0] = cos ( theta );
|
|
c[0][1] = - sin ( theta );
|
|
c[1][0] = sin ( theta );
|
|
c[1][1] = cos ( theta );
|
|
}
|
|
else {
|
|
printf ( "\n" );
|
|
printf ( "TMAT_ROT_AXIS - Fatal error!\n" );
|
|
printf ( " Illegal rotation axis: %c.\n", axis );
|
|
printf ( " Legal choices are 'X', 'Y', or 'Z'.\n" );
|
|
return;
|
|
}
|
|
|
|
tmat_mxm ( c, a, d );
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
for ( j = 0; j < 4; j++ ) {
|
|
b[i][j] = d[i][j];
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
/*********************************************************************/
|
|
|
|
void tmat_rot_vector ( float a[4][4], float b[4][4], float angle,
|
|
float v1, float v2, float v3 )
|
|
|
|
/*********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TMAT_ROT_VECTOR applies a rotation about a vector to the geometric transformation matrix.
|
|
|
|
Modified:
|
|
|
|
27 July 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Reference:
|
|
|
|
Foley, van Dam, Feiner, Hughes,
|
|
Computer Graphics, Principles and Practice,
|
|
Addison Wesley, Second Edition, 1990.
|
|
|
|
Parameters:
|
|
|
|
Input, float A[4][4], the current geometric transformation matrix.
|
|
|
|
Output, float B[4][4], the modified geometric transformation matrix.
|
|
A and B may share the same memory.
|
|
|
|
Input, float ANGLE, the angle, in degrees, of the rotation.
|
|
|
|
Input, float V1, V2, V3, the X, Y and Z coordinates of a (nonzero)
|
|
point defining a vector from the origin. The rotation will occur
|
|
about this axis.
|
|
*/
|
|
{
|
|
float c[4][4];
|
|
float ca;
|
|
float d[4][4];
|
|
int i;
|
|
int j;
|
|
float sa;
|
|
float theta;
|
|
|
|
if ( v1 * v1 + v2 * v2 + v3 * v3 == 0.0 ) {
|
|
return;
|
|
}
|
|
|
|
theta = angle * DEG_TO_RAD;
|
|
|
|
tmat_init ( c );
|
|
|
|
ca = cos ( theta );
|
|
sa = sin ( theta );
|
|
|
|
c[0][0] = v1 * v1 + ca * ( 1.0 - v1 * v1 );
|
|
c[0][1] = ( 1.0 - ca ) * v1 * v2 - sa * v3;
|
|
c[0][2] = ( 1.0 - ca ) * v1 * v3 + sa * v2;
|
|
|
|
c[1][0] = ( 1.0 - ca ) * v2 * v1 + sa * v3;
|
|
c[1][1] = v2 * v2 + ca * ( 1.0 - v2 * v2 );
|
|
c[1][2] = ( 1.0 - ca ) * v2 * v3 - sa * v1;
|
|
|
|
c[2][0] = ( 1.0 - ca ) * v3 * v1 - sa * v2;
|
|
c[2][1] = ( 1.0 - ca ) * v3 * v2 + sa * v1;
|
|
c[2][2] = v3 * v3 + ca * ( 1.0 - v3 * v3 );
|
|
|
|
tmat_mxm ( c, a, d );
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
for ( j = 0; j < 4; j++ ) {
|
|
b[i][j] = d[i][j];
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
/*********************************************************************/
|
|
|
|
void tmat_scale ( float a[4][4], float b[4][4], float sx, float sy,
|
|
float sz )
|
|
|
|
/*********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TMAT_SCALE applies a scaling to the geometric transformation matrix.
|
|
|
|
Modified:
|
|
|
|
19 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Reference:
|
|
|
|
Foley, van Dam, Feiner, Hughes,
|
|
Computer Graphics, Principles and Practice,
|
|
Addison Wesley, Second Edition, 1990.
|
|
|
|
Parameters:
|
|
|
|
Input, float A[4][4], the current geometric transformation matrix.
|
|
|
|
Output, float B[4][4], the modified geometric transformation matrix.
|
|
A and B may share the same memory.
|
|
|
|
Input, float SX, SY, SZ, the scalings to be applied to the X, Y and
|
|
Z coordinates.
|
|
*/
|
|
{
|
|
float c[4][4];
|
|
float d[4][4];
|
|
int i;
|
|
int j;
|
|
|
|
tmat_init ( c );
|
|
|
|
c[0][0] = sx;
|
|
c[1][1] = sy;
|
|
c[2][2] = sz;
|
|
|
|
tmat_mxm ( c, a, d );
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
for ( j = 0; j < 4; j++ ) {
|
|
b[i][j] = d[i][j];
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
/*********************************************************************/
|
|
|
|
void tmat_shear ( float a[4][4], float b[4][4], char *axis, float s )
|
|
|
|
/*********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TMAT_SHEAR applies a shear to the geometric transformation matrix.
|
|
|
|
Modified:
|
|
|
|
19 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Reference:
|
|
|
|
Foley, van Dam, Feiner, Hughes,
|
|
Computer Graphics, Principles and Practice,
|
|
Addison Wesley, Second Edition, 1990.
|
|
|
|
Parameters:
|
|
|
|
Input, float A[4][4], the current geometric transformation matrix.
|
|
|
|
Output, float B[4][4], the modified geometric transformation matrix.
|
|
A and B may share the same memory.
|
|
|
|
Input, character*3 AXIS, is 'XY', 'XZ', 'YX', 'YZ', 'ZX' or 'ZY',
|
|
specifying the shear equation:
|
|
|
|
XY: x' = x + s * y;
|
|
XZ: x' = x + s * z;
|
|
YX: y' = y + s * x;
|
|
YZ: y' = y + s * z;
|
|
ZX: z' = z + s * x;
|
|
ZY: z' = z + s * y.
|
|
|
|
Input, float S, the shear coefficient.
|
|
*/
|
|
{
|
|
float c[4][4];
|
|
float d[4][4];
|
|
int i;
|
|
int j;
|
|
|
|
tmat_init ( c );
|
|
|
|
if ( strcmp ( axis, "XY" ) == 0 || strcmp ( axis, "xy" ) == 0 ) {
|
|
c[0][1] = s;
|
|
}
|
|
else if ( strcmp ( axis, "XZ" ) == 0 || strcmp ( axis, "xz" ) == 0 ) {
|
|
c[0][2] = s;
|
|
}
|
|
else if ( strcmp ( axis, "YX" ) == 0 || strcmp ( axis, "yx" ) == 0 ) {
|
|
c[1][0] = s;
|
|
}
|
|
else if ( strcmp ( axis, "YZ" ) == 0 || strcmp ( axis, "yz" ) == 0 ) {
|
|
c[1][2] = s;
|
|
}
|
|
else if ( strcmp ( axis, "ZX" ) == 0 || strcmp ( axis, "zx" ) == 0 ) {
|
|
c[2][0] = s;
|
|
}
|
|
else if ( strcmp ( axis, "ZY" ) == 0 || strcmp ( axis, "zy" ) == 0 ) {
|
|
c[2][1] = s;
|
|
}
|
|
else {
|
|
printf ( "\n" );
|
|
printf ( "TMAT_SHEAR - Fatal error!\n" );
|
|
printf ( " Illegal shear axis: %s.\n", axis );
|
|
printf ( " Legal choices are XY, XZ, YX, YZ, ZX, or ZY.\n" );
|
|
return;
|
|
}
|
|
|
|
tmat_mxm ( c, a, d );
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
for ( j = 0; j < 4; j++ ) {
|
|
b[i][j] = d[i][j];
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
/*********************************************************************/
|
|
|
|
void tmat_trans ( float a[4][4], float b[4][4], float x, float y,
|
|
float z )
|
|
|
|
/*********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TMAT_TRANS applies a translation to the geometric transformation matrix.
|
|
|
|
Modified:
|
|
|
|
19 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Reference:
|
|
|
|
Foley, van Dam, Feiner, Hughes,
|
|
Computer Graphics, Principles and Practice,
|
|
Addison Wesley, Second Edition, 1990.
|
|
|
|
Parameters:
|
|
|
|
Input, float A[4][4], the current geometric transformation matrix.
|
|
|
|
Output, float B[4][4], the modified transformation matrix.
|
|
A and B may share the same memory.
|
|
|
|
Input, float X, Y, Z, the translation. This may be thought of as the
|
|
point that the origin moves to under the translation.
|
|
*/
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
for ( j = 0; j < 4; j++ ) {
|
|
b[i][j] = a[i][j];
|
|
}
|
|
}
|
|
b[0][3] = b[0][3] + x;
|
|
b[1][3] = b[1][3] + y;
|
|
b[2][3] = b[2][3] + z;
|
|
|
|
return;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int tria_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TRIA_READ reads an ASCII triangle file.
|
|
|
|
Example:
|
|
|
|
12 <-- Number of triangles
|
|
|
|
(x,y,z) and (nx,ny,nz) of normal vector at:
|
|
|
|
0.0 0.0 0.0 0.3 0.3 0.3 node 1 of triangle 1.
|
|
1.0 0.0 0.0 0.3 0.1 0.3 node 2 of triangle 1,
|
|
0.0 1.0 0.0 0.3 0.1 0.3 node 3 of triangle 1,
|
|
1.0 0.5 0.0 0.3 0.1 0.3 node 1 of triangle 2,
|
|
...
|
|
0.0 0.5 0.5 0.3 0.1 0.3 node 3 of triangle 12.
|
|
|
|
Modified:
|
|
|
|
22 June 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
float cvec[3];
|
|
int icor3;
|
|
int iface;
|
|
int iface_hi;
|
|
int iface_lo;
|
|
int ivert;
|
|
int face_num2;
|
|
float r1;
|
|
float r2;
|
|
float r3;
|
|
float r4;
|
|
float r5;
|
|
float r6;
|
|
/*
|
|
Get the number of triangles.
|
|
*/
|
|
fgets ( input, LINE_MAX_LEN, filein );
|
|
text_num = text_num + 1;
|
|
sscanf ( input, "%d", &face_num2 );
|
|
/*
|
|
For each triangle:
|
|
*/
|
|
iface_lo = face_num;
|
|
iface_hi = face_num + face_num2;
|
|
|
|
for ( iface = iface_lo; iface < iface_hi; iface++ ) {
|
|
|
|
if ( iface < FACE_MAX ) {
|
|
face_order[iface] = 3;
|
|
face_material[iface] = 0;
|
|
}
|
|
/*
|
|
For each face:
|
|
*/
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
|
|
fgets ( input, LINE_MAX_LEN, filein );
|
|
text_num = text_num + 1;
|
|
sscanf ( input, "%e %e %e %e %e %e", &r1, &r2, &r3, &r4, &r5, &r6 );
|
|
|
|
cvec[0] = r1;
|
|
cvec[1] = r2;
|
|
cvec[2] = r3;
|
|
|
|
if ( cor3_num < 1000 ) {
|
|
icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
|
|
}
|
|
else {
|
|
icor3 = -1;
|
|
}
|
|
|
|
if ( icor3 == -1 ) {
|
|
icor3 = cor3_num;
|
|
if ( cor3_num < COR3_MAX ) {
|
|
cor3[0][cor3_num] = cvec[0];
|
|
cor3[1][cor3_num] = cvec[1];
|
|
cor3[2][cor3_num] = cvec[2];
|
|
}
|
|
cor3_num = cor3_num + 1;
|
|
}
|
|
else {
|
|
dup_num = dup_num + 1;
|
|
}
|
|
|
|
if ( iface < FACE_MAX ) {
|
|
|
|
face[ivert][iface] = icor3;
|
|
vertex_material[ivert][iface] = 0;
|
|
vertex_normal[0][ivert][iface] = r4;
|
|
vertex_normal[1][ivert][iface] = r5;
|
|
vertex_normal[2][ivert][iface] = r6;
|
|
}
|
|
|
|
}
|
|
}
|
|
face_num = face_num + face_num2;
|
|
|
|
return SUCCESS;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
int tria_write ( FILE *fileout )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TRIA_WRITE writes the graphics data to an ASCII "triangle" file.
|
|
|
|
Discussion:
|
|
|
|
This is just a private format that Greg Hood requested from me.
|
|
|
|
Example:
|
|
|
|
12 <-- Number of triangles
|
|
|
|
(x,y,z) and (nx,ny,nz) of normal vector at:
|
|
|
|
0.0 0.0 0.0 0.3 0.3 0.3 node 1 of triangle 1.
|
|
1.0 0.0 0.0 0.3 0.1 0.3 node 2 of triangle 1,
|
|
0.0 1.0 0.0 0.3 0.1 0.3 node 3 of triangle 1,
|
|
1.0 0.5 0.0 0.3 0.1 0.3 node 1 of triangle 2,
|
|
...
|
|
0.0 0.5 0.5 0.3 0.1 0.3 node 3 of triangle 12.
|
|
|
|
Modified:
|
|
|
|
10 June 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int face2[3];
|
|
int icor3;
|
|
int iface;
|
|
int jlo;
|
|
int k;
|
|
int face_num2;
|
|
int text_num;
|
|
float nx;
|
|
float ny;
|
|
float nz;
|
|
float x;
|
|
float y;
|
|
float z;
|
|
|
|
text_num = 0;
|
|
/*
|
|
Determine the number of triangular faces.
|
|
*/
|
|
face_num2 = 0;
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( jlo = 0; jlo < face_order[iface] - 2; jlo ++ ) {
|
|
face_num2 = face_num2 + 1;
|
|
}
|
|
}
|
|
|
|
fprintf ( fileout, "%d\n", face_num2 );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Do the next face.
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
/*
|
|
Break the face up into triangles, anchored at node 1.
|
|
*/
|
|
for ( jlo = 0; jlo < face_order[iface] - 2; jlo ++ ) {
|
|
|
|
face2[0] = face[ 0][iface];
|
|
face2[1] = face[jlo+1][iface];
|
|
face2[2] = face[jlo+2][iface];
|
|
|
|
for ( k = 0; k < 3; k++ ) {
|
|
|
|
icor3 = face2[k];
|
|
|
|
x = cor3[0][icor3];
|
|
y = cor3[1][icor3];
|
|
z = cor3[2][icor3];
|
|
|
|
nx = cor3_normal[0][icor3];
|
|
ny = cor3_normal[1][icor3];
|
|
nz = cor3_normal[2][icor3];
|
|
|
|
fprintf ( fileout, "%f %f %f %f %f %f\n", x, y, z, nx, ny, nz );
|
|
|
|
text_num = text_num + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "TRIA_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int trib_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TRIB_READ reads a binary triangle file.
|
|
|
|
Example:
|
|
|
|
4 byte int = number of triangles
|
|
|
|
For each triangular face:
|
|
|
|
3 4-byte floats = coordinates of first node;
|
|
3 4-byte floats = components of normal vector at first node;
|
|
3 4-byte floats = coordinates of second node;
|
|
3 4-byte floats = components of normal vector at second node;
|
|
3 4-byte floats = coordinates of third node;
|
|
3 4-byte floats = components of normal vector at third node.
|
|
|
|
Modified:
|
|
|
|
22 June 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
float cvec[3];
|
|
int icor3;
|
|
int i;
|
|
int iface;
|
|
int iface_hi;
|
|
int iface_lo;
|
|
int ivert;
|
|
int face_num2;
|
|
/*
|
|
Read the number of triangles in the file.
|
|
*/
|
|
face_num2 = long_int_read ( filein );
|
|
bytes_num = bytes_num + 4;
|
|
/*
|
|
For each (triangular) face,
|
|
read the coordinates and normal vectors of three vertices,
|
|
*/
|
|
iface_lo = face_num;
|
|
iface_hi = face_num + face_num2;
|
|
|
|
for ( iface = iface_lo; iface < iface_hi; iface++ ) {
|
|
|
|
if ( iface < FACE_MAX ) {
|
|
face_order[iface] = 3;
|
|
face_material[iface] = 0;
|
|
}
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
cvec[i] = float_read ( filein );
|
|
bytes_num = bytes_num + 4;
|
|
}
|
|
|
|
if ( cor3_num < 1000 ) {
|
|
icor3 = rcol_find ( cor3, 3, cor3_num, cvec );
|
|
}
|
|
else {
|
|
icor3 = -1;
|
|
}
|
|
|
|
if ( icor3 == -1 ) {
|
|
icor3 = cor3_num;
|
|
if ( cor3_num < COR3_MAX ) {
|
|
cor3[0][cor3_num] = cvec[0];
|
|
cor3[1][cor3_num] = cvec[1];
|
|
cor3[2][cor3_num] = cvec[2];
|
|
}
|
|
cor3_num = cor3_num + 1;
|
|
}
|
|
else {
|
|
dup_num = dup_num + 1;
|
|
}
|
|
|
|
if ( iface < FACE_MAX ) {
|
|
|
|
face[ivert][iface] = icor3;
|
|
vertex_material[ivert][iface] = 0;
|
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
vertex_normal[i][ivert][iface] = float_read ( filein );
|
|
bytes_num = bytes_num + 4;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
face_num = face_num + face_num2;
|
|
|
|
return SUCCESS;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
int trib_write ( FILE *fileout )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TRIB_WRITE writes the graphics data to a binary "triangle" file.
|
|
|
|
Discussion:
|
|
|
|
This is just a private format that Greg Hood requested from me.
|
|
|
|
Example:
|
|
|
|
12 Number of triangles
|
|
0.0 x at node 1, triangle 1,
|
|
0.0 y at node 1, triangle 1,
|
|
0.0 z at node 1, triangle 1,
|
|
0.3 nx at node 1, triangle 1,
|
|
0.3 ny at node 1, triangle 1,
|
|
0.3 nz at node 1, triangle 1.
|
|
1.0 x at node 2, triangle 1,
|
|
...
|
|
0.7 nz at node 3, triangle 1.
|
|
1.2 x at node 1, triangle 2,
|
|
...
|
|
0.3 nz at node 3, triangle 2.
|
|
9.3 x at node 1, triangle 3,
|
|
...
|
|
0.3 nz at node 3, triangle 12.
|
|
|
|
Modified:
|
|
|
|
16 June 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int face2[3];
|
|
int icor3;
|
|
int iface;
|
|
int jlo;
|
|
int k;
|
|
int face_num2;
|
|
float nx;
|
|
float ny;
|
|
float nz;
|
|
float x;
|
|
float y;
|
|
float z;
|
|
|
|
bytes_num = 0;
|
|
/*
|
|
Determine the number of triangular faces.
|
|
*/
|
|
face_num2 = 0;
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( jlo = 0; jlo < face_order[iface] - 2; jlo ++ ) {
|
|
face_num2 = face_num2 + 1;
|
|
}
|
|
}
|
|
|
|
bytes_num = bytes_num + long_int_write ( fileout, face_num2 );
|
|
/*
|
|
Do the next face.
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
/*
|
|
Break the face up into triangles, anchored at node 1.
|
|
*/
|
|
for ( jlo = 0; jlo < face_order[iface] - 2; jlo ++ ) {
|
|
|
|
face2[0] = face[ 0][iface];
|
|
face2[1] = face[jlo+1][iface];
|
|
face2[2] = face[jlo+2][iface];
|
|
|
|
for ( k = 0; k < 3; k++ ) {
|
|
|
|
icor3 = face2[k];
|
|
|
|
x = cor3[0][icor3];
|
|
y = cor3[1][icor3];
|
|
z = cor3[2][icor3];
|
|
|
|
nx = cor3_normal[0][icor3];
|
|
ny = cor3_normal[1][icor3];
|
|
nz = cor3_normal[2][icor3];
|
|
|
|
bytes_num = bytes_num + float_write ( fileout, x );
|
|
bytes_num = bytes_num + float_write ( fileout, y );
|
|
bytes_num = bytes_num + float_write ( fileout, z );
|
|
bytes_num = bytes_num + float_write ( fileout, nx );
|
|
bytes_num = bytes_num + float_write ( fileout, ny );
|
|
bytes_num = bytes_num + float_write ( fileout, nz );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "TRIB_WRITE - Wrote %d bytes.\n", bytes_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int txt_write ( FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
TXT_WRITE writes the graphics data to a text file.
|
|
|
|
Modified:
|
|
|
|
25 June 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int iface;
|
|
int iline;
|
|
int imat;
|
|
int ivert;
|
|
int nitem;
|
|
int text_num;
|
|
|
|
text_num = 0;
|
|
|
|
fprintf ( fileout, "%s created by IVCON.\n", fileout_name );
|
|
fprintf ( fileout, "Original data in %s.\n", filein_name );
|
|
fprintf ( fileout, "Object name is %s.\n", object_name );
|
|
fprintf ( fileout, "Object origin at %f %f %f.\n", origin[0], origin[1],
|
|
origin[2] );
|
|
fprintf ( fileout, "Object pivot at %f %f %f.\n", pivot[0], pivot[1],
|
|
pivot[2] );
|
|
text_num = text_num + 5;
|
|
/*
|
|
TRANSFORMATION MATRIX.
|
|
*/
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "Transformation matrix:\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
fprintf ( fileout, " %f %f %f %f\n", transform_matrix[i][0],
|
|
transform_matrix[i][1], transform_matrix[i][2], transform_matrix[i][3] );
|
|
text_num = text_num + 1;
|
|
}
|
|
/*
|
|
NODES.
|
|
*/
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " %d nodes.\n", cor3_num );
|
|
text_num = text_num + 2;
|
|
|
|
if ( cor3_num > 0 ) {
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " Node coordinate data:\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( i = 0; i < cor3_num; i++ ) {
|
|
fprintf ( fileout, " %d %f %f %f\n ", i, cor3[0][i], cor3[1][i],
|
|
cor3[2][i] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " Node normal vectors:\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( i = 0; i < cor3_num; i++ ) {
|
|
fprintf ( fileout, " %d %f %f %f\n ", i, cor3_normal[0][i],
|
|
cor3_normal[1][i], cor3_normal[2][i] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " Node materials:\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( i = 0; i < cor3_num; i++ ) {
|
|
fprintf ( fileout, " %d %d\n ", i, cor3_material[i] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
if ( texture_num > 0 ) {
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " Node texture coordinates:\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( i = 0; i < cor3_num; i++ ) {
|
|
fprintf ( fileout, " %d %f %f\n ", i, cor3_tex_uv[0][i],
|
|
cor3_tex_uv[1][i] );
|
|
text_num = text_num + 1;
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
LINES.
|
|
*/
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " %d line data items.\n", line_num );
|
|
text_num = text_num + 2;
|
|
|
|
if ( line_num > 0 ) {
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " Line index data:\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
nitem = 0;
|
|
|
|
for ( iline = 0; iline < line_num; iline++ ) {
|
|
|
|
fprintf ( fileout, " %d", line_dex[iline] );
|
|
nitem = nitem + 1;
|
|
|
|
if ( iline == line_num - 1 || line_dex[iline] == -1 || nitem >= 10 ) {
|
|
nitem = 0;
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
}
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " Line materials:\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
nitem = 0;
|
|
|
|
for ( iline = 0; iline < line_num; iline++ ) {
|
|
|
|
fprintf ( fileout, " %d", line_material[iline] );
|
|
nitem = nitem + 1;
|
|
|
|
if ( iline == line_num - 1 || line_material[iline] == -1 || nitem >= 10 ) {
|
|
nitem = 0;
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
}
|
|
|
|
}
|
|
/*
|
|
COLOR DATA
|
|
*/
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " %d colors.\n", color_num );
|
|
text_num = text_num + 2;
|
|
/*
|
|
FACES.
|
|
*/
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " %d faces.\n", face_num );
|
|
text_num = text_num + 2;
|
|
|
|
if ( face_num > 0 ) {
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " Face, Material, Number of vertices, Smoothing, Flags:\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
fprintf ( fileout, " %d %d %d %d %d\n", iface, face_material[iface],
|
|
face_order[iface], face_smooth[iface], face_flags[iface] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " Face, Vertices\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
fprintf ( fileout, "%d ", iface );
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
fprintf ( fileout, " %d", face[ivert][iface] );
|
|
}
|
|
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " Face normal vectors:\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
fprintf ( fileout, " %d %f %f %f\n", iface, face_normal[0][iface],
|
|
face_normal[1][iface], face_normal[2][iface] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
if ( texture_num > 0 ) {
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " Face texture coordinates:\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
fprintf ( fileout, " %d %f %f\n", iface, face_tex_uv[0][iface],
|
|
face_tex_uv[1][iface] );
|
|
text_num = text_num + 1;
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
VERTICES.
|
|
*/
|
|
if ( face_num > 0 ) {
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "Vertex normal vectors:\n" );
|
|
text_num = text_num + 2;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
fprintf ( fileout, " %d %d %f %f %f\n", iface, ivert,
|
|
vertex_normal[0][ivert][iface], vertex_normal[1][ivert][iface],
|
|
vertex_normal[2][ivert][iface] );
|
|
text_num = text_num + 1;
|
|
}
|
|
}
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "Vertex materials:\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
fprintf ( fileout, "%d", iface );
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
fprintf ( fileout, " %d", vertex_material[ivert][iface] );
|
|
}
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
if ( texture_num > 0 ) {
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "Vertex UV texture coordinates:\n" );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
fprintf ( fileout, "%d %d %f %f\n", iface, ivert,
|
|
vertex_tex_uv[0][ivert][iface], vertex_tex_uv[1][ivert][iface] );
|
|
text_num = text_num + 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
MATERIALS.
|
|
*/
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "%d materials.\n", material_num );
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "Index Name R G B A\n" );
|
|
fprintf ( fileout, "\n" );
|
|
|
|
text_num = text_num + 5;
|
|
|
|
for ( imat = 0; imat < material_num; imat++ ) {
|
|
fprintf ( fileout, "%d %s %f %f %f %f\n", imat, material_name[imat],
|
|
material_rgba[0][imat], material_rgba[1][imat], material_rgba[2][imat],
|
|
material_rgba[3][imat] );
|
|
text_num = text_num + 1;
|
|
}
|
|
/*
|
|
TEXTURES.
|
|
*/
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "%d textures.\n", texture_num );
|
|
text_num = text_num + 2;
|
|
|
|
if ( texture_num > 0 ) {
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "Index Name\n" );
|
|
fprintf ( fileout, "\n" );
|
|
for ( i = 0; i < texture_num; i++ ) {
|
|
fprintf ( fileout, "%d %s\n", i, texture_name[i] );
|
|
}
|
|
text_num = text_num + 3;
|
|
}
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "TXT_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
int ucd_write ( FILE *fileout )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
UCD_WRITE writes graphics data to an AVS UCD file.
|
|
|
|
Examples:
|
|
|
|
# cube.ucd created by IVREAD.
|
|
#
|
|
# Material RGB to hue map:
|
|
#
|
|
# material R G B Alpha Hue
|
|
#
|
|
# 0 0.94 0.70 0.15 1.000 0.116
|
|
# 1 0.24 0.70 0.85 1.000 0.541
|
|
# 2 0.24 0.00 0.85 1.000 0.666
|
|
#
|
|
# The node data is
|
|
# node # / material # / RGBA / Hue
|
|
#
|
|
8 6 6 0 0
|
|
0 0.0 0.0 0.0
|
|
1 1.0 0.0 0.0
|
|
2 1.0 1.0 0.0
|
|
3 0.0 1.0 0.0
|
|
4 0.0 0.0 1.0
|
|
5 1.0 0.0 1.0
|
|
6 1.0 1.0 1.0
|
|
7 0.0 1.0 1.0
|
|
0 0 quad 0 1 2 3
|
|
1 0 quad 0 4 5 1
|
|
2 0 quad 1 5 6 2
|
|
3 0 quad 2 6 7 3
|
|
4 0 quad 3 7 4 0
|
|
5 0 quad 4 7 6 5
|
|
3 1 4 1
|
|
material, 0...2
|
|
RGBA, 0-1/0-1/0-1/0-1
|
|
Hue, 0-1
|
|
0 0 0.94 0.70 0.15 1.0 0.116
|
|
1 0 0.94 0.70 0.15 1.0 0.116
|
|
2 0 0.94 0.70 0.15 1.0 0.116
|
|
3 0 0.94 0.70 0.15 1.0 0.116
|
|
4 1 0.24 0.70 0.85 1.0 0.541
|
|
5 1 0.24 0.70 0.85 1.0 0.541
|
|
6 2 0.24 0.24 0.85 0.0 0.666
|
|
7 2 0.24 0.24 0.85 0.0 0.666
|
|
|
|
Modified:
|
|
|
|
22 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
*/
|
|
{
|
|
float a;
|
|
float b;
|
|
float g;
|
|
float h;
|
|
int i;
|
|
int imat;
|
|
int j;
|
|
int text_num;
|
|
float r;
|
|
|
|
text_num = 0;
|
|
|
|
fprintf ( fileout, "# %s created by IVREAD.\n", fileout_name );
|
|
fprintf ( fileout, "#\n" );
|
|
fprintf ( fileout, "# Material RGB to Hue map:\n" );
|
|
fprintf ( fileout, "#\n" );
|
|
fprintf ( fileout, "# material R G B Alpha Hue\n" );
|
|
fprintf ( fileout, "#\n" );
|
|
|
|
text_num = text_num + 6;
|
|
|
|
for ( j = 0; j < material_num; j++ ) {
|
|
r = material_rgba[0][j];
|
|
g = material_rgba[1][j];
|
|
b = material_rgba[2][j];
|
|
a = material_rgba[3][j];
|
|
h = rgb_to_hue ( r, g, b );
|
|
fprintf ( fileout, "# %d %f %f %f %f %f\n", j, r, g, b, a, h );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, "#\n" );
|
|
fprintf ( fileout, "# The node data is\n" );
|
|
fprintf ( fileout, "# node # / material # / RGBA / Hue\n" );
|
|
fprintf ( fileout, "#\n" );
|
|
text_num = text_num + 4;
|
|
|
|
fprintf ( fileout, "%d %d 6 0 0\n", cor3_num, face_num );
|
|
text_num = text_num + 1;
|
|
|
|
for ( j = 0; j < cor3_num; j++ ) {
|
|
fprintf ( fileout, "%d %f %f %f\n", j, cor3[0][j], cor3[1][j],
|
|
cor3[2][j] );
|
|
text_num = text_num + 1;
|
|
}
|
|
/*
|
|
NOTE:
|
|
UCD only accepts triangles and quadrilaterals, not higher order
|
|
polygons. We would need to break polygons up to proceed.
|
|
*/
|
|
for ( j = 0; j < face_num; j++ ) {
|
|
|
|
fprintf ( fileout, "%d %d", j, face_material[j] );
|
|
|
|
if ( face_order[j] == 3 ) {
|
|
fprintf ( fileout, " tri" );
|
|
}
|
|
else if ( face_order[j] == 4 ) {
|
|
fprintf ( fileout, " quad" );
|
|
}
|
|
else {
|
|
fprintf ( fileout, " ???" );
|
|
}
|
|
|
|
for ( i = 0; i < face_order[j]; i++ ) {
|
|
fprintf ( fileout, "%d", face[i][j] );
|
|
}
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
|
|
}
|
|
|
|
fprintf ( fileout, "3 1 4 1\n" );
|
|
fprintf ( fileout, "material, 0...%d\n", material_num - 1 );
|
|
fprintf ( fileout, "RGBA, 0-1/0-1/0-1/0-1\n" );
|
|
fprintf ( fileout, "Hue, 0-1\n" );
|
|
text_num = text_num + 4;
|
|
|
|
for ( j = 0; j < cor3_num; j++ ) {
|
|
imat = cor3_material[j];
|
|
r = material_rgba[0][imat];
|
|
g = material_rgba[1][imat];
|
|
b = material_rgba[2][imat];
|
|
a = material_rgba[3][imat];
|
|
h = rgb_to_hue ( r, g, b );
|
|
|
|
fprintf ( fileout, "%d %d %f %f %f %f %f\n", j, imat, r, g, b, a, h );
|
|
text_num = text_num + 1;
|
|
}
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "UCD_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
void vertex_normal_set ( void )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
VERTEX_NORMAL_SET recomputes the face vertex normal vectors.
|
|
|
|
Modified:
|
|
|
|
12 October 1998
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int i0;
|
|
int i1;
|
|
int i2;
|
|
int iface;
|
|
int ivert;
|
|
int jp1;
|
|
int jp2;
|
|
int nfix;
|
|
float norm;
|
|
float temp;
|
|
float x0;
|
|
float x1;
|
|
float x2;
|
|
float xc;
|
|
float y0;
|
|
float y1;
|
|
float y2;
|
|
float yc;
|
|
float z0;
|
|
float z1;
|
|
float z2;
|
|
float zc;
|
|
|
|
if ( face_num <= 0 ) {
|
|
return;
|
|
}
|
|
|
|
nfix = 0;
|
|
/*
|
|
Consider each face.
|
|
*/
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
|
|
norm = 0.0;
|
|
for ( i = 0; i < 3; i++ ) {
|
|
temp = vertex_normal[i][ivert][iface];
|
|
norm = norm + temp * temp;
|
|
}
|
|
norm = ( float ) sqrt ( norm );
|
|
|
|
if ( norm == 0.0 ) {
|
|
|
|
nfix = nfix + 1;
|
|
|
|
i0 = face[ivert][iface];
|
|
x0 = cor3[0][i0];
|
|
y0 = cor3[1][i0];
|
|
z0 = cor3[2][i0];
|
|
|
|
jp1 = ivert + 1;
|
|
if ( jp1 >= face_order[iface] ) {
|
|
jp1 = jp1 - face_order[iface];
|
|
}
|
|
i1 = face[jp1][iface];
|
|
x1 = cor3[0][i1];
|
|
y1 = cor3[1][i1];
|
|
z1 = cor3[2][i1];
|
|
|
|
jp2 = ivert + 2;
|
|
if ( jp2 >= face_order[iface] ) {
|
|
jp2 = jp2 - face_order[iface];
|
|
}
|
|
i2 = face[jp2][iface];
|
|
x2 = cor3[0][i2];
|
|
y2 = cor3[1][i2];
|
|
z2 = cor3[2][i2];
|
|
|
|
xc = ( y1 - y0 ) * ( z2 - z0 ) - ( z1 - z0 ) * ( y2 - y0 );
|
|
yc = ( z1 - z0 ) * ( x2 - x0 ) - ( x1 - x0 ) * ( z2 - z0 );
|
|
zc = ( x1 - x0 ) * ( y2 - y0 ) - ( y1 - y0 ) * ( x2 - x0 );
|
|
|
|
norm = ( float ) sqrt ( xc * xc + yc * yc + zc * zc );
|
|
|
|
if ( norm == 0.0 ) {
|
|
xc = ( float ) 1.0 / sqrt ( 3.0 );
|
|
yc = ( float ) 1.0 / sqrt ( 3.0 );
|
|
zc = ( float ) 1.0 / sqrt ( 3.0 );
|
|
}
|
|
else {
|
|
xc = xc / norm;
|
|
yc = yc / norm;
|
|
zc = zc / norm;
|
|
}
|
|
|
|
vertex_normal[0][ivert][iface] = xc;
|
|
vertex_normal[1][ivert][iface] = yc;
|
|
vertex_normal[2][ivert][iface] = zc;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( nfix > 0 ) {
|
|
printf ( "\n" );
|
|
printf ( "VERTEX_NORMAL_SET: Recomputed %d face vertex normals.\n", nfix );
|
|
}
|
|
|
|
return;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
void vertex_to_face_material ( void )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
VERTEX_TO_FACE_MATERIAL extends vertex material definitions to faces.
|
|
|
|
Discussion:
|
|
|
|
Assuming material indices are defined for all the vertices, this
|
|
routine assigns to each face the material associated with its
|
|
first vertex.
|
|
|
|
Modified:
|
|
|
|
22 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int iface;
|
|
int ivert;
|
|
|
|
ivert = 0;
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
face_material[iface] = vertex_material[ivert][iface];
|
|
}
|
|
|
|
return;
|
|
}
|
|
/**********************************************************************/
|
|
|
|
void vertex_to_node_material ( void )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
VERTEX_TO_NODE_MATERIAL extends vertex material definitions to nodes.
|
|
|
|
Discussion:
|
|
|
|
A NODE is a point in space.
|
|
A VERTEX is a node as used in a particular face.
|
|
One node may be used as a vertex in several faces, or none.
|
|
This routine simply runs through all the vertices, and assigns
|
|
the material of the vertex to the corresponding node. If a
|
|
node appears as a vertex several times, then the node will
|
|
end up having the material of the vertex that occurs "last".
|
|
|
|
Modified:
|
|
|
|
22 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int iface;
|
|
int ivert;
|
|
int node;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
node = face[ivert][iface];
|
|
cor3_material[node] = vertex_material[ivert][iface];
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
int vla_read ( FILE *filein )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
VLA_READ reads a VLA file.
|
|
|
|
Examples:
|
|
|
|
set comment cube.vla created by IVREAD
|
|
set comment Original data in cube.iv.
|
|
set comment
|
|
set intensity EXPLICIT
|
|
set parametric NON_PARAMETRIC
|
|
set filecontent LINES
|
|
set filetype NEW
|
|
set depthcue 0
|
|
set defaultdraw stellar
|
|
set coordsys RIGHT
|
|
set author IVREAD
|
|
set site Buhl Planetarium
|
|
set library_id UNKNOWN
|
|
P 8.59816 5.55317 -3.05561 1.00000
|
|
L 8.59816 2.49756 0.000000E+00 1.00000
|
|
L 8.59816 2.49756 -3.05561 1.00000
|
|
L 8.59816 5.55317 -3.05561 1.00000
|
|
P 8.59816 5.55317 0.000000E+00 1.00000
|
|
...etc...
|
|
L 2.48695 2.49756 -3.05561 1.00000
|
|
|
|
Modified:
|
|
|
|
23 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int i;
|
|
int icor3;
|
|
int dup_num;
|
|
char *next;
|
|
int text_num;
|
|
float r1;
|
|
float r2;
|
|
float r3;
|
|
float temp[3];
|
|
char token[LINE_MAX_LEN];
|
|
int width;
|
|
/*
|
|
Initialize.
|
|
*/
|
|
dup_num = 0;
|
|
text_num = 0;
|
|
/*
|
|
Read the next line of the file into INPUT.
|
|
*/
|
|
while ( fgets ( input, LINE_MAX_LEN, filein ) != NULL ) {
|
|
|
|
text_num = text_num + 1;
|
|
/*
|
|
Advance to the first nonspace character in INPUT.
|
|
*/
|
|
for ( next = input; *next != '\0' && isspace(*next); next++ ) {
|
|
}
|
|
/*
|
|
Skip blank lines and comments.
|
|
*/
|
|
if ( *next == '\0' || *next == ';' ) {
|
|
continue;
|
|
}
|
|
/*
|
|
Extract the first word in this line.
|
|
*/
|
|
sscanf ( next, "%s%n", token, &width );
|
|
/*
|
|
Set NEXT to point to just after this token.
|
|
*/
|
|
next = next + width;
|
|
/*
|
|
SET (ignore)
|
|
*/
|
|
if ( leqi ( token, "set" ) == TRUE ) {
|
|
}
|
|
/*
|
|
P (begin a line)
|
|
L (continue a line)
|
|
*/
|
|
else if ( leqi ( token, "P" ) == TRUE || leqi ( token, "L") == TRUE ) {
|
|
|
|
if ( leqi ( token, "P" ) == TRUE ) {
|
|
if ( line_num > 0 ) {
|
|
if ( line_num < LINES_MAX ) {
|
|
line_dex[line_num] = -1;
|
|
line_material[line_num] = -1;
|
|
line_num = line_num + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
sscanf ( next, "%e %e %e", &r1, &r2, &r3 );
|
|
|
|
temp[0] = r1;
|
|
temp[1] = r2;
|
|
temp[2] = r3;
|
|
|
|
if ( cor3_num < 1000 ) {
|
|
icor3 = rcol_find ( cor3, 3, cor3_num, temp );
|
|
}
|
|
else {
|
|
icor3 = -1;
|
|
}
|
|
|
|
if ( icor3 == -1 ) {
|
|
|
|
icor3 = cor3_num;
|
|
|
|
if ( cor3_num < COR3_MAX ) {
|
|
for ( i = 0; i < 3; i++ ) {
|
|
cor3[i][cor3_num] = temp[i];
|
|
}
|
|
}
|
|
cor3_num = cor3_num + 1;
|
|
}
|
|
else {
|
|
dup_num = dup_num + 1;
|
|
}
|
|
|
|
if ( line_num < LINES_MAX ) {
|
|
line_dex[line_num] = icor3;
|
|
line_material[line_num] = 0;
|
|
line_num = line_num + 1;
|
|
}
|
|
}
|
|
/*
|
|
Unexpected or unrecognized.
|
|
*/
|
|
else {
|
|
printf ( "\n" );
|
|
printf ( "VLA_READ - Fatal error!\n" );
|
|
printf ( " Unrecognized first word on line.\n" );
|
|
return ERROR;
|
|
}
|
|
|
|
}
|
|
|
|
if ( line_num > 0 ) {
|
|
if ( line_num < LINES_MAX ) {
|
|
line_dex[line_num] = -1;
|
|
line_material[line_num] = -1;
|
|
line_num = line_num + 1;
|
|
}
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int vla_write ( FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
VLA_WRITE writes internal graphics information to a VLA file.
|
|
|
|
Discussion:
|
|
|
|
Comments begin with a semicolon in column 1.
|
|
The X, Y, Z coordinates of points begin with a "P" to
|
|
denote the beginning of a line, and "L" to denote the
|
|
continuation of a line. The fourth entry is intensity, which
|
|
should be between 0.0 and 1.0.
|
|
|
|
Examples:
|
|
|
|
set comment cube.vla created by IVREAD
|
|
set comment Original data in cube.iv.
|
|
set comment
|
|
set intensity EXPLICIT
|
|
set parametric NON_PARAMETRIC
|
|
set filecontent LINES
|
|
set filetype NEW
|
|
set depthcue 0
|
|
set defaultdraw stellar
|
|
set coordsys RIGHT
|
|
set author IVREAD
|
|
set site Buhl Planetarium
|
|
set library_id UNKNOWN
|
|
P 8.59816 5.55317 -3.05561 1.00000
|
|
L 8.59816 2.49756 0.000000E+00 1.00000
|
|
L 8.59816 2.49756 -3.05561 1.00000
|
|
L 8.59816 5.55317 -3.05561 1.00000
|
|
P 8.59816 5.55317 0.000000E+00 1.00000
|
|
...etc...
|
|
L 2.48695 2.49756 -3.05561 1.00000
|
|
|
|
Modified:
|
|
|
|
22 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
char c;
|
|
int iline;
|
|
float intense = 1.0;
|
|
int k;
|
|
int text_num;
|
|
/*
|
|
Initialize.
|
|
*/
|
|
text_num = 0;
|
|
|
|
fprintf ( fileout, "set comment %s created by IVCON.\n", fileout_name );
|
|
fprintf ( fileout, "set comment Original data in %s.\n", filein_name );
|
|
fprintf ( fileout, "set comment\n" );
|
|
fprintf ( fileout, "set intensity EXPLICIT\n" );
|
|
fprintf ( fileout, "set parametric NON_PARAMETRIC\n" );
|
|
fprintf ( fileout, "set filecontent LINES\n" );
|
|
fprintf ( fileout, "set filetype NEW\n" );
|
|
fprintf ( fileout, "set depthcue 0\n" );
|
|
fprintf ( fileout, "set defaultdraw stellar\n" );
|
|
fprintf ( fileout, "set coordsys RIGHT\n" );
|
|
fprintf ( fileout, "set author IVCON\n" );
|
|
fprintf ( fileout, "set site Buhl Planetarium\n" );
|
|
fprintf ( fileout, "set library_id UNKNOWN\n" );
|
|
|
|
text_num = text_num + 13;
|
|
|
|
c = 'P';
|
|
|
|
for ( iline = 0; iline < line_num; iline++ ) {
|
|
|
|
k = line_dex[iline];
|
|
|
|
if ( k == -1 ) {
|
|
|
|
c = 'P';
|
|
}
|
|
else {
|
|
|
|
fprintf ( fileout, "%c %f %f %f %f\n",
|
|
c, cor3[0][k], cor3[1][k], cor3[2][k], intense );
|
|
|
|
text_num = text_num + 1;
|
|
|
|
c = 'L';
|
|
}
|
|
}
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "VLA_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
|
|
int wrl_write ( FILE *fileout )
|
|
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
WRL_WRITE writes graphics data to a WRL file.
|
|
|
|
Example:
|
|
|
|
#VRML V2.0 utf8
|
|
|
|
WorldInfo {
|
|
title "cube.iv."
|
|
string "WRL file generated by IVREAD.
|
|
}
|
|
|
|
Group {
|
|
children [
|
|
|
|
Shape {
|
|
|
|
appearance Appearance {
|
|
material Material {
|
|
diffuseColor 0.0 0.0 0.0
|
|
emissiveColor 0.0 0.0 0.0
|
|
shininess 1.0
|
|
}
|
|
} #end of appearance
|
|
|
|
geometry IndexedLineSet {
|
|
|
|
coord Coordinate {
|
|
point [
|
|
8.59816 5.55317 -3.05561
|
|
8.59816 2.49756 0.000000E+00
|
|
...etc...
|
|
2.48695 2.49756 -3.05561
|
|
]
|
|
}
|
|
|
|
coordIndex [
|
|
0 1 2 -1 3 4 5 6 7 8 -
|
|
9 10 -1 11 12 -1 13 14 15 -1 1
|
|
...etc...
|
|
191 -1
|
|
]
|
|
|
|
colorPerVertex TRUE
|
|
|
|
colorIndex [
|
|
0 0 0 -1 2 3 1 1 4 7 -
|
|
10 9 -1 7 7 -1 3 2 2 -1 1
|
|
...etc...
|
|
180 -1
|
|
]
|
|
|
|
} #end of geometry
|
|
|
|
} #end of Shape
|
|
|
|
] #end of children
|
|
|
|
} #end of Group
|
|
|
|
Modified:
|
|
|
|
23 May 1999
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int icor3;
|
|
int iface;
|
|
int itemp;
|
|
int ivert;
|
|
int j;
|
|
int length;
|
|
int ndx;
|
|
|
|
text_num = 0;
|
|
|
|
fprintf ( fileout, "#VRML V2.0 utf8\n" );
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " WorldInfo {\n" );
|
|
fprintf ( fileout, " title \"%s\"\n", fileout_name );
|
|
fprintf ( fileout, " info \"WRL file generated by IVREAD.\"\n" );
|
|
fprintf ( fileout, " info \"Original data in %s\"\n", filein_name );
|
|
fprintf ( fileout, " }\n" );
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " Group {\n" );
|
|
fprintf ( fileout, " children [\n" );
|
|
fprintf ( fileout, " Shape {\n" );
|
|
fprintf ( fileout, " appearance Appearance {\n" );
|
|
fprintf ( fileout, " material Material {\n" );
|
|
fprintf ( fileout, " diffuseColor 0.0 0.0 0.0\n" );
|
|
fprintf ( fileout, " emissiveColor 0.0 0.0 0.0\n" );
|
|
fprintf ( fileout, " shininess 1.0\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
|
|
text_num = text_num + 18;
|
|
/*
|
|
IndexedLineSet
|
|
*/
|
|
if ( line_num > 0 ) {
|
|
|
|
fprintf ( fileout, " geometry IndexedLineSet {\n" );
|
|
/*
|
|
IndexedLineSet coord
|
|
*/
|
|
fprintf ( fileout, " coord Coordinate {\n" );
|
|
fprintf ( fileout, " point [\n" );
|
|
|
|
text_num = text_num + 3;
|
|
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
fprintf ( fileout, " %f %f %f\n", cor3[0][icor3],
|
|
cor3[1][icor3], cor3[2][icor3] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 2;
|
|
/*
|
|
IndexedLineSet coordIndex.
|
|
*/
|
|
fprintf ( fileout, " coordIndex [\n" );
|
|
|
|
text_num = text_num + 1;
|
|
|
|
length = 0;
|
|
for ( j = 0; j < line_num; j++ ) {
|
|
fprintf ( fileout, "%d ", line_dex[j] );
|
|
length = length + 1;
|
|
if ( line_dex[j] == -1 || length >= 10 || j == line_num - 1 ) {
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
length = 0;
|
|
}
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
Colors. (materials)
|
|
*/
|
|
fprintf ( fileout, " color Color {\n" );
|
|
fprintf ( fileout, " color [\n" );
|
|
text_num = text_num + 2;
|
|
|
|
for ( j = 0; j < material_num; j++ ) {
|
|
fprintf ( fileout, " %f %f %f\n", material_rgba[0][j],
|
|
material_rgba[1][j], material_rgba[2][j] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
fprintf ( fileout, " colorPerVertex TRUE\n" );
|
|
/*
|
|
IndexedLineset colorIndex
|
|
*/
|
|
fprintf ( fileout, " colorIndex [\n" );
|
|
|
|
text_num = text_num + 4;
|
|
|
|
length = 0;
|
|
for ( j = 0; j < line_num; j++ ) {
|
|
fprintf ( fileout, "%d ", line_material[j] );
|
|
length = length + 1;
|
|
if ( line_dex[j] == -1 || length >= 10 || j == line_num - 1 ) {
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
length = 0;
|
|
}
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 2;
|
|
|
|
}
|
|
/*
|
|
End of IndexedLineSet
|
|
|
|
IndexedFaceSet
|
|
*/
|
|
if ( face_num > 0 ) {
|
|
|
|
fprintf ( fileout, " geometry IndexedFaceSet {\n" );
|
|
/*
|
|
IndexedFaceSet coord
|
|
*/
|
|
fprintf ( fileout, " coord Coordinate {\n" );
|
|
fprintf ( fileout, " point [\n" );
|
|
|
|
text_num = text_num + 3;
|
|
|
|
for ( icor3 = 0; icor3 < cor3_num; icor3++ ) {
|
|
fprintf ( fileout, " %f %f %f\n", cor3[0][icor3],
|
|
cor3[1][icor3], cor3[2][icor3] );
|
|
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
/*
|
|
IndexedFaceSet coordIndex.
|
|
*/
|
|
fprintf ( fileout, " coordIndex [\n" );
|
|
|
|
text_num = text_num + 3;
|
|
|
|
length = 0;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
for ( ivert = 0; ivert <= face_order[iface]; ivert++ ) {
|
|
|
|
if ( ivert <= face_order[iface] ) {
|
|
itemp = face[ivert][iface];
|
|
}
|
|
else {
|
|
itemp = 0;
|
|
}
|
|
|
|
fprintf ( fileout, "%d ", itemp );
|
|
length = length + 1;
|
|
|
|
if ( itemp == -1 || length >= 10 ||
|
|
( iface == face_num - 1 && ivert == face_order[iface] ) ) {
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
length = 0;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
text_num = text_num + 1;
|
|
/*
|
|
IndexedFaceset colorIndex
|
|
*/
|
|
fprintf ( fileout, " colorIndex [\n" );
|
|
text_num = text_num + 1;
|
|
|
|
length = 0;
|
|
ndx = 0;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
|
|
for ( ivert = 0; ivert <= face_order[iface]; ivert++ ) {
|
|
|
|
if ( ivert <= face_order[iface] ) {
|
|
itemp = vertex_material[ivert][iface];
|
|
ndx = ndx + 1;
|
|
}
|
|
else {
|
|
itemp = 0;
|
|
}
|
|
|
|
fprintf ( fileout, "%d ", itemp );
|
|
length = length + 1;
|
|
|
|
if ( itemp == -1 || length >= 10 ||
|
|
( iface == face_num - 1 && ivert == face_order[iface] ) ) {
|
|
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
length = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf ( fileout, " ]\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
text_num = text_num + 2;
|
|
|
|
}
|
|
/*
|
|
End of IndexedFaceSet
|
|
|
|
End of:
|
|
Shape
|
|
children
|
|
Group
|
|
*/
|
|
fprintf ( fileout, " }\n" );
|
|
fprintf ( fileout, " ]\n" );
|
|
fprintf ( fileout, " }\n" );
|
|
|
|
text_num = text_num + 3;
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "WRL_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
|
|
int xgl_write ( FILE *fileout )
|
|
|
|
/******************************************************************************/
|
|
|
|
/*
|
|
Purpose:
|
|
|
|
XGL_WRITE writes an XGL file.
|
|
|
|
Discussion:
|
|
|
|
Two corrections to the routine were pointed out by
|
|
Mike Phillips, msphil@widowmaker.com, on 17 September 2001,
|
|
and are gratefully acknowledged.
|
|
|
|
Example:
|
|
|
|
<WORLD>
|
|
|
|
<BACKGROUND>
|
|
<BACKCOLOR> 0.1, 0.1, 0.1 </BACKCOLOR>
|
|
</BACKGROUND>
|
|
|
|
<LIGHTING>
|
|
<AMBIENT> 0.2, 0.1, 0.1 </AMBIENT>
|
|
<DIRECTIONALLIGHT>
|
|
<DIFFUSE> 0.1, 0.2, 0.1 </DIFFUSE>
|
|
<DIRECTION> 0, 0, 100 </DIRECTION>
|
|
<SPECULAR> 0.1, 0.1, 0.2 </SPECULAR>
|
|
</DIRECTIONALLIGHT>
|
|
</LIGHTING>
|
|
|
|
<MESH ID = "0">
|
|
|
|
<P ID="0"> -0.5, -0.5, 1 </P>
|
|
<P ID="1"> 0.5, -0.5, 1 </P>
|
|
<P ID="2"> 0.5, 0.5, 1 </P>
|
|
<P ID="3"> -0.5, 0.5, 1 </P>
|
|
<P ID="4"> 0.5, -0.5, 0 </P>
|
|
<P ID="5"> -0.5, -0.5, 0 </P>
|
|
<P ID="6"> -0.5, 0.5, 0 </P>
|
|
<P ID="7"> 0.5, 0.5, 0 </P>
|
|
|
|
<N ID="0"> -0.408248, -0.408248, 0.816497 </N>
|
|
<N ID="1"> 0.666667, -0.666667, 0.333333 </N>
|
|
<N ID="2"> 0.408248, 0.408248, 0.816497 </N>
|
|
<N ID="3"> -0.666667, 0.666667, 0.333333 </N>
|
|
<N ID="4"> 0.408248, -0.408248, -0.816497 </N>
|
|
<N ID="5"> -0.666667, -0.666667, -0.333333 </N>
|
|
<N ID="6"> -0.408248, 0.408248, -0.816497 </N>
|
|
<N ID="7"> 0.666667, 0.666667, -0.333333 </N>
|
|
|
|
<MAT ID="0">
|
|
<ALPHA> 0.9 </ALPHA>
|
|
<AMB> 0.1, 0.1, 0.1 </AMB>
|
|
<DIFF> 0.2, 0.1, 0.1 </DIFF>
|
|
<EMISS> 0.1, 0.2, 0.1 </EMISS>
|
|
<SHINE> 0.8 </SHINE>
|
|
<SPEC> 0.1, 0.1, 0.2 </SPEC>
|
|
</MAT>
|
|
|
|
<F>
|
|
<MATREF> 0 </MATREF>
|
|
<FV1><PREF> 0 </PREF><NREF> 0 </NREF></FV1>
|
|
<FV2><PREF> 1 </PREF><NREF> 1 </NREF></FV2>
|
|
<FV3><PREF> 2 </PREF><NREF> 2 </NREF></FV3>
|
|
</F>
|
|
<F>
|
|
<MATREF> 0 </MATREF>
|
|
<FV1><PREF> 0 </PREF><NREF> 0 </NREF></FV1>
|
|
<FV2><PREF> 2 </PREF><NREF> 2 </NREF></FV2>
|
|
<FV3><PREF> 3 </PREF><NREF> 3 </NREF></FV3>
|
|
</F>
|
|
<F>
|
|
<MATREF> 0 </MATREF>
|
|
<FV1><PREF> 4 </PREF><NREF> 4 </NREF></FV1>
|
|
<FV2><PREF> 5 </PREF><NREF> 5 </NREF></FV2>
|
|
<FV3><PREF> 6 </PREF><NREF> 6 </NREF></FV3>
|
|
</F>
|
|
<F>
|
|
<MATREF> 0 </MATREF>
|
|
<FV1><PREF> 4 </PREF><NREF> 4 </NREF></FV1>
|
|
<FV2><PREF> 6 </PREF><NREF> 6 </NREF></FV2>
|
|
<FV3><PREF> 7 </PREF><NREF> 7 </NREF></FV3>
|
|
</F>
|
|
<F>
|
|
<MATREF> 0 </MATREF>
|
|
<FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
|
|
<FV2><PREF> 0 </PREF><NREF> 0 </NREF></FV2>
|
|
<FV3><PREF> 3 </PREF><NREF> 3 </NREF></FV3>
|
|
</F>
|
|
<F>
|
|
<MATREF> 0 </MATREF>
|
|
<FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
|
|
<FV2><PREF> 3 </PREF><NREF> 3 </NREF></FV2>
|
|
<FV3><PREF> 6 </PREF><NREF> 6 </NREF></FV3>
|
|
</F>
|
|
<F>
|
|
<MATREF> 0 </MATREF>
|
|
<FV1><PREF> 1 </PREF><NREF> 1 </NREF></FV1>
|
|
<FV2><PREF> 4 </PREF><NREF> 4 </NREF></FV2>
|
|
<FV3><PREF> 7 </PREF><NREF> 7 </NREF></FV3>
|
|
</F>
|
|
<F>
|
|
<MATREF> 0 </MATREF>
|
|
<FV1><PREF> 1 </PREF><NREF> 1 </NREF></FV1>
|
|
<FV2><PREF> 7 </PREF><NREF> 7 </NREF></FV2>
|
|
<FV3><PREF> 2 </PREF><NREF> 2 </NREF></FV3>
|
|
</F>
|
|
<F>
|
|
<MATREF> 0 </MATREF>
|
|
<FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
|
|
<FV2><PREF> 4 </PREF><NREF> 4 </NREF></FV2>
|
|
<FV3><PREF> 1 </PREF><NREF> 1 </NREF></FV3>
|
|
</F>
|
|
<F>
|
|
<MATREF> 0 </MATREF>
|
|
<FV1><PREF> 5 </PREF><NREF> 5 </NREF></FV1>
|
|
<FV2><PREF> 1 </PREF><NREF> 1 </NREF></FV2>
|
|
<FV3><PREF> 0 </PREF><NREF> 0 </NREF></FV3>
|
|
</F>
|
|
<F>
|
|
<MATREF> 0 </MATREF>
|
|
<FV1><PREF> 3 </PREF><NREF> 3 </NREF></FV1>
|
|
<FV2><PREF> 2 </PREF><NREF> 2 </NREF></FV2>
|
|
<FV3><PREF> 7 </PREF><NREF> 7 </NREF></FV3>
|
|
</F>
|
|
<F>
|
|
<MATREF> 0 </MATREF>
|
|
<FV1><PREF> 3 </PREF><NREF> 3 </NREF></FV1>
|
|
<FV2><PREF> 7 </PREF><NREF> 7 </NREF></FV2>
|
|
<FV3><PREF> 6 </PREF><NREF> 6 </NREF></FV3>
|
|
</F>
|
|
</MESH>
|
|
|
|
<OBJECT>
|
|
<TRANSFORM>
|
|
<FORWARD> 0, 0, 0 </FORWARD>
|
|
<POSITION> 0, 0, 0 </POSITION>
|
|
<SCALE> 1, 1, 1 </SCALE>
|
|
<UP> 1, 1, 1 </UP>
|
|
</TRANSFORM>
|
|
<MESHREF> 0 </MESHREF>
|
|
</OBJECT>
|
|
|
|
</WORLD>
|
|
|
|
Reference:
|
|
|
|
XGL specification at http://www.xglspec.org/
|
|
|
|
Modified:
|
|
|
|
17 September 2001
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
*/
|
|
{
|
|
int iface;
|
|
int ivert;
|
|
int j;
|
|
float light_ambient_rgb[3];
|
|
float light_diffuse_rgb[3];
|
|
float light_direction[3];
|
|
float light_specular_rgb[3];
|
|
int material;
|
|
float material_alpha;
|
|
float material_amb_rgb[3];
|
|
float material_diff_rgb[3];
|
|
float material_emiss_rgb[3];
|
|
float material_shine;
|
|
float material_spec_rgb[3];
|
|
int mesh;
|
|
int mesh_num = 1;
|
|
int object;
|
|
float transform_forward[3];
|
|
float transform_position[3];
|
|
float transform_scale[3];
|
|
float transform_up[3];
|
|
/*
|
|
Make up some placeholder values for now.
|
|
*/
|
|
light_ambient_rgb[0] = 0.2;
|
|
light_ambient_rgb[1] = 0.1;
|
|
light_ambient_rgb[2] = 0.1;
|
|
|
|
light_diffuse_rgb[0] = 0.1;
|
|
light_diffuse_rgb[1] = 0.2;
|
|
light_diffuse_rgb[2] = 0.1;
|
|
|
|
light_direction[0] = 0.0;
|
|
light_direction[1] = 0.0;
|
|
light_direction[2] = 100.0;
|
|
|
|
light_specular_rgb[0] = 0.1;
|
|
light_specular_rgb[1] = 0.1;
|
|
light_specular_rgb[2] = 0.2;
|
|
|
|
material_alpha = 0.9;
|
|
|
|
material_amb_rgb[0] = 0.1;
|
|
material_amb_rgb[1] = 0.1;
|
|
material_amb_rgb[2] = 0.1;
|
|
|
|
material_diff_rgb[0] = 0.2;
|
|
material_diff_rgb[1] = 0.1;
|
|
material_diff_rgb[2] = 0.1;
|
|
|
|
material_emiss_rgb[0] = 0.1;
|
|
material_emiss_rgb[1] = 0.2;
|
|
material_emiss_rgb[2] = 0.1;
|
|
|
|
material_shine = 0.8;
|
|
|
|
material_spec_rgb[0] = 0.1;
|
|
material_spec_rgb[1] = 0.1;
|
|
material_spec_rgb[2] = 0.2;
|
|
|
|
transform_forward[0] = 0.0;
|
|
transform_forward[1] = 0.0;
|
|
transform_forward[2] = 0.0;
|
|
|
|
transform_position[0] = 0.0;
|
|
transform_position[1] = 0.0;
|
|
transform_position[2] = 0.0;
|
|
|
|
transform_scale[0] = 1.0;
|
|
transform_scale[1] = 1.0;
|
|
transform_scale[2] = 1.0;
|
|
|
|
transform_up[0] = 1.0;
|
|
transform_up[1] = 1.0;
|
|
transform_up[2] = 1.0;
|
|
|
|
object_num = 1;
|
|
|
|
text_num = 0;
|
|
|
|
fprintf ( fileout, "<WORLD>\n" );
|
|
fprintf ( fileout, "\n" );
|
|
|
|
text_num = text_num + 2;
|
|
|
|
fprintf ( fileout, " <BACKGROUND>\n" );
|
|
fprintf ( fileout, " <BACKCOLOR> %f, %f, %f </BACKCOLOR>\n",
|
|
background_rgb[0], background_rgb[1], background_rgb[2] );
|
|
fprintf ( fileout, " </BACKGROUND>\n" );
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " <LIGHTING>\n" );
|
|
fprintf ( fileout, " <AMBIENT> %f, %f, %f </AMBIENT>\n",
|
|
light_ambient_rgb[0], light_ambient_rgb[1], light_ambient_rgb[2] );
|
|
fprintf ( fileout, " <DIRECTIONALLIGHT>\n" );
|
|
fprintf ( fileout, " <DIFFUSE> %f, %f, %f </DIFFUSE>\n",
|
|
light_diffuse_rgb[0], light_diffuse_rgb[1], light_diffuse_rgb[2] );
|
|
fprintf ( fileout, " <DIRECTION> %f, %f, %f </DIRECTION>\n",
|
|
light_direction[0], light_direction[1], light_direction[2] );
|
|
fprintf ( fileout, " <SPECULAR> %f, %f, %f </SPECULAR>\n",
|
|
light_specular_rgb[0], light_specular_rgb[1], light_specular_rgb[2] );
|
|
fprintf ( fileout, " </DIRECTIONALLIGHT>\n" );
|
|
fprintf ( fileout, " </LIGHTING>\n" );
|
|
|
|
text_num = text_num + 12;
|
|
|
|
for ( mesh = 0; mesh < mesh_num; mesh++ ) {
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " <MESH ID = \"%d\">\n", mesh );
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 3;
|
|
|
|
for ( j = 0; j < cor3_num; j++ ) {
|
|
fprintf ( fileout, " <P ID=\"%d\"> %f, %f, %f </P>\n", j,
|
|
cor3[0][j], cor3[1][j], cor3[2][j] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
for ( j = 0; j < cor3_num; j++ ) {
|
|
fprintf ( fileout, " <N ID=\"%d\"> %f, %f, %f </N>\n", j,
|
|
cor3_normal[0][j], cor3_normal[1][j], cor3_normal[2][j] );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
for ( material = 0; material < material_num; material++ ) {
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, " <MAT ID=\"%d\">\n", material );
|
|
fprintf ( fileout, " <ALPHA> %f </ALPHA>\n", material_alpha );
|
|
fprintf ( fileout, " <AMB> %f, %f, %f </AMB>\n",
|
|
material_amb_rgb[0], material_amb_rgb[1], material_amb_rgb[2] );
|
|
fprintf ( fileout, " <DIFF> %f, %f, %f </DIFF>\n",
|
|
material_diff_rgb[0], material_diff_rgb[1], material_diff_rgb[2] );
|
|
fprintf ( fileout, " <EMISS> %f, %f, %f </EMISS>\n",
|
|
material_emiss_rgb[0], material_emiss_rgb[1], material_emiss_rgb[2] );
|
|
fprintf ( fileout, " <SHINE> %f </SHINE>\n", material_shine );
|
|
fprintf ( fileout, " <SPEC> %f, %f, %f </SPEC>\n",
|
|
material_spec_rgb[0], material_spec_rgb[1], material_spec_rgb[2] );
|
|
fprintf ( fileout, " </MAT>\n" );
|
|
text_num = text_num + 9;
|
|
}
|
|
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
|
|
for ( iface = 0; iface < face_num; iface++ ) {
|
|
fprintf ( fileout, " <F>\n" );
|
|
fprintf ( fileout, " <MATREF> %d </MATREF>\n", face_material[iface] );
|
|
text_num = text_num + 2;
|
|
for ( ivert = 0; ivert < face_order[iface]; ivert++ ) {
|
|
fprintf ( fileout,
|
|
" <FV%d><PREF> %d </PREF><NREF> %d </NREF></FV%d>\n",
|
|
ivert+1, face[ivert][iface], face[ivert][iface], ivert+1 );
|
|
text_num = text_num + 1;
|
|
}
|
|
fprintf ( fileout, " </F>\n" );
|
|
text_num = text_num + 1;
|
|
}
|
|
|
|
fprintf ( fileout, " </MESH>\n" );
|
|
text_num = text_num + 1;
|
|
|
|
}
|
|
|
|
fprintf ( fileout, "\n" );
|
|
text_num = text_num + 1;
|
|
|
|
for ( object = 0; object < object_num; object++ ) {
|
|
|
|
fprintf ( fileout, " <OBJECT>\n" );
|
|
fprintf ( fileout, " <TRANSFORM>\n" );
|
|
fprintf ( fileout, " <FORWARD> %f, %f, %f </FORWARD>\n",
|
|
transform_forward[0], transform_forward[1], transform_forward[2] );
|
|
fprintf ( fileout, " <POSITION> %f, %f, %f </POSITION>\n",
|
|
transform_position[0], transform_position[1], transform_position[2] );
|
|
fprintf ( fileout, "' <SCALE> %f, %f, %f </SCALE>\n",
|
|
transform_scale[0], transform_scale[1], transform_scale[2] );
|
|
fprintf ( fileout, " <UP> %f, %f, %f </UP>\n",
|
|
transform_up[0], transform_up[1], transform_up[2] );
|
|
fprintf ( fileout, " </TRANSFORM>\n" );
|
|
mesh = 0;
|
|
fprintf ( fileout, " <MESHREF> %d </MESHREF>\n", mesh );
|
|
fprintf ( fileout, " </OBJECT>\n" );
|
|
text_num = text_num + 9;
|
|
|
|
}
|
|
|
|
fprintf ( fileout, "\n" );
|
|
fprintf ( fileout, "</WORLD>\n" );
|
|
text_num = text_num + 2;
|
|
|
|
/*
|
|
Report.
|
|
*/
|
|
printf ( "\n" );
|
|
printf ( "XGL_WRITE - Wrote %d text lines.\n", text_num );
|
|
|
|
return SUCCESS;
|
|
}
|