Back to index

radiance  4R0+20100331
readmesh.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char RCSid[] = "$Id: readmesh.c,v 2.13 2004/09/14 02:53:50 greg Exp $";
00003 #endif
00004 /*
00005  *  Routines for reading a compiled mesh from a file
00006  */
00007 
00008 #include  <time.h>
00009 
00010 #include  "platform.h"
00011 #include  "standard.h"
00012 #include  "octree.h"
00013 #include  "object.h"
00014 #include  "mesh.h"
00015 #include  "resolu.h"
00016 
00017 #ifdef getc_unlocked        /* avoid horrendous overhead of flockfile */
00018 #undef getc
00019 #define getc    getc_unlocked
00020 #endif
00021 
00022 static char   *meshfn;      /* input file name */
00023 static FILE   *meshfp;      /* mesh file pointer */
00024 static int    objsize;      /* sizeof(OBJECT) from writer */
00025 
00026 
00027 static void
00028 mesherror(etyp, msg)               /* mesh read error */
00029 int  etyp;
00030 char  *msg;
00031 {
00032        char  msgbuf[128];
00033 
00034        sprintf(msgbuf, "(%s): %s", meshfn, msg);
00035        error(etyp, msgbuf);
00036 }
00037 
00038 
00039 static long
00040 mgetint(siz)                       /* get a siz-byte integer */
00041 int  siz;
00042 {
00043        register long  r;
00044 
00045        r = getint(siz, meshfp);
00046        if (feof(meshfp))
00047               mesherror(USER, "truncated mesh file");
00048        return(r);
00049 }
00050 
00051 
00052 static double
00053 mgetflt()                          /* get a floating point number */
00054 {
00055        double r;
00056 
00057        r = getflt(meshfp);
00058        if (feof(meshfp))
00059               mesherror(USER, "truncated mesh file");
00060        return(r);
00061 }
00062        
00063 
00064 static OCTREE
00065 getfullnode()                      /* get a set, return fullnode */
00066 {
00067        OBJECT set[MAXSET+1];
00068        register int  i;
00069 
00070        if ((set[0] = mgetint(objsize)) > MAXSET)
00071               mesherror(USER, "bad set in getfullnode");
00072        for (i = 1; i <= set[0]; i++)
00073               set[i] = mgetint(objsize);
00074        return(fullnode(set));
00075 }      
00076 
00077 
00078 static OCTREE
00079 gettree()                          /* get a pre-ordered octree */
00080 {
00081        register OCTREE       ot;
00082        register int  i;
00083        
00084        switch (getc(meshfp)) {
00085               case OT_EMPTY:
00086                      return(EMPTY);
00087               case OT_FULL:
00088                      return(getfullnode());
00089               case OT_TREE:
00090                      if ((ot = octalloc()) == EMPTY)
00091                             mesherror(SYSTEM, "out of tree space in readmesh");
00092                      for (i = 0; i < 8; i++)
00093                             octkid(ot, i) = gettree();
00094                      return(ot);
00095               case EOF:
00096                      mesherror(USER, "truncated mesh octree");
00097               default:
00098                      mesherror(USER, "damaged mesh octree");
00099        }
00100        return (OCTREE)NULL; /* pro forma return */
00101 }
00102 
00103 
00104 static void
00105 skiptree()                         /* skip octree on input */
00106 {
00107        register int  i;
00108        
00109        switch (getc(meshfp)) {
00110        case OT_EMPTY:
00111               return;
00112        case OT_FULL:
00113               for (i = mgetint(objsize)*objsize; i-- > 0; )
00114                      if (getc(meshfp) == EOF)
00115                             mesherror(USER, "truncated mesh octree");
00116               return;
00117        case OT_TREE:
00118               for (i = 0; i < 8; i++)
00119                      skiptree();
00120               return;
00121        case EOF:
00122               mesherror(USER, "truncated mesh octree");
00123        default:
00124               mesherror(USER, "damaged mesh octree");
00125        }
00126 }
00127 
00128 
00129 static void
00130 getpatch(pp)                       /* load a mesh patch */
00131 register MESHPATCH   *pp;
00132 {
00133        int    flags;
00134        int    i, j;
00135                                    /* vertex flags */
00136        flags = mgetint(1);
00137        if (!(flags & MT_V) || flags & ~(MT_V|MT_N|MT_UV))
00138               mesherror(USER, "bad patch flags");
00139                                    /* allocate vertices */
00140        pp->nverts = mgetint(2);
00141        if (pp->nverts <= 0 || pp->nverts > 256)
00142               mesherror(USER, "bad number of patch vertices");
00143        pp->xyz = (uint32 (*)[3])malloc(pp->nverts*3*sizeof(uint32));
00144        if (pp->xyz == NULL)
00145               goto nomem;
00146        if (flags & MT_N) {
00147               pp->norm = (int32 *)calloc(pp->nverts, sizeof(int32));
00148               if (pp->norm == NULL)
00149                      goto nomem;
00150        } else
00151               pp->norm = NULL;
00152        if (flags & MT_UV) {
00153               pp->uv = (uint32 (*)[2])calloc(pp->nverts, 2*sizeof(uint32));
00154               if (pp->uv == NULL)
00155                      goto nomem;
00156        } else
00157               pp->uv = NULL;
00158                                    /* vertex xyz locations */
00159        for (i = 0; i < pp->nverts; i++)
00160               for (j = 0; j < 3; j++)
00161                      pp->xyz[i][j] = mgetint(4);
00162                                    /* vertex normals */
00163        if (flags & MT_N)
00164               for (i = 0; i < pp->nverts; i++)
00165                      pp->norm[i] = mgetint(4);
00166                                    /* uv coordinates */
00167        if (flags & MT_UV)
00168               for (i = 0; i < pp->nverts; i++)
00169                      for (j = 0; j < 2; j++)
00170                             pp->uv[i][j] = mgetint(4);
00171                                    /* local triangles */
00172        pp->ntris = mgetint(2);
00173        if (pp->ntris < 0 || pp->ntris > 512)
00174               mesherror(USER, "bad number of local triangles");
00175        if (pp->ntris) {
00176               pp->tri = (struct PTri *)malloc(pp->ntris *
00177                                           sizeof(struct PTri));
00178               if (pp->tri == NULL)
00179                      goto nomem;
00180               for (i = 0; i < pp->ntris; i++) {
00181                      pp->tri[i].v1 = mgetint(1);
00182                      pp->tri[i].v2 = mgetint(1);
00183                      pp->tri[i].v3 = mgetint(1);
00184               }
00185        } else
00186               pp->tri = NULL;
00187                                    /* local triangle material(s) */
00188        if (mgetint(2) > 1) {
00189               pp->trimat = (int16 *)malloc(pp->ntris*sizeof(int16));
00190               if (pp->trimat == NULL)
00191                      goto nomem;
00192               for (i = 0; i < pp->ntris; i++)
00193                      pp->trimat[i] = mgetint(2);
00194        } else {
00195               pp->solemat = mgetint(2);
00196               pp->trimat = NULL;
00197        }
00198                                    /* joiner triangles */
00199        pp->nj1tris = mgetint(2);
00200        if (pp->nj1tris < 0 || pp->nj1tris > 512)
00201               mesherror(USER, "bad number of joiner triangles");
00202        if (pp->nj1tris) {
00203               pp->j1tri = (struct PJoin1 *)malloc(pp->nj1tris *
00204                                           sizeof(struct PJoin1));
00205               if (pp->j1tri == NULL)
00206                      goto nomem;
00207               for (i = 0; i < pp->nj1tris; i++) {
00208                      pp->j1tri[i].v1j = mgetint(4);
00209                      pp->j1tri[i].v2 = mgetint(1);
00210                      pp->j1tri[i].v3 = mgetint(1);
00211                      pp->j1tri[i].mat = mgetint(2);
00212               }
00213        } else
00214               pp->j1tri = NULL;
00215                                    /* double joiner triangles */
00216        pp->nj2tris = mgetint(2);
00217        if (pp->nj2tris < 0 || pp->nj2tris > 256)
00218               mesherror(USER, "bad number of double joiner triangles");
00219        if (pp->nj2tris) {
00220               pp->j2tri = (struct PJoin2 *)malloc(pp->nj2tris *
00221                                           sizeof(struct PJoin2));
00222               if (pp->j2tri == NULL)
00223                      goto nomem;
00224               for (i = 0; i < pp->nj2tris; i++) {
00225                      pp->j2tri[i].v1j = mgetint(4);
00226                      pp->j2tri[i].v2j = mgetint(4);
00227                      pp->j2tri[i].v3 = mgetint(1);
00228                      pp->j2tri[i].mat = mgetint(2);
00229               }
00230        } else
00231               pp->j2tri = NULL;
00232        return;
00233 nomem:
00234        error(SYSTEM, "out of mesh memory in getpatch");
00235 }
00236 
00237 
00238 void
00239 readmesh(mp, path, flags)          /* read in mesh structures */
00240 MESH   *mp;
00241 char   *path;
00242 int    flags;
00243 {
00244        char   *err;
00245        char   sbuf[64];
00246        int    i;
00247                                    /* check what's loaded */
00248        flags &= (IO_INFO|IO_BOUNDS|IO_TREE|IO_SCENE) & ~mp->ldflags;
00249                                    /* open input file */
00250        if (path == NULL) {
00251               meshfn = "standard input";
00252               meshfp = stdin;
00253        } else if ((meshfp = fopen(meshfn=path, "r")) == NULL) {
00254               sprintf(errmsg, "cannot open mesh file \"%s\"", path);
00255               error(SYSTEM, errmsg);
00256        }
00257        SET_FILE_BINARY(meshfp);
00258                                    /* read header */
00259        checkheader(meshfp, MESHFMT, flags&IO_INFO ? stdout : (FILE *)NULL);
00260                                    /* read format number */
00261        objsize = getint(2, meshfp) - MESHMAGIC;
00262        if (objsize <= 0 || objsize > MAXOBJSIZ || objsize > sizeof(long))
00263               mesherror(USER, "incompatible mesh format");
00264                                    /* read boundaries */
00265        if (flags & IO_BOUNDS) {
00266               for (i = 0; i < 3; i++)
00267                      mp->mcube.cuorg[i] = atof(getstr(sbuf, meshfp));
00268               mp->mcube.cusize = atof(getstr(sbuf, meshfp));
00269               for (i = 0; i < 2; i++) {
00270                      mp->uvlim[0][i] = mgetflt();
00271                      mp->uvlim[1][i] = mgetflt();
00272               }
00273        } else {
00274               for (i = 0; i < 4; i++)
00275                      getstr(sbuf, meshfp);
00276               for (i = 0; i < 4; i++)
00277                      mgetflt();
00278        }
00279                                    /* read the octree */
00280        if (flags & IO_TREE)
00281               mp->mcube.cutree = gettree();
00282        else if (flags & IO_SCENE)
00283               skiptree();
00284                                    /* read materials and patches */
00285        if (flags & IO_SCENE) {
00286               mp->mat0 = nobjects;
00287               readscene(meshfp, objsize);
00288               mp->nmats = nobjects - mp->mat0;
00289               mp->npatches = mgetint(4);
00290               mp->patch = (MESHPATCH *)calloc(mp->npatches,
00291                                    sizeof(MESHPATCH));
00292               if (mp->patch == NULL)
00293                      mesherror(SYSTEM, "out of patch memory");
00294               for (i = 0; i < mp->npatches; i++)
00295                      getpatch(&mp->patch[i]);
00296        }
00297                                    /* clean up */
00298        fclose(meshfp);
00299        mp->ldflags |= flags;
00300                                    /* verify data */
00301        if ((err = checkmesh(mp)) != NULL)
00302               mesherror(USER, err);
00303 }