--- ray/src/rt/rv3.c 1989/11/01 16:12:20 1.8 +++ ray/src/rt/rv3.c 1995/08/18 10:27:11 2.9 @@ -1,4 +1,4 @@ -/* Copyright (c) 1987 Regents of the University of California */ +/* Copyright (c) 1994 Regents of the University of California */ #ifndef lint static char SCCSid[] = "$SunId$ LBL"; @@ -18,7 +18,21 @@ static char SCCSid[] = "$SunId$ LBL"; #include "random.h" +#ifndef WFLUSH +#ifdef SPEED +#define WFLUSH (5*SPEED) +#else +#define WFLUSH 100 /* flush after this many rays */ +#endif +#endif +#ifdef SMLFLT +#define sscanvec(s,v) (sscanf(s,"%f %f %f",v,v+1,v+2)==3) +#else +#define sscanvec(s,v) (sscanf(s,"%lf %lf %lf",v,v+1,v+2)==3) +#endif + + getrect(s, r) /* get a box */ char *s; register RECT *r; @@ -27,8 +41,8 @@ register RECT *r; if (*s && !strncmp(s, "all", strlen(s))) { r->l = r->d = 0; - r->r = ourview.hresolu; - r->u = ourview.vresolu; + r->r = hresolu; + r->u = vresolu; return(0); } if (sscanf(s, "%d %d %d %d", &x0, &y0, &x1, &y1) != 4) { @@ -57,8 +71,8 @@ register RECT *r; } if (r->l < 0) r->l = 0; if (r->d < 0) r->d = 0; - if (r->r > ourview.hresolu) r->r = ourview.hresolu; - if (r->u > ourview.vresolu) r->u = ourview.vresolu; + if (r->r > hresolu) r->r = hresolu; + if (r->u > vresolu) r->u = vresolu; if (r->l > r->r) r->l = r->r; if (r->d > r->u) r->d = r->u; return(0); @@ -83,13 +97,17 @@ double *mp; error(COMMAND, "illegal magnification"); return(-1); } - if (sscanf(s, "%*lf %lf %lf %lf", &vec[0], &vec[1], &vec[2]) != 3) { + if (!sscanvec(sskip(s), vec)) { if (dev->getcur == NULL) return(-1); (*dev->comout)("Pick view center\n"); if ((*dev->getcur)(&x, &y) == ABORT) return(-1); - rayview(thisray.rorg, thisray.rdir, &ourview, x+.5, y+.5); + if ((thisray.rmax = viewray(thisray.rorg, thisray.rdir, + &ourview, (x+.5)/hresolu, (y+.5)/vresolu)) < -FTINY) { + error(COMMAND, "not on image"); + return(-1); + } if (!direc || ourview.type == VT_PAR) { rayorigin(&thisray, NULL, PRIMARY, 1.0); if (!localhit(&thisray, &thescene)) { @@ -129,9 +147,10 @@ paint(p, xmin, ymin, xmax, ymax) /* compute and paint register PNODE *p; int xmin, ymin, xmax, ymax; { + extern unsigned long nrays; + static unsigned long lastflush = 0; static RAY thisray; double h, v; - register int i; if (xmax - xmin <= 0 || ymax - ymin <= 0) { /* empty */ p->x = xmin; @@ -140,20 +159,29 @@ int xmin, ymin, xmax, ymax; return; } /* jitter ray direction */ - p->x = h = xmin + (xmax-xmin)*frandom(); - p->y = v = ymin + (ymax-ymin)*frandom(); + h = xmin + (xmax-xmin)*frandom(); + v = ymin + (ymax-ymin)*frandom(); - rayview(thisray.rorg, thisray.rdir, &ourview, h, v); + if ((thisray.rmax = viewray(thisray.rorg, thisray.rdir, &ourview, + h/hresolu, v/vresolu)) < -FTINY) { + setcolor(thisray.rcol, 0.0, 0.0, 0.0); + } else { + rayorigin(&thisray, NULL, PRIMARY, 1.0); + samplendx++; + rayvalue(&thisray); + } - rayorigin(&thisray, NULL, PRIMARY, 1.0); - - rayvalue(&thisray); - + p->x = h; + p->y = v; copycolor(p->v, thisray.rcol); - scalecolor(p->v, exposure); (*dev->paintr)(greyscale?greyof(p->v):p->v, xmin, ymin, xmax, ymax); + + if (dev->flush != NULL && nrays - lastflush >= WFLUSH) { + lastflush = nrays; + (*dev->flush)(); + } } @@ -161,24 +189,27 @@ newimage() /* start a new image */ { /* free old image */ freepkids(&ptrunk); - /* set up frame */ - if (ourview.hresolu > dev->xsiz || ourview.vresolu > dev->ysiz) - newview(&ourview); /* beware recursive loop! */ + /* save reserve memory */ + fillreserves(); + /* compute resolution */ + hresolu = dev->xsiz; + vresolu = dev->ysiz; + normaspect(viewaspect(&ourview), &dev->pixaspect, &hresolu, &vresolu); pframe.l = pframe.d = 0; - pframe.r = ourview.hresolu; pframe.u = ourview.vresolu; + pframe.r = hresolu; pframe.u = vresolu; pdepth = 0; /* clear device */ - (*dev->clear)(ourview.hresolu, ourview.vresolu); + (*dev->clear)(hresolu, vresolu); /* get first value */ - paint(&ptrunk, 0, 0, ourview.hresolu, ourview.vresolu); + paint(&ptrunk, 0, 0, hresolu, vresolu); } redraw() /* redraw the image */ { - (*dev->clear)(ourview.hresolu, ourview.vresolu); + (*dev->clear)(hresolu, vresolu); (*dev->comout)("redrawing...\n"); - repaint(0, 0, ourview.hresolu, ourview.vresolu); + repaint(0, 0, hresolu, vresolu); (*dev->comout)("\n"); } @@ -191,7 +222,7 @@ int xmin, ymin, xmax, ymax; reg.l = xmin; reg.r = xmax; reg.d = ymin; reg.u = ymax; - paintrect(&ptrunk, 0, 0, ourview.hresolu, ourview.vresolu, ®); + paintrect(&ptrunk, 0, 0, hresolu, vresolu, ®); } @@ -339,21 +370,13 @@ register VIEW *vp; { char *err; - if (vp->hresolu > dev->xsiz || vp->vresolu > dev->ysiz) /* shrink */ - if (vp->vresolu * dev->xsiz < vp->hresolu * dev->ysiz) { - vp->vresolu = dev->xsiz * vp->vresolu / vp->hresolu; - vp->hresolu = dev->xsiz; - } else { - vp->hresolu = dev->ysiz * vp->hresolu / vp->vresolu; - vp->vresolu = dev->ysiz; - } if ((err = setview(vp)) != NULL) { sprintf(errmsg, "view not set - %s", err); error(COMMAND, errmsg); - } else if (bcmp(vp, &ourview, sizeof(VIEW))) { - bcopy(&ourview, &oldview, sizeof(VIEW)); - bcopy(vp, &ourview, sizeof(VIEW)); - newimage(); /* newimage() calls with vp=&ourview! */ + } else if (bcmp((char *)vp, (char *)&ourview, sizeof(VIEW))) { + copystruct(&oldview, &ourview); + copystruct(&ourview, vp); + newimage(); } } @@ -362,14 +385,13 @@ moveview(angle, elev, mag, vc) /* move viewpoint */ double angle, elev, mag; FVECT vc; { - extern double sqrt(), dist2(); double d; FVECT v1; VIEW nv; register int i; VCOPY(nv.vup, ourview.vup); - nv.hresolu = ourview.hresolu; nv.vresolu = ourview.vresolu; + nv.hoff = ourview.hoff; nv.voff = ourview.voff; spinvector(nv.vdir, ourview.vdir, ourview.vup, angle*(PI/180.)); if (elev != 0.0) { fcross(v1, ourview.vup, nv.vdir); @@ -382,10 +404,20 @@ FVECT vc; d = 0.0; /* don't move closer */ for (i = 0; i < 3; i++) d += (vc[i] - ourview.vp[i])*ourview.vdir[i]; + nv.vfore = ourview.vfore; + nv.vaft = ourview.vaft; } else { nv.horiz = ourview.horiz; nv.vert = ourview.vert; d = sqrt(dist2(ourview.vp, vc)) / mag; + if ((nv.vfore = ourview.vfore) > FTINY) { + nv.vfore += d - d*mag; + if (nv.vfore < 0.0) nv.vfore = 0.0; + } + if ((nv.vaft = ourview.vaft) > FTINY) { + nv.vaft += d - d*mag; + if (nv.vaft <= nv.vfore) nv.vaft = 0.0; + } } for (i = 0; i < 3; i++) nv.vp[i] = vc[i] - d*nv.vdir[i]; @@ -393,24 +425,46 @@ FVECT vc; } -spinvector(vres, vorig, vnorm, theta) /* rotate vector around normal */ -FVECT vres, vorig, vnorm; -double theta; +zoomview(vp, zf) /* zoom in or out */ +register VIEW *vp; +double zf; { - extern double sin(), cos(); - double sint, cost, dotp; - FVECT vperp; - register int i; - - if (theta == 0.0) { - VCOPY(vres, vorig); + switch (vp->type) { + case VT_PAR: /* parallel view */ + vp->horiz /= zf; + vp->vert /= zf; return; + case VT_ANG: /* angular fisheye */ + vp->horiz /= zf; + if (vp->horiz > 360.) + vp->horiz = 360.; + vp->vert /= zf; + if (vp->vert > 360.) + vp->vert = 360.; + return; + case VT_CYL: /* cylindrical panorama */ + vp->horiz /= zf; + if (vp->horiz > 360.) + vp->horiz = 360.; + vp->vert = atan(tan(vp->vert*(PI/180./2.))/zf) / (PI/180./2.); + return; + case VT_PER: /* perspective view */ + vp->horiz = atan(tan(vp->horiz*(PI/180./2.))/zf) / + (PI/180./2.); + vp->vert = atan(tan(vp->vert*(PI/180./2.))/zf) / + (PI/180./2.); + return; + case VT_HEM: /* hemispherical fisheye */ + vp->horiz = sin(vp->horiz*(PI/180./2.))/zf; + if (vp->horiz >= 1.0-FTINY) + vp->horiz = 180.; + else + vp->horiz = asin(vp->horiz) / (PI/180./2.); + vp->vert = sin(vp->vert*(PI/180./2.))/zf; + if (vp->vert >= 1.0-FTINY) + vp->vert = 180.; + else + vp->vert = asin(vp->vert) / (PI/180./2.); + return; } - sint = sin(theta); - cost = cos(theta); - dotp = DOT(vorig, vnorm); - fcross(vperp, vnorm, vorig); - for (i = 0; i < 3; i++) - vres[i] = vnorm[i]*dotp*(1.-cost) + - vorig[i]*cost + vperp[i]*sint; }