Back to index

radiance  4R0+20100331
mgf2inv.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: mgf2inv.c,v 1.11 2003/11/15 17:54:06 schorsch Exp $";
00003 #endif
00004 /*
00005  * Convert MGF to Inventor file.
00006  *
00007  *     December 1995 Greg Ward
00008  */
00009 
00010 #include <stdio.h>
00011 
00012 #include <stdlib.h>
00013 
00014 #include <math.h>
00015 
00016 #include <ctype.h>
00017 
00018 #include <string.h>
00019 
00020 #include "parser.h"
00021 
00022 #include "lookup.h"
00023 
00024 #define O_INV1              1      /* Inventor 1.0 output */
00025 #define O_INV2              2      /* Inventor 2.0 output */
00026 #define O_VRML1             3      /* VRML 1.0 output */
00027 
00028 #define MAXID        48     /* maximum identifier length */
00029 
00030 #define VERTFMT             "%+16.9e %+16.9e %+16.9e\n%+6.3f %+6.3f %+6.3f"
00031 #define VZVECT              "+0.000 +0.000 +0.000"
00032 #define VFSEPPOS     50     /* position of newline in above */
00033 #define VFLEN        72     /* total vertex string length */
00034 #define MAXVERT             10240  /* maximum cached vertices */
00035 
00036 #define setvkey(k,v) sprintf(k,VERTFMT,(v)->p[0],(v)->p[1],(v)->p[2],\
00037                                    (v)->n[0],(v)->n[1],(v)->n[2]);
00038 
00039 char   vlist[MAXVERT][VFLEN];      /* our vertex cache */
00040 int    nverts;                     /* current cache size */
00041 
00042 LUTAB  vert_tab = LU_SINIT(NULL,NULL);
00043 
00044 struct face {
00045        struct face   *next;        /* next face in list */
00046        short         nv;           /* number of vertices */
00047        short         vl[3];        /* vertex index list (variable) */
00048 }      *flist, *flast;             /* our face cache */
00049 
00050 #define newface(n)   (struct face *)malloc(sizeof(struct face) + \
00051                             ((n) > 3 ? (n)-3 : 0)*sizeof(short))
00052 #define freeface(f)  free((MEM_PTR)f)
00053 
00054 #define       TABSTOP              8      /* assumed number of characters per tab */
00055 #define       SHIFTW        2      /* nesting shift width */
00056 #define MAXIND              15     /* maximum indent level */
00057 
00058 char   tabs[MAXIND*SHIFTW+1];      /* current tab-in string */
00059 
00060 #define curmatname   (c_cmname == NULL ? "mat" : to_id(c_cmname))
00061 
00062 int    outtype = O_INV2;    /* output format */
00063 
00064 int i_comment(int ac, char **av);
00065 int i_object(int ac, char **av);
00066 int i_xf(int ac, char **av);
00067 int put_xform(register XF_SPEC *spec);
00068 int put_material(void);
00069 int i_face(int ac, char **av);
00070 int i_sph(int ac, char **av);
00071 int i_cyl(int ac, char **av);
00072 char * to_id(register char *name);
00073 char * to_id(register char *name);
00074 void flush_cache(void); 
00075 
00076 
00077 int
00078 main(
00079        int    argc,
00080        char   *argv[]
00081 )
00082 {
00083        int    i;
00084                             /* initialize dispatch table */
00085        mg_ehand[MG_E_COMMENT] = i_comment;       /* we pass comments */
00086        mg_ehand[MG_E_COLOR] = c_hcolor;   /* they get color */
00087        mg_ehand[MG_E_CMIX] = c_hcolor;           /* they mix colors */
00088        mg_ehand[MG_E_CSPEC] = c_hcolor;   /* they get spectra */
00089        mg_ehand[MG_E_CXY] = c_hcolor;            /* they get chromaticities */
00090        mg_ehand[MG_E_CCT] = c_hcolor;            /* they get color temp's */
00091        mg_ehand[MG_E_CYL] = i_cyl;        /* we do cylinders */
00092        mg_ehand[MG_E_ED] = c_hmaterial;   /* they get emission */
00093        mg_ehand[MG_E_FACE] = i_face;             /* we do faces */
00094        mg_ehand[MG_E_MATERIAL] = c_hmaterial;    /* they get materials */
00095        mg_ehand[MG_E_NORMAL] = c_hvertex; /* they get normals */
00096        mg_ehand[MG_E_OBJECT] = i_object;  /* we track object names */
00097        mg_ehand[MG_E_POINT] = c_hvertex;  /* they get points */
00098        mg_ehand[MG_E_RD] = c_hmaterial;   /* they get diffuse refl. */
00099        mg_ehand[MG_E_RS] = c_hmaterial;   /* they get specular refl. */
00100        mg_ehand[MG_E_SIDES] = c_hmaterial;       /* they get # sides */
00101        mg_ehand[MG_E_SPH] = i_sph;        /* we do spheres */
00102        mg_ehand[MG_E_TD] = c_hmaterial;   /* they get diffuse trans. */
00103        mg_ehand[MG_E_TS] = c_hmaterial;   /* they get specular trans. */
00104        mg_ehand[MG_E_VERTEX] = c_hvertex; /* they get vertices */
00105        mg_ehand[MG_E_XF] = i_xf;          /* we track transforms */
00106        mg_init();           /* initialize the parser */
00107                             /* get options and print format line */
00108        for (i = 1; i < argc && argv[i][0] == '-'; i++)
00109               if (!strcmp(argv[i], "-vrml"))
00110                      outtype = O_VRML1;
00111               else if (!strcmp(argv[i], "-1"))
00112                      outtype = O_INV1;
00113               else if (!strcmp(argv[i], "-2"))
00114                      outtype = O_INV2;
00115               else
00116                      goto userr;
00117        switch (outtype) {
00118        case O_INV1:
00119               printf("#Inventor V1.0 ascii\n");
00120               break;
00121        case O_INV2:
00122               printf("#Inventor V2.0 ascii\n");
00123               break;
00124        case O_VRML1:
00125               printf("#VRML V1.0 ascii\n");
00126               break;
00127        }
00128        printf("## Translated from MGF Version %d.%d\n", MG_VMAJOR, MG_VMINOR);
00129        printf("Separator {\n");           /* begin root node */
00130                                           /* general properties */
00131        printf("MaterialBinding { value OVERALL }\n");
00132        printf("NormalBinding { value PER_VERTEX_INDEXED }\n");
00133        if (outtype != O_INV1) {
00134               printf("ShapeHints {\n");
00135               printf("\tvertexOrdering CLOCKWISE\n");
00136               printf("\tfaceType UNKNOWN_FACE_TYPE\n");
00137               printf("}\n");
00138        }
00139        if (i == argc) {     /* load standard input */
00140               if (mg_load(NULL) != MG_OK)
00141                      exit(1);
00142               if (mg_nunknown)
00143                      printf("## %s: %u unknown entities\n",
00144                                    argv[0], mg_nunknown);
00145        }
00146                             /* load MGF files */
00147        for ( ; i < argc; i++) {
00148               printf("## %s %s ##############################\n",
00149                             argv[0], argv[i]);
00150               mg_nunknown = 0;
00151               if (mg_load(argv[i]) != MG_OK)
00152                      exit(1);
00153               if (mg_nunknown)
00154                      printf("## %s %s: %u unknown entities\n",
00155                                    argv[0], argv[i], mg_nunknown);
00156        }
00157        flush_cache();              /* flush face cache, just in case */
00158        printf("}\n");              /* close root node */
00159        exit(0);
00160 userr:
00161        fprintf(stderr, "%s: [-1|-2|-vrml] [file] ..\n", argv[0]);
00162        exit(1);
00163 }
00164 
00165 
00166 void
00167 indent(                            /* indent in or out */
00168        int    deeper
00169 )
00170 {
00171        static int    level;        /* current nesting level */
00172        register int  i;
00173        register char *cp;
00174 
00175        if (deeper) level++;        /* in or out? */
00176        else if (level > 0) level--;
00177                                    /* compute actual shift */
00178        if ((i = level) > MAXIND) i = MAXIND;
00179        cp = tabs;
00180        for (i *= SHIFTW; i >= TABSTOP; i -= TABSTOP)
00181               *cp++ = '\t';
00182        while (i--)
00183               *cp++ = ' ';
00184        *cp = '\0';
00185 }
00186 
00187 
00188 int
00189 i_comment(                  /* transfer comment as is */
00190        int    ac,
00191        char   **av
00192 )
00193 {
00194        fputs(tabs, stdout);
00195        putchar('#');               /* Inventor comment character */
00196        while (--ac > 0) {
00197               putchar(' ');
00198               fputs(*++av, stdout);
00199        }
00200        putchar('\n');
00201        return(MG_OK);
00202 }
00203 
00204 
00205 int
00206 i_object(                   /* group object name */
00207        int    ac,
00208        char   **av
00209 )
00210 {
00211        static int    objnest;
00212 
00213        flush_cache();                     /* flush cached objects */
00214        if (ac == 2) {                            /* start group */
00215               printf("%sDEF %s Group {\n", tabs, to_id(av[1]));
00216               indent(1);
00217               objnest++;
00218               return(MG_OK);
00219        }
00220        if (ac == 1) {                            /* end group */
00221               if (--objnest < 0)
00222                      return(MG_ECNTXT);
00223               indent(0);
00224               fputs(tabs, stdout);
00225               fputs("}\n", stdout);
00226               return(MG_OK);
00227        }
00228        return(MG_EARGC);
00229 }
00230 
00231 
00232 int
00233 i_xf(                       /* transform object(s) */
00234        int    ac,
00235        char   **av
00236 )
00237 {
00238        static long   xfid;
00239        register XF_SPEC     *spec;
00240 
00241        flush_cache();                     /* flush cached objects */
00242        if (ac == 1) {                     /* end of transform */
00243               if ((spec = xf_context) == NULL)
00244                      return(MG_ECNTXT);
00245               indent(0);                  /* close original segment */
00246               printf("%s}\n", tabs);
00247               indent(0);
00248               printf("%s}\n", tabs);
00249               if (spec->xarr != NULL) {   /* check for iteration */
00250                      register struct xf_array    *ap = spec->xarr;
00251                      register int  n;
00252 
00253                      ap->aarg[ap->ndim-1].i = 1; /* iterate array */
00254                      for ( ; ; ) {
00255                             n = ap->ndim-1;
00256                             while (ap->aarg[n].i < ap->aarg[n].n) {
00257                                    sprintf(ap->aarg[n].arg, "%d",
00258                                                  ap->aarg[n].i);
00259                                    printf("%sSeparator {\n", tabs);
00260                                    indent(1);
00261                                    (void)put_xform(spec);
00262                                    printf("%sUSE _xf%ld\n", tabs,
00263                                                  spec->xid);
00264                                    indent(0);
00265                                    printf("%s}\n", tabs);
00266                                    ++ap->aarg[n].i;
00267                             }
00268                             ap->aarg[n].i = 0;
00269                             (void)strcpy(ap->aarg[n].arg, "0");
00270                             while (n-- && ++ap->aarg[n].i >= ap->aarg[n].n) {
00271                                    ap->aarg[n].i = 0;
00272                                    (void)strcpy(ap->aarg[n].arg, "0");
00273                             }
00274                             if (n < 0)
00275                                    break;
00276                             sprintf(ap->aarg[n].arg, "%d", ap->aarg[n].i);
00277                      }
00278               }
00279                                           /* pop transform */
00280               xf_context = spec->prev;
00281               free_xf(spec);
00282               return(MG_OK);
00283        }
00284                                    /* else allocate new transform */
00285        if ((spec = new_xf(ac-1, av+1)) == NULL)
00286               return(MG_EMEM);
00287        spec->xid = ++xfid;         /* assign unique ID */
00288        spec->prev = xf_context;    /* push onto stack */
00289        xf_context = spec;
00290                                    /* translate xf specification */
00291        printf("%sSeparator {\n", tabs);
00292        indent(1);
00293        if (put_xform(spec) < 0)
00294               return(MG_ETYPE);
00295        printf("%sDEF _xf%ld Group {\n", tabs, spec->xid);      /* begin */
00296        indent(1);
00297        return(MG_OK);
00298 }
00299 
00300 
00301 int
00302 put_xform(                  /* translate and print transform */
00303        register XF_SPEC     *spec
00304 )
00305 {
00306        register char **av;
00307        register int  n;
00308 
00309        n = xf_ac(spec) - xf_ac(spec->prev);
00310        if (xf(&spec->xf, n, av=xf_av(spec)) != n)
00311               return(-1);
00312        printf("%sMatrixTransform {\n", tabs);
00313        indent(1);
00314        printf("%s# xf", tabs);            /* put out original as comment */
00315        while (n--) {
00316               putchar(' ');
00317               fputs(*av++, stdout);
00318        }
00319        putchar('\n');                     /* put out computed matrix */
00320        printf("%smatrix %13.9g %13.9g %13.9g %13.9g\n", tabs,
00321                      spec->xf.xfm[0][0], spec->xf.xfm[0][1],
00322                      spec->xf.xfm[0][2], spec->xf.xfm[0][3]);
00323        for (n = 1; n < 4; n++)
00324               printf("%s       %13.9g %13.9g %13.9g %13.9g\n", tabs,
00325                             spec->xf.xfm[n][0], spec->xf.xfm[n][1],
00326                             spec->xf.xfm[n][2], spec->xf.xfm[n][3]);
00327        indent(0);
00328        printf("%s}\n", tabs);
00329        return(0);
00330 }
00331 
00332 
00333 int
00334 put_material(void)                 /* put out current material */
00335 {
00336        char   *mname = curmatname;
00337        float  rgbval[3];
00338 
00339        if (!c_cmaterial->clock) {  /* current, just use it */
00340               printf("%sUSE %s\n", tabs, mname);
00341               return(0);
00342        }
00343                             /* else update definition */
00344        printf("%sDEF %s Group {\n", tabs, mname);
00345        indent(1);
00346        printf("%sMaterial {\n", tabs);
00347        indent(1);
00348        mgf2rgb(&c_cmaterial->rd_c, c_cmaterial->rd, rgbval);
00349        printf("%sambientColor %.4f %.4f %.4f\n", tabs,
00350                      rgbval[0], rgbval[1], rgbval[2]);
00351        printf("%sdiffuseColor %.4f %.4f %.4f\n", tabs,
00352                      rgbval[0], rgbval[1], rgbval[2]);
00353        if (c_cmaterial->rs > FTINY) {
00354               mgf2rgb(&c_cmaterial->rs_c, c_cmaterial->rs, rgbval);
00355               printf("%sspecularColor %.4f %.4f %.4f\n", tabs,
00356                             rgbval[0], rgbval[1], rgbval[2]);
00357               printf("%sshininess %.3f\n", tabs, 1.-sqrt(c_cmaterial->rs_a));
00358        }
00359        if (c_cmaterial->ed > FTINY) {
00360               mgf2rgb(&c_cmaterial->ed_c, 1.0, rgbval);
00361               printf("%semissiveColor %.4f %.4f %.4f\n", tabs,
00362                             rgbval[0], rgbval[1], rgbval[2]);
00363        }
00364        if (c_cmaterial->ts > FTINY)
00365               printf("%stransparency %.4f\n", tabs,
00366                             c_cmaterial->ts + c_cmaterial->td);
00367        indent(0);
00368        printf("%s}\n", tabs);
00369        if (outtype != O_INV1)
00370               printf("%sShapeHints { shapeType %s faceType UNKNOWN_FACE_TYPE }\n",
00371                      tabs,
00372                      c_cmaterial->sided ? "SOLID" : "UNKNOWN_SHAPE_TYPE");
00373        indent(0);
00374        printf("%s}\n", tabs);
00375        c_cmaterial->clock = 0;
00376        return(0);
00377 }
00378 
00379 
00380 int
00381 i_face(                     /* translate an N-sided face */
00382        int    ac,
00383        char   **av
00384 )
00385 {
00386        static char   lastmat[MAXID];
00387        struct face   *newf;
00388        register C_VERTEX    *vp;
00389        register LUENT       *lp;
00390        register int  i;
00391 
00392        if (ac < 4)
00393               return(MG_EARGC);
00394        if ( strcmp(lastmat, curmatname) || c_cmaterial->clock ||
00395                      nverts == 0 || nverts+ac-1 >= MAXVERT) {
00396               flush_cache();                     /* new cache */
00397               lu_init(&vert_tab, MAXVERT);
00398               printf("%sSeparator {\n", tabs);
00399               indent(1);
00400               if (put_material() < 0)            /* put out material */
00401                      return(MG_EBADMAT);
00402               (void)strcpy(lastmat, curmatname);
00403        }
00404                             /* allocate new face */
00405        if ((newf = newface(ac-1)) == NULL)
00406               return(MG_EMEM);
00407        newf->nv = ac-1;
00408                             /* get vertex references */
00409        for (i = 0; i < newf->nv; i++) {
00410               if ((vp = c_getvert(av[i+1])) == NULL)
00411                      return(MG_EUNDEF);
00412               setvkey(vlist[nverts], vp);
00413               lp = lu_find(&vert_tab, vlist[nverts]);
00414               if (lp == NULL)
00415                      return(MG_EMEM);
00416               if (lp->key == NULL)
00417                      lp->key = (char *)vlist[nverts++];
00418               newf->vl[i] = ((char (*)[VFLEN])lp->key - vlist);
00419        }
00420                             /* add to face list */
00421        newf->next = NULL;
00422        if (flist == NULL)
00423               flist = newf;
00424        else
00425               flast->next = newf;
00426        flast = newf;
00427        return(MG_OK);              /* we'll actually put it out later */
00428 }
00429 
00430 
00431 int
00432 i_sph(               /* translate sphere description */
00433        int    ac,
00434        char   **av
00435 )
00436 {
00437        register C_VERTEX    *cent;
00438 
00439        if (ac != 3)
00440               return(MG_EARGC);
00441        flush_cache();              /* flush vertex cache */
00442        printf("%sSeparator {\n", tabs);
00443        indent(1);
00444                             /* put out current material */
00445        if (put_material() < 0)
00446               return(MG_EBADMAT);
00447                             /* get center */
00448        if ((cent = c_getvert(av[1])) == NULL)
00449               return(MG_EUNDEF);
00450                             /* get radius */
00451        if (!isflt(av[2]))
00452               return(MG_ETYPE);
00453        printf("%sTranslation { translation %13.9g %13.9g %13.9g }\n", tabs,
00454                      cent->p[0], cent->p[1], cent->p[2]);
00455        printf("%sSphere { radius %s }\n", tabs, av[2]);
00456        indent(0);
00457        printf("%s}\n", tabs);
00458        return(MG_OK);
00459 }
00460 
00461 
00462 int
00463 i_cyl(               /* translate a cylinder description */
00464        int    ac,
00465        char   **av
00466 )
00467 {
00468        register C_VERTEX    *v1, *v2;
00469        FVECT  va;
00470        double length, angle;
00471 
00472        if (ac != 4)
00473               return(MG_EARGC);
00474        flush_cache();              /* flush vertex cache */
00475        printf("%sSeparator {\n", tabs);
00476        indent(1);
00477                             /* put out current material */
00478        if (put_material() < 0)
00479               return(MG_EBADMAT);
00480                             /* get endpoints */
00481        if (((v1 = c_getvert(av[1])) == NULL) | ((v2 = c_getvert(av[3])) == NULL))
00482               return(MG_EUNDEF);
00483                             /* get radius */
00484        if (!isflt(av[2]))
00485               return(MG_ETYPE);
00486                             /* compute transform */
00487        va[0] = v2->p[0] - v1->p[0];
00488        va[1] = v2->p[1] - v1->p[1];
00489        va[2] = v2->p[2] - v1->p[2];
00490        length = sqrt(DOT(va,va));
00491        if (va[1] >= length)
00492               angle = 0.;
00493        else if (va[1] <= -length)
00494               angle = PI;
00495        else
00496               angle = acos(va[1]/length);
00497        printf("%sTranslation { translation %13.9g %13.9g %13.9g }\n", tabs,
00498                      .5*(v1->p[0]+v2->p[0]), .5*(v1->p[1]+v2->p[1]),
00499                      .5*(v1->p[2]+v2->p[2]));
00500        printf("%sRotation { rotation %.9g %.9g %.9g %.9g }\n", tabs,
00501                      va[2], 0., -va[0], angle);
00502                             /* open-ended */
00503        printf("%sCylinder { parts SIDES height %13.9g radius %s }\n", tabs,
00504                      length, av[2]);
00505        indent(0);
00506        printf("%s}\n", tabs);
00507        return(MG_OK);
00508 }
00509 
00510 
00511 char *
00512 to_id(               /* make sure a name is a valid Inventor ID */
00513        register char *name
00514 )
00515 {
00516        static char   id[MAXID];
00517        register char *cp;
00518 
00519        for (cp = id; *name && cp < MAXID-1+id; name++)
00520               if (isalnum(*name) || *name == '_')
00521                      *cp++ = *name;
00522               else
00523                      *cp++ = '_';
00524        *cp = '\0';
00525        return(id);
00526 }
00527 
00528 
00529 void
00530 flush_cache(void)                  /* put out cached faces */
00531 {
00532        int    donorms = 0;
00533        register struct face *f;
00534        register int  i;
00535 
00536        if (nverts == 0)
00537               return;
00538                                    /* put out coordinates */
00539        printf("%sCoordinate3 {\n", tabs);
00540        indent(1);
00541        vlist[0][VFSEPPOS] = '\0';
00542        printf("%spoint [ %s", tabs, vlist[0]);
00543        for (i = 1; i < nverts; i++) {
00544               vlist[i][VFSEPPOS] = '\0';
00545               printf(",\n%s        %s", tabs, vlist[i]);
00546               if (strcmp(VFSEPPOS+1+vlist[i], VZVECT))
00547                      donorms++;
00548        }
00549        indent(0);
00550        printf(" ]\n%s}\n", tabs);
00551        if (donorms) {                     /* put out normals */
00552               printf("%sNormal {\n", tabs);
00553               indent(1);
00554               printf("%svector [ %s", tabs, VFSEPPOS+1+vlist[0]);
00555               for (i = 1; i < nverts; i++)
00556                      printf(",\n%s         %s", tabs, VFSEPPOS+1+vlist[i]);
00557               indent(0);
00558               printf(" ]\n%s}\n", tabs);
00559        }
00560                                    /* put out faces */
00561        printf("%sIndexedFaceSet {\n", tabs);
00562        indent(1);
00563        f = flist;                  /* coordinate indices */
00564        printf("%scoordIndex [ %d", tabs, f->vl[0]);
00565        for (i = 1; i < f->nv; i++)
00566               printf(", %d", f->vl[i]);
00567        for (f = f->next; f != NULL; f = f->next) {
00568               printf(", -1,\n%s             %d", tabs, f->vl[0]);
00569               for (i = 1; i < f->nv; i++)
00570                      printf(", %d", f->vl[i]);
00571        }
00572        printf(" ]\n");
00573        if (donorms) {
00574               f = flist;                  /* normal indices */
00575               printf("%snormalIndex [ %d", tabs, f->vl[0]);
00576               for (i = 1; i < f->nv; i++)
00577                      printf(", %d", f->vl[i]);
00578               for (f = f->next; f != NULL; f = f->next) {
00579                      printf(", -1,\n%s              %d", tabs, f->vl[0]);
00580                      for (i = 1; i < f->nv; i++)
00581                             printf(", %d", f->vl[i]);
00582               }
00583               printf(" ]\n");
00584        }
00585        indent(0);                  /* close IndexedFaceSet */
00586        printf("%s}\n", tabs);
00587        indent(0);                  /* close face group */
00588        printf("%s}\n", tabs);
00589        while ((f = flist) != NULL) {      /* free face list */
00590               flist = f->next;
00591               freeface(f);
00592        }
00593        lu_done(&vert_tab);         /* clear lookup table */
00594        nverts = 0;
00595 }