ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/mgf2inv.c
Revision: 1.8
Committed: Fri Feb 28 20:11:29 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 1.7: +3 -4 lines
Log Message:
Updates for 3.5 release

File Contents

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