--- ray/src/ot/cvmesh.c 2003/03/11 17:08:55 2.1 +++ ray/src/ot/cvmesh.c 2004/01/29 22:21:34 2.8 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: cvmesh.c,v 2.1 2003/03/11 17:08:55 greg Exp $"; +static const char RCSid[] = "$Id: cvmesh.c,v 2.8 2004/01/29 22:21:34 greg Exp $"; #endif /* * Radiance triangle mesh conversion routines @@ -10,6 +10,7 @@ static const char RCSid[] = "$Id: cvmesh.c,v 2.1 2003/ #include "cvmesh.h" #include "otypes.h" #include "face.h" +#include "tmesh.h" /* * We need to divide faces into triangles and record auxiliary information @@ -23,11 +24,11 @@ typedef struct { int fl; /* flags of what we're storing */ OBJECT obj; /* mesh triangle ID */ FVECT vn[3]; /* normals */ - FLOAT vc[3][2]; /* uv coords. */ + RREAL vc[3][2]; /* uv coords. */ } TRIDATA; #define tdsize(fl) ((fl)&MT_UV ? sizeof(TRIDATA) : \ - (fl)&MT_N ? sizeof(TRIDATA)-2*sizeof(FLOAT) : \ + (fl)&MT_N ? sizeof(TRIDATA)-6*sizeof(RREAL) : \ sizeof(int)+sizeof(OBJECT)) #define OMARGIN (10*FTINY) /* margin around global cube */ @@ -57,8 +58,8 @@ char *nm; ourmesh->nref = 1; ourmesh->ldflags = 0; ourmesh->mcube.cutree = EMPTY; - ourmesh->uvlim[0][0] = ourmesh->uvlim[1][0] = FHUGE; - ourmesh->uvlim[0][1] = ourmesh->uvlim[1][1] = -FHUGE; + ourmesh->uvlim[0][0] = ourmesh->uvlim[0][1] = FHUGE; + ourmesh->uvlim[1][0] = ourmesh->uvlim[1][1] = -FHUGE; meshbounds[0][0] = meshbounds[0][1] = meshbounds[0][2] = FHUGE; meshbounds[1][0] = meshbounds[1][1] = meshbounds[1][2] = -FHUGE; return(ourmesh); @@ -69,15 +70,16 @@ nomem: int -cvpoly(n, vp, vn, vc) /* convert a polygon to extended triangles */ +cvpoly(mo, n, vp, vn, vc) /* convert a polygon to extended triangles */ +OBJECT mo; int n; FVECT *vp; FVECT *vn; -FLOAT (*vc)[2]; +RREAL (*vc)[2]; { int tcnt = 0; int flags; - FLOAT *tn[3], *tc[3]; + RREAL *tn[3], *tc[3]; int *ord; int i, j; @@ -97,7 +99,7 @@ FLOAT (*vc)[2]; tc[0] = tc[1] = tc[2] = NULL; } if (n == 3) /* output single triangle */ - return(cvtri(vp[0], vp[1], vp[2], + return(cvtri(mo, vp[0], vp[1], vp[2], tn[0], tn[1], tn[2], tc[0], tc[1], tc[2])); @@ -114,12 +116,9 @@ FLOAT (*vc)[2]; if (flags & MT_UV) for (i = 3; i--; ) tc[i] = vc[ord[i]]; - i = cvtri(vp[ord[0]], vp[ord[1]], vp[ord[2]], + tcnt += cvtri(mo, vp[ord[0]], vp[ord[1]], vp[ord[2]], tn[0], tn[1], tn[2], tc[0], tc[1], tc[2]); - if (i < 0) - return(i); - tcnt += i; /* remove vertex and rotate */ n--; j = ord[0]; @@ -135,7 +134,7 @@ FLOAT (*vc)[2]; static void add2bounds(vp, vc) /* add point and uv coordinate to bounds */ FVECT vp; -FLOAT vc[2]; +RREAL vc[2]; { register int j; @@ -157,49 +156,77 @@ FLOAT vc[2]; int /* create an extended triangle */ -cvtri(vp1, vp2, vp3, vn1, vn2, vn3, vc1, vc2, vc3) +cvtri(mo, vp1, vp2, vp3, vn1, vn2, vn3, vc1, vc2, vc3) +OBJECT mo; FVECT vp1, vp2, vp3; FVECT vn1, vn2, vn3; -FLOAT vc1[2], vc2[2], vc3[2]; +RREAL vc1[2], vc2[2], vc3[2]; { - char buf[32]; - int flags; - TRIDATA *ts; - OBJECT fobj; - FACE *f; - OBJREC *fop; - int j; + static OBJECT fobj = OVOID; + char buf[32]; + int flags; + TRIDATA *ts; + FACE *f; + OBJREC *fop; + int j; - flags = MT_V; - if (vn1 != NULL && vn2 != NULL && vn3 != NULL) - flags |= MT_N; + flags = MT_V; /* check what we have */ + if (vn1 != NULL && vn2 != NULL && vn3 != NULL) { + RREAL *rp; + switch (flat_tri(vp1, vp2, vp3, vn1, vn2, vn3)) { + case ISBENT: + flags |= MT_N; + /* fall through */ + case ISFLAT: + break; + case RVBENT: + flags |= MT_N; + rp = vn1; vn1 = vn3; vn3 = rp; + /* fall through */ + case RVFLAT: + rp = vp1; vp1 = vp3; vp3 = rp; + rp = vc1; vc1 = vc3; vc3 = rp; + break; + case DEGEN: + error(WARNING, "degenerate triangle"); + return(0); + default: + error(INTERNAL, "bad return from flat_tri()"); + } + } if (vc1 != NULL && vc2 != NULL && vc3 != NULL) flags |= MT_UV; - /* create extended triangle */ - fobj = newobject(); - if (fobj == OVOID) - return(-1); - fop = objptr(fobj); - fop->omod = OVOID; - fop->otype = OBJ_FACE; - sprintf(buf, "t%d", fobj); - fop->oname = savqstr(buf); - fop->oargs.nfargs = 9; - fop->oargs.farg = (FLOAT *)malloc(9*sizeof(FLOAT)); - if (fop->oargs.farg == NULL) - goto nomem; + if (fobj == OVOID) { /* create new triangle object */ + fobj = newobject(); + if (fobj == OVOID) + goto nomem; + fop = objptr(fobj); + fop->omod = mo; + fop->otype = OBJ_FACE; + sprintf(buf, "t%d", fobj); + fop->oname = savqstr(buf); + fop->oargs.nfargs = 9; + fop->oargs.farg = (RREAL *)malloc(9*sizeof(RREAL)); + if (fop->oargs.farg == NULL) + goto nomem; + } else { /* else reuse failed one */ + fop = objptr(fobj); + if (fop->otype != OBJ_FACE || fop->oargs.nfargs != 9) + error(CONSISTENCY, "code error 1 in cvtri"); + } for (j = 3; j--; ) { fop->oargs.farg[j] = vp1[j]; fop->oargs.farg[3+j] = vp2[j]; fop->oargs.farg[6+j] = vp3[j]; } /* create face record */ - if ((f = getface(fop)) == NULL || f->area == 0.) { - freeobjects(fobj, 1); + f = getface(fop); + if (f->area == 0.) { + free_os(fop); return(0); } if (fop->os != (char *)f) - error(CONSISTENCY, "code error in cvtri"); + error(CONSISTENCY, "code error 2 in cvtri"); /* follow with auxliary data */ f = (FACE *)realloc((void *)f, sizeof(FACE)+tdsize(flags)); if (f == NULL) @@ -226,6 +253,7 @@ FLOAT vc1[2], vc2[2], vc3[2]; add2bounds(vp1, vc1); add2bounds(vp2, vc2); add2bounds(vp3, vc3); + fobj = OVOID; /* we used this one */ return(1); nomem: error(SYSTEM, "out of memory in cvtri"); @@ -263,7 +291,7 @@ OBJECT obj; for (i = 3; i--; ) for (j = 2; j--; ) vert[i].uv[j] = ts->vc[i][j]; - ts->obj = addmeshtri(ourmesh, vert); + ts->obj = addmeshtri(ourmesh, vert, o->omod); if (ts->obj == OVOID) error(INTERNAL, "addmeshtri failed"); return(ts->obj); @@ -279,7 +307,7 @@ cvmeshbounds() /* set mesh boundaries */ return; /* fix coordinate bounds */ for (i = 0; i < 3; i++) { - if (meshbounds[0][i] >= meshbounds[1][i]) + if (meshbounds[0][i] > meshbounds[1][i]) error(USER, "no polygons in mesh"); meshbounds[0][i] -= OMARGIN; meshbounds[1][i] += OMARGIN; @@ -290,14 +318,15 @@ cvmeshbounds() /* set mesh boundaries */ for (i = 0; i < 3; i++) ourmesh->mcube.cuorg[i] = (meshbounds[1][i]+meshbounds[0][i] - ourmesh->mcube.cusize)*.5; - if (ourmesh->uvlim[0][0] >= ourmesh->uvlim[1][0]) { + if (ourmesh->uvlim[0][0] > ourmesh->uvlim[1][0]) { ourmesh->uvlim[0][0] = ourmesh->uvlim[0][1] = 0.; ourmesh->uvlim[1][0] = ourmesh->uvlim[1][1] = 0.; } else { for (i = 0; i < 2; i++) { - double marg; - marg = 1e-6*(ourmesh->uvlim[1][i] - - ourmesh->uvlim[0][i]); + double marg; /* expand past endpoints */ + marg = (2./(1L<<(8*sizeof(uint16)))) * + (ourmesh->uvlim[1][i] - + ourmesh->uvlim[0][i]); ourmesh->uvlim[0][i] -= marg; ourmesh->uvlim[1][i] += marg; }