| 1 | greg | 1.1 | #ifndef lint | 
| 2 | schorsch | 1.11 | static const char       RCSid[] = "$Id: mgf2inv.c,v 1.10 2003/08/05 20:40:16 greg Exp $"; | 
| 3 | greg | 1.1 | #endif | 
| 4 |  |  | /* | 
| 5 |  |  | * Convert MGF to Inventor file. | 
| 6 |  |  | * | 
| 7 |  |  | *      December 1995   Greg Ward | 
| 8 |  |  | */ | 
| 9 |  |  |  | 
| 10 |  |  | #include <stdio.h> | 
| 11 | greg | 1.8 |  | 
| 12 |  |  | #include <stdlib.h> | 
| 13 | greg | 1.1 |  | 
| 14 |  |  | #include <math.h> | 
| 15 |  |  |  | 
| 16 | greg | 1.2 | #include <ctype.h> | 
| 17 |  |  |  | 
| 18 | greg | 1.6 | #include <string.h> | 
| 19 |  |  |  | 
| 20 | greg | 1.1 | #include "parser.h" | 
| 21 |  |  |  | 
| 22 | greg | 1.3 | #include "lookup.h" | 
| 23 |  |  |  | 
| 24 | greg | 1.2 | #define O_INV1          1       /* Inventor 1.0 output */ | 
| 25 |  |  | #define O_INV2          2       /* Inventor 2.0 output */ | 
| 26 | gregl | 1.7 | #define O_VRML1         3       /* VRML 1.0 output */ | 
| 27 | greg | 1.1 |  | 
| 28 | greg | 1.3 | #define MAXID           48      /* maximum identifier length */ | 
| 29 |  |  |  | 
| 30 |  |  | #define VERTFMT         "%+16.9e %+16.9e %+16.9e\n%+6.3f %+6.3f %+6.3f" | 
| 31 |  |  | #define VZVECT          "+0.000 +0.000 +0.000" | 
| 32 |  |  | #define VFSEPPOS        50      /* position of newline in above */ | 
| 33 |  |  | #define VFLEN           72      /* total vertex string length */ | 
| 34 |  |  | #define MAXVERT         10240   /* maximum cached vertices */ | 
| 35 |  |  |  | 
| 36 |  |  | #define setvkey(k,v)    sprintf(k,VERTFMT,(v)->p[0],(v)->p[1],(v)->p[2],\ | 
| 37 |  |  | (v)->n[0],(v)->n[1],(v)->n[2]); | 
| 38 |  |  |  | 
| 39 |  |  | char    vlist[MAXVERT][VFLEN];  /* our vertex cache */ | 
| 40 |  |  | int     nverts;                 /* current cache size */ | 
| 41 |  |  |  | 
| 42 |  |  | LUTAB   vert_tab = LU_SINIT(NULL,NULL); | 
| 43 |  |  |  | 
| 44 |  |  | struct face { | 
| 45 |  |  | struct face     *next;          /* next face in list */ | 
| 46 |  |  | short           nv;             /* number of vertices */ | 
| 47 |  |  | short           vl[3];          /* vertex index list (variable) */ | 
| 48 |  |  | }       *flist, *flast;         /* our face cache */ | 
| 49 |  |  |  | 
| 50 |  |  | #define newface(n)      (struct face *)malloc(sizeof(struct face) + \ | 
| 51 |  |  | ((n) > 3 ? (n)-3 : 0)*sizeof(short)) | 
| 52 |  |  | #define freeface(f)     free((MEM_PTR)f) | 
| 53 |  |  |  | 
| 54 | greg | 1.1 | #define TABSTOP         8       /* assumed number of characters per tab */ | 
| 55 |  |  | #define SHIFTW          2       /* nesting shift width */ | 
| 56 |  |  | #define MAXIND          15      /* maximum indent level */ | 
| 57 |  |  |  | 
| 58 | greg | 1.2 | char    tabs[MAXIND*SHIFTW+1];  /* current tab-in string */ | 
| 59 | greg | 1.1 |  | 
| 60 | greg | 1.3 | #define curmatname      (c_cmname == NULL ? "mat" : to_id(c_cmname)) | 
| 61 |  |  |  | 
| 62 | greg | 1.2 | int     outtype = O_INV2;       /* output format */ | 
| 63 | greg | 1.1 |  | 
| 64 | schorsch | 1.11 | int i_comment(int ac, char **av); | 
| 65 |  |  | int i_object(int ac, char **av); | 
| 66 |  |  | int i_xf(int ac, char **av); | 
| 67 |  |  | int put_xform(register XF_SPEC *spec); | 
| 68 |  |  | int put_material(void); | 
| 69 |  |  | int i_face(int ac, char **av); | 
| 70 |  |  | int i_sph(int ac, char **av); | 
| 71 |  |  | int i_cyl(int ac, char **av); | 
| 72 |  |  | char * to_id(register char *name); | 
| 73 |  |  | char * to_id(register char *name); | 
| 74 |  |  | void flush_cache(void); | 
| 75 | greg | 1.1 |  | 
| 76 |  |  |  | 
| 77 | schorsch | 1.11 | int | 
| 78 |  |  | main( | 
| 79 |  |  | int     argc, | 
| 80 |  |  | char    *argv[] | 
| 81 |  |  | ) | 
| 82 | greg | 1.1 | { | 
| 83 |  |  | int     i; | 
| 84 |  |  | /* initialize dispatch table */ | 
| 85 |  |  | mg_ehand[MG_E_COMMENT] = i_comment;     /* we pass comments */ | 
| 86 |  |  | mg_ehand[MG_E_COLOR] = c_hcolor;        /* they get color */ | 
| 87 |  |  | mg_ehand[MG_E_CMIX] = c_hcolor;         /* they mix colors */ | 
| 88 |  |  | mg_ehand[MG_E_CSPEC] = c_hcolor;        /* they get spectra */ | 
| 89 |  |  | mg_ehand[MG_E_CXY] = c_hcolor;          /* they get chromaticities */ | 
| 90 |  |  | mg_ehand[MG_E_CCT] = c_hcolor;          /* they get color temp's */ | 
| 91 |  |  | mg_ehand[MG_E_CYL] = i_cyl;             /* we do cylinders */ | 
| 92 |  |  | mg_ehand[MG_E_ED] = c_hmaterial;        /* they get emission */ | 
| 93 |  |  | mg_ehand[MG_E_FACE] = i_face;           /* we do faces */ | 
| 94 |  |  | mg_ehand[MG_E_MATERIAL] = c_hmaterial;  /* they get materials */ | 
| 95 |  |  | mg_ehand[MG_E_NORMAL] = c_hvertex;      /* they get normals */ | 
| 96 |  |  | mg_ehand[MG_E_OBJECT] = i_object;       /* we track object names */ | 
| 97 |  |  | mg_ehand[MG_E_POINT] = c_hvertex;       /* they get points */ | 
| 98 |  |  | mg_ehand[MG_E_RD] = c_hmaterial;        /* they get diffuse refl. */ | 
| 99 |  |  | mg_ehand[MG_E_RS] = c_hmaterial;        /* they get specular refl. */ | 
| 100 |  |  | mg_ehand[MG_E_SIDES] = c_hmaterial;     /* they get # sides */ | 
| 101 |  |  | mg_ehand[MG_E_SPH] = i_sph;             /* we do spheres */ | 
| 102 |  |  | mg_ehand[MG_E_TD] = c_hmaterial;        /* they get diffuse trans. */ | 
| 103 |  |  | mg_ehand[MG_E_TS] = c_hmaterial;        /* they get specular trans. */ | 
| 104 |  |  | mg_ehand[MG_E_VERTEX] = c_hvertex;      /* they get vertices */ | 
| 105 |  |  | mg_ehand[MG_E_XF] = i_xf;               /* we track transforms */ | 
| 106 |  |  | mg_init();              /* initialize the parser */ | 
| 107 | greg | 1.2 | /* get options and print format line */ | 
| 108 |  |  | for (i = 1; i < argc && argv[i][0] == '-'; i++) | 
| 109 |  |  | if (!strcmp(argv[i], "-vrml")) | 
| 110 | gregl | 1.7 | outtype = O_VRML1; | 
| 111 | greg | 1.2 | else if (!strcmp(argv[i], "-1")) | 
| 112 |  |  | outtype = O_INV1; | 
| 113 |  |  | else if (!strcmp(argv[i], "-2")) | 
| 114 |  |  | outtype = O_INV2; | 
| 115 |  |  | else | 
| 116 |  |  | goto userr; | 
| 117 |  |  | switch (outtype) { | 
| 118 |  |  | case O_INV1: | 
| 119 |  |  | printf("#Inventor V1.0 ascii\n"); | 
| 120 |  |  | break; | 
| 121 |  |  | case O_INV2: | 
| 122 |  |  | printf("#Inventor V2.0 ascii\n"); | 
| 123 |  |  | break; | 
| 124 | gregl | 1.7 | case O_VRML1: | 
| 125 |  |  | printf("#VRML V1.0 ascii\n"); | 
| 126 | greg | 1.2 | break; | 
| 127 |  |  | } | 
| 128 | greg | 1.1 | printf("## Translated from MGF Version %d.%d\n", MG_VMAJOR, MG_VMINOR); | 
| 129 |  |  | printf("Separator {\n");                /* begin root node */ | 
| 130 |  |  | /* general properties */ | 
| 131 |  |  | printf("MaterialBinding { value OVERALL }\n"); | 
| 132 | greg | 1.2 | printf("NormalBinding { value PER_VERTEX_INDEXED }\n"); | 
| 133 |  |  | if (outtype != O_INV1) { | 
| 134 |  |  | printf("ShapeHints {\n"); | 
| 135 |  |  | printf("\tvertexOrdering CLOCKWISE\n"); | 
| 136 |  |  | printf("\tfaceType UNKNOWN_FACE_TYPE\n"); | 
| 137 |  |  | printf("}\n"); | 
| 138 |  |  | } | 
| 139 | greg | 1.1 | if (i == argc) {        /* load standard input */ | 
| 140 |  |  | if (mg_load(NULL) != MG_OK) | 
| 141 |  |  | exit(1); | 
| 142 |  |  | if (mg_nunknown) | 
| 143 |  |  | printf("## %s: %u unknown entities\n", | 
| 144 |  |  | argv[0], mg_nunknown); | 
| 145 |  |  | } | 
| 146 |  |  | /* load MGF files */ | 
| 147 |  |  | for ( ; i < argc; i++) { | 
| 148 |  |  | printf("## %s %s ##############################\n", | 
| 149 |  |  | argv[0], argv[i]); | 
| 150 |  |  | mg_nunknown = 0; | 
| 151 |  |  | if (mg_load(argv[i]) != MG_OK) | 
| 152 |  |  | exit(1); | 
| 153 |  |  | if (mg_nunknown) | 
| 154 |  |  | printf("## %s %s: %u unknown entities\n", | 
| 155 |  |  | argv[0], argv[i], mg_nunknown); | 
| 156 |  |  | } | 
| 157 | greg | 1.3 | flush_cache();          /* flush face cache, just in case */ | 
| 158 |  |  | printf("}\n");          /* close root node */ | 
| 159 | greg | 1.1 | exit(0); | 
| 160 | greg | 1.2 | userr: | 
| 161 |  |  | fprintf(stderr, "%s: [-1|-2|-vrml] [file] ..\n", argv[0]); | 
| 162 |  |  | exit(1); | 
| 163 | greg | 1.1 | } | 
| 164 |  |  |  | 
| 165 |  |  |  | 
| 166 | schorsch | 1.11 | void | 
| 167 |  |  | indent(                         /* indent in or out */ | 
| 168 |  |  | int     deeper | 
| 169 |  |  | ) | 
| 170 | greg | 1.1 | { | 
| 171 |  |  | static int      level;          /* current nesting level */ | 
| 172 |  |  | register int    i; | 
| 173 |  |  | register char   *cp; | 
| 174 |  |  |  | 
| 175 |  |  | if (deeper) level++;            /* in or out? */ | 
| 176 |  |  | else if (level > 0) level--; | 
| 177 |  |  | /* compute actual shift */ | 
| 178 |  |  | if ((i = level) > MAXIND) i = MAXIND; | 
| 179 |  |  | cp = tabs; | 
| 180 |  |  | for (i *= SHIFTW; i >= TABSTOP; i -= TABSTOP) | 
| 181 |  |  | *cp++ = '\t'; | 
| 182 |  |  | while (i--) | 
| 183 |  |  | *cp++ = ' '; | 
| 184 |  |  | *cp = '\0'; | 
| 185 |  |  | } | 
| 186 |  |  |  | 
| 187 |  |  |  | 
| 188 |  |  | int | 
| 189 | schorsch | 1.11 | i_comment(                      /* transfer comment as is */ | 
| 190 |  |  | int     ac, | 
| 191 |  |  | char    **av | 
| 192 |  |  | ) | 
| 193 | greg | 1.1 | { | 
| 194 |  |  | fputs(tabs, stdout); | 
| 195 |  |  | putchar('#');                   /* Inventor comment character */ | 
| 196 |  |  | while (--ac > 0) { | 
| 197 |  |  | putchar(' '); | 
| 198 |  |  | fputs(*++av, stdout); | 
| 199 |  |  | } | 
| 200 |  |  | putchar('\n'); | 
| 201 |  |  | return(MG_OK); | 
| 202 |  |  | } | 
| 203 |  |  |  | 
| 204 |  |  |  | 
| 205 |  |  | int | 
| 206 | schorsch | 1.11 | i_object(                       /* group object name */ | 
| 207 |  |  | int     ac, | 
| 208 |  |  | char    **av | 
| 209 |  |  | ) | 
| 210 | greg | 1.1 | { | 
| 211 |  |  | static int      objnest; | 
| 212 |  |  |  | 
| 213 | greg | 1.3 | flush_cache();                  /* flush cached objects */ | 
| 214 | greg | 1.1 | if (ac == 2) {                          /* start group */ | 
| 215 | greg | 1.2 | printf("%sDEF %s Group {\n", tabs, to_id(av[1])); | 
| 216 | greg | 1.1 | indent(1); | 
| 217 |  |  | objnest++; | 
| 218 |  |  | return(MG_OK); | 
| 219 |  |  | } | 
| 220 |  |  | if (ac == 1) {                          /* end group */ | 
| 221 |  |  | if (--objnest < 0) | 
| 222 |  |  | return(MG_ECNTXT); | 
| 223 |  |  | indent(0); | 
| 224 |  |  | fputs(tabs, stdout); | 
| 225 |  |  | fputs("}\n", stdout); | 
| 226 |  |  | return(MG_OK); | 
| 227 |  |  | } | 
| 228 |  |  | return(MG_EARGC); | 
| 229 |  |  | } | 
| 230 |  |  |  | 
| 231 |  |  |  | 
| 232 |  |  | int | 
| 233 | schorsch | 1.11 | i_xf(                           /* transform object(s) */ | 
| 234 |  |  | int     ac, | 
| 235 |  |  | char    **av | 
| 236 |  |  | ) | 
| 237 | greg | 1.1 | { | 
| 238 |  |  | static long     xfid; | 
| 239 |  |  | register XF_SPEC        *spec; | 
| 240 |  |  |  | 
| 241 | greg | 1.3 | flush_cache();                  /* flush cached objects */ | 
| 242 | greg | 1.1 | if (ac == 1) {                  /* end of transform */ | 
| 243 |  |  | if ((spec = xf_context) == NULL) | 
| 244 |  |  | return(MG_ECNTXT); | 
| 245 |  |  | indent(0);                      /* close original segment */ | 
| 246 |  |  | printf("%s}\n", tabs); | 
| 247 |  |  | indent(0); | 
| 248 |  |  | printf("%s}\n", tabs); | 
| 249 |  |  | if (spec->xarr != NULL) {       /* check for iteration */ | 
| 250 |  |  | register struct xf_array        *ap = spec->xarr; | 
| 251 |  |  | register int    n; | 
| 252 |  |  |  | 
| 253 |  |  | ap->aarg[ap->ndim-1].i = 1;     /* iterate array */ | 
| 254 |  |  | for ( ; ; ) { | 
| 255 |  |  | n = ap->ndim-1; | 
| 256 |  |  | while (ap->aarg[n].i < ap->aarg[n].n) { | 
| 257 |  |  | sprintf(ap->aarg[n].arg, "%d", | 
| 258 |  |  | ap->aarg[n].i); | 
| 259 |  |  | printf("%sSeparator {\n", tabs); | 
| 260 |  |  | indent(1); | 
| 261 |  |  | (void)put_xform(spec); | 
| 262 |  |  | printf("%sUSE _xf%ld\n", tabs, | 
| 263 |  |  | spec->xid); | 
| 264 |  |  | indent(0); | 
| 265 |  |  | printf("%s}\n", tabs); | 
| 266 |  |  | ++ap->aarg[n].i; | 
| 267 |  |  | } | 
| 268 |  |  | ap->aarg[n].i = 0; | 
| 269 |  |  | (void)strcpy(ap->aarg[n].arg, "0"); | 
| 270 |  |  | while (n-- && ++ap->aarg[n].i >= ap->aarg[n].n) { | 
| 271 |  |  | ap->aarg[n].i = 0; | 
| 272 |  |  | (void)strcpy(ap->aarg[n].arg, "0"); | 
| 273 |  |  | } | 
| 274 |  |  | if (n < 0) | 
| 275 |  |  | break; | 
| 276 |  |  | sprintf(ap->aarg[n].arg, "%d", ap->aarg[n].i); | 
| 277 |  |  | } | 
| 278 |  |  | } | 
| 279 |  |  | /* pop transform */ | 
| 280 |  |  | xf_context = spec->prev; | 
| 281 |  |  | free_xf(spec); | 
| 282 |  |  | return(MG_OK); | 
| 283 |  |  | } | 
| 284 |  |  | /* else allocate new transform */ | 
| 285 |  |  | if ((spec = new_xf(ac-1, av+1)) == NULL) | 
| 286 |  |  | return(MG_EMEM); | 
| 287 |  |  | spec->xid = ++xfid;             /* assign unique ID */ | 
| 288 |  |  | spec->prev = xf_context;        /* push onto stack */ | 
| 289 |  |  | xf_context = spec; | 
| 290 |  |  | /* translate xf specification */ | 
| 291 |  |  | printf("%sSeparator {\n", tabs); | 
| 292 |  |  | indent(1); | 
| 293 |  |  | if (put_xform(spec) < 0) | 
| 294 |  |  | return(MG_ETYPE); | 
| 295 |  |  | printf("%sDEF _xf%ld Group {\n", tabs, spec->xid);      /* begin */ | 
| 296 |  |  | indent(1); | 
| 297 |  |  | return(MG_OK); | 
| 298 |  |  | } | 
| 299 |  |  |  | 
| 300 |  |  |  | 
| 301 |  |  | int | 
| 302 | schorsch | 1.11 | put_xform(                      /* translate and print transform */ | 
| 303 |  |  | register XF_SPEC        *spec | 
| 304 |  |  | ) | 
| 305 | greg | 1.1 | { | 
| 306 |  |  | register char   **av; | 
| 307 |  |  | register int    n; | 
| 308 |  |  |  | 
| 309 |  |  | n = xf_ac(spec) - xf_ac(spec->prev); | 
| 310 |  |  | if (xf(&spec->xf, n, av=xf_av(spec)) != n) | 
| 311 |  |  | return(-1); | 
| 312 |  |  | printf("%sMatrixTransform {\n", tabs); | 
| 313 |  |  | indent(1); | 
| 314 |  |  | printf("%s# xf", tabs);         /* put out original as comment */ | 
| 315 |  |  | while (n--) { | 
| 316 |  |  | putchar(' '); | 
| 317 |  |  | fputs(*av++, stdout); | 
| 318 |  |  | } | 
| 319 |  |  | putchar('\n');                  /* put out computed matrix */ | 
| 320 |  |  | printf("%smatrix %13.9g %13.9g %13.9g %13.9g\n", tabs, | 
| 321 |  |  | spec->xf.xfm[0][0], spec->xf.xfm[0][1], | 
| 322 |  |  | spec->xf.xfm[0][2], spec->xf.xfm[0][3]); | 
| 323 |  |  | for (n = 1; n < 4; n++) | 
| 324 |  |  | printf("%s       %13.9g %13.9g %13.9g %13.9g\n", tabs, | 
| 325 |  |  | spec->xf.xfm[n][0], spec->xf.xfm[n][1], | 
| 326 |  |  | spec->xf.xfm[n][2], spec->xf.xfm[n][3]); | 
| 327 |  |  | indent(0); | 
| 328 |  |  | printf("%s}\n", tabs); | 
| 329 |  |  | return(0); | 
| 330 |  |  | } | 
| 331 |  |  |  | 
| 332 |  |  |  | 
| 333 |  |  | int | 
| 334 | schorsch | 1.11 | put_material(void)                      /* put out current material */ | 
| 335 | greg | 1.1 | { | 
| 336 | greg | 1.3 | char    *mname = curmatname; | 
| 337 | greg | 1.1 | float   rgbval[3]; | 
| 338 |  |  |  | 
| 339 |  |  | if (!c_cmaterial->clock) {      /* current, just use it */ | 
| 340 | greg | 1.3 | printf("%sUSE %s\n", tabs, mname); | 
| 341 | greg | 1.1 | return(0); | 
| 342 |  |  | } | 
| 343 |  |  | /* else update definition */ | 
| 344 | greg | 1.3 | printf("%sDEF %s Group {\n", tabs, mname); | 
| 345 | greg | 1.1 | indent(1); | 
| 346 |  |  | printf("%sMaterial {\n", tabs); | 
| 347 |  |  | indent(1); | 
| 348 |  |  | mgf2rgb(&c_cmaterial->rd_c, c_cmaterial->rd, rgbval); | 
| 349 | greg | 1.2 | printf("%sambientColor %.4f %.4f %.4f\n", tabs, | 
| 350 | greg | 1.1 | rgbval[0], rgbval[1], rgbval[2]); | 
| 351 | greg | 1.2 | printf("%sdiffuseColor %.4f %.4f %.4f\n", tabs, | 
| 352 | greg | 1.1 | rgbval[0], rgbval[1], rgbval[2]); | 
| 353 |  |  | if (c_cmaterial->rs > FTINY) { | 
| 354 |  |  | mgf2rgb(&c_cmaterial->rs_c, c_cmaterial->rs, rgbval); | 
| 355 | greg | 1.2 | printf("%sspecularColor %.4f %.4f %.4f\n", tabs, | 
| 356 | greg | 1.1 | rgbval[0], rgbval[1], rgbval[2]); | 
| 357 | greg | 1.4 | printf("%sshininess %.3f\n", tabs, 1.-sqrt(c_cmaterial->rs_a)); | 
| 358 | greg | 1.1 | } | 
| 359 |  |  | if (c_cmaterial->ed > FTINY) { | 
| 360 |  |  | mgf2rgb(&c_cmaterial->ed_c, 1.0, rgbval); | 
| 361 |  |  | printf("%semissiveColor %.4f %.4f %.4f\n", tabs, | 
| 362 |  |  | rgbval[0], rgbval[1], rgbval[2]); | 
| 363 |  |  | } | 
| 364 |  |  | if (c_cmaterial->ts > FTINY) | 
| 365 |  |  | printf("%stransparency %.4f\n", tabs, | 
| 366 |  |  | c_cmaterial->ts + c_cmaterial->td); | 
| 367 |  |  | indent(0); | 
| 368 |  |  | printf("%s}\n", tabs); | 
| 369 | greg | 1.2 | if (outtype != O_INV1) | 
| 370 | greg | 1.10 | printf("%sShapeHints { shapeType %s faceType UNKNOWN_FACE_TYPE }\n", | 
| 371 |  |  | tabs, | 
| 372 | greg | 1.1 | c_cmaterial->sided ? "SOLID" : "UNKNOWN_SHAPE_TYPE"); | 
| 373 |  |  | indent(0); | 
| 374 |  |  | printf("%s}\n", tabs); | 
| 375 |  |  | c_cmaterial->clock = 0; | 
| 376 |  |  | return(0); | 
| 377 |  |  | } | 
| 378 |  |  |  | 
| 379 |  |  |  | 
| 380 |  |  | int | 
| 381 | schorsch | 1.11 | i_face(                 /* translate an N-sided face */ | 
| 382 |  |  | int     ac, | 
| 383 |  |  | char    **av | 
| 384 |  |  | ) | 
| 385 | greg | 1.1 | { | 
| 386 | greg | 1.3 | static char     lastmat[MAXID]; | 
| 387 |  |  | struct face     *newf; | 
| 388 |  |  | register C_VERTEX       *vp; | 
| 389 |  |  | register LUENT  *lp; | 
| 390 | greg | 1.1 | register int    i; | 
| 391 |  |  |  | 
| 392 |  |  | if (ac < 4) | 
| 393 |  |  | return(MG_EARGC); | 
| 394 | greg | 1.3 | if ( strcmp(lastmat, curmatname) || c_cmaterial->clock || | 
| 395 |  |  | nverts == 0 || nverts+ac-1 >= MAXVERT) { | 
| 396 |  |  | flush_cache();                  /* new cache */ | 
| 397 |  |  | lu_init(&vert_tab, MAXVERT); | 
| 398 |  |  | printf("%sSeparator {\n", tabs); | 
| 399 |  |  | indent(1); | 
| 400 |  |  | if (put_material() < 0)         /* put out material */ | 
| 401 |  |  | return(MG_EBADMAT); | 
| 402 |  |  | (void)strcpy(lastmat, curmatname); | 
| 403 |  |  | } | 
| 404 |  |  | /* allocate new face */ | 
| 405 |  |  | if ((newf = newface(ac-1)) == NULL) | 
| 406 |  |  | return(MG_EMEM); | 
| 407 |  |  | newf->nv = ac-1; | 
| 408 | greg | 1.1 | /* get vertex references */ | 
| 409 | greg | 1.3 | for (i = 0; i < newf->nv; i++) { | 
| 410 |  |  | if ((vp = c_getvert(av[i+1])) == NULL) | 
| 411 | greg | 1.1 | return(MG_EUNDEF); | 
| 412 | greg | 1.3 | setvkey(vlist[nverts], vp); | 
| 413 |  |  | lp = lu_find(&vert_tab, vlist[nverts]); | 
| 414 |  |  | if (lp == NULL) | 
| 415 |  |  | return(MG_EMEM); | 
| 416 |  |  | if (lp->key == NULL) | 
| 417 |  |  | lp->key = (char *)vlist[nverts++]; | 
| 418 |  |  | newf->vl[i] = ((char (*)[VFLEN])lp->key - vlist); | 
| 419 | greg | 1.1 | } | 
| 420 | greg | 1.3 | /* add to face list */ | 
| 421 |  |  | newf->next = NULL; | 
| 422 |  |  | if (flist == NULL) | 
| 423 |  |  | flist = newf; | 
| 424 |  |  | else | 
| 425 |  |  | flast->next = newf; | 
| 426 |  |  | flast = newf; | 
| 427 |  |  | return(MG_OK);          /* we'll actually put it out later */ | 
| 428 | greg | 1.1 | } | 
| 429 |  |  |  | 
| 430 |  |  |  | 
| 431 |  |  | int | 
| 432 | schorsch | 1.11 | i_sph(                  /* translate sphere description */ | 
| 433 |  |  | int     ac, | 
| 434 |  |  | char    **av | 
| 435 |  |  | ) | 
| 436 | greg | 1.1 | { | 
| 437 |  |  | register C_VERTEX       *cent; | 
| 438 |  |  |  | 
| 439 |  |  | if (ac != 3) | 
| 440 |  |  | return(MG_EARGC); | 
| 441 | greg | 1.3 | flush_cache();          /* flush vertex cache */ | 
| 442 | greg | 1.1 | printf("%sSeparator {\n", tabs); | 
| 443 |  |  | indent(1); | 
| 444 |  |  | /* put out current material */ | 
| 445 |  |  | if (put_material() < 0) | 
| 446 |  |  | return(MG_EBADMAT); | 
| 447 |  |  | /* get center */ | 
| 448 |  |  | if ((cent = c_getvert(av[1])) == NULL) | 
| 449 |  |  | return(MG_EUNDEF); | 
| 450 |  |  | /* get radius */ | 
| 451 |  |  | if (!isflt(av[2])) | 
| 452 |  |  | return(MG_ETYPE); | 
| 453 |  |  | printf("%sTranslation { translation %13.9g %13.9g %13.9g }\n", tabs, | 
| 454 |  |  | cent->p[0], cent->p[1], cent->p[2]); | 
| 455 |  |  | printf("%sSphere { radius %s }\n", tabs, av[2]); | 
| 456 |  |  | indent(0); | 
| 457 |  |  | printf("%s}\n", tabs); | 
| 458 |  |  | return(MG_OK); | 
| 459 |  |  | } | 
| 460 |  |  |  | 
| 461 |  |  |  | 
| 462 |  |  | int | 
| 463 | schorsch | 1.11 | i_cyl(                  /* translate a cylinder description */ | 
| 464 |  |  | int     ac, | 
| 465 |  |  | char    **av | 
| 466 |  |  | ) | 
| 467 | greg | 1.1 | { | 
| 468 |  |  | register C_VERTEX       *v1, *v2; | 
| 469 |  |  | FVECT   va; | 
| 470 |  |  | double  length, angle; | 
| 471 |  |  |  | 
| 472 |  |  | if (ac != 4) | 
| 473 |  |  | return(MG_EARGC); | 
| 474 | greg | 1.3 | flush_cache();          /* flush vertex cache */ | 
| 475 | greg | 1.1 | printf("%sSeparator {\n", tabs); | 
| 476 |  |  | indent(1); | 
| 477 |  |  | /* put out current material */ | 
| 478 |  |  | if (put_material() < 0) | 
| 479 |  |  | return(MG_EBADMAT); | 
| 480 |  |  | /* get endpoints */ | 
| 481 | schorsch | 1.9 | if (((v1 = c_getvert(av[1])) == NULL) | ((v2 = c_getvert(av[3])) == NULL)) | 
| 482 | greg | 1.1 | return(MG_EUNDEF); | 
| 483 |  |  | /* get radius */ | 
| 484 |  |  | if (!isflt(av[2])) | 
| 485 |  |  | return(MG_ETYPE); | 
| 486 |  |  | /* compute transform */ | 
| 487 |  |  | va[0] = v2->p[0] - v1->p[0]; | 
| 488 |  |  | va[1] = v2->p[1] - v1->p[1]; | 
| 489 |  |  | va[2] = v2->p[2] - v1->p[2]; | 
| 490 |  |  | length = sqrt(DOT(va,va)); | 
| 491 | greg | 1.5 | if (va[1] >= length) | 
| 492 |  |  | angle = 0.; | 
| 493 |  |  | else if (va[1] <= -length) | 
| 494 |  |  | angle = PI; | 
| 495 |  |  | else | 
| 496 |  |  | angle = acos(va[1]/length); | 
| 497 | greg | 1.1 | printf("%sTranslation { translation %13.9g %13.9g %13.9g }\n", tabs, | 
| 498 |  |  | .5*(v1->p[0]+v2->p[0]), .5*(v1->p[1]+v2->p[1]), | 
| 499 |  |  | .5*(v1->p[2]+v2->p[2])); | 
| 500 | greg | 1.2 | printf("%sRotation { rotation %.9g %.9g %.9g %.9g }\n", tabs, | 
| 501 |  |  | va[2], 0., -va[0], angle); | 
| 502 | greg | 1.1 | /* open-ended */ | 
| 503 |  |  | printf("%sCylinder { parts SIDES height %13.9g radius %s }\n", tabs, | 
| 504 |  |  | length, av[2]); | 
| 505 |  |  | indent(0); | 
| 506 |  |  | printf("%s}\n", tabs); | 
| 507 |  |  | return(MG_OK); | 
| 508 | greg | 1.2 | } | 
| 509 |  |  |  | 
| 510 |  |  |  | 
| 511 |  |  | char * | 
| 512 | schorsch | 1.11 | to_id(                  /* make sure a name is a valid Inventor ID */ | 
| 513 |  |  | register char   *name | 
| 514 |  |  | ) | 
| 515 | greg | 1.2 | { | 
| 516 | greg | 1.3 | static char     id[MAXID]; | 
| 517 | greg | 1.2 | register char   *cp; | 
| 518 |  |  |  | 
| 519 | greg | 1.3 | for (cp = id; *name && cp < MAXID-1+id; name++) | 
| 520 | greg | 1.2 | if (isalnum(*name) || *name == '_') | 
| 521 |  |  | *cp++ = *name; | 
| 522 |  |  | else | 
| 523 |  |  | *cp++ = '_'; | 
| 524 |  |  | *cp = '\0'; | 
| 525 |  |  | return(id); | 
| 526 | greg | 1.3 | } | 
| 527 |  |  |  | 
| 528 |  |  |  | 
| 529 | schorsch | 1.11 | void | 
| 530 |  |  | flush_cache(void)                       /* put out cached faces */ | 
| 531 | greg | 1.3 | { | 
| 532 |  |  | int     donorms = 0; | 
| 533 |  |  | register struct face    *f; | 
| 534 |  |  | register int    i; | 
| 535 |  |  |  | 
| 536 |  |  | if (nverts == 0) | 
| 537 |  |  | return; | 
| 538 |  |  | /* put out coordinates */ | 
| 539 |  |  | printf("%sCoordinate3 {\n", tabs); | 
| 540 |  |  | indent(1); | 
| 541 |  |  | vlist[0][VFSEPPOS] = '\0'; | 
| 542 |  |  | printf("%spoint [ %s", tabs, vlist[0]); | 
| 543 |  |  | for (i = 1; i < nverts; i++) { | 
| 544 |  |  | vlist[i][VFSEPPOS] = '\0'; | 
| 545 |  |  | printf(",\n%s        %s", tabs, vlist[i]); | 
| 546 |  |  | if (strcmp(VFSEPPOS+1+vlist[i], VZVECT)) | 
| 547 |  |  | donorms++; | 
| 548 |  |  | } | 
| 549 |  |  | indent(0); | 
| 550 |  |  | printf(" ]\n%s}\n", tabs); | 
| 551 |  |  | if (donorms) {                  /* put out normals */ | 
| 552 |  |  | printf("%sNormal {\n", tabs); | 
| 553 |  |  | indent(1); | 
| 554 |  |  | printf("%svector [ %s", tabs, VFSEPPOS+1+vlist[0]); | 
| 555 |  |  | for (i = 1; i < nverts; i++) | 
| 556 |  |  | printf(",\n%s         %s", tabs, VFSEPPOS+1+vlist[i]); | 
| 557 |  |  | indent(0); | 
| 558 |  |  | printf(" ]\n%s}\n", tabs); | 
| 559 |  |  | } | 
| 560 |  |  | /* put out faces */ | 
| 561 |  |  | printf("%sIndexedFaceSet {\n", tabs); | 
| 562 |  |  | indent(1); | 
| 563 |  |  | f = flist;                      /* coordinate indices */ | 
| 564 |  |  | printf("%scoordIndex [ %d", tabs, f->vl[0]); | 
| 565 |  |  | for (i = 1; i < f->nv; i++) | 
| 566 |  |  | printf(", %d", f->vl[i]); | 
| 567 |  |  | for (f = f->next; f != NULL; f = f->next) { | 
| 568 |  |  | printf(", -1,\n%s             %d", tabs, f->vl[0]); | 
| 569 |  |  | for (i = 1; i < f->nv; i++) | 
| 570 |  |  | printf(", %d", f->vl[i]); | 
| 571 |  |  | } | 
| 572 |  |  | printf(" ]\n"); | 
| 573 |  |  | if (donorms) { | 
| 574 |  |  | f = flist;                      /* normal indices */ | 
| 575 |  |  | printf("%snormalIndex [ %d", tabs, f->vl[0]); | 
| 576 |  |  | for (i = 1; i < f->nv; i++) | 
| 577 |  |  | printf(", %d", f->vl[i]); | 
| 578 |  |  | for (f = f->next; f != NULL; f = f->next) { | 
| 579 |  |  | printf(", -1,\n%s              %d", tabs, f->vl[0]); | 
| 580 |  |  | for (i = 1; i < f->nv; i++) | 
| 581 |  |  | printf(", %d", f->vl[i]); | 
| 582 |  |  | } | 
| 583 |  |  | printf(" ]\n"); | 
| 584 |  |  | } | 
| 585 |  |  | indent(0);                      /* close IndexedFaceSet */ | 
| 586 |  |  | printf("%s}\n", tabs); | 
| 587 |  |  | indent(0);                      /* close face group */ | 
| 588 |  |  | printf("%s}\n", tabs); | 
| 589 |  |  | while ((f = flist) != NULL) {   /* free face list */ | 
| 590 |  |  | flist = f->next; | 
| 591 |  |  | freeface(f); | 
| 592 |  |  | } | 
| 593 |  |  | lu_done(&vert_tab);             /* clear lookup table */ | 
| 594 |  |  | nverts = 0; | 
| 595 | greg | 1.1 | } |