Back to index

radiance  4R0+20100331
Classes | Defines | Typedefs | Functions
mesh.h File Reference
#include "lookup.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  MESHPATCH
struct  MESHPATCH::PTri
struct  MESHPATCH::PJoin1
struct  MESHPATCH::PJoin2
struct  mesh
struct  MESHINST
struct  MESHVERT

Defines

#define BYTE   unsigned char
#define MT_V   01
#define MT_N   02
#define MT_UV   04
#define MT_ALL   07
#define MESHFMT   "Radiance_tmesh"
#define MESHMAGIC   ( 1 *MAXOBJSIZ+311) /* increment first value */

Typedefs

typedef struct mesh MESH

Functions

MESHgetmesh (char *mname, int flags)
MESHINSTgetmeshinst (OBJREC *o, int flags)
int getmeshtrivid (int32 tvid[3], OBJECT *mo, MESH *mp, OBJECT ti)
int getmeshvert (MESHVERT *vp, MESH *mp, int32 vid, int what)
int getmeshtri (MESHVERT tv[3], OBJECT *mo, MESH *mp, OBJECT ti, int what)
OBJRECgetmeshpseudo (MESH *mp, OBJECT mo)
int32 addmeshvert (MESH *mp, MESHVERT *vp)
OBJECT addmeshtri (MESH *mp, MESHVERT tv[3], OBJECT mo)
char * checkmesh (MESH *mp)
void printmeshstats (MESH *ms, FILE *fp)
void freemesh (MESH *ms)
void freemeshinst (OBJREC *o)
void readmesh (MESH *mp, char *path, int flags)
void writemesh (MESH *mp, FILE *fp)

Class Documentation

struct MESHPATCH

Definition at line 51 of file mesh.h.

Collaboration diagram for MESHPATCH:
Class Members
struct PJoin1 * j1tri
struct PJoin2 * j2tri
short nj1tris
short nj2tris
int32 * norm
short ntris
short nverts
short solemat
struct PTri * tri
int16 * trimat
uint32(* uv
uint32(* xyz
struct MESHPATCH::PTri

Definition at line 55 of file mesh.h.

Class Members
BYTE v1
BYTE v2
BYTE v3
struct MESHPATCH::PJoin1

Definition at line 60 of file mesh.h.

Class Members
int16 mat
int32 v1j
BYTE v2
BYTE v3
struct MESHPATCH::PJoin2

Definition at line 65 of file mesh.h.

Class Members
int16 mat
int32 v1j
int32 v2j
BYTE v3
struct mesh

Definition at line 77 of file mesh.h.

Collaboration diagram for mesh:
Class Members
int ldflags
LUTAB lut
OBJECT mat0
CUBE mcube
char * name
struct mesh * next
OBJECT nmats
int npatches
int nref
MESHPATCH * patch
OBJREC * pseudo
RREAL uvlim
struct MESHINST

Definition at line 93 of file mesh.h.

Collaboration diagram for MESHINST:
Class Members
MESH * msh
FULLXF x
struct MESHVERT

Definition at line 105 of file mesh.h.

Class Members
int fl
FVECT n
RREAL uv
FVECT v

Define Documentation

#define BYTE   unsigned char

Definition at line 17 of file mesh.h.

#define MESHFMT   "Radiance_tmesh"

Definition at line 113 of file mesh.h.

#define MESHMAGIC   ( 1 *MAXOBJSIZ+311) /* increment first value */

Definition at line 115 of file mesh.h.

#define MT_ALL   07

Definition at line 102 of file mesh.h.

#define MT_N   02

Definition at line 100 of file mesh.h.

#define MT_UV   04

Definition at line 101 of file mesh.h.

#define MT_V   01

Definition at line 99 of file mesh.h.


Typedef Documentation

typedef struct mesh MESH

Function Documentation

OBJECT addmeshtri ( MESH mp,
MESHVERT  tv[3],
OBJECT  mo 
)
int32 addmeshvert ( MESH mp,
MESHVERT vp 
)

Definition at line 299 of file mesh.c.

{
       LUENT         *lvp;
       MCVERT        cv;
       register int  i;

       if (!(vp->fl & MT_V))
              return(-1);
                                   /* encode vertex */
       for (i = 0; i < 3; i++) {
              if (vp->v[i] < mp->mcube.cuorg[i])
                     return(-1);
              if (vp->v[i] >= mp->mcube.cuorg[i] + mp->mcube.cusize)
                     return(-1);
              cv.xyz[i] = (uint32)(4294967296. *
                            (vp->v[i] - mp->mcube.cuorg[i]) /
                            mp->mcube.cusize);
       }
       if (vp->fl & MT_N)          /* assumes normalized! */
              cv.norm = encodedir(vp->n);
       if (vp->fl & MT_UV)
              for (i = 0; i < 2; i++) {
                     if (vp->uv[i] <= mp->uvlim[0][i])
                            return(-1);
                     if (vp->uv[i] >= mp->uvlim[1][i])
                            return(-1);
                     cv.uv[i] = (uint32)(4294967296. *
                                   (vp->uv[i] - mp->uvlim[0][i]) /
                                   (mp->uvlim[1][i] - mp->uvlim[0][i]));
              }
       cv.fl = vp->fl;
       if (mp->lut.tsiz == 0) {
              mp->lut.hashf = cvhash;
              mp->lut.keycmp = cvcmp;
              mp->lut.freek = free;
              if (!lu_init(&mp->lut, 50000))
                     goto nomem;
       }
                                   /* find entry */
       lvp = lu_find(&mp->lut, (char *)&cv);
       if (lvp == NULL)
              goto nomem;
       if (lvp->key == NULL) {
              lvp->key = (char *)malloc(sizeof(MCVERT)+sizeof(int32));
              memcpy((void *)lvp->key, (void *)&cv, sizeof(MCVERT));
       }
       if (lvp->data == NULL) {    /* new vertex */
              register MESHPATCH   *pp;
              if (mp->npatches <= 0) {
                     mp->patch = (MESHPATCH *)calloc(MPATCHBLKSIZ,
                                   sizeof(MESHPATCH));
                     if (mp->patch == NULL)
                            goto nomem;
                     mp->npatches = 1;
              } else if (mp->patch[mp->npatches-1].nverts >= 256) {
                     if (mp->npatches % MPATCHBLKSIZ == 0) {
                            mp->patch = (MESHPATCH *)realloc(
                                          (void *)mp->patch,
                                   (mp->npatches + MPATCHBLKSIZ)*
                                          sizeof(MESHPATCH));
                            memset((void *)(mp->patch + mp->npatches), '\0',
                                   MPATCHBLKSIZ*sizeof(MESHPATCH));
                     }
                     if (mp->npatches++ >= 1L<<22)
                            error(INTERNAL, "too many mesh patches");
              }
              pp = &mp->patch[mp->npatches-1];
              if (pp->xyz == NULL) {
                     pp->xyz = (uint32 (*)[3])calloc(256, 3*sizeof(int32));
                     if (pp->xyz == NULL)
                            goto nomem;
              }
              for (i = 0; i < 3; i++)
                     pp->xyz[pp->nverts][i] = cv.xyz[i];
              if (cv.fl & MT_N) {
                     if (pp->norm == NULL) {
                            pp->norm = (int32 *)calloc(256, sizeof(int32));
                            if (pp->norm == NULL)
                                   goto nomem;
                     }
                     pp->norm[pp->nverts] = cv.norm;
              }
              if (cv.fl & MT_UV) {
                     if (pp->uv == NULL) {
                            pp->uv = (uint32 (*)[2])calloc(256,
                                          2*sizeof(uint32));
                            if (pp->uv == NULL)
                                   goto nomem;
                     }
                     for (i = 0; i < 2; i++)
                            pp->uv[pp->nverts][i] = cv.uv[i];
              }
              pp->nverts++;
              lvp->data = lvp->key + sizeof(MCVERT);
              *(int32 *)lvp->data = (mp->npatches-1) << 8 | (pp->nverts-1);
       }
       return(*(int32 *)lvp->data);
nomem:
       error(SYSTEM, "out of memory in addmeshvert");
       return(-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* checkmesh ( MESH mp)

Definition at line 502 of file mesh.c.

{
       static char   embuf[128];
       int           nouvbounds = 1;
       register int  i;
                                   /* basic checks */
       if (mp == NULL)
              return("NULL mesh pointer");
       if (!mp->ldflags)
              return("unassigned mesh");
       if (mp->name == NULL)
              return("missing mesh name");
       if (mp->nref <= 0)
              return("unreferenced mesh");
                                   /* check boundaries */
       if (mp->ldflags & IO_BOUNDS) {
              if (mp->mcube.cusize <= FTINY)
                     return("illegal octree bounds in mesh");
              nouvbounds = (mp->uvlim[1][0] - mp->uvlim[0][0] <= FTINY ||
                            mp->uvlim[1][1] - mp->uvlim[0][1] <= FTINY);
       }
                                   /* check octree */
       if (mp->ldflags & IO_TREE) {
              if (isempty(mp->mcube.cutree))
                     error(WARNING, "empty mesh octree");
       }
                                   /* check scene data */
       if (mp->ldflags & IO_SCENE) {
              if (!(mp->ldflags & IO_BOUNDS))
                     return("unbounded scene in mesh");
              if (mp->mat0 < 0 || mp->mat0+mp->nmats > nobjects)
                     return("bad mesh modifier range");
              for (i = mp->mat0+mp->nmats; i-- > mp->mat0; ) {
                     int    otyp = objptr(i)->otype;
                     if (!ismodifier(otyp)) {
                            sprintf(embuf,
                                   "non-modifier in mesh (%s \"%s\")",
                                   ofun[otyp].funame, objptr(i)->oname);
                            return(embuf);
                     }
              }
              if (mp->npatches <= 0)
                     error(WARNING, "no patches in mesh");
              for (i = 0; i < mp->npatches; i++) {
                     register MESHPATCH   *pp = &mp->patch[i];
                     if (pp->nverts <= 0)
                            error(WARNING, "no vertices in patch");
                     else {
                            if (pp->xyz == NULL)
                                   return("missing patch vertex list");
                            if (nouvbounds && pp->uv != NULL)
                                   return("unreferenced uv coordinates");
                     }
                     if (pp->ntris > 0 && pp->tri == NULL)
                            return("missing patch triangle list");
                     if (pp->nj1tris > 0 && pp->j1tri == NULL)
                            return("missing patch joiner triangle list");
                     if (pp->nj2tris > 0 && pp->j2tri == NULL)
                            return("missing patch double-joiner list");
              }
       }
       return(NULL);               /* seems OK */
}

Here is the call graph for this function:

Here is the caller graph for this function:

void freemesh ( MESH ms)

Definition at line 646 of file mesh.c.

{
       MESH   mhead;
       MESH   *msp;
       
       if (ms == NULL)
              return;
       if (ms->nref <= 0)
              error(CONSISTENCY, "unreferenced mesh in freemesh");
       ms->nref--;
       if (ms->nref)        /* still in use */
              return;
                            /* else remove from list */
       mhead.next = mlist;
       for (msp = &mhead; msp->next != NULL; msp = msp->next)
              if (msp->next == ms) {
                     msp->next = ms->next;
                     ms->next = NULL;
                     break;
              }
       if (ms->next != NULL)       /* can't be in list anymore */
              error(CONSISTENCY, "unlisted mesh in freemesh");
       mlist = mhead.next;
                            /* free mesh data */
       freestr(ms->name);
       octfree(ms->mcube.cutree);
       lu_done(&ms->lut);
       if (ms->npatches > 0) {
              register MESHPATCH   *pp = ms->patch + ms->npatches;
              while (pp-- > ms->patch) {
                     if (pp->j2tri != NULL)
                            free((void *)pp->j2tri);
                     if (pp->j1tri != NULL)
                            free((void *)pp->j1tri);
                     if (pp->tri != NULL)
                            free((void *)pp->tri);
                     if (pp->uv != NULL)
                            free((void *)pp->uv);
                     if (pp->norm != NULL)
                            free((void *)pp->norm);
                     if (pp->xyz != NULL)
                            free((void *)pp->xyz);
              }
              free((void *)ms->patch);
       }
       if (ms->pseudo != NULL)
              free((void *)ms->pseudo);
       free((void *)ms);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void freemeshinst ( OBJREC o)

Definition at line 699 of file mesh.c.

{
       if (o->os == NULL)
              return;
       freemesh((*(MESHINST *)o->os).msh);
       free((void *)o->os);
       o->os = NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

MESH* getmesh ( char *  mname,
int  flags 
)

Definition at line 83 of file mesh.c.

{
       char  *pathname;
       register MESH  *ms;

       flags &= IO_LEGAL;
       for (ms = mlist; ms != NULL; ms = ms->next)
              if (!strcmp(mname, ms->name)) {
                     ms->nref++;   /* increase reference count */
                     break;
              }
       if (ms == NULL) {           /* load first time */
              ms = (MESH *)calloc(1, sizeof(MESH));
              if (ms == NULL)
                     error(SYSTEM, "out of memory in getmesh");
              ms->name = savestr(mname);
              ms->nref = 1;
              ms->mcube.cutree = EMPTY;
              ms->next = mlist;
              mlist = ms;
       }
       if ((pathname = getpath(mname, getrlibpath(), R_OK)) == NULL) {
              sprintf(errmsg, "cannot find mesh file \"%s\"", mname);
              error(USER, errmsg);
       }
       flags &= ~ms->ldflags;
       if (flags)
              readmesh(ms, pathname, flags);
       return(ms);
}

Here is the call graph for this function:

Here is the caller graph for this function:

MESHINST* getmeshinst ( OBJREC o,
int  flags 
)

Definition at line 118 of file mesh.c.

{
       register MESHINST  *ins;

       flags &= IO_LEGAL;
       if ((ins = (MESHINST *)o->os) == NULL) {
              if ((ins = (MESHINST *)malloc(sizeof(MESHINST))) == NULL)
                     error(SYSTEM, "out of memory in getmeshinst");
              if (o->oargs.nsargs < 1)
                     objerror(o, USER, "bad # of arguments");
              if (fullxf(&ins->x, o->oargs.nsargs-1,
                            o->oargs.sarg+1) != o->oargs.nsargs-1)
                     objerror(o, USER, "bad transform");
              if (ins->x.f.sca < 0.0) {
                     ins->x.f.sca = -ins->x.f.sca;
                     ins->x.b.sca = -ins->x.b.sca;
              }
              ins->msh = NULL;
              o->os = (char *)ins;
       }
       if (ins->msh == NULL)
              ins->msh = getmesh(o->oargs.sarg[0], flags);
       else if ((flags &= ~ins->msh->ldflags))
              readmesh(ins->msh,
                     getpath(o->oargs.sarg[0], getrlibpath(), R_OK),
                            flags);
       return(ins);
}

Here is the call graph for this function:

Here is the caller graph for this function:

OBJREC* getmeshpseudo ( MESH mp,
OBJECT  mo 
)

Definition at line 256 of file mesh.c.

{
       if (mo < mp->mat0 || mo >= mp->mat0 + mp->nmats)
              error(INTERNAL, "modifier out of range in getmeshpseudo");
       if (mp->pseudo == NULL) {
              register int  i;
              mp->pseudo = (OBJREC *)calloc(mp->nmats, sizeof(OBJREC));
              if (mp->pseudo == NULL)
                     error(SYSTEM, "out of memory in getmeshpseudo");
              for (i = mp->nmats; i--; ) {
                     mp->pseudo[i].omod = mp->mat0 + i;
                     mp->pseudo[i].otype = OBJ_FACE;
                     mp->pseudo[i].oname = "M-Tri";
              }
       }
       return(&mp->pseudo[mo - mp->mat0]);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int getmeshtri ( MESHVERT  tv[3],
OBJECT mo,
MESH mp,
OBJECT  ti,
int  what 
)
int getmeshtrivid ( int32  tvid[3],
OBJECT mo,
MESH mp,
OBJECT  ti 
)
int getmeshvert ( MESHVERT vp,
MESH mp,
int32  vid,
int  what 
)

Definition at line 212 of file mesh.c.

{
       int           pn = vid >> 8;
       MESHPATCH     *pp;
       double        vres;
       register int  i;
       
       vp->fl = 0;
       if (pn >= mp->npatches)
              return(0);
       pp = &mp->patch[pn];
       vid &= 0xff;
       if (vid >= pp->nverts)
              return(0);
                                   /* get location */
       if (what & MT_V) {
              vres = (1./4294967296.)*mp->mcube.cusize;
              for (i = 0; i < 3; i++)
                     vp->v[i] = mp->mcube.cuorg[i] +
                                   (pp->xyz[vid][i] + .5)*vres;
              vp->fl |= MT_V;
       }
                                   /* get normal */
       if (what & MT_N && pp->norm != NULL && pp->norm[vid]) {
              decodedir(vp->n, pp->norm[vid]);
              vp->fl |= MT_N;
       }
                                   /* get (u,v) */
       if (what & MT_UV && pp->uv != NULL && pp->uv[vid][0]) {
              for (i = 0; i < 2; i++)
                     vp->uv[i] = mp->uvlim[0][i] +
                            (mp->uvlim[1][i] - mp->uvlim[0][i])*
                            (pp->uv[vid][i] + .5)*(1./4294967296.);
              vp->fl |= MT_UV;
       }
       return(vp->fl);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void printmeshstats ( MESH ms,
FILE *  fp 
)

Definition at line 592 of file mesh.c.

{
       int    lfcnt=0, lecnt=0, locnt=0;
       int    vcnt=0, ncnt=0, uvcnt=0;
       int    nscnt=0, uvscnt=0;
       int    tcnt=0, t1cnt=0, t2cnt=0;
       int    i, j;
       
       tallyoctree(ms->mcube.cutree, &lecnt, &lfcnt, &locnt);
       for (i = 0; i < ms->npatches; i++) {
              register MESHPATCH   *pp = &ms->patch[i];
              vcnt += pp->nverts;
              if (pp->norm != NULL) {
                     for (j = pp->nverts; j--; )
                            if (pp->norm[j])
                                   ncnt++;
                     nscnt += pp->nverts;
              }
              if (pp->uv != NULL) {
                     for (j = pp->nverts; j--; )
                            if (pp->uv[j][0])
                                   uvcnt++;
                     uvscnt += pp->nverts;
              }
              tcnt += pp->ntris;
              t1cnt += pp->nj1tris;
              t2cnt += pp->nj2tris;
       }
       fprintf(fp, "Mesh statistics:\n");
       fprintf(fp, "\t%ld materials\n", ms->nmats);
       fprintf(fp, "\t%d patches (%.2f MBytes)\n", ms->npatches,
                     (ms->npatches*sizeof(MESHPATCH) +
                     vcnt*3*sizeof(uint32) +
                     nscnt*sizeof(int32) +
                     uvscnt*2*sizeof(uint32) +
                     tcnt*sizeof(struct PTri) +
                     t1cnt*sizeof(struct PJoin1) +
                     t2cnt*sizeof(struct PJoin2))/(1024.*1024.));
       fprintf(fp, "\t%d vertices (%.1f%% w/ normals, %.1f%% w/ uv)\n",
                     vcnt, 100.*ncnt/vcnt, 100.*uvcnt/vcnt);
       fprintf(fp, "\t%d triangles (%.1f%% local, %.1f%% joiner)\n",
                     tcnt+t1cnt+t2cnt,
                     100.*tcnt/(tcnt+t1cnt+t2cnt),
                     100.*t1cnt/(tcnt+t1cnt+t2cnt));
       fprintf(fp,
       "\t%d leaves in octree (%.1f%% empty, %.2f avg. set size)\n",
                     lfcnt+lecnt, 100.*lecnt/(lfcnt+lecnt),
                     (double)locnt/lfcnt);
}

Here is the call graph for this function:

void readmesh ( MESH mp,
char *  path,
int  flags 
)

Definition at line 239 of file readmesh.c.

{
       char   *err;
       char   sbuf[64];
       int    i;
                                   /* check what's loaded */
       flags &= (IO_INFO|IO_BOUNDS|IO_TREE|IO_SCENE) & ~mp->ldflags;
                                   /* open input file */
       if (path == NULL) {
              meshfn = "standard input";
              meshfp = stdin;
       } else if ((meshfp = fopen(meshfn=path, "r")) == NULL) {
              sprintf(errmsg, "cannot open mesh file \"%s\"", path);
              error(SYSTEM, errmsg);
       }
       SET_FILE_BINARY(meshfp);
                                   /* read header */
       checkheader(meshfp, MESHFMT, flags&IO_INFO ? stdout : (FILE *)NULL);
                                   /* read format number */
       objsize = getint(2, meshfp) - MESHMAGIC;
       if (objsize <= 0 || objsize > MAXOBJSIZ || objsize > sizeof(long))
              mesherror(USER, "incompatible mesh format");
                                   /* read boundaries */
       if (flags & IO_BOUNDS) {
              for (i = 0; i < 3; i++)
                     mp->mcube.cuorg[i] = atof(getstr(sbuf, meshfp));
              mp->mcube.cusize = atof(getstr(sbuf, meshfp));
              for (i = 0; i < 2; i++) {
                     mp->uvlim[0][i] = mgetflt();
                     mp->uvlim[1][i] = mgetflt();
              }
       } else {
              for (i = 0; i < 4; i++)
                     getstr(sbuf, meshfp);
              for (i = 0; i < 4; i++)
                     mgetflt();
       }
                                   /* read the octree */
       if (flags & IO_TREE)
              mp->mcube.cutree = gettree();
       else if (flags & IO_SCENE)
              skiptree();
                                   /* read materials and patches */
       if (flags & IO_SCENE) {
              mp->mat0 = nobjects;
              readscene(meshfp, objsize);
              mp->nmats = nobjects - mp->mat0;
              mp->npatches = mgetint(4);
              mp->patch = (MESHPATCH *)calloc(mp->npatches,
                                   sizeof(MESHPATCH));
              if (mp->patch == NULL)
                     mesherror(SYSTEM, "out of patch memory");
              for (i = 0; i < mp->npatches; i++)
                     getpatch(&mp->patch[i]);
       }
                                   /* clean up */
       fclose(meshfp);
       mp->ldflags |= flags;
                                   /* verify data */
       if ((err = checkmesh(mp)) != NULL)
              mesherror(USER, err);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void writemesh ( MESH mp,
FILE *  fp 
)

Definition at line 125 of file writemesh.c.

{
       char   *err;
       char   sbuf[64];
       int    i;
                                   /* do we have everything? */
       if ((mp->ldflags & (IO_SCENE|IO_TREE|IO_BOUNDS)) !=
                     (IO_SCENE|IO_TREE|IO_BOUNDS))
              error(INTERNAL, "missing data in writemesh");
                                   /* validate mesh data */
       if ((err = checkmesh(mp)) != NULL)
              error(USER, err);
                                   /* write format number */
       putint((long)(MESHMAGIC+sizeof(OBJECT)), 2, fp);
                                   /* write boundaries */
       for (i = 0; i < 3; i++) {
              sprintf(sbuf, "%.12g", mp->mcube.cuorg[i]);
              putstr(sbuf, fp);
       }
       sprintf(sbuf, "%.12g", mp->mcube.cusize);
       putstr(sbuf, fp);
       for (i = 0; i < 2; i++) {
              putflt(mp->uvlim[0][i], fp);
              putflt(mp->uvlim[1][i], fp);
       }
                                   /* write the octree */
       puttree(mp->mcube.cutree, fp);
                                   /* write the materials */
       writescene(mp->mat0, mp->nmats, fp);
                                   /* write the patches */
       putint((long)mp->npatches, 4, fp);
       for (i = 0; i < mp->npatches; i++)
              putpatch(&mp->patch[i], fp);
       if (ferror(fp))
              error(SYSTEM, "write error in writemesh");
}

Here is the call graph for this function:

Here is the caller graph for this function: