--- ray/src/rt/ambient.c 1989/08/08 17:31:23 1.6 +++ ray/src/rt/ambient.c 1991/06/06 10:48:50 1.13 @@ -17,12 +17,12 @@ static char SCCSid[] = "$SunId$ LBL"; #include "octree.h" +#include "otypes.h" + #include "random.h" #define OCTSCALE 0.5 /* ceil((valid rad.)/(cube size)) */ -#define WDONE 4 /* stop if wsum/wmin is at or above */ - extern CUBE thescene; /* contains space boundaries */ extern COLOR ambval; /* global ambient component */ @@ -34,14 +34,19 @@ extern int ambounce; /* number of ambient bounces */ extern char *amblist[]; /* ambient include/exclude list */ extern int ambincl; /* include == 1, exclude == 0 */ -OBJECT ambset[128]; /* ambient include/exclude set */ +#define MAXASET 511 /* maximum number of elements in ambient set */ +OBJECT ambset[MAXASET+1]={0}; /* ambient include/exclude set */ double maxarad; /* maximum ambient radius */ double minarad; /* minimum ambient radius */ +/* + * Since we've defined our vectors as float below to save space, + * watch out for changes in the definitions of VCOPY() and DOT(). + */ typedef struct ambval { - FVECT pos; /* position in space */ - FVECT dir; /* normal direction */ + float pos[3]; /* position in space */ + float dir[3]; /* normal direction */ int lvl; /* recursion level of parent ray */ float weight; /* weight of parent ray */ COLOR val; /* computed ambient value */ @@ -76,21 +81,8 @@ setambient(afile) /* initialize calculation */ char *afile; { long ftell(); - char **amblp; - OBJECT obj; AMBVAL amb; - /* set up ambient set */ - ambset[0] = 0; - for (amblp = amblist; *amblp != NULL; amblp++) { - if ((obj = modifier(*amblp)) == OVOID) { - sprintf(errmsg, "unknown %s modifier \"%s\"", - ambincl ? "include" : "exclude", *amblp); - error(WARNING, errmsg); - continue; - } - if (!inset(ambset, obj)) - insertelem(ambset, obj); - } + maxarad = thescene.cusize / 2.0; /* maximum radius */ /* minimum radius */ minarad = ambres > 0 ? thescene.cusize/ambres : 0.0; @@ -98,7 +90,7 @@ char *afile; /* open ambient file */ if (afile != NULL) if ((ambfp = fopen(afile, "r+")) != NULL) { - while (fread(&amb, sizeof(AMBVAL), 1, ambfp) == 1) + while (fread((char *)&amb,sizeof(AMBVAL),1,ambfp) == 1) avinsert(&amb, &atrunk, thescene.cuorg, thescene.cusize); /* align */ @@ -111,6 +103,28 @@ char *afile; } +ambnotify(obj) /* record new modifier */ +OBJECT obj; +{ + static int hitlimit = 0; + register OBJREC *o = objptr(obj); + register char **amblp; + + if (hitlimit || !ismodifier(o->otype)) + return; + for (amblp = amblist; *amblp != NULL; amblp++) + if (!strcmp(o->oname, *amblp)) { + if (ambset[0] >= MAXASET) { + error(WARNING, "too many modifiers in ambient list"); + hitlimit++; + return; /* should this be fatal? */ + } + insertelem(ambset, obj); + return; + } +} + + ambient(acol, r) /* compute ambient component for ray */ COLOR acol; register RAY *r; @@ -166,28 +180,8 @@ double s; int i; register int j; register AMBVAL *av; - + /* do this node */ wsum = 0.0; - /* check children first */ - if (at->kid != NULL) { - s *= 0.5; - for (i = 0; i < 8; i++) { - for (j = 0; j < 3; j++) { - ck0[j] = c0[j]; - if (1<rop[j] < ck0[j] - OCTSCALE*s) - break; - if (r->rop[j] > ck0[j] + (1.0+OCTSCALE)*s) - break; - } - if (j == 3) - wsum += sumambient(acol, r, at->kid+i, ck0, s); - } - if (wsum*ambacc >= WDONE) - return(wsum); /* close enough */ - } - /* check this node */ for (av = at->alist; av != NULL; av = av->next) { /* * Ray strength test. @@ -219,13 +213,13 @@ double s; for (j = 0; j < 3; j++) d += (r->rop[j] - av->pos[j]) * (av->dir[j] + r->ron[j]); - if (d < -minarad) + if (d*0.5 < -minarad*ambacc) continue; /* * Jittering final test reduces image artifacts. */ wt = sqrt(e1) + sqrt(e2); - wt *= 0.9 + 0.2*frandom(); + wt *= .9 + .2*frandom(); if (wt > ambacc) continue; if (wt <= 1e-3) @@ -237,6 +231,23 @@ double s; scalecolor(ct, wt); addcolor(acol, ct); } + if (at->kid == NULL) + return(wsum); + /* do children */ + s *= 0.5; + for (i = 0; i < 8; i++) { + for (j = 0; j < 3; j++) { + ck0[j] = c0[j]; + if (1<rop[j] < ck0[j] - OCTSCALE*s) + break; + if (r->rop[j] > ck0[j] + (1.0+OCTSCALE)*s) + break; + } + if (j == 3) + wsum += sumambient(acol, r, at->kid+i, ck0, s); + } return(wsum); } @@ -271,6 +282,7 @@ register RAY *r; { extern int ambcmp(); extern double sin(), cos(), sqrt(); + int hlist[4]; double phi, xd, yd, zd; double b, b2; register AMBSAMP *div; @@ -295,7 +307,8 @@ register RAY *r; div = (AMBSAMP *)malloc(ndivs*sizeof(AMBSAMP)); if (div == NULL) error(SYSTEM, "out of memory in doambient"); - } + } else + div = NULL; /* make axes */ uy[0] = uy[1] = uy[2] = 0.0; for (k = 0; k < 3; k++) @@ -305,23 +318,31 @@ register RAY *r; fcross(ux, r->ron, uy); normalize(ux); fcross(uy, ux, r->ron); + /* set up urand */ + hlist[0] = r->rno; /* sample divisions */ arad = 0.0; ne = 0; - for (i = 0; i < nt; i++) + for (i = 0; i < nt; i++) { + hlist[1] = i; for (j = 0; j < np; j++) { rayorigin(&ar, r, AMBIENT, 0.5); /* pretested */ - zd = sqrt((i+frandom())/nt); - phi = 2.0*PI * (j+frandom())/np; + hlist[2] = j; + hlist[3] = 0; + zd = sqrt((i+urand(ilhash(hlist,4)))/nt); + hlist[3] = 1; + phi = 2.0*PI * (j+urand(ilhash(hlist,4)))/np; xd = cos(phi) * zd; yd = sin(phi) * zd; zd = sqrt(1.0 - zd*zd); for (k = 0; k < 3; k++) ar.rdir[k] = xd*ux[k]+yd*uy[k]+zd*r->ron[k]; + dimlist[ndims++] = i*np + j + 38813; rayvalue(&ar); + ndims--; if (ar.rot < FHUGE) arad += 1.0 / ar.rot; - if (ns > 0) { /* save division */ + if (div != NULL) { /* save division */ div[ne].k = 0.0; copycolor(div[ne].v, ar.rcol); div[ne].n = 0; @@ -356,6 +377,7 @@ register RAY *r; } else addcolor(acol, ar.rcol); } + } for (k = 0; k < ne; k++) { /* compute errors */ if (div[k].n > 1) div[k].k /= div[k].n; @@ -371,14 +393,21 @@ register RAY *r; /* super-sample */ for (i = ns; i > 0; i--) { rayorigin(&ar, r, AMBIENT, 0.5); /* pretested */ - zd = sqrt((div[0].t+frandom())/nt); - phi = 2.0*PI * (div[0].p+frandom())/np; + hlist[1] = div[0].t; + hlist[2] = div[0].p; + hlist[3] = 0; + zd = sqrt((div[0].t+urand(ilhash(hlist,4)+div[0].n))/nt); + hlist[3] = 1; + phi = 2.0*PI * (div[0].p+urand(ilhash(hlist,4)+div[0].n))/np; xd = cos(phi) * zd; yd = sin(phi) * zd; zd = sqrt(1.0 - zd*zd); for (k = 0; k < 3; k++) ar.rdir[k] = xd*ux[k]+yd*uy[k]+zd*r->ron[k]; + dimlist[ndims++] = div[0].t*np + div[0].p + 38813; rayvalue(&ar); + ndims--; + rayvalue(&ar); if (ar.rot < FHUGE) arad += 1.0 / ar.rot; /* recompute error */ @@ -391,13 +420,16 @@ register RAY *r; dnew.k = b2/(dnew.n*dnew.n); /* reinsert */ for (k = 0; k < ne-1 && dnew.k < div[k+1].k; k++) - bcopy(&div[k+1], &div[k], sizeof(AMBSAMP)); - bcopy(&dnew, &div[k], sizeof(AMBSAMP)); + copystruct(&div[k], &div[k+1]); + copystruct(&div[k], &dnew); if (ne >= i) { /* extract darkest division */ ne--; - if (div[ne].n > 1) - scalecolor(div[ne].v, 1.0/div[ne].n); + if (div[ne].n > 1) { + b = 1.0/div[ne].n; + scalecolor(div[ne].v, b); + div[ne].n = 1; + } addcolor(acol, div[ne].v); } } @@ -410,7 +442,7 @@ register RAY *r; arad = maxarad; else if (arad < minarad) arad = minarad; - if (ns > 0) + if (div != NULL) free((char *)div); return(arad); } @@ -437,7 +469,7 @@ AMBVAL *av; #endif if (ambfp == NULL) return; - if (fwrite(av, sizeof(AMBVAL), 1, ambfp) != 1) + if (fwrite((char *)av, sizeof(AMBVAL), 1, ambfp) != 1) goto writerr; #ifdef AMBFLUSH if (++nunflshed >= AMBFLUSH) { @@ -466,7 +498,7 @@ double s; if ((av = newambval()) == NULL) goto memerr; - bcopy(aval, av, sizeof(AMBVAL)); + copystruct(av, aval); VCOPY(ck0, c0); while (s*(OCTSCALE/2) > av->rad*ambacc) { if (at->kid == NULL)