--- ray/src/px/pinterp.c 1990/01/18 23:58:29 1.23 +++ ray/src/px/pinterp.c 1990/10/15 11:01:48 1.30 @@ -10,7 +10,7 @@ static char SCCSid[] = "$SunId$ LBL"; #include "standard.h" -#include +#include #include "view.h" @@ -28,7 +28,7 @@ static char SCCSid[] = "$SunId$ LBL"; #define PACKSIZ 42 /* calculation packet size */ -#define RTCOM "rtrace -h -ovl -fff -x %d %s" +#define RTCOM "rtrace -h -ovl -fff %s" #define ABS(x) ((x)>0?(x):-(x)) @@ -46,9 +46,10 @@ float *ourzbuf; /* corresponding z-buffer */ char *progname; -int fill = F_FORE|F_BACK; /* selected fill algorithm */ +int fillo = F_FORE|F_BACK; /* selected fill options */ +int fillsamp = 0; /* sample separation (0 == inf) */ extern int backfill(), rcalfill(); /* fill functions */ -int (*deffill)() = backfill; /* selected fill function */ +int (*fillfunc)() = backfill; /* selected fill function */ COLR backcolr = BLKCOLR; /* background color */ double backz = 0.0; /* background z value */ int normdist = 1; /* normalized distance? */ @@ -59,6 +60,7 @@ int gotview; /* got input view? */ int thresolu, tvresolu; /* input resolution */ double theirexp; /* input picture exposure */ double theirs2ours[4][4]; /* transformation matrix */ +int hasmatrix = 0; /* has transformation matrix */ int childpid = -1; /* id of fill process */ FILE *psend, *precv; /* pipes to/from fill calculation */ @@ -98,35 +100,39 @@ char *argv[]; switch (argv[i][2]) { case '0': /* none */ check(3,0); - fill = 0; + fillo = 0; break; case 'f': /* foreground */ check(3,0); - fill = F_FORE; + fillo = F_FORE; break; case 'b': /* background */ check(3,0); - fill = F_BACK; + fillo = F_BACK; break; case 'a': /* all */ check(3,0); - fill = F_FORE|F_BACK; + fillo = F_FORE|F_BACK; break; + case 's': /* sample */ + check(3,1); + fillsamp = atoi(argv[++i]); + break; case 'c': /* color */ check(3,3); - deffill = backfill; + fillfunc = backfill; setcolr(backcolr, atof(argv[i+1]), atof(argv[i+2]), atof(argv[i+3])); i += 3; break; case 'z': /* z value */ check(3,1); - deffill = backfill; + fillfunc = backfill; backz = atof(argv[++i]); break; case 'r': /* rtrace */ check(3,1); - deffill = rcalfill; + fillfunc = rcalfill; calstart(RTCOM, argv[++i]); break; default: @@ -188,24 +194,24 @@ char *argv[]; for ( ; i < argc; i += 2) addpicture(argv[i], argv[i+1]); /* fill in spaces */ - if (fill&F_BACK) - backpicture(); + if (fillo&F_BACK) + backpicture(fillfunc, fillsamp); else - fillpicture(); + fillpicture(fillfunc); /* close calculation */ caldone(); /* add to header */ printargs(argc, argv, stdout); if (gotvfile) { - printf(VIEWSTR); + fputs(VIEWSTR, stdout); fprintview(&ourview, stdout); - printf("\n"); + putc('\n', stdout); } if (pixaspect < .99 || pixaspect > 1.01) fputaspect(pixaspect, stdout); if (ourexp > 0 && (ourexp < .995 || ourexp > 1.005)) fputexpos(ourexp, stdout); - printf("\n"); + putc('\n', stdout); /* write picture */ writepicture(); /* write z file */ @@ -225,10 +231,11 @@ userr: headline(s) /* process header string */ char *s; { - static char *altname[] = {"rview","rpict","pinterp",VIEWSTR,NULL}; + static char *altname[] = {VIEWSTR,"rpict","rview","pinterp",NULL}; register char **an; - printf("\t%s", s); + putc('\t', stdout); + fputs(s, stdout); if (isexpos(s)) { theirexp *= exposval(s); @@ -278,7 +285,7 @@ char *pfile, *zspec; exit(1); } /* compute transformation */ - pixform(theirs2ours, &theirview, &ourview); + hasmatrix = pixform(theirs2ours, &theirview, &ourview); /* allocate scanlines */ scanin = (COLR *)malloc(thresolu*sizeof(COLR)); zin = (float *)malloc(thresolu*sizeof(float)); @@ -325,6 +332,10 @@ register VIEW *vw1, *vw2; { double m4t[4][4]; + if (vw1->type != VT_PER && vw1->type != VT_PAR) + return(0); + if (vw2->type != VT_PER && vw2->type != VT_PAR) + return(0); setident4(xfmat); xfmat[0][0] = vw1->hvec[0]; xfmat[0][1] = vw1->hvec[1]; @@ -352,6 +363,7 @@ register VIEW *vw1, *vw2; m4t[2][2] = vw2->vdir[2]; m4t[3][2] = -DOT(vw2->vp,vw2->vdir); multmat4(xfmat, xfmat, m4t); + return(1); } @@ -362,34 +374,19 @@ float *zline; struct position *lasty; /* input/output */ { extern double sqrt(); - double pos[3]; + FVECT pos; struct position lastx, newpos; register int x; lastx.z = 0; for (x = thresolu-1; x >= 0; x--) { - pos[0] = (x+.5)/thresolu + theirview.hoff - .5; - pos[1] = (y+.5)/tvresolu + theirview.voff - .5; + pos[0] = (x+.5)/thresolu; + pos[1] = (y+.5)/tvresolu; pos[2] = zline[x]; - if (theirview.type == VT_PER) { - if (normdist) /* adjust for eye-ray distance */ - pos[2] /= sqrt( 1. - + pos[0]*pos[0]*theirview.hn2 - + pos[1]*pos[1]*theirview.vn2 ); - pos[0] *= pos[2]; - pos[1] *= pos[2]; - } - multp3(pos, pos, theirs2ours); - if (pos[2] <= 0) { + if (movepixel(pos) < 0) { lasty[x].z = lastx.z = 0; /* mark invalid */ continue; } - if (ourview.type == VT_PER) { - pos[0] /= pos[2]; - pos[1] /= pos[2]; - } - pos[0] += .5 - ourview.hoff; - pos[1] += .5 - ourview.voff; newpos.x = pos[0] * hresolu; newpos.y = pos[1] * vresolu; newpos.z = zline[x]; @@ -419,7 +416,7 @@ double z; register int x, y; /* final position */ /* compute vector p0p1 */ - if (fill&F_FORE && ABS(p1->z-p0->z) <= zt) { + if (fillo&F_FORE && ABS(p1->z-p0->z) <= zt) { s1x = p1->x - p0->x; s1y = p1->y - p0->y; l1 = ABS(s1x); @@ -430,7 +427,7 @@ double z; p1isy = -1; } /* compute vector p0p2 */ - if (fill&F_FORE && ABS(p2->z-p0->z) <= zt) { + if (fillo&F_FORE && ABS(p2->z-p0->z) <= zt) { s2x = p2->x - p0->x; s2y = p2->y - p0->y; if (p1isy == 1) @@ -448,7 +445,11 @@ double z; y1 = p0->y + c1*s1y/l1; for (c2 = l2; c2-- > 0; ) { x = x1 + c2*s2x/l2; + if (x < 0 || x >= hresolu) + continue; y = y1 + c2*s2y/l2; + if (y < 0 || y >= vresolu) + continue; if (zscan(y)[x] <= 0 || zscan(y)[x]-z > zeps*zscan(y)[x]) { zscan(y)[x] = z; @@ -459,8 +460,49 @@ double z; } -backpicture() /* background fill algorithm */ +movepixel(pos) /* reposition image point */ +FVECT pos; { + FVECT pt, direc; + + if (hasmatrix) { + pos[0] += theirview.hoff - .5; + pos[1] += theirview.voff - .5; + if (theirview.type == VT_PER) { + if (normdist) /* adjust for eye-ray distance */ + pos[2] /= sqrt( 1. + + pos[0]*pos[0]*theirview.hn2 + + pos[1]*pos[1]*theirview.vn2 ); + pos[0] *= pos[2]; + pos[1] *= pos[2]; + } + multp3(pos, pos, theirs2ours); + if (pos[2] <= 0) + return(-1); + if (ourview.type == VT_PER) { + pos[0] /= pos[2]; + pos[1] /= pos[2]; + } + pos[0] += .5 - ourview.hoff; + pos[1] += .5 - ourview.voff; + return(0); + } + if (viewray(pt, direc, &theirview, pos[0], pos[1]) < 0) + return(-1); + pt[0] += direc[0]*pos[2]; + pt[1] += direc[1]*pos[2]; + pt[2] += direc[2]*pos[2]; + viewpixel(&pos[0], &pos[1], &pos[2], &ourview, pt); + if (pos[2] <= 0) + return(-1); + return(0); +} + + +backpicture(fill, samp) /* background fill algorithm */ +int (*fill)(); +int samp; +{ int *yback, xback; int y; COLR pfill; @@ -510,28 +552,40 @@ backpicture() /* background fill algorithm */ xback = x-1; } /* - * Check to see if we have no background for - * this pixel. If not, use background color. + * If we have no background for this pixel, + * use the given fill function. */ - if (xback < 0 && yback[x] < 0) { - (*deffill)(x,y); - continue; - } + if (xback < 0 && yback[x] < 0) + goto fillit; /* * Compare, and use the background that is * farther, unless one of them is next to us. + * If the background is too distant, call + * the fill function. */ if ( yback[x] < 0 || (xback >= 0 && ABS(x-xback) <= 1) || ( ABS(y-yback[x]) > 1 && zscan(yback[x])[x] < zscan(y)[xback] ) ) { + if (samp > 0 && ABS(x-xback) >= samp) + goto fillit; copycolr(pscan(y)[x],pscan(y)[xback]); zscan(y)[x] = zscan(y)[xback]; } else { + if (samp > 0 && ABS(y-yback[x]) > samp) + goto fillit; copycolr(pscan(y)[x],pscan(yback[x])[x]); zscan(y)[x] = zscan(yback[x])[x]; } + continue; + fillit: + (*fill)(x,y); + if (fill == rcalfill) { /* use it */ + clearqueue(); + xback = x; + yback[x] = y; + } } else { /* full pixel */ yback[x] = -2; xback = -2; @@ -541,14 +595,15 @@ backpicture() /* background fill algorithm */ } -fillpicture() /* paint in empty pixels with default */ +fillpicture(fill) /* paint in empty pixels using fill */ +int (*fill)(); { register int x, y; for (y = 0; y < vresolu; y++) for (x = 0; x < hresolu; x++) if (zscan(y)[x] <= 0) - (*deffill)(x,y); + (*fill)(x,y); } @@ -583,10 +638,10 @@ char *fname; if (donorm) { double vx, yzn2; register int x; - yzn2 = y - .5*(vresolu-1); + yzn2 = (y+.5)/vresolu + ourview.voff - .5; yzn2 = 1. + yzn2*yzn2*ourview.vn2; for (x = 0; x < hresolu; x++) { - vx = x - .5*(hresolu-1); + vx = (x+.5)/hresolu + ourview.hoff - .5; zout[x] = zscan(y)[x] * sqrt(vx*vx*ourview.hn2 + yzn2); } @@ -635,7 +690,7 @@ char *prog, *args; fprintf(stderr, "%s: too many calculations\n", progname); exit(1); } - sprintf(combuf, prog, PACKSIZ, args); + sprintf(combuf, prog, args); if (pipe(p0) < 0 || pipe(p1) < 0) syserror(); if ((childpid = vfork()) == 0) { /* fork calculation */ @@ -671,7 +726,9 @@ caldone() /* done with calculation */ if (childpid == -1) return; - clearqueue(1); + clearqueue(); + fclose(psend); + fclose(precv); while ((pid = wait(0)) != -1 && pid != childpid) ; childpid = -1; @@ -682,7 +739,7 @@ rcalfill(x, y) /* fill with ray-calculated pixel */ int x, y; { if (queuesiz >= PACKSIZ) /* flush queue if needed */ - clearqueue(0); + clearqueue(); /* add position to queue */ queue[queuesiz][0] = x; queue[queuesiz][1] = y; @@ -690,8 +747,7 @@ int x, y; } -clearqueue(done) /* process queue */ -int done; +clearqueue() /* process queue */ { FVECT orig, dir; float fbuf[6]; @@ -705,7 +761,10 @@ int done; fbuf[3] = dir[0]; fbuf[4] = dir[1]; fbuf[5] = dir[2]; fwrite((char *)fbuf, sizeof(float), 6, psend); } - if ((done ? fclose(psend) : fflush(psend)) == EOF) + /* flush output and get results */ + fbuf[3] = fbuf[4] = fbuf[5] = 0.0; /* mark */ + fwrite((char *)fbuf, sizeof(float), 6, psend); + if (fflush(psend) == EOF) syserror(); for (i = 0; i < queuesiz; i++) { if (fread((char *)fbuf, sizeof(float), 4, precv) < 4) { @@ -722,8 +781,6 @@ int done; fbuf[0], fbuf[1], fbuf[2]); zscan(queue[i][1])[queue[i][0]] = fbuf[3]; } - if (done) - fclose(precv); queuesiz = 0; }