ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/mgf2inv.c
Revision: 1.5
Committed: Wed Feb 5 14:53:33 1997 UTC (27 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.4: +6 -1 lines
Log Message:
fixed floating point error due to round-off passed to acos()

File Contents

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