Back to index

radiance  4R0+20100331
tmesh2rad.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: tmesh2rad.c,v 2.16 2008/11/10 19:08:18 greg Exp $";
00003 #endif
00004 /*
00005  * Convert a trianglular mesh into a Radiance description.
00006  *
00007  * Unlike most other converters, we have defined a file
00008  * format for the input ourselves.  The format contains eight types,
00009  * each of which is identified by a single letter.  These are:
00010  *
00011  *     # comment            = a comment.  Continues until end of line.
00012  *     v id Px Py Pz        = a vertex.  The id must be an integer.
00013  *     n Nx Ny Nz           = a normal.  Corresponds to most recent vertex.
00014  *     i Iu Iv                     = an index.  Corresponds to most recent vertex.
00015  *     p picture            = a picture.  Used as a pattern for following.
00016  *     m material           = a material name.  Used for what follows.
00017  *     o object             = an object name.  Used for what follows.
00018  *     t id1 id2 id3        = a triangle.
00019  *
00020  * Only the 't' type results in any output.  The others merely set values
00021  * to be used in generating triangles.  If no picture or "p -" is given,
00022  * there will be no pattern associated with the geometry.  If no material
00023  * or "m -" is given, no material will be associated.  (Note that this
00024  * only makes sense for a mesh which is to be put into an octree for
00025  * instancing.)  Using a pattern requires that each vertex have an
00026  * associated index value for generating the colorpict primitive.
00027  * Likewise, an interpolated surface normal also requires that each
00028  * vertex of the triangle have an associated normal vector.
00029  * It is not necessary for the normal vectors to have unit length.
00030  */
00031 
00032 #include <stdlib.h>
00033 #include <stdio.h>
00034 
00035 #include "rtmath.h"
00036 
00037 #include "tmesh.h"
00038 
00039 #define VOIDID              "void"        /* this is defined in object.h */
00040 
00041 #define PATNAME             "T-pat"              /* triangle pattern name (reused) */
00042 #define TEXNAME             "T-nor"              /* triangle texture name (reused) */
00043 
00044 #define V_DEFINED    01            /* this vertex is defined */
00045 #define V_HASNORM    02            /* vertex has surface normal */
00046 #define V_HASINDX    04            /* vertex has index */
00047 
00048 typedef struct {
00049        short  flags;        /* vertex flags, from above */
00050        FVECT  pos;          /* location */
00051        FVECT  nor;          /* normal */
00052        float  ndx[2];              /* picture index */
00053 } VERTEX;
00054 
00055 VERTEX *vlist = NULL;              /* our vertex list */
00056 int    nverts = 0;          /* number of vertices in our list */
00057 
00058 #define novert(i)    (((i)<0)|((i)>=nverts) || !(vlist[i].flags&V_DEFINED))
00059 
00060 #define CHUNKSIZ     128    /* vertex allocation chunk size */
00061 
00062 extern VERTEX *vnew();      /* allocate a vertex (never freed) */
00063 
00064 char   *defmat = VOIDID;    /* default (starting) material name */
00065 char   *defpat = "";        /* default (starting) picture name */
00066 char   *defobj = "T";              /* default (starting) object name */
00067 
00068 void convert(char *fname, FILE *fp);
00069 void triangle(char *pn,char *mod,char *obj, VERTEX *v1,VERTEX *v2,VERTEX *v3);
00070 VERTEX *vnew(int id, double x, double y, double z);
00071 void syntax(char *fn, FILE *fp, char *er);
00072 
00073 
00074 int
00075 main(         /* read in T-mesh files and convert */
00076        int    argc,
00077        char   *argv[]
00078 )
00079 {
00080        FILE   *fp;
00081        int    i;
00082 
00083        for (i = 1; i < argc && argv[i][0] == '-'; i++)
00084               switch (argv[i][1]) {
00085               case 'o':            /* object name */
00086                      defobj = argv[++i];
00087                      break;
00088               case 'm':            /* default material */
00089                      defmat = argv[++i];
00090                      break;
00091               case 'p':            /* default picture */
00092                      defpat = argv[++i];
00093                      break;
00094               default:
00095                      fprintf(stderr,
00096                      "Usage: %s [-o obj][-m mat][-p hdr] [file ..]\n",
00097                                    argv[0]);
00098                      exit(1);
00099               }
00100        if (i >= argc)
00101               convert("<stdin>", stdin);
00102        else
00103               for ( ; i < argc; i++) {
00104                      if ((fp = fopen(argv[i], "r")) == NULL) {
00105                             perror(argv[i]);
00106                             exit(1);
00107                      }
00108                      convert(argv[i], fp);
00109                      fclose(fp);
00110               }
00111        exit(0);
00112 }
00113 
00114 
00115 void
00116 convert(             /* convert a T-mesh */
00117        char   *fname,
00118        FILE   *fp
00119 )
00120 {
00121        char   typ[4];
00122        int    id[3];
00123        double vec[3];
00124        char   picfile[128];
00125        char   matname[64];
00126        char   objname[64];
00127        register int  i;
00128        register VERTEX      *lastv;
00129                                    /* start fresh */
00130        i = nverts;
00131        lastv = vlist;
00132        while (i--)
00133               (lastv++)->flags = 0;
00134        lastv = NULL;
00135        strcpy(picfile, defpat);
00136        strcpy(matname, defmat);
00137        strcpy(objname, defobj);
00138 
00139        printf("\n## T-mesh read from: %s\n", fname);
00140                                    /* scan until EOF */
00141        while (fscanf(fp, "%1s", typ) == 1)
00142               switch (typ[0]) {
00143               case 'v':            /* vertex */
00144                      if (fscanf(fp, "%d %lf %lf %lf", &id[0],
00145                                    &vec[0], &vec[1], &vec[2]) != 4)
00146                             syntax(fname, fp, "Bad vertex");
00147                      lastv = vnew(id[0], vec[0], vec[1], vec[2]);
00148                      break;
00149               case 't':            /* triangle */
00150                      if (fscanf(fp, "%d %d %d", &id[0], &id[1], &id[2]) != 3)
00151                             syntax(fname, fp, "Bad triangle");
00152                      if (novert(id[0]) | novert(id[1]) | novert(id[2]))
00153                             syntax(fname, fp, "Undefined triangle vertex");
00154                      triangle(picfile, matname, objname, &vlist[id[0]],
00155                                    &vlist[id[1]], &vlist[id[2]]);
00156                      break;
00157               case 'n':            /* surface normal */
00158                      if (lastv == NULL)
00159                             syntax(fname, fp, "No vertex for normal");
00160                      if (fscanf(fp, "%lf %lf %lf",
00161                                    &vec[0], &vec[1], &vec[2]) != 3)
00162                             syntax(fname, fp, "Bad vertex normal");
00163                      lastv->nor[0] = vec[0];
00164                      lastv->nor[1] = vec[1];
00165                      lastv->nor[2] = vec[2];
00166                      if (normalize(lastv->nor) == 0.0)
00167                             syntax(fname, fp, "Zero vertex normal");
00168                      lastv->flags |= V_HASNORM;
00169                      break;
00170               case 'i':            /* index position */
00171                      if (lastv == NULL)
00172                             syntax(fname, fp, "No vertex for index");
00173                      if (fscanf(fp, "%lf %lf", &vec[0], &vec[1]) != 2)
00174                             syntax(fname, fp, "Bad index");
00175                      lastv->ndx[0] = vec[0];
00176                      lastv->ndx[1] = vec[1];
00177                      lastv->flags |= V_HASINDX;
00178                      break;
00179               case 'o':            /* object name */
00180                      if (fscanf(fp, "%s", objname) != 1)
00181                             syntax(fname, fp, "Bad object name");
00182                      break;
00183               case 'm':            /* material */
00184                      if (fscanf(fp, "%s", matname) != 1)
00185                             syntax(fname, fp, "Bad material");
00186                      if (matname[0] == '-' && !matname[1])
00187                             strcpy(matname, VOIDID);
00188                      break;
00189               case 'p':            /* picture */
00190                      if (fscanf(fp, "%s", picfile) != 1)
00191                             syntax(fname, fp, "Bad pattern");
00192                      if (picfile[0] == '-' && !picfile[1])
00193                             picfile[0] = '\0';
00194                      break;
00195               case '#':            /* comment */
00196                      fputs("\n#", stdout);
00197                      while ((i = getc(fp)) != EOF) {
00198                             putchar(i);
00199                             if (i == '\n')
00200                                    break;
00201                      }
00202                      break;
00203               default:
00204                      syntax(fname, fp, "Unknown type");
00205                      break;
00206               }
00207 }
00208 
00209 
00210 void
00211 triangle(     /* put out a triangle */
00212        char   *pn,
00213        char   *mod,
00214        char   *obj,
00215        register VERTEX      *v1,
00216        register VERTEX      *v2,
00217        register VERTEX      *v3
00218 )
00219 {
00220        static char   vfmt[] = "%18.12g %18.12g %18.12g\n";
00221        static int    ntri = 0;
00222        int           flatness = ISFLAT;
00223        BARYCCM       bvecs;
00224        RREAL  bvm[3][3];
00225        register int  i;
00226                                    /* compute barycentric coordinates */
00227        if (v1->flags & v2->flags & v3->flags & (V_HASINDX|V_HASNORM))
00228               if (comp_baryc(&bvecs, v1->pos, v2->pos, v3->pos) < 0)
00229                      return;
00230                                    /* check flatness */
00231        if (v1->flags & v2->flags & v3->flags & V_HASNORM) {
00232               flatness = flat_tri(v1->pos, v2->pos, v3->pos,
00233                                    v1->nor, v2->nor, v3->nor);
00234               if (flatness == DEGEN)
00235                      return;
00236        }
00237                                    /* put out texture (if any) */
00238        if (flatness == ISBENT || flatness == RVBENT) {
00239               printf("\n%s texfunc %s\n", mod, TEXNAME);
00240               mod = TEXNAME;
00241               printf("4 dx dy dz %s\n", TCALNAME);
00242               printf("0\n");
00243               for (i = 0; i < 3; i++) {
00244                      bvm[i][0] = v1->nor[i];
00245                      bvm[i][1] = v2->nor[i];
00246                      bvm[i][2] = v3->nor[i];
00247               }
00248               put_baryc(&bvecs, bvm, 3);
00249        }
00250                                    /* put out pattern (if any) */
00251        if (*pn && (v1->flags & v2->flags & v3->flags & V_HASINDX)) {
00252               printf("\n%s colorpict %s\n", mod, PATNAME);
00253               mod = PATNAME;
00254               printf("7 noneg noneg noneg %s %s u v\n", pn, TCALNAME);
00255               printf("0\n");
00256               for (i = 0; i < 2; i++) {
00257                      bvm[i][0] = v1->ndx[i];
00258                      bvm[i][1] = v2->ndx[i];
00259                      bvm[i][2] = v3->ndx[i];
00260               }
00261               put_baryc(&bvecs, bvm, 2);
00262        }
00263                                    /* put out (reversed) triangle */
00264        printf("\n%s polygon %s.%d\n", mod, obj, ++ntri);
00265        printf("0\n0\n9\n");
00266        if (flatness == RVFLAT || flatness == RVBENT) {
00267               printf(vfmt, v3->pos[0],v3->pos[1],v3->pos[2]);
00268               printf(vfmt, v2->pos[0],v2->pos[1],v2->pos[2]);
00269               printf(vfmt, v1->pos[0],v1->pos[1],v1->pos[2]);
00270        } else {
00271               printf(vfmt, v1->pos[0],v1->pos[1],v1->pos[2]);
00272               printf(vfmt, v2->pos[0],v2->pos[1],v2->pos[2]);
00273               printf(vfmt, v3->pos[0],v3->pos[1],v3->pos[2]);
00274        }
00275 }
00276 
00277 
00278 VERTEX *
00279 vnew(                /* create a new vertex */
00280        register int  id,
00281        double x,
00282        double y,
00283        double z
00284 )
00285 {
00286        register int  i;
00287 
00288        if (id >= nverts) {         /* get some more */
00289               i = nverts;
00290               nverts = CHUNKSIZ*((id/CHUNKSIZ)+1);
00291               if (vlist == NULL)
00292                      vlist = (VERTEX *)malloc(nverts*sizeof(VERTEX));
00293               else
00294                      vlist = (VERTEX *)realloc((void *)vlist,
00295                                    nverts*sizeof(VERTEX));
00296               if (vlist == NULL) {
00297                      fprintf(stderr,
00298                      "Out of memory while allocating vertex %d\n", id);
00299                      exit(1);
00300               }
00301               while (i < nverts)          /* clear what's new */
00302                      vlist[i++].flags = 0;
00303        }
00304                                    /* assign new vertex */
00305        vlist[id].pos[0] = x;
00306        vlist[id].pos[1] = y;
00307        vlist[id].pos[2] = z;
00308        vlist[id].flags = V_DEFINED;
00309                                    /* return it */
00310        return(&vlist[id]);
00311 }
00312 
00313 
00314 void
00315 syntax(                     /* report syntax error and exit */
00316        char   *fn,
00317        register FILE *fp,
00318        char   *er
00319 )
00320 {
00321        extern long   ftell();
00322        register long cpos;
00323        register int  c;
00324        int    lineno;
00325 
00326        if (fp == stdin)
00327               fprintf(stderr, "%s: T-mesh format error: %s\n", fn, er);
00328        else {
00329               cpos = ftell(fp);
00330               fseek(fp, 0L, 0);
00331               lineno = 1;
00332               while (cpos-- > 0) {
00333                      if ((c = getc(fp)) == EOF)
00334                             break;
00335                      if (c == '\n')
00336                             lineno++;
00337               }
00338               fprintf(stderr, "%s: T-mesh format error at line %d: %s\n",
00339                             fn, lineno, er);
00340        }
00341        exit(1);
00342 }