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