--- ray/src/cv/obj2rad.c 1994/04/14 13:36:18 2.7 +++ ray/src/cv/obj2rad.c 2003/11/15 17:54:06 2.22 @@ -1,9 +1,6 @@ -/* Copyright (c) 1994 Regents of the University of California */ - #ifndef lint -static char SCCSid[] = "$SunId$ LBL"; +static const char RCSid[] = "$Id: obj2rad.c,v 2.22 2003/11/15 17:54:06 schorsch Exp $"; #endif - /* * Convert a Wavefront .obj file to Radiance format. * @@ -13,32 +10,31 @@ static char SCCSid[] = "$SunId$ LBL"; * I'm not sure they work correctly. (Taken out -- see TEXMAPS defines.) */ -#include "standard.h" +#include +#include +#include +#include "rtmath.h" +#include "rtio.h" +#include "resolu.h" #include "trans.h" +#include "tmesh.h" -#include -#define TCALNAME "tmesh.cal" /* triangle interp. file */ -#define QCALNAME "surf.cal" /* quad interp. file */ #define PATNAME "M-pat" /* mesh pattern name (reused) */ #define TEXNAME "M-nor" /* mesh texture name (reused) */ #define DEFOBJ "unnamed" /* default object name */ #define DEFMAT "white" /* default material name */ -#define ABS(x) ((x)>=0 ? (x) : -(x)) - #define pvect(v) printf("%18.12g %18.12g %18.12g\n",(v)[0],(v)[1],(v)[2]) FVECT *vlist; /* our vertex list */ int nvs; /* number of vertices in our list */ FVECT *vnlist; /* vertex normal list */ int nvns; -FLOAT (*vtlist)[2]; /* map vertex list */ +RREAL (*vtlist)[2]; /* map vertex list */ int nvts; -typedef FLOAT BARYCCM[3][4]; /* barycentric coordinate system */ - typedef int VNDX[3]; /* vertex index (point,map,normal) */ #define CHUNKSIZ 256 /* vertex allocation chunk size */ @@ -70,7 +66,7 @@ RULEHD *ourmapping = NULL; char *defmat = DEFMAT; /* default (starting) material name */ char *defobj = DEFOBJ; /* default (starting) object name */ -char *getmtl(), *getonm(); +int flatten = 0; /* discard surface normal information */ char mapname[128]; /* current picture file */ char matname[64]; /* current material name */ @@ -80,10 +76,28 @@ char *inpfile; /* input file name */ int lineno; /* current line number */ int faceno; /* current face number */ +static void getnames(FILE *fp); +static void convert(FILE *fp); +static int getstmt(char *av[MAXARG], FILE *fp); +static char * getmtl(void); +static char * getonm(void); +static int matchrule(RULEHD *rp); +static int cvtndx(VNDX vi, char *vs); +static int nonplanar(int ac, char **av); +static int putface(int ac, char **av); +static int puttri(char *v1, char *v2, char *v3); +static void freeverts(void); +static int newv(double x, double y, double z); +static int newvn(double x, double y, double z); +static int newvt(double x, double y); +static void syntax(char *er); -main(argc, argv) /* read in .obj file and convert */ -int argc; -char *argv[]; + +int +main( /* read in .obj file and convert */ + int argc, + char *argv[] +) { int donames = 0; int i; @@ -99,10 +113,13 @@ char *argv[]; case 'm': /* use custom mapfile */ ourmapping = getmapping(argv[++i], &qlist); break; + case 'f': /* flatten surfaces */ + flatten++; + break; default: goto userr; } - if (i > argc | i < argc-1) + if ((i > argc) | (i < argc-1)) goto userr; if (i == argc) inpfile = ""; @@ -125,21 +142,23 @@ char *argv[]; } exit(0); userr: - fprintf(stderr, "Usage: %s [-o obj][-m mapping][-n] [file.obj]\n", + fprintf(stderr, "Usage: %s [-o obj][-m mapping][-n][-f] [file.obj]\n", argv[0]); exit(1); } -getnames(fp) /* get valid qualifier names */ -FILE *fp; +void +getnames( /* get valid qualifier names */ + FILE *fp +) { char *argv[MAXARG]; int argc; ID tmpid; register int i; - while (argc = getstmt(argv, fp)) + while ( (argc = getstmt(argv, fp)) ) switch (argv[0][0]) { case 'f': /* face */ if (!argv[0][1]) @@ -180,8 +199,10 @@ FILE *fp; } -convert(fp) /* convert a T-mesh */ -FILE *fp; +void +convert( /* convert a T-mesh */ + FILE *fp +) { char *argv[MAXARG]; int argc; @@ -190,7 +211,7 @@ FILE *fp; nstats = nunknown = 0; /* scan until EOF */ - while (argc = getstmt(argv, fp)) { + while ( (argc = getstmt(argv, fp)) ) { switch (argv[0][0]) { case 'v': /* vertex */ switch (argv[0][1]) { @@ -232,11 +253,6 @@ FILE *fp; if (!puttri(argv[1], argv[2], argv[3])) syntax("Bad triangle"); break; - case 4: - if (!putquad(argv[1], argv[2], - argv[3], argv[4])) - syntax("Bad quad"); - break; default: if (!putface(argc-1, argv+1)) syntax("Bad face"); @@ -289,9 +305,10 @@ FILE *fp; int -getstmt(av, fp) /* read the next statement from fp */ -register char *av[MAXARG]; -FILE *fp; +getstmt( /* read the next statement from fp */ + register char *av[MAXARG], + FILE *fp +) { extern char *fgetline(); static char sbuf[MAXARG*10]; @@ -323,7 +340,7 @@ FILE *fp; char * -getmtl() /* figure material for this face */ +getmtl(void) /* figure material for this face */ { register RULEHD *rp = ourmapping; @@ -349,7 +366,7 @@ getmtl() /* figure material for this face */ char * -getonm() /* invent a good name for object */ +getonm(void) /* invent a good name for object */ { static char name[64]; register char *cp1, *cp2; @@ -364,7 +381,7 @@ getonm() /* invent a good name for object */ cp2 = group[i]; if (cp1 > name) *cp1++ = '.'; - while (*cp1 = *cp2++) + while ( (*cp1 = *cp2++) ) if (++cp1 >= name+sizeof(name)-2) { *cp1 = '\0'; return(name); @@ -374,8 +391,10 @@ getonm() /* invent a good name for object */ } -matchrule(rp) /* check for a match on this rule */ -register RULEHD *rp; +int +matchrule( /* check for a match on this rule */ + register RULEHD *rp +) { ID tmpid; int gotmatch; @@ -425,9 +444,11 @@ register RULEHD *rp; } -cvtndx(vi, vs) /* convert vertex string to index */ -register VNDX vi; -register char *vs; +int +cvtndx( /* convert vertex string to index */ + register VNDX vi, + register char *vs +) { /* get point */ vi[0] = atoi(vs); @@ -435,7 +456,7 @@ register char *vs; if (vi[0]-- > nvs) return(0); } else if (vi[0] < 0) { - vi[0] = nvs + vi[0]; + vi[0] += nvs; if (vi[0] < 0) return(0); } else @@ -449,7 +470,7 @@ register char *vs; if (vi[1]-- > nvts) return(0); } else if (vi[1] < 0) { - vi[1] = nvts + vi[1]; + vi[1] += nvts; if (vi[1] < 0) return(0); } else @@ -463,7 +484,7 @@ register char *vs; if (vi[2]-- > nvns) return(0); } else if (vi[2] < 0) { - vi[2] = nvns + vi[2]; + vi[2] += nvns; if (vi[2] < 0) return(0); } else @@ -472,19 +493,21 @@ register char *vs; } -nonplanar(ac, av) /* are vertices are non-planar? */ -register int ac; -register char **av; +int +nonplanar( /* are vertices non-planar? */ + register int ac, + register char **av +) { VNDX vi; - FLOAT *p0, *p1; + RREAL *p0, *p1; FVECT v1, v2, nsum, newn; double d; register int i; if (!cvtndx(vi, av[0])) return(0); - if (vi[2] >= 0) + if (!flatten && vi[2] >= 0) return(1); /* has interpolated normals */ if (ac < 4) return(0); /* it's a triangle! */ @@ -523,26 +546,26 @@ register char **av; } -putface(ac, av) /* put out an N-sided polygon */ -int ac; -register char **av; +int +putface( /* put out an N-sided polygon */ + int ac, + register char **av +) { VNDX vi; char *cp; register int i; - if (nonplanar(ac, av)) { /* break into quads and triangles */ - while (ac > 3) { - if (!putquad(av[0], av[1], av[2], av[3])) + if (nonplanar(ac, av)) { /* break into triangles */ + while (ac > 2) { + if (!puttri(av[0], av[1], av[2])) return(0); - ac -= 2; /* remove two vertices & rotate */ + ac--; /* remove vertex & rotate */ cp = av[0]; for (i = 0; i < ac-1; i++) - av[i] = av[i+3]; + av[i] = av[i+2]; av[i] = cp; } - if (ac == 3 && !puttri(av[0], av[1], av[2])) - return(0); return(1); } if ((cp = getmtl()) == NULL) @@ -558,13 +581,20 @@ register char **av; } -puttri(v1, v2, v3) /* put out a triangle */ -char *v1, *v2, *v3; +int +puttri( /* put out a triangle */ + char *v1, + char *v2, + char *v3 +) { char *mod; VNDX v1i, v2i, v3i; BARYCCM bvecs; - int texOK, patOK; + RREAL bcoor[3][3]; + int texOK = 0, patOK; + int flatness; + register int i; if ((mod = getmtl()) == NULL) return(-1); @@ -572,14 +602,33 @@ char *v1, *v2, *v3; if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3)) return(0); /* compute barycentric coordinates */ - texOK = (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0); + if (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0) + flatness = flat_tri(vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]], + vnlist[v1i[2]], vnlist[v2i[2]], vnlist[v3i[2]]); + else + flatness = ISFLAT; + + switch (flatness) { + case DEGEN: /* zero area */ + return(-1); + case RVFLAT: /* reversed normals, but flat */ + case ISFLAT: /* smoothing unnecessary */ + texOK = 0; + break; + case RVBENT: /* reversed normals with smoothing */ + case ISBENT: /* proper smoothing */ + texOK = 1; + break; + } + if (flatten) + texOK = 0; #ifdef TEXMAPS patOK = mapname[0] && (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0); #else patOK = 0; #endif if (texOK | patOK) - if (comp_baryc(bvecs, vlist[v1i[0]], vlist[v2i[0]], + if (comp_baryc(&bvecs, vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]]) < 0) return(-1); /* put out texture (if any) */ @@ -587,17 +636,13 @@ char *v1, *v2, *v3; printf("\n%s texfunc %s\n", mod, TEXNAME); mod = TEXNAME; printf("4 dx dy dz %s\n", TCALNAME); - printf("0\n21\n"); - put_baryc(bvecs); - printf("\t%14.12g %14.12g %14.12g\n", - vnlist[v1i[2]][0], vnlist[v2i[2]][0], - vnlist[v3i[2]][0]); - printf("\t%14.12g %14.12g %14.12g\n", - vnlist[v1i[2]][1], vnlist[v2i[2]][1], - vnlist[v3i[2]][1]); - printf("\t%14.12g %14.12g %14.12g\n", - vnlist[v1i[2]][2], vnlist[v2i[2]][2], - vnlist[v3i[2]][2]); + printf("0\n"); + for (i = 0; i < 3; i++) { + bcoor[i][0] = vnlist[v1i[2]][i]; + bcoor[i][1] = vnlist[v2i[2]][i]; + bcoor[i][2] = vnlist[v3i[2]][i]; + } + put_baryc(&bvecs, bcoor, 3); } #ifdef TEXMAPS /* put out pattern (if any) */ @@ -605,265 +650,61 @@ char *v1, *v2, *v3; printf("\n%s colorpict %s\n", mod, PATNAME); mod = PATNAME; printf("7 noneg noneg noneg %s %s u v\n", mapname, TCALNAME); - printf("0\n18\n"); - put_baryc(bvecs); - printf("\t%f %f %f\n", vtlist[v1i[1]][0], - vtlist[v2i[1]][0], vtlist[v3i[1]][0]); - printf("\t%f %f %f\n", vtlist[v1i[1]][1], - vtlist[v2i[1]][1], vtlist[v3i[1]][1]); + printf("0\n"); + for (i = 0; i < 2; i++) { + bcoor[i][0] = vtlist[v1i[1]][i]; + bcoor[i][1] = vtlist[v2i[1]][i]; + bcoor[i][2] = vtlist[v3i[1]][i]; + } + put_baryc(&bvecs, bcoor, 2); } #endif - /* put out triangle */ + /* put out (reversed) triangle */ printf("\n%s polygon %s.%d\n", mod, getonm(), faceno); printf("0\n0\n9\n"); - pvect(vlist[v1i[0]]); - pvect(vlist[v2i[0]]); - pvect(vlist[v3i[0]]); - - return(1); -} - - -int -comp_baryc(bcm, v1, v2, v3) /* compute barycentric vectors */ -register BARYCCM bcm; -FLOAT *v1, *v2, *v3; -{ - FLOAT *vt; - FVECT va, vab, vcb; - double d; - register int i, j; - - for (j = 0; j < 3; j++) { - for (i = 0; i < 3; i++) { - vab[i] = v1[i] - v2[i]; - vcb[i] = v3[i] - v2[i]; - } - d = DOT(vcb,vcb); - if (d <= FTINY) - return(-1); - d = DOT(vcb,vab)/d; - for (i = 0; i < 3; i++) - va[i] = vab[i] - vcb[i]*d; - d = DOT(va,va); - if (d <= FTINY) - return(-1); - for (i = 0; i < 3; i++) { - va[i] /= d; - bcm[j][i] = va[i]; - } - bcm[j][3] = -DOT(v2,va); - /* rotate vertices */ - vt = v1; - v1 = v2; - v2 = v3; - v3 = vt; + if (flatness == RVFLAT || flatness == RVBENT) { + pvect(vlist[v3i[0]]); + pvect(vlist[v2i[0]]); + pvect(vlist[v1i[0]]); + } else { + pvect(vlist[v1i[0]]); + pvect(vlist[v2i[0]]); + pvect(vlist[v3i[0]]); } - return(0); -} - - -put_baryc(bcm) /* put barycentric coord. vectors */ -register BARYCCM bcm; -{ - register int i; - - for (i = 0; i < 3; i++) - printf("%14.8f %14.8f %14.8f %14.8f\n", - bcm[i][0], bcm[i][1], bcm[i][2], bcm[i][3]); -} - - -putquad(p0, p1, p3, p2) /* put out a quadrilateral */ -char *p0, *p1, *p3, *p2; /* names correspond to binary pos. */ -{ - VNDX p0i, p1i, p2i, p3i; - FVECT norm[4]; - char *mod, *name; - int axis; - FVECT v1, v2, vc1, vc2; - int ok1, ok2; - -#ifdef TEXMAPS - /* also should output texture index coordinates, - * which will require new .cal file - */ -#endif - if ((mod = getmtl()) == NULL) - return(-1); - name = getonm(); - /* get actual indices */ - if (!cvtndx(p0i,p0) || !cvtndx(p1i,p1) || - !cvtndx(p2i,p2) || !cvtndx(p3i,p3)) - return(0); - /* compute exact normals */ - fvsum(v1, vlist[p1i[0]], vlist[p0i[0]], -1.0); - fvsum(v2, vlist[p2i[0]], vlist[p0i[0]], -1.0); - fcross(vc1, v1, v2); - ok1 = normalize(vc1) != 0.0; - fvsum(v1, vlist[p2i[0]], vlist[p3i[0]], -1.0); - fvsum(v2, vlist[p1i[0]], vlist[p3i[0]], -1.0); - fcross(vc2, v1, v2); - ok2 = normalize(vc2) != 0.0; - if (!(ok1 | ok2)) - return(-1); - /* compute normal interpolation */ - axis = norminterp(norm, p0i, p1i, p2i, p3i); - - /* put out quadrilateral? */ - if (ok1 & ok2 && fabs(fdot(vc1,vc2)) >= 1.0-FTINY) { - printf("\n%s ", mod); - if (axis != -1) { - printf("texfunc %s\n", TEXNAME); - printf("4 surf_dx surf_dy surf_dz %s\n", QCALNAME); - printf("0\n13\t%d\n", axis); - pvect(norm[0]); - pvect(norm[1]); - pvect(norm[2]); - fvsum(v1, norm[3], vc1, -0.5); - fvsum(v1, v1, vc2, -0.5); - pvect(v1); - printf("\n%s ", TEXNAME); - } - printf("polygon %s.%d\n", name, faceno); - printf("0\n0\n12\n"); - pvect(vlist[p0i[0]]); - pvect(vlist[p1i[0]]); - pvect(vlist[p3i[0]]); - pvect(vlist[p2i[0]]); - return(1); - } - /* put out triangles? */ - if (ok1) { - printf("\n%s ", mod); - if (axis != -1) { - printf("texfunc %s\n", TEXNAME); - printf("4 surf_dx surf_dy surf_dz %s\n", QCALNAME); - printf("0\n13\t%d\n", axis); - pvect(norm[0]); - pvect(norm[1]); - pvect(norm[2]); - fvsum(v1, norm[3], vc1, -1.0); - pvect(v1); - printf("\n%s ", TEXNAME); - } - printf("polygon %s.%da\n", name, faceno); - printf("0\n0\n9\n"); - pvect(vlist[p0i[0]]); - pvect(vlist[p1i[0]]); - pvect(vlist[p2i[0]]); - } - if (ok2) { - printf("\n%s ", mod); - if (axis != -1) { - printf("texfunc %s\n", TEXNAME); - printf("4 surf_dx surf_dy surf_dz %s\n", QCALNAME); - printf("0\n13\t%d\n", axis); - pvect(norm[0]); - pvect(norm[1]); - pvect(norm[2]); - fvsum(v2, norm[3], vc2, -1.0); - pvect(v2); - printf("\n%s ", TEXNAME); - } - printf("polygon %s.%db\n", name, faceno); - printf("0\n0\n9\n"); - pvect(vlist[p2i[0]]); - pvect(vlist[p1i[0]]); - pvect(vlist[p3i[0]]); - } return(1); } -int -norminterp(resmat, p0i, p1i, p2i, p3i) /* compute normal interpolation */ -register FVECT resmat[4]; -register VNDX p0i, p1i, p2i, p3i; +void +freeverts(void) /* free all vertices */ { -#define u ((ax+1)%3) -#define v ((ax+2)%3) - - register int ax; - MAT4 eqnmat; - FVECT v1; - register int i, j; - -#ifdef TEXMAPS - /* also check for texture indices */ -#endif - if (!(p0i[2]>=0 && p1i[2]>=0 && p2i[2]>=0 && p3i[2]>=0)) - return(-1); - /* find dominant axis */ - VCOPY(v1, vnlist[p0i[2]]); - fvsum(v1, v1, vnlist[p1i[2]], 1.0); - fvsum(v1, v1, vnlist[p2i[2]], 1.0); - fvsum(v1, v1, vnlist[p3i[2]], 1.0); - ax = ABS(v1[0]) > ABS(v1[1]) ? 0 : 1; - ax = ABS(v1[ax]) > ABS(v1[2]) ? ax : 2; - /* assign equation matrix */ - eqnmat[0][0] = vlist[p0i[0]][u]*vlist[p0i[0]][v]; - eqnmat[0][1] = vlist[p0i[0]][u]; - eqnmat[0][2] = vlist[p0i[0]][v]; - eqnmat[0][3] = 1.0; - eqnmat[1][0] = vlist[p1i[0]][u]*vlist[p1i[0]][v]; - eqnmat[1][1] = vlist[p1i[0]][u]; - eqnmat[1][2] = vlist[p1i[0]][v]; - eqnmat[1][3] = 1.0; - eqnmat[2][0] = vlist[p2i[0]][u]*vlist[p2i[0]][v]; - eqnmat[2][1] = vlist[p2i[0]][u]; - eqnmat[2][2] = vlist[p2i[0]][v]; - eqnmat[2][3] = 1.0; - eqnmat[3][0] = vlist[p3i[0]][u]*vlist[p3i[0]][v]; - eqnmat[3][1] = vlist[p3i[0]][u]; - eqnmat[3][2] = vlist[p3i[0]][v]; - eqnmat[3][3] = 1.0; - /* invert matrix (solve system) */ - if (!invmat4(eqnmat, eqnmat)) - return(-1); /* no solution */ - /* compute result matrix */ - for (j = 0; j < 4; j++) - for (i = 0; i < 3; i++) - resmat[j][i] = eqnmat[j][0]*vnlist[p0i[2]][i] + - eqnmat[j][1]*vnlist[p1i[2]][i] + - eqnmat[j][2]*vnlist[p2i[2]][i] + - eqnmat[j][3]*vnlist[p3i[2]][i]; -#ifdef TEXMAPS - /* compute result matrix for texture indices */ -#endif - return(ax); - -#undef u -#undef v -} - - -freeverts() /* free all vertices */ -{ if (nvs) { - free((char *)vlist); + free((void *)vlist); nvs = 0; } if (nvts) { - free((char *)vtlist); + free((void *)vtlist); nvts = 0; } if (nvns) { - free((char *)vnlist); + free((void *)vnlist); nvns = 0; } } int -newv(x, y, z) /* create a new vertex */ -double x, y, z; +newv( /* create a new vertex */ + double x, + double y, + double z +) { if (!(nvs%CHUNKSIZ)) { /* allocate next block */ if (nvs == 0) vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT)); else - vlist = (FVECT *)realloc((char *)vlist, + vlist = (FVECT *)realloc((void *)vlist, (nvs+CHUNKSIZ)*sizeof(FVECT)); if (vlist == NULL) { fprintf(stderr, @@ -880,14 +721,17 @@ double x, y, z; int -newvn(x, y, z) /* create a new vertex normal */ -double x, y, z; +newvn( /* create a new vertex normal */ + double x, + double y, + double z +) { if (!(nvns%CHUNKSIZ)) { /* allocate next block */ if (nvns == 0) vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT)); else - vnlist = (FVECT *)realloc((char *)vnlist, + vnlist = (FVECT *)realloc((void *)vnlist, (nvns+CHUNKSIZ)*sizeof(FVECT)); if (vnlist == NULL) { fprintf(stderr, @@ -906,15 +750,17 @@ double x, y, z; int -newvt(x, y) /* create a new texture map vertex */ -double x, y; +newvt( /* create a new texture map vertex */ + double x, + double y +) { if (!(nvts%CHUNKSIZ)) { /* allocate next block */ if (nvts == 0) - vtlist = (FLOAT (*)[2])malloc(CHUNKSIZ*2*sizeof(FLOAT)); + vtlist = (RREAL (*)[2])malloc(CHUNKSIZ*2*sizeof(RREAL)); else - vtlist = (FLOAT (*)[2])realloc((char *)vtlist, - (nvts+CHUNKSIZ)*2*sizeof(FLOAT)); + vtlist = (RREAL (*)[2])realloc((void *)vtlist, + (nvts+CHUNKSIZ)*2*sizeof(RREAL)); if (vtlist == NULL) { fprintf(stderr, "Out of memory while allocating texture vertex %d\n", @@ -929,8 +775,10 @@ double x, y; } -syntax(er) /* report syntax error and exit */ -char *er; +void +syntax( /* report syntax error and exit */ + char *er +) { fprintf(stderr, "%s: Wavefront syntax error near line %d: %s\n", inpfile, lineno, er);