--- ray/src/rt/normal.c 1995/09/26 15:05:32 2.30 +++ ray/src/rt/normal.c 1998/12/16 18:14:58 2.37 @@ -1,7 +1,7 @@ -/* Copyright (c) 1995 Regents of the University of California */ +/* Copyright (c) 1998 Silicon Graphics, Inc. */ #ifndef lint -static char SCCSid[] = "$SunId$ LBL"; +static char SCCSid[] = "$SunId$ SGI"; #endif /* @@ -25,6 +25,10 @@ extern double specjitter; /* specular sampling jitte extern int backvis; /* back faces visible? */ +#ifndef MAXITER +#define MAXITER 10 /* maximum # specular ray attempts */ +#endif + static gaussamp(); /* @@ -228,7 +232,7 @@ register RAY *r; } else nd.tdiff = nd.tspec = nd.trans = 0.0; /* transmitted ray */ - if ((nd.specfl&(SP_TRAN|SP_PURE)) == (SP_TRAN|SP_PURE)) { + if ((nd.specfl&(SP_TRAN|SP_PURE|SP_TBLT)) == (SP_TRAN|SP_PURE)) { RAY lr; if (rayorigin(&lr, r, TRANS, nd.tspec) == 0) { VCOPY(lr.rdir, nd.prdir); @@ -265,18 +269,18 @@ register RAY *r; if (hastexture && DOT(nd.vrefl, r->ron) <= FTINY) for (i = 0; i < 3; i++) /* safety measure */ nd.vrefl[i] = r->rdir[i] + 2.*r->rod*r->ron[i]; - - if (!(r->crtype & SHADOW) && nd.specfl & SP_PURE) { - RAY lr; - if (rayorigin(&lr, r, REFLECTED, nd.rspec) == 0) { - VCOPY(lr.rdir, nd.vrefl); - rayvalue(&lr); - multcolor(lr.rcol, nd.scolor); - addcolor(r->rcol, lr.rcol); - if (!hastexture && nd.specfl & SP_FLAT) { - mirtest = 2.*bright(lr.rcol); - mirdist = r->rot + lr.rt; - } + } + /* reflected ray */ + if ((nd.specfl&(SP_REFL|SP_PURE|SP_RBLT)) == (SP_REFL|SP_PURE)) { + RAY lr; + if (rayorigin(&lr, r, REFLECTED, nd.rspec) == 0) { + VCOPY(lr.rdir, nd.vrefl); + rayvalue(&lr); + multcolor(lr.rcol, nd.scolor); + addcolor(r->rcol, lr.rcol); + if (!hastexture && nd.specfl & SP_FLAT) { + mirtest = 2.*bright(lr.rcol); + mirdist = r->rot + lr.rt; } } } @@ -286,11 +290,11 @@ register RAY *r; if (nd.specfl & SP_PURE && nd.rdiff <= FTINY && nd.tdiff <= FTINY) return(1); /* 100% pure specular */ - if (nd.specfl & (SP_REFL|SP_TRAN) && !(nd.specfl & SP_PURE)) - gaussamp(r, &nd); + if (!(nd.specfl & SP_PURE)) + gaussamp(r, &nd); /* checks *BLT flags */ if (nd.rdiff > FTINY) { /* ambient from this side */ - ambient(ctmp, r); + ambient(ctmp, r, hastexture?nd.pnorm:r->ron); if (nd.specfl & SP_RBLT) scalecolor(ctmp, 1.0-nd.trans); else @@ -300,7 +304,14 @@ register RAY *r; } if (nd.tdiff > FTINY) { /* ambient from other side */ flipsurface(r); - ambient(ctmp, r); + if (hastexture) { + FVECT bnorm; + bnorm[0] = -nd.pnorm[0]; + bnorm[1] = -nd.pnorm[1]; + bnorm[2] = -nd.pnorm[2]; + ambient(ctmp, r, bnorm); + } else + ambient(ctmp, r, r->ron); if (nd.specfl & SP_TBLT) scalecolor(ctmp, nd.trans); else @@ -331,6 +342,7 @@ register NORMDAT *np; FVECT u, v, h; double rv[2]; double d, sinp, cosp; + int niter; register int i; /* quick test */ if ((np->specfl & (SP_REFL|SP_RBLT)) != SP_REFL && @@ -349,52 +361,63 @@ register NORMDAT *np; if ((np->specfl & (SP_REFL|SP_RBLT)) == SP_REFL && rayorigin(&sr, r, SPECULAR, np->rspec) == 0) { dimlist[ndims++] = (int)np->mp; - d = urand(ilhash(dimlist,ndims)+samplendx); - multisamp(rv, 2, d); - d = 2.0*PI * rv[0]; - cosp = cos(d); - sinp = sin(d); - rv[1] = 1.0 - specjitter*rv[1]; - if (rv[1] <= FTINY) - d = 1.0; - else - d = sqrt( np->alpha2 * -log(rv[1]) ); - for (i = 0; i < 3; i++) - h[i] = np->pnorm[i] + d*(cosp*u[i] + sinp*v[i]); - d = -2.0 * DOT(h, r->rdir) / (1.0 + d*d); - for (i = 0; i < 3; i++) - sr.rdir[i] = r->rdir[i] + d*h[i]; - if (DOT(sr.rdir, r->ron) <= FTINY) - VCOPY(sr.rdir, np->vrefl); /* jitter no good */ - rayvalue(&sr); - multcolor(sr.rcol, np->scolor); - addcolor(r->rcol, sr.rcol); + for (niter = 0; niter < MAXITER; niter++) { + if (niter) + d = frandom(); + else + d = urand(ilhash(dimlist,ndims)+samplendx); + multisamp(rv, 2, d); + d = 2.0*PI * rv[0]; + cosp = tcos(d); + sinp = tsin(d); + rv[1] = 1.0 - specjitter*rv[1]; + if (rv[1] <= FTINY) + d = 1.0; + else + d = sqrt( np->alpha2 * -log(rv[1]) ); + for (i = 0; i < 3; i++) + h[i] = np->pnorm[i] + d*(cosp*u[i] + sinp*v[i]); + d = -2.0 * DOT(h, r->rdir) / (1.0 + d*d); + for (i = 0; i < 3; i++) + sr.rdir[i] = r->rdir[i] + d*h[i]; + if (DOT(sr.rdir, r->ron) > FTINY) { + rayvalue(&sr); + multcolor(sr.rcol, np->scolor); + addcolor(r->rcol, sr.rcol); + break; + } + } ndims--; } /* compute transmission */ if ((np->specfl & (SP_TRAN|SP_TBLT)) == SP_TRAN && rayorigin(&sr, r, SPECULAR, np->tspec) == 0) { dimlist[ndims++] = (int)np->mp; - d = urand(ilhash(dimlist,ndims)+1823+samplendx); - multisamp(rv, 2, d); - d = 2.0*PI * rv[0]; - cosp = cos(d); - sinp = sin(d); - rv[1] = 1.0 - specjitter*rv[1]; - if (rv[1] <= FTINY) - d = 1.0; - else - d = sqrt( -log(rv[1]) * np->alpha2 ); - for (i = 0; i < 3; i++) - sr.rdir[i] = np->prdir[i] + d*(cosp*u[i] + sinp*v[i]); - if (DOT(sr.rdir, r->ron) < -FTINY) - normalize(sr.rdir); /* OK, normalize */ - else - VCOPY(sr.rdir, np->prdir); /* else no jitter */ - rayvalue(&sr); - scalecolor(sr.rcol, np->tspec); - multcolor(sr.rcol, np->mcolor); /* modified by color */ - addcolor(r->rcol, sr.rcol); + for (niter = 0; niter < MAXITER; niter++) { + if (niter) + d = frandom(); + else + d = urand(ilhash(dimlist,ndims)+1823+samplendx); + multisamp(rv, 2, d); + d = 2.0*PI * rv[0]; + cosp = tcos(d); + sinp = tsin(d); + rv[1] = 1.0 - specjitter*rv[1]; + if (rv[1] <= FTINY) + d = 1.0; + else + d = sqrt( np->alpha2 * -log(rv[1]) ); + for (i = 0; i < 3; i++) + sr.rdir[i] = np->prdir[i] + d*(cosp*u[i] + sinp*v[i]); + if (DOT(sr.rdir, r->ron) < -FTINY) { + normalize(sr.rdir); /* OK, normalize */ + rayvalue(&sr); + scalecolor(sr.rcol, np->tspec); + multcolor(sr.rcol, np->mcolor); /* modified */ + addcolor(r->rcol, sr.rcol); + break; + } + } ndims--; } }