ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgf2inv.c
Revision: 2.1
Committed: Fri Feb 18 00:40:25 2011 UTC (13 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R1
Log Message:
Major code reorg, moving mgflib to common and introducing BSDF material

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: mgf2inv.c,v 1.12 2011/01/14 05:46:12 greg Exp $";
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 "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 #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(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 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
76
77 int
78 main(
79 int argc,
80 char *argv[]
81 )
82 {
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 /* get options and print format line */
108 for (i = 1; i < argc && argv[i][0] == '-'; i++)
109 if (!strcmp(argv[i], "-vrml"))
110 outtype = O_VRML1;
111 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 case O_VRML1:
125 printf("#VRML V1.0 ascii\n");
126 break;
127 }
128 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 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 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 flush_cache(); /* flush face cache, just in case */
158 printf("}\n"); /* close root node */
159 exit(0);
160 userr:
161 fprintf(stderr, "%s: [-1|-2|-vrml] [file] ..\n", argv[0]);
162 exit(1);
163 }
164
165
166 void
167 indent( /* indent in or out */
168 int deeper
169 )
170 {
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 i_comment( /* transfer comment as is */
190 int ac,
191 char **av
192 )
193 {
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 i_object( /* group object name */
207 int ac,
208 char **av
209 )
210 {
211 static int objnest;
212
213 flush_cache(); /* flush cached objects */
214 if (ac == 2) { /* start group */
215 printf("%sDEF %s Group {\n", tabs, to_id(av[1]));
216 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 i_xf( /* transform object(s) */
234 int ac,
235 char **av
236 )
237 {
238 static long xfid;
239 register XF_SPEC *spec;
240
241 flush_cache(); /* flush cached objects */
242 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 put_xform( /* translate and print transform */
303 register XF_SPEC *spec
304 )
305 {
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 put_material(void) /* put out current material */
335 {
336 char *mname = curmatname;
337 float rgbval[3];
338
339 if (!c_cmaterial->clock) { /* current, just use it */
340 printf("%sUSE %s\n", tabs, mname);
341 return(0);
342 }
343 /* else update definition */
344 printf("%sDEF %s Group {\n", tabs, mname);
345 indent(1);
346 printf("%sMaterial {\n", tabs);
347 indent(1);
348 ccy2rgb(&c_cmaterial->rd_c, c_cmaterial->rd, rgbval);
349 printf("%sambientColor %.4f %.4f %.4f\n", tabs,
350 rgbval[0], rgbval[1], rgbval[2]);
351 printf("%sdiffuseColor %.4f %.4f %.4f\n", tabs,
352 rgbval[0], rgbval[1], rgbval[2]);
353 if (c_cmaterial->rs > FTINY) {
354 ccy2rgb(&c_cmaterial->rs_c, c_cmaterial->rs, rgbval);
355 printf("%sspecularColor %.4f %.4f %.4f\n", tabs,
356 rgbval[0], rgbval[1], rgbval[2]);
357 printf("%sshininess %.3f\n", tabs, 1.-sqrt(c_cmaterial->rs_a));
358 }
359 if (c_cmaterial->ed > FTINY) {
360 ccy2rgb(&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 if (outtype != O_INV1)
370 printf("%sShapeHints { shapeType %s faceType UNKNOWN_FACE_TYPE }\n",
371 tabs,
372 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 i_face( /* translate an N-sided face */
382 int ac,
383 char **av
384 )
385 {
386 static char lastmat[MAXID];
387 struct face *newf;
388 register C_VERTEX *vp;
389 register LUENT *lp;
390 register int i;
391
392 if (ac < 4)
393 return(MG_EARGC);
394 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 /* get vertex references */
409 for (i = 0; i < newf->nv; i++) {
410 if ((vp = c_getvert(av[i+1])) == NULL)
411 return(MG_EUNDEF);
412 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 }
420 /* 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 }
429
430
431 int
432 i_sph( /* translate sphere description */
433 int ac,
434 char **av
435 )
436 {
437 register C_VERTEX *cent;
438
439 if (ac != 3)
440 return(MG_EARGC);
441 flush_cache(); /* flush vertex cache */
442 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 i_cyl( /* translate a cylinder description */
464 int ac,
465 char **av
466 )
467 {
468 register C_VERTEX *v1, *v2;
469 FVECT va;
470 double length, angle;
471
472 if (ac != 4)
473 return(MG_EARGC);
474 flush_cache(); /* flush vertex cache */
475 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 if (((v1 = c_getvert(av[1])) == NULL) | ((v2 = c_getvert(av[3])) == NULL))
482 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 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 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 printf("%sRotation { rotation %.9g %.9g %.9g %.9g }\n", tabs,
501 va[2], 0., -va[0], angle);
502 /* 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 }
509
510
511 char *
512 to_id( /* make sure a name is a valid Inventor ID */
513 register char *name
514 )
515 {
516 static char id[MAXID];
517 register char *cp;
518
519 for (cp = id; *name && cp < MAXID-1+id; name++)
520 if (isalnum(*name) || *name == '_')
521 *cp++ = *name;
522 else
523 *cp++ = '_';
524 *cp = '\0';
525 return(id);
526 }
527
528
529 void
530 flush_cache(void) /* put out cached faces */
531 {
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 }