--- ray/src/cv/obj2rad.c 1994/04/13 17:24:24 2.5 +++ ray/src/cv/obj2rad.c 1994/06/15 12:50:37 2.11 @@ -10,7 +10,7 @@ static char SCCSid[] = "$SunId$ LBL"; * Currently, we support only polygonal geometry. Non-planar * faces are broken rather haphazardly into triangles. * Also, texture map indices only work for triangles, though - * I'm not sure they work correctly. + * I'm not sure they work correctly. (Taken out -- see TEXMAPS defines.) */ #include "standard.h" @@ -20,7 +20,6 @@ static char SCCSid[] = "$SunId$ LBL"; #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 */ @@ -37,7 +36,10 @@ int nvns; FLOAT (*vtlist)[2]; /* map vertex list */ int nvts; -typedef FLOAT BARYCCM[3][4]; /* barycentric coordinate system */ +typedef struct { + int ax; /* major axis */ + FLOAT tm[2][3]; /* transformation */ +} BARYCCM; typedef int VNDX[3]; /* vertex index (point,map,normal) */ @@ -69,23 +71,25 @@ RULEHD *ourmapping = NULL; char *defmat = DEFMAT; /* default (starting) material name */ char *defobj = DEFOBJ; /* default (starting) object name */ -int donames = 0; /* only get qualifier names */ +int flatten = 0; /* discard surface normal information */ + char *getmtl(), *getonm(); char mapname[128]; /* current picture file */ char matname[64]; /* current material name */ char group[16][32]; /* current group names */ char objname[128]; /* current object name */ +char *inpfile; /* input file name */ int lineno; /* current line number */ -int faceno; /* number of faces read */ +int faceno; /* current face number */ main(argc, argv) /* read in .obj file and convert */ int argc; char *argv[]; { - char *fname; + int donames = 0; int i; for (i = 1; i < argc && argv[i][0] == '-'; i++) @@ -99,20 +103,23 @@ 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) goto userr; if (i == argc) - fname = ""; - else if (freopen(fname=argv[i], "r", stdin) == NULL) { - fprintf(stderr, "%s: cannot open\n", fname); + inpfile = ""; + else if (freopen(inpfile=argv[i], "r", stdin) == NULL) { + fprintf(stderr, "%s: cannot open\n", inpfile); exit(1); } if (donames) { /* scan for ids */ getnames(stdin); - printf("filename \"%s\"\n", fname); + printf("filename \"%s\"\n", inpfile); printf("filetype \"Wavefront\"\n"); write_quals(&qlist, qual, stdout); printf("qualifier %s begin\n", qlist.qual[Q_FAC]); @@ -121,11 +128,11 @@ char *argv[]; } else { /* translate file */ printf("# "); printargs(argc, argv, stdout); - convert(fname, stdin); + convert(stdin); } 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); } @@ -180,20 +187,14 @@ FILE *fp; } -convert(fname, fp) /* convert a T-mesh */ -char *fname; +convert(fp) /* convert a T-mesh */ FILE *fp; { char *argv[MAXARG]; int argc; int nstats, nunknown; register int i; - /* start fresh */ - freeverts(); - mapname[0] = '\0'; - strcpy(matname, defmat); - strcpy(objname, defobj); - lineno = 0; + nstats = nunknown = 0; /* scan until EOF */ while (argc = getstmt(argv, fp)) { @@ -202,7 +203,7 @@ FILE *fp; switch (argv[0][1]) { case '\0': /* point */ if (badarg(argc-1,argv+1,"fff")) - syntax(fname, lineno, "Bad vertex"); + syntax("Bad vertex"); newv(atof(argv[1]), atof(argv[2]), atof(argv[3])); break; @@ -210,10 +211,10 @@ FILE *fp; if (argv[0][2]) goto unknown; if (badarg(argc-1,argv+1,"fff")) - syntax(fname, lineno, "Bad normal"); + syntax("Bad normal"); if (!newvn(atof(argv[1]), atof(argv[2]), atof(argv[3]))) - syntax(fname, lineno, "Zero normal"); + syntax("Zero normal"); break; case 't': /* texture map */ if (argv[0][2]) @@ -232,20 +233,15 @@ FILE *fp; faceno++; switch (argc-1) { case 0: case 1: case 2: - syntax(fname, lineno, "Too few vertices"); + syntax("Too few vertices"); break; case 3: if (!puttri(argv[1], argv[2], argv[3])) - syntax(fname, lineno, "Bad triangle"); + syntax("Bad triangle"); break; - case 4: - if (!putquad(argv[1], argv[2], - argv[3], argv[4])) - syntax(fname, lineno, "Bad quad"); - break; default: if (!putface(argc-1, argv+1)) - syntax(fname, lineno, "Bad face"); + syntax("Bad face"); break; } break; @@ -260,7 +256,7 @@ FILE *fp; if (!strcmp(argv[1], "off")) mapname[0] = '\0'; else - strcpy(mapname, argv[1]); + sprintf(mapname, "%s.pic", argv[1]); } else goto unknown; break; @@ -279,6 +275,7 @@ FILE *fp; group[i-1][0] = '\0'; break; case '#': /* comment */ + printargs(argc, argv, stdout); break; default:; /* something we don't deal with */ unknown: @@ -287,7 +284,7 @@ FILE *fp; } nstats++; } - printf("\n# Done processing file: %s\n", fname); + printf("\n# Done processing file: %s\n", inpfile); printf("# %d lines, %d statements, %d unrecognized\n", lineno, nstats, nunknown); } @@ -332,8 +329,13 @@ getmtl() /* figure material for this face */ { register RULEHD *rp = ourmapping; - if (rp == NULL) /* no rule set */ - return(matname); + if (rp == NULL) { /* no rule set */ + if (matname[0]) + return(matname); + if (group[0][0]) + return(group[0]); + return(defmat); + } /* check for match */ do { if (matchrule(rp)) { @@ -354,10 +356,11 @@ getonm() /* invent a good name for object */ static char name[64]; register char *cp1, *cp2; register int i; - - if (!group[0][0] || strcmp(objname, DEFOBJ)) - return(objname); /* good enough for us */ - + /* check for preset */ + if (objname[0]) + return(objname); + if (!group[0][0]) + return(defobj); cp1 = name; /* else make name out of groups */ for (i = 0; group[i][0]; i++) { cp2 = group[i]; @@ -381,12 +384,16 @@ register RULEHD *rp; register int i; if (rp->qflg & FL(Q_MTL)) { + if (!matname[0]) + return(0); tmpid.number = 0; tmpid.name = matname; if (!matchid(&tmpid, &idm(rp)[Q_MTL])) return(0); } if (rp->qflg & FL(Q_MAP)) { + if (!mapname[0]) + return(0); tmpid.number = 0; tmpid.name = mapname; if (!matchid(&tmpid, &idm(rp)[Q_MAP])) @@ -403,6 +410,8 @@ register RULEHD *rp; return(0); } if (rp->qflg & FL(Q_OBJ)) { + if (!objname[0]) + return(0); tmpid.number = 0; tmpid.name = objname; if (!matchid(&tmpid, &idm(rp)[Q_OBJ])) @@ -428,7 +437,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 @@ -442,7 +451,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 @@ -456,7 +465,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 @@ -465,7 +474,7 @@ register char *vs; } -nonplanar(ac, av) /* are vertices are non-planar? */ +nonplanar(ac, av) /* are vertices non-planar? */ register int ac; register char **av; { @@ -521,24 +530,24 @@ int ac; register char **av; { VNDX vi; - char *mod; + 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 */ - for (i = 1; i < ac; i++) + ac--; /* remove vertex & rotate */ + cp = av[0]; + for (i = 0; i < ac-1; i++) av[i] = av[i+2]; + av[i] = cp; } - if (ac == 3 && !puttri(av[0], av[1], av[2])) - return(0); return(1); } - if ((mod = getmtl()) == NULL) + if ((cp = getmtl()) == NULL) return(-1); - printf("\n%s polygon %s.%d\n", mod, getonm(), faceno); + printf("\n%s polygon %s.%d\n", cp, getonm(), faceno); printf("0\n0\n%d\n", 3*ac); for (i = 0; i < ac; i++) { if (!cvtndx(vi, av[i])) @@ -563,10 +572,14 @@ 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); + texOK = !flatten && (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=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) */ @@ -574,8 +587,8 @@ 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("0\n16 "); + put_baryc(&bvecs); printf("\t%14.12g %14.12g %14.12g\n", vnlist[v1i[2]][0], vnlist[v2i[2]][0], vnlist[v3i[2]][0]); @@ -586,18 +599,20 @@ char *v1, *v2, *v3; vnlist[v1i[2]][2], vnlist[v2i[2]][2], vnlist[v3i[2]][2]); } +#ifdef TEXMAPS /* put out pattern (if any) */ if (patOK) { 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("0\n13 "); + 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]); } +#endif /* put out triangle */ printf("\n%s polygon %s.%d\n", mod, getonm(), faceno); printf("0\n0\n9\n"); @@ -611,33 +626,41 @@ char *v1, *v2, *v3; int comp_baryc(bcm, v1, v2, v3) /* compute barycentric vectors */ -register BARYCCM bcm; +register BARYCCM *bcm; FLOAT *v1, *v2, *v3; { FLOAT *vt; FVECT va, vab, vcb; double d; + int ax0, ax1; 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); + /* compute major axis */ + for (i = 0; i < 3; i++) { + vab[i] = v1[i] - v2[i]; + vcb[i] = v3[i] - v2[i]; + } + fcross(va, vab, vcb); + bcm->ax = ABS(va[0]) > ABS(va[1]) ? 0 : 1; + bcm->ax = ABS(va[bcm->ax]) > ABS(va[2]) ? bcm->ax : 2; + ax0 = (bcm->ax + 1) % 3; + ax1 = (bcm->ax + 2) % 3; + for (j = 0; j < 2; j++) { + vab[0] = v1[ax0] - v2[ax0]; + vcb[0] = v3[ax0] - v2[ax0]; + vab[1] = v1[ax1] - v2[ax1]; + vcb[1] = v3[ax1] - v2[ax1]; + d = vcb[0]*vcb[0] + vcb[1]*vcb[1]; 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); + d = (vcb[0]*vab[0]+vcb[1]*vab[1])/d; + va[0] = vab[0] - vcb[0]*d; + va[1] = vab[1] - vcb[1]*d; + d = va[0]*va[0] + va[1]*va[1]; 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); + bcm->tm[j][0] = va[0] /= d; + bcm->tm[j][1] = va[1] /= d; + bcm->tm[j][2] = -(v2[ax0]*va[0]+v2[ax1]*va[1]); /* rotate vertices */ vt = v1; v1 = v2; @@ -649,169 +672,16 @@ FLOAT *v1, *v2, *v3; put_baryc(bcm) /* put barycentric coord. vectors */ -register BARYCCM bcm; +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]); + printf("\t%d\n", bcm->ax); + printf("%14.8f %14.8f %14.8f\n", + bcm->tm[0][0], bcm->tm[0][1], bcm->tm[0][2]); + printf("%14.8f %14.8f %14.8f\n", + bcm->tm[1][0], bcm->tm[1][1], bcm->tm[1][2]); } -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; - - 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; -{ -#define u ((ax+1)%3) -#define v ((ax+2)%3) - - register int ax; - MAT4 eqnmat; - FVECT v1; - register int i, j; - - 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]; - return(ax); - -#undef u -#undef v -} - - freeverts() /* free all vertices */ { if (nvs) { @@ -903,12 +773,10 @@ double x, y; } -syntax(fn, ln, er) /* report syntax error and exit */ -char *fn; -int ln; +syntax(er) /* report syntax error and exit */ char *er; { fprintf(stderr, "%s: Wavefront syntax error near line %d: %s\n", - fn, ln, er); + inpfile, lineno, er); exit(1); }