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