--- ray/src/rt/ambient.c 2003/02/22 02:07:28 2.47
+++ ray/src/rt/ambient.c 2007/09/15 05:16:10 2.66
@@ -1,5 +1,5 @@
#ifndef lint
-static const char RCSid[] = "$Id: ambient.c,v 2.47 2003/02/22 02:07:28 greg Exp $";
+static const char RCSid[] = "$Id: ambient.c,v 2.66 2007/09/15 05:16:10 greg Exp $";
#endif
/*
* ambient.c - routines dealing with ambient (inter-reflected) component.
@@ -7,69 +7,15 @@ static const char RCSid[] = "$Id: ambient.c,v 2.47 200
* Declarations of external symbols in ambient.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 "platform.h"
+#include "ray.h"
#include "otypes.h"
-
+#include "resolu.h"
#include "ambient.h"
-
#include "random.h"
#ifndef OCTSCALE
@@ -78,7 +24,9 @@ static const char RCSid[] = "$Id: ambient.c,v 2.47 200
extern char *shm_boundary; /* memory sharing boundary */
-#define MAXASET 511 /* maximum number of elements in ambient set */
+#ifndef MAXASET
+#define MAXASET 2047 /* maximum number of elements in ambient set */
+#endif
OBJECT ambset[MAXASET+1]={0}; /* ambient include/exclude set */
double maxarad; /* maximum ambient radius */
@@ -90,10 +38,10 @@ static FILE *ambfp = NULL; /* ambient file pointer */
static int nunflshed = 0; /* number of unflushed ambient values */
#ifndef SORT_THRESH
-#ifdef BIGMEM
-#define SORT_THRESH ((9L<<20)/sizeof(AMBVAL))
-#else
+#ifdef SMLMEM
#define SORT_THRESH ((3L<<20)/sizeof(AMBVAL))
+#else
+#define SORT_THRESH ((9L<<20)/sizeof(AMBVAL))
#endif
#endif
#ifndef SORT_INTVL
@@ -130,17 +78,30 @@ static long lastpos = -1; /* last flush position */
#define newambval() (AMBVAL *)malloc(sizeof(AMBVAL))
#define freeav(av) free((void *)av);
-static void initambfile(), avsave(), avinsert(), sortambvals(), unloadatree();
-static int avlmemi();
-static AMBVAL *avstore();
+static void initambfile(int creat);
+static void avsave(AMBVAL *av);
+static AMBVAL *avstore(AMBVAL *aval);
+static AMBTREE *newambtree(void);
+static void freeambtree(AMBTREE *atp);
+
+typedef void unloadtf_t(void *);
+static unloadtf_t avinsert;
+static unloadtf_t av2list;
+static void unloadatree(AMBTREE *at, unloadtf_t *f);
+
+static int aposcmp(const void *avp1, const void *avp2);
+static int avlmemi(AMBVAL *avaddr);
+static void sortambvals(int always);
+
#ifdef F_SETLKW
-static void aflock();
+static void aflock(int typ);
#endif
-void
-setambres(ar) /* set ambient resolution */
-int ar;
+extern void
+setambres( /* set ambient resolution */
+ int ar
+)
{
ambres = ar < 0 ? 0 : ar; /* may be done already */
/* set min & max radii */
@@ -160,9 +121,10 @@ int ar;
}
-void
-setambacc(newa) /* set ambient accuracy */
-double newa;
+extern void
+setambacc( /* set ambient accuracy */
+ double newa
+)
{
double ambdiff;
@@ -174,11 +136,11 @@ double newa;
}
-void
-setambient() /* initialize calculation */
+extern void
+setambient(void) /* initialize calculation */
{
int readonly = 0;
- long pos, flen;
+ long flen;
AMBVAL amb;
/* make sure we're fresh */
ambdone();
@@ -198,7 +160,7 @@ setambient() /* initialize calculation */
readonly = (ambfp = fopen(ambfile, "r")) != NULL;
if (ambfp != NULL) {
initambfile(0); /* file exists */
- pos = ftell(ambfp);
+ lastpos = ftell(ambfp);
while (readambval(&amb, ambfp))
avinsert(avstore(&amb));
nambshare = nambvals; /* share loaded values */
@@ -212,29 +174,31 @@ setambient() /* initialize calculation */
return; /* avoid ambsync() */
}
/* align file pointer */
- pos += (long)nambvals*AMBVALSIZ;
- flen = lseek(fileno(ambfp), (off_t)0L, 2);
- if (flen != pos) {
+ lastpos += (long)nambvals*AMBVALSIZ;
+ flen = lseek(fileno(ambfp), (off_t)0, SEEK_END);
+ if (flen != lastpos) {
sprintf(errmsg,
"ignoring last %ld values in ambient file (corrupted)",
- (flen - pos)/AMBVALSIZ);
+ (flen - lastpos)/AMBVALSIZ);
error(WARNING, errmsg);
- fseek(ambfp, pos, 0);
- ftruncate(fileno(ambfp), (off_t)pos);
+ fseek(ambfp, lastpos, SEEK_SET);
+#ifndef _WIN32 /* XXX we need a replacement for that one */
+ ftruncate(fileno(ambfp), (off_t)lastpos);
+#endif
}
} else if ((ambfp = fopen(ambfile, "w+")) != NULL) {
initambfile(1); /* else create new file */
+ lastpos = ftell(ambfp);
} else {
sprintf(errmsg, "cannot open ambient file \"%s\"", ambfile);
error(SYSTEM, errmsg);
}
- nunflshed++; /* lie */
- ambsync();
+ ambsync(); /* load previous values */
}
-void
-ambdone() /* close ambient file and free memory */
+extern void
+ambdone(void) /* close ambient file and free memory */
{
if (ambfp != NULL) { /* close ambient file */
ambsync();
@@ -259,9 +223,10 @@ ambdone() /* close ambient file and free memory */
}
-void
-ambnotify(obj) /* record new modifier */
-OBJECT obj;
+extern void
+ambnotify( /* record new modifier */
+ OBJECT obj
+)
{
static int hitlimit = 0;
register OBJREC *o;
@@ -288,13 +253,15 @@ OBJECT obj;
}
-void
-ambient(acol, r, nrm) /* compute ambient component for ray */
-COLOR acol;
-register RAY *r;
-FVECT nrm;
+extern void
+multambient( /* compute ambient component & multiply by coef. */
+ COLOR aval,
+ register RAY *r,
+ FVECT nrm
+)
{
static int rdepth = 0; /* ambient recursion */
+ COLOR acol;
double d, l;
if (ambdiv <= 0) /* no ambient calculation */
@@ -308,55 +275,64 @@ FVECT nrm;
goto dumbamb;
if (ambacc <= FTINY) { /* no ambient storage */
+ copycolor(acol, aval);
rdepth++;
d = doambient(acol, r, r->rweight, NULL, NULL);
rdepth--;
if (d <= FTINY)
goto dumbamb;
+ copycolor(aval, acol);
return;
}
if (tracktime) /* sort to minimize thrashing */
sortambvals(0);
- /* get ambient value */
+ /* interpolate ambient value */
setcolor(acol, 0.0, 0.0, 0.0);
d = sumambient(acol, r, nrm, rdepth,
&atrunk, thescene.cuorg, thescene.cusize);
if (d > FTINY) {
- scalecolor(acol, 1.0/d);
+ d = 1.0/d;
+ scalecolor(acol, d);
+ multcolor(aval, acol);
return;
}
rdepth++; /* need to cache new value */
d = makeambient(acol, r, nrm, rdepth-1);
rdepth--;
- if (d > FTINY)
+ if (d > FTINY) {
+ multcolor(aval, acol); /* got new value */
return;
+ }
dumbamb: /* return global value */
- copycolor(acol, ambval);
- if (ambvwt <= 0 | navsum == 0)
+ if ((ambvwt <= 0) | (navsum == 0)) {
+ multcolor(aval, ambval);
return;
+ }
l = bright(ambval); /* average in computations */
if (l > FTINY) {
d = (log(l)*(double)ambvwt + avsum) /
(double)(ambvwt + navsum);
d = exp(d) / l;
- scalecolor(acol, d); /* apply color of ambval */
+ scalecolor(aval, d);
+ multcolor(aval, ambval); /* apply color of ambval */
} else {
d = exp( avsum / (double)navsum );
- setcolor(acol, d, d, d); /* neutral color */
+ scalecolor(aval, d); /* neutral color */
}
}
-double
-sumambient(acol, r, rn, al, at, c0, s) /* get interpolated ambient value */
-COLOR acol;
-register RAY *r;
-FVECT rn;
-int al;
-AMBTREE *at;
-FVECT c0;
-double s;
+extern double
+sumambient( /* get interpolated ambient value */
+ COLOR acol,
+ register RAY *r,
+ FVECT rn,
+ int al,
+ AMBTREE *at,
+ FVECT c0,
+ double s
+)
{
double d, e1, e2, wt, wsum;
COLOR ct;
@@ -376,7 +352,7 @@ double s;
*/
if (av->lvl > al) /* list sorted, so this works */
break;
- if (av->weight < r->rweight-FTINY)
+ if (av->weight < 0.9*r->rweight)
continue;
/*
* Ambient radius test.
@@ -455,30 +431,39 @@ double s;
break;
}
if (j == 3)
- wsum += sumambient(acol, r, rn, al, at->kid+i, ck0, s);
+ wsum += sumambient(acol, r, rn, al,
+ at->kid+i, ck0, s);
}
return(wsum);
}
-double
-makeambient(acol, r, rn, al) /* make a new ambient value */
-COLOR acol;
-register RAY *r;
-FVECT rn;
-int al;
+extern double
+makeambient( /* make a new ambient value for storage */
+ COLOR acol,
+ RAY *r,
+ FVECT rn,
+ int al
+)
{
AMBVAL amb;
FVECT gp, gd;
- /* compute weight */
- amb.weight = pow(AVGREFL, (double)al);
- if (r->rweight < 0.1*amb.weight) /* heuristic */
- amb.weight = r->rweight;
+ int i;
+
+ amb.weight = 1.0; /* compute weight */
+ for (i = al; i-- > 0; )
+ amb.weight *= AVGREFL;
+ if (r->rweight < 0.1*amb.weight) /* heuristic override */
+ amb.weight = 1.25*r->rweight;
+ setcolor(acol, AVGREFL, AVGREFL, AVGREFL);
/* compute ambient */
amb.rad = doambient(acol, r, amb.weight, gp, gd);
- if (amb.rad <= FTINY)
+ if (amb.rad <= FTINY) {
+ setcolor(acol, 0.0, 0.0, 0.0);
return(0.0);
- /* store it */
+ }
+ scalecolor(acol, 1./AVGREFL); /* undo assumed reflectance */
+ /* store value */
VCOPY(amb.pos, r->rop);
VCOPY(amb.dir, r->ron);
amb.lvl = al;
@@ -493,11 +478,13 @@ int al;
}
-void
-extambient(cr, ap, pv, nv) /* extrapolate value at pv, nv */
-COLOR cr;
-register AMBVAL *ap;
-FVECT pv, nv;
+extern void
+extambient( /* extrapolate value at pv, nv */
+ COLOR cr,
+ register AMBVAL *ap,
+ FVECT pv,
+ FVECT nv
+)
{
FVECT v1;
register int i;
@@ -520,8 +507,9 @@ FVECT pv, nv;
static void
-initambfile(creat) /* initialize ambient file */
-int creat;
+initambfile( /* initialize ambient file */
+ int creat
+)
{
extern char *progname, *octname;
static char *mybuf = NULL;
@@ -529,9 +517,7 @@ int creat;
#ifdef F_SETLKW
aflock(creat ? F_WRLCK : F_RDLCK);
#endif
-#ifdef MSDOS
- setmode(fileno(ambfp), O_BINARY);
-#endif
+ SET_FILE_BINARY(ambfp);
if (mybuf == NULL)
mybuf = (char *)bmalloc(BUFSIZ+8);
setbuf(ambfp, mybuf);
@@ -558,8 +544,9 @@ int creat;
static void
-avsave(av) /* insert and save an ambient value */
-AMBVAL *av;
+avsave( /* insert and save an ambient value */
+ AMBVAL *av
+)
{
avinsert(avstore(av));
if (ambfp == NULL)
@@ -576,15 +563,16 @@ writerr:
static AMBVAL *
-avstore(aval) /* allocate memory and store aval */
-register AMBVAL *aval;
+avstore( /* allocate memory and store aval */
+ register AMBVAL *aval
+)
{
register AMBVAL *av;
double d;
if ((av = newambval()) == NULL)
error(SYSTEM, "out of memory in avstore");
- copystruct(av, aval);
+ *av = *aval;
av->latick = ambclock;
av->next = NULL;
nambvals++;
@@ -603,7 +591,7 @@ static AMBTREE *atfreelist = NULL; /* free ambient tr
static AMBTREE *
-newambtree() /* allocate 8 ambient tree structs */
+newambtree(void) /* allocate 8 ambient tree structs */
{
register AMBTREE *atp, *upperlim;
@@ -619,14 +607,15 @@ newambtree() /* allocate 8 ambient tree structs */
}
atp = atfreelist;
atfreelist = atp->kid;
- bzero((char *)atp, 8*sizeof(AMBTREE));
+ memset((char *)atp, '\0', 8*sizeof(AMBTREE));
return(atp);
}
static void
-freeambtree(atp) /* free 8 ambient tree structs */
-AMBTREE *atp;
+freeambtree( /* free 8 ambient tree structs */
+ AMBTREE *atp
+)
{
atp->kid = atfreelist;
atfreelist = atp;
@@ -634,8 +623,9 @@ AMBTREE *atp;
static void
-avinsert(av) /* insert ambient value in our tree */
-register AMBVAL *av;
+avinsert( /* insert ambient value in our tree */
+ void *av
+)
{
register AMBTREE *at;
register AMBVAL *ap;
@@ -645,19 +635,19 @@ register AMBVAL *av;
int branch;
register int i;
- if (av->rad <= FTINY)
+ if (((AMBVAL*)av)->rad <= FTINY)
error(CONSISTENCY, "zero ambient radius in avinsert");
at = &atrunk;
VCOPY(ck0, thescene.cuorg);
s = thescene.cusize;
- while (s*(OCTSCALE/2) > av->rad*ambacc) {
+ while (s*(OCTSCALE/2) > ((AMBVAL*)av)->rad*ambacc) {
if (at->kid == NULL)
if ((at->kid = newambtree()) == NULL)
error(SYSTEM, "out of memory in avinsert");
s *= 0.5;
branch = 0;
for (i = 0; i < 3; i++)
- if (av->pos[i] > ck0[i] + s) {
+ if (((AMBVAL*)av)->pos[i] > ck0[i] + s) {
ck0[i] += s;
branch |= 1 << i;
}
@@ -665,18 +655,19 @@ register AMBVAL *av;
}
avh.next = at->alist; /* order by increasing level */
for (ap = &avh; ap->next != NULL; ap = ap->next)
- if (ap->next->lvl >= av->lvl)
+ if (ap->next->lvl >= ((AMBVAL*)av)->lvl)
break;
- av->next = ap->next;
- ap->next = av;
+ ((AMBVAL*)av)->next = ap->next;
+ ap->next = (AMBVAL*)av;
at->alist = avh.next;
}
static void
-unloadatree(at, f) /* unload an ambient value tree */
-register AMBTREE *at;
-void (*f)();
+unloadatree( /* unload an ambient value tree */
+ register AMBTREE *at,
+ unloadtf_t *f
+)
{
register AMBVAL *av;
register int i;
@@ -701,25 +692,29 @@ static struct avl {
static AMBVAL **avlist2; /* memory positions for sorting */
static int i_avlist; /* index for lists */
+static int alatcmp(const void *av1, const void *av2);
-static int
-av2list(av)
-register AMBVAL *av;
+static void
+av2list(
+ void *av
+)
{
#ifdef DEBUG
if (i_avlist >= nambvals)
error(CONSISTENCY, "too many ambient values in av2list1");
#endif
- avlist1[i_avlist].p = avlist2[i_avlist] = av;
- avlist1[i_avlist++].t = av->latick;
+ avlist1[i_avlist].p = avlist2[i_avlist] = (AMBVAL*)av;
+ avlist1[i_avlist++].t = ((AMBVAL*)av)->latick;
}
static int
-alatcmp(av1, av2) /* compare ambient values for MRA */
-struct avl *av1, *av2;
+alatcmp( /* compare ambient values for MRA */
+ const void *av1,
+ const void *av2
+)
{
- register long lc = av2->t - av1->t;
+ register long lc = ((struct avl *)av2)->t - ((struct avl *)av1)->t;
return(lc<0 ? -1 : lc>0 ? 1 : 0);
}
@@ -731,8 +726,10 @@ struct avl *av1, *av2;
* assumes pointers differ by exact struct size increments.
*/
static int
-aposcmp(avp1, avp2) /* compare ambient value positions */
-const void *avp1, *avp2;
+aposcmp( /* compare ambient value positions */
+ const void *avp1,
+ const void *avp2
+)
{
register long diff = *(char * const *)avp1 - *(char * const *)avp2;
if (diff < 0)
@@ -742,8 +739,9 @@ const void *avp1, *avp2;
#if 1
static int
-avlmemi(avaddr) /* find list position from address */
-AMBVAL *avaddr;
+avlmemi( /* find list position from address */
+ AMBVAL *avaddr
+)
{
register AMBVAL **avlpp;
@@ -760,8 +758,9 @@ AMBVAL *avaddr;
static void
-sortambvals(always) /* resort ambient values */
-int always;
+sortambvals( /* resort ambient values */
+ int always
+)
{
AMBTREE oldatrunk;
AMBVAL tav, *tap, *pnext;
@@ -796,7 +795,7 @@ int always;
if (avlist2 != NULL)
free((void *)avlist2);
if (always) { /* rebuild without sorting */
- copystruct(&oldatrunk, &atrunk);
+ oldatrunk = atrunk;
atrunk.alist = NULL;
atrunk.kid = NULL;
unloadatree(&oldatrunk, avinsert);
@@ -827,14 +826,14 @@ int always;
if (avlist1[i].p == NULL)
continue;
tap = avlist2[i];
- copystruct(&tav, tap);
+ tav = *tap;
for (j = i; (pnext = avlist1[j].p) != tap;
j = avlmemi(pnext)) {
- copystruct(avlist2[j], pnext);
+ *(avlist2[j]) = *pnext;
avinsert(avlist2[j]);
avlist1[j].p = NULL;
}
- copystruct(avlist2[j], &tav);
+ *(avlist2[j]) = tav;
avinsert(avlist2[j]);
avlist1[j].p = NULL;
}
@@ -859,40 +858,41 @@ int always;
#ifdef F_SETLKW
static void
-aflock(typ) /* lock/unlock ambient file */
-int typ;
+aflock( /* lock/unlock ambient file */
+ int typ
+)
{
static struct flock fls; /* static so initialized to zeroes */
+ if (typ == fls.l_type) /* already called? */
+ return;
fls.l_type = typ;
if (fcntl(fileno(ambfp), F_SETLKW, &fls) < 0)
error(SYSTEM, "cannot (un)lock ambient file");
}
-int
-ambsync() /* synchronize ambient file */
+extern int
+ambsync(void) /* synchronize ambient file */
{
long flen;
AMBVAL avs;
register int n;
- if (nunflshed == 0)
+ if (ambfp == NULL) /* no ambient file? */
return(0);
- if (lastpos < 0) /* initializing (locked in initambfile) */
- goto syncend;
- /* gain exclusive access */
- aflock(F_WRLCK);
+ /* gain appropriate access */
+ aflock(nunflshed ? F_WRLCK : F_RDLCK);
/* see if file has grown */
- if ((flen = lseek(fileno(ambfp), (off_t)0L, 2)) < 0)
+ if ((flen = lseek(fileno(ambfp), (off_t)0, SEEK_END)) < 0)
goto seekerr;
- if (n = flen - lastpos) { /* file has grown */
+ if ( (n = flen - lastpos) ) { /* file has grown */
if (ambinp == NULL) { /* use duplicate filedes */
ambinp = fdopen(dup(fileno(ambfp)), "r");
if (ambinp == NULL)
error(SYSTEM, "fdopen failed in ambsync");
}
- if (fseek(ambinp, lastpos, 0) < 0)
+ if (fseek(ambinp, lastpos, SEEK_SET) < 0)
goto seekerr;
while (n >= AMBVALSIZ) { /* load contributed values */
if (!readambval(&avs, ambinp)) {
@@ -905,9 +905,10 @@ ambsync() /* synchronize ambient file */
avinsert(avstore(&avs));
n -= AMBVALSIZ;
}
+ lastpos = flen - n;
/*** seek always as safety measure
if (n) ***/ /* alignment */
- if (lseek(fileno(ambfp), (off_t)(flen-n), 0) < 0)
+ if (lseek(fileno(ambfp), (off_t)lastpos, SEEK_SET) < 0)
goto seekerr;
}
#ifdef DEBUG
@@ -918,23 +919,26 @@ ambsync() /* synchronize ambient file */
error(CONSISTENCY, errmsg);
}
#endif
-syncend:
n = fflush(ambfp); /* calls write() at last */
- if ((lastpos = lseek(fileno(ambfp), (off_t)0L, 1)) < 0)
+ if (n != EOF)
+ lastpos += (long)nunflshed*AMBVALSIZ;
+ else if ((lastpos = lseek(fileno(ambfp), (off_t)0, SEEK_CUR)) < 0)
goto seekerr;
+
aflock(F_UNLCK); /* release file */
nunflshed = 0;
return(n);
seekerr:
error(SYSTEM, "seek failed in ambsync");
+ return -1; /* pro forma return */
}
#else
-int
-ambsync() /* flush ambient file */
+extern int
+ambsync(void) /* flush ambient file */
{
- if (nunflshed == 0)
+ if (ambfp == NULL)
return(0);
nunflshed = 0;
return(fflush(ambfp));