--- ray/src/rt/rv3.c 2003/02/22 02:07:29 2.10
+++ ray/src/rt/rv3.c 2008/09/05 21:34:09 2.28
@@ -1,5 +1,5 @@
#ifndef lint
-static const char RCSid[] = "$Id: rv3.c,v 2.10 2003/02/22 02:07:29 greg Exp $";
+static const char RCSid[] = "$Id: rv3.c,v 2.28 2008/09/05 21:34:09 greg Exp $";
#endif
/*
* rv3.c - miscellaneous routines for rview.
@@ -7,76 +7,17 @@ static const char RCSid[] = "$Id: rv3.c,v 2.10 2003/02
* External symbols declared in rpaint.h
*/
-/* ====================================================================
- * The Radiance Software License, Version 1.0
- *
- * Copyright (c) 1990 - 2002 The Regents of the University of California,
- * through Lawrence Berkeley National Laboratory. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes Radiance software
- * (http://radsite.lbl.gov/)
- * developed by the Lawrence Berkeley National Laboratory
- * (http://www.lbl.gov/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
- * and "The Regents of the University of California" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact radiance@radsite.lbl.gov.
- *
- * 5. Products derived from this software may not be called "Radiance",
- * nor may "Radiance" appear in their name, without prior written
- * permission of Lawrence Berkeley National Laboratory.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of Lawrence Berkeley National Laboratory. For more
- * information on Lawrence Berkeley National Laboratory, please see
- * .
- */
+#include "copyright.h"
-#include "ray.h"
+#include
+#include "ray.h"
#include "rpaint.h"
-
#include "random.h"
#ifndef WFLUSH
-#ifdef SPEED
-#define WFLUSH (5*SPEED)
-#else
-#define WFLUSH 100 /* flush after this many rays */
+#define WFLUSH 64 /* flush after this many rays */
#endif
-#endif
#ifdef SMLFLT
#define sscanvec(s,v) (sscanf(s,"%f %f %f",v,v+1,v+2)==3)
@@ -84,11 +25,13 @@ static const char RCSid[] = "$Id: rv3.c,v 2.10 2003/02
#define sscanvec(s,v) (sscanf(s,"%lf %lf %lf",v,v+1,v+2)==3)
#endif
+static unsigned long niflush; /* flushes since newimage() */
int
-getrect(s, r) /* get a box */
-char *s;
-register RECT *r;
+getrect( /* get a box */
+ char *s,
+ RECT *r
+)
{
int x0, y0, x1, y1;
@@ -133,15 +76,16 @@ register RECT *r;
int
-getinterest(s, direc, vec, mp) /* get area of interest */
-char *s;
-int direc;
-FVECT vec;
-double *mp;
+getinterest( /* get area of interest */
+ char *s,
+ int direc,
+ FVECT vec,
+ double *mp
+)
{
int x, y;
RAY thisray;
- register int i;
+ int i;
if (sscanf(s, "%lf", mp) != 1)
*mp = 1.0;
@@ -163,7 +107,7 @@ double *mp;
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);
@@ -177,16 +121,22 @@ 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);
}
float * /* keep consistent with COLOR typedef */
-greyof(col) /* convert color to greyscale */
-register COLOR col;
+greyof( /* convert color to greyscale */
+ COLOR col
+)
{
static COLOR gcol;
double b;
@@ -196,72 +146,145 @@ register COLOR col;
return(gcol);
}
+static void
+recolor( /* recolor the given node */
+ PNODE *p
+)
+{
+ while (p->kid != NULL) { /* need to propogate down */
+ int mx = (p->xmin + p->xmax) >> 1;
+ int my = (p->ymin + p->ymax) >> 1;
+ int ki;
+ if (p->x >= mx)
+ ki = (p->y >= my) ? UR : DR;
+ else
+ ki = (p->y >= my) ? UL : DL;
+ pcopy(p, p->kid+ki);
+ p = p->kid + ki;
+ }
-void
-paint(p, xmin, ymin, xmax, ymax) /* compute and paint a rectangle */
-register PNODE *p;
-int xmin, ymin, xmax, ymax;
+ (*dev->paintr)(greyscale?greyof(p->v):p->v,
+ p->xmin, p->ymin, p->xmax, p->ymax);
+}
+
+int
+paint( /* compute and paint a rectangle */
+ PNODE *p
+)
{
+ extern int ray_pnprocs;
static unsigned long lastflush = 0;
static RAY thisray;
+ int flushintvl;
double h, v;
- if (xmax - xmin <= 0 || ymax - ymin <= 0) { /* empty */
- p->x = xmin;
- p->y = ymin;
+ if (p->xmax - p->xmin <= 0 || p->ymax - p->ymin <= 0) { /* empty */
+ p->x = p->xmin;
+ p->y = p->ymin;
setcolor(p->v, 0.0, 0.0, 0.0);
- return;
+ return(0);
}
/* jitter ray direction */
- h = xmin + (xmax-xmin)*frandom();
- v = ymin + (ymax-ymin)*frandom();
+ p->x = h = p->xmin + (p->xmax-p->xmin)*frandom();
+ p->y = v = p->ymin + (p->ymax-p->ymin)*frandom();
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);
+ int rval;
+ rayorigin(&thisray, PRIMARY, NULL, NULL);
+ thisray.rno = (unsigned long)p;
+ rval = ray_pqueue(&thisray);
+ if (!rval)
+ return(0);
+ if (rval < 0)
+ return(-1);
+ p = (PNODE *)thisray.rno;
}
- 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);
+ recolor(p); /* paint it */
- if (dev->flush != NULL && nrays - lastflush >= WFLUSH) {
- lastflush = nrays;
+ if (ambounce <= 0) /* shall we check for input? */
+ flushintvl = ray_pnprocs*WFLUSH;
+ else if (niflush < WFLUSH)
+ flushintvl = ray_pnprocs*niflush/(ambounce+1);
+ else
+ flushintvl = ray_pnprocs*WFLUSH/(ambounce+1);
+
+ if (dev->flush != NULL && raynum - lastflush >= flushintvl) {
+ lastflush = raynum;
(*dev->flush)();
+ niflush++;
}
+ return(1);
}
+int
+waitrays(void) /* finish up pending rays */
+{
+ int nwaited = 0;
+ int rval;
+ RAY raydone;
+
+ while ((rval = ray_presult(&raydone, 0)) > 0) {
+ PNODE *p = (PNODE *)raydone.rno;
+ copycolor(p->v, raydone.rcol);
+ scalecolor(p->v, exposure);
+ recolor(p);
+ nwaited++;
+ }
+ if (rval < 0)
+ return(-1);
+ return(nwaited);
+}
+
+
void
-newimage() /* start a new image */
+newimage( /* start a new image */
+ char *s
+)
{
+ int newnp;
+ /* change in nproc? */
+ if (s != NULL && sscanf(s, "%d", &newnp) == 1 && newnp > 0) {
+ if (!newparam) {
+ if (newnp < nproc)
+ ray_pclose(nproc - newnp);
+ else
+ ray_popen(newnp - nproc);
+ }
+ nproc = newnp;
+ }
/* free old image */
freepkids(&ptrunk);
- /* 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 = hresolu; pframe.u = vresolu;
+ ptrunk.xmin = ptrunk.ymin = pframe.l = pframe.d = 0;
+ ptrunk.xmax = pframe.r = hresolu;
+ ptrunk.ymax = pframe.u = vresolu;
pdepth = 0;
/* clear device */
(*dev->clear)(hresolu, vresolu);
- /* get first value */
- paint(&ptrunk, 0, 0, hresolu, vresolu);
+
+ if (newparam) { /* (re)start rendering procs */
+ ray_pclose(0);
+ ray_popen(nproc);
+ newparam = 0;
+ }
+ niflush = 0; /* get first value */
+ paint(&ptrunk);
}
void
-redraw() /* redraw the image */
+redraw(void) /* redraw the image */
{
(*dev->clear)(hresolu, vresolu);
(*dev->comout)("redrawing...\n");
@@ -271,81 +294,80 @@ redraw() /* redraw the image */
void
-repaint(xmin, ymin, xmax, ymax) /* repaint a region */
-int xmin, ymin, xmax, ymax;
+repaint( /* repaint a region */
+ int xmin,
+ int ymin,
+ int xmax,
+ int ymax
+)
{
RECT reg;
reg.l = xmin; reg.r = xmax;
reg.d = ymin; reg.u = ymax;
- paintrect(&ptrunk, 0, 0, hresolu, vresolu, ®);
+ paintrect(&ptrunk, ®);
}
void
-paintrect(p, xmin, ymin, xmax, ymax, r) /* paint picture rectangle */
-register PNODE *p;
-int xmin, ymin, xmax, ymax;
-register RECT *r;
+paintrect( /* paint picture rectangle */
+ PNODE *p,
+ RECT *r
+)
{
int mx, my;
- if (xmax - xmin <= 0 || ymax - ymin <= 0)
+ if (p->xmax - p->xmin <= 0 || p->ymax - p->ymin <= 0)
return;
if (p->kid == NULL) {
(*dev->paintr)(greyscale?greyof(p->v):p->v,
- xmin, ymin, xmax, ymax); /* do this */
+ p->xmin, p->ymin, p->xmax, p->ymax); /* do this */
return;
}
- mx = (xmin + xmax) >> 1; /* do kids */
- my = (ymin + ymax) >> 1;
+ mx = (p->xmin + p->xmax) >> 1; /* do kids */
+ my = (p->ymin + p->ymax) >> 1;
if (mx > r->l) {
if (my > r->d)
- paintrect(p->kid+DL, xmin, ymin, mx, my, r);
+ paintrect(p->kid+DL, r);
if (my < r->u)
- paintrect(p->kid+UL, xmin, my, mx, ymax, r);
+ paintrect(p->kid+UL, r);
}
if (mx < r->r) {
if (my > r->d)
- paintrect(p->kid+DR, mx, ymin, xmax, my, r);
+ paintrect(p->kid+DR, r);
if (my < r->u)
- paintrect(p->kid+UR, mx, my, xmax, ymax, r);
+ paintrect(p->kid+UR, r);
}
}
PNODE *
-findrect(x, y, p, r, pd) /* find a rectangle */
-int x, y;
-register PNODE *p;
-register RECT *r;
-int pd;
+findrect( /* find a rectangle */
+ int x,
+ int y,
+ PNODE *p,
+ int pd
+)
{
int mx, my;
while (p->kid != NULL && pd--) {
- mx = (r->l + r->r) >> 1;
- my = (r->d + r->u) >> 1;
+ mx = (p->xmin + p->xmax) >> 1;
+ my = (p->ymin + p->ymax) >> 1;
if (x < mx) {
- r->r = mx;
if (y < my) {
- r->u = my;
p = p->kid+DL;
} else {
- r->d = my;
p = p->kid+UL;
}
} else {
- r->l = mx;
if (y < my) {
- r->u = my;
p = p->kid+DR;
} else {
- r->d = my;
p = p->kid+UR;
}
}
@@ -355,10 +377,35 @@ int pd;
void
-scalepict(p, sf) /* scale picture values */
-register PNODE *p;
-double sf;
+compavg( /* recompute averages */
+ PNODE *p
+)
{
+ int i, navg;
+
+ if (p->kid == NULL)
+ return;
+
+ setcolor(p->v, .0, .0, .0);
+ navg = 0;
+ for (i = 0; i < 4; i++) {
+ if (p->kid[i].xmin >= p->kid[i].xmax) continue;
+ if (p->kid[i].ymin >= p->kid[i].ymax) continue;
+ compavg(p->kid+i);
+ addcolor(p->v, p->kid[i].v);
+ navg++;
+ }
+ if (navg > 1)
+ scalecolor(p->v, 1./navg);
+}
+
+
+void
+scalepict( /* scale picture values */
+ PNODE *p,
+ double sf
+)
+{
scalecolor(p->v, sf); /* do this node */
if (p->kid == NULL)
@@ -372,13 +419,15 @@ double sf;
void
-getpictcolrs(yoff, scan, p, xsiz, ysiz) /* get scanline from picture */
-int yoff;
-register COLR *scan;
-register PNODE *p;
-int xsiz, ysiz;
+getpictcolrs( /* get scanline from picture */
+ int yoff,
+ COLR *scan,
+ PNODE *p,
+ int xsiz,
+ int ysiz
+)
{
- register int mx;
+ int mx;
int my;
if (p->kid == NULL) { /* do this node */
@@ -403,8 +452,9 @@ int xsiz, ysiz;
void
-freepkids(p) /* free pnode's children */
-register PNODE *p;
+freepkids( /* free pnode's children */
+ PNODE *p
+)
{
if (p->kid == NULL)
return;
@@ -418,60 +468,59 @@ register PNODE *p;
void
-newview(vp) /* change viewing parameters */
-register VIEW *vp;
+newview( /* change viewing parameters */
+ VIEW *vp
+)
{
char *err;
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);
- newimage();
+ } else if (memcmp((char *)vp, (char *)&ourview, sizeof(VIEW))) {
+ oldview = ourview;
+ ourview = *vp;
+ newimage(NULL);
}
}
void
-moveview(angle, elev, mag, vc) /* move viewpoint */
-double angle, elev, mag;
-FVECT vc;
+moveview( /* move viewpoint */
+ double angle,
+ double elev,
+ double mag,
+ FVECT vc
+)
{
double d;
FVECT v1;
- VIEW nv;
- register int i;
+ VIEW nv = ourview;
+ 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];
- 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) {
+ if (nv.vfore > FTINY) {
nv.vfore += d - d*mag;
if (nv.vfore < 0.0) nv.vfore = 0.0;
}
- if ((nv.vaft = ourview.vaft) > FTINY) {
+ 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];
@@ -480,8 +529,10 @@ FVECT vc;
void
-pcopy(p1, p2) /* copy paint node p1 into p2 */
-register PNODE *p1, *p2;
+pcopy( /* copy paint node p1 into p2 */
+ PNODE *p1,
+ PNODE *p2
+)
{
copycolor(p2->v, p1->v);
p2->x = p1->x;
@@ -490,9 +541,10 @@ register PNODE *p1, *p2;
void
-zoomview(vp, zf) /* zoom in or out */
-register VIEW *vp;
-double zf;
+zoomview( /* zoom in or out */
+ VIEW *vp,
+ double zf
+)
{
switch (vp->type) {
case VT_PAR: /* parallel view */
@@ -506,6 +558,18 @@ double zf;
vp->vert /= zf;
if (vp->vert > 360.)
vp->vert = 360.;
+ return;
+ case VT_PLS: /* planisphere fisheye */
+ vp->horiz = sin((PI/180./2.)*vp->horiz) /
+ (1.0 + cos((PI/180./2.)*vp->horiz)) / zf;
+ vp->horiz *= vp->horiz;
+ vp->horiz = (2.*180./PI)*acos((1. - vp->horiz) /
+ (1. + vp->horiz));
+ vp->vert = sin((PI/180./2.)*vp->vert) /
+ (1.0 + cos((PI/180./2.)*vp->vert)) / zf;
+ vp->vert *= vp->vert;
+ vp->vert = (2.*180./PI)*acos((1. - vp->vert) /
+ (1. + vp->vert));
return;
case VT_CYL: /* cylindrical panorama */
vp->horiz /= zf;