ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgf2inv.c
Revision: 2.5
Committed: Mon Nov 20 18:32:11 2023 UTC (5 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.4: +3 -1 lines
Log Message:
fix: Added #include of color.h

File Contents

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