--- ray/src/rt/rv3.c 1990/06/26 09:00:19 1.16 +++ ray/src/rt/rv3.c 2005/09/19 02:23:58 2.19 @@ -1,28 +1,32 @@ -/* Copyright (c) 1987 Regents of the University of California */ - #ifndef lint -static char SCCSid[] = "$SunId$ LBL"; +static const char RCSid[] = "$Id: rv3.c,v 2.19 2005/09/19 02:23:58 greg Exp $"; #endif - /* * rv3.c - miscellaneous routines for rview. * - * 5/11/87 + * External symbols declared in rpaint.h */ -#include "ray.h" +#include "copyright.h" -#include "octree.h" +#include +#include "ray.h" #include "rpaint.h" - #include "random.h" #ifndef WFLUSH -#define WFLUSH 30 /* flush after this many rays */ +#define WFLUSH 2048 /* flush after this many rays */ #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 + +int getrect(s, r) /* get a box */ char *s; register RECT *r; @@ -69,6 +73,7 @@ register RECT *r; } +int getinterest(s, direc, vec, mp) /* get area of interest */ char *s; int direc; @@ -87,16 +92,19 @@ 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); - viewray(thisray.rorg, thisray.rdir, &ourview, - (x+.5)/hresolu, (y+.5)/vresolu); + 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); + rayorigin(&thisray, PRIMARY, NULL, NULL); if (!localhit(&thisray, &thescene)) { error(COMMAND, "not a local object"); return(-1); @@ -110,9 +118,14 @@ double *mp; VCOPY(vec, thisray.rdir); else VCOPY(vec, thisray.rop); - } else if (direc) - for (i = 0; i < 3; i++) - vec[i] -= ourview.vp[i]; + } else if (direc) { + for (i = 0; i < 3; i++) + vec[i] -= ourview.vp[i]; + if (normalize(vec) == 0.0) { + error(COMMAND, "point at view origin"); + return(-1); + } + } return(0); } @@ -130,12 +143,12 @@ register COLOR col; } +void paint(p, xmin, ymin, xmax, ymax) /* compute and paint a rectangle */ register PNODE *p; int xmin, ymin, xmax, ymax; { - extern long nrays; - static long lastflush = 0; + static unsigned long lastflush = 0; static RAY thisray; double h, v; @@ -149,9 +162,14 @@ int xmin, ymin, xmax, ymax; h = xmin + (xmax-xmin)*frandom(); v = ymin + (ymax-ymin)*frandom(); - viewray(thisray.rorg, thisray.rdir, &ourview, h/hresolu, v/vresolu); - rayorigin(&thisray, NULL, PRIMARY, 1.0); - rayvalue(&thisray); + 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, PRIMARY, NULL, NULL); + samplendx = rand_samp ? random() : samplendx+1; + rayvalue(&thisray); + } p->x = h; p->y = v; @@ -167,10 +185,13 @@ int xmin, ymin, xmax, ymax; } +void newimage() /* start a new image */ { /* free old image */ freepkids(&ptrunk); + /* save reserve memory */ + fillreserves(); /* compute resolution */ hresolu = dev->xsiz; vresolu = dev->ysiz; @@ -185,6 +206,7 @@ newimage() /* start a new image */ } +void redraw() /* redraw the image */ { (*dev->clear)(hresolu, vresolu); @@ -194,6 +216,7 @@ redraw() /* redraw the image */ } +void repaint(xmin, ymin, xmax, ymax) /* repaint a region */ int xmin, ymin, xmax, ymax; { @@ -206,6 +229,7 @@ int xmin, ymin, xmax, ymax; } +void paintrect(p, xmin, ymin, xmax, ymax, r) /* paint picture rectangle */ register PNODE *p; int xmin, ymin, xmax, ymax; @@ -276,6 +300,7 @@ int pd; } +void scalepict(p, sf) /* scale picture values */ register PNODE *p; double sf; @@ -292,6 +317,7 @@ double sf; } +void getpictcolrs(yoff, scan, p, xsiz, ysiz) /* get scanline from picture */ int yoff; register COLR *scan; @@ -322,15 +348,7 @@ int xsiz, ysiz; } -pcopy(p1, p2) /* copy paint node p1 into p2 */ -register PNODE *p1, *p2; -{ - copycolor(p2->v, p1->v); - p2->x = p1->x; - p2->y = p1->y; -} - - +void freepkids(p) /* free pnode's children */ register PNODE *p; { @@ -340,11 +358,12 @@ register PNODE *p; freepkids(p->kid+DR); freepkids(p->kid+UL); freepkids(p->kid+UR); - free((char *)p->kid); + free((void *)p->kid); p->kid = NULL; } +void newview(vp) /* change viewing parameters */ register VIEW *vp; { @@ -353,42 +372,47 @@ register VIEW *vp; if ((err = setview(vp)) != NULL) { sprintf(errmsg, "view not set - %s", err); error(COMMAND, errmsg); - } else if (bcmp((char *)vp, (char *)&ourview, sizeof(VIEW))) { - copystruct(&oldview, &ourview); - copystruct(&ourview, vp); + } else if (memcmp((char *)vp, (char *)&ourview, sizeof(VIEW))) { + oldview = ourview; + ourview = *vp; newimage(); } } +void moveview(angle, elev, mag, vc) /* move viewpoint */ double angle, elev, mag; FVECT vc; { - extern double sqrt(), dist2(); double d; FVECT v1; - VIEW nv; + VIEW nv = ourview; register int i; - VCOPY(nv.vup, ourview.vup); - 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); normalize(v1); spinvector(nv.vdir, nv.vdir, v1, elev*(PI/180.)); } - if ((nv.type = ourview.type) == VT_PAR) { - nv.horiz = ourview.horiz / mag; - nv.vert = ourview.vert / mag; + if (nv.type == VT_PAR) { + nv.horiz /= mag; + nv.vert /= mag; d = 0.0; /* don't move closer */ for (i = 0; i < 3; i++) d += (vc[i] - ourview.vp[i])*ourview.vdir[i]; } else { - nv.horiz = ourview.horiz; - nv.vert = ourview.vert; d = sqrt(dist2(ourview.vp, vc)) / mag; + if (nv.vfore > FTINY) { + nv.vfore += d - d*mag; + if (nv.vfore < 0.0) nv.vfore = 0.0; + } + if (nv.vaft > FTINY) { + nv.vaft += d - d*mag; + if (nv.vaft <= nv.vfore) nv.vaft = 0.0; + } + nv.vdist /= mag; } for (i = 0; i < 3; i++) nv.vp[i] = vc[i] - d*nv.vdir[i]; @@ -396,24 +420,57 @@ FVECT vc; } -spinvector(vres, vorig, vnorm, theta) /* rotate vector around normal */ -FVECT vres, vorig, vnorm; -double theta; +void +pcopy(p1, p2) /* copy paint node p1 into p2 */ +register PNODE *p1, *p2; { - extern double sin(), cos(); - double sint, cost, dotp; - FVECT vperp; - register int i; - - if (theta == 0.0) { - VCOPY(vres, vorig); + copycolor(p2->v, p1->v); + p2->x = p1->x; + p2->y = p1->y; +} + + +void +zoomview(vp, zf) /* zoom in or out */ +register VIEW *vp; +double zf; +{ + 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; }