--- ray/src/rt/raytrace.c 2005/03/10 22:37:00 2.46 +++ ray/src/rt/raytrace.c 2005/06/21 15:06:50 2.52 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: raytrace.c,v 2.46 2005/03/10 22:37:00 greg Exp $"; +static const char RCSid[] = "$Id: raytrace.c,v 2.52 2005/06/21 15:06:50 greg Exp $"; #endif /* * raytrace.c - routines for tracing and shading rays. @@ -13,6 +13,7 @@ static const char RCSid[] = "$Id: raytrace.c,v 2.46 20 #include "source.h" #include "otypes.h" #include "otspecial.h" +#include "random.h" #define MAXCSET ((MAXSET+1)*2-1) /* maximum check set size */ @@ -36,14 +37,22 @@ static void checkset(OBJECT *os, OBJECT *cs); extern int rayorigin( /* start new ray from old one */ - register RAY *r, - register RAY *ro, + RAY *r, int rt, - double rw + const RAY *ro, + const COLOR rc ) { - double re; - + double rw, re; + /* assign coefficient/weight */ + if (rc == NULL) { + rw = 1.0; + setcolor(r->rcoef, 1., 1., 1.); + } else { + rw = intens(rc); + if (rc != r->rcoef) + copycolor(r->rcoef, rc); + } if ((r->parent = ro) == NULL) { /* primary ray */ r->rlvl = 0; r->rweight = rw; @@ -55,10 +64,11 @@ rayorigin( /* start new ray from old one */ copycolor(r->albedo, salbedo); r->gecc = seccg; r->slights = NULL; - } else if (ro->rot >= FHUGE) { /* illegal continuation */ - memset(r, 0, sizeof(RAY)); - return(-1); } else { /* spawned ray */ + if (ro->rot >= FHUGE) { + memset(r, 0, sizeof(RAY)); + return(-1); /* illegal continuation */ + } r->rlvl = ro->rlvl; if (rt & RAYREFL) { r->rlvl++; @@ -78,14 +88,31 @@ rayorigin( /* start new ray from old one */ r->crtype = ro->crtype | (r->rtype = rt); VCOPY(r->rorg, ro->rop); r->rweight = ro->rweight * rw; - /* estimate absorption */ + /* estimate extinction */ re = colval(ro->cext,RED) < colval(ro->cext,GRN) ? colval(ro->cext,RED) : colval(ro->cext,GRN); if (colval(ro->cext,BLU) < re) re = colval(ro->cext,BLU); - if (re > 0.) - r->rweight *= exp(-re*ro->rot); + re *= ro->rot; + if (re > .1) + r->rweight *= exp(-re); } rayclear(r); + if (r->crtype & SHADOW) /* shadow commitment */ + return(0); + if (maxdepth <= 0 && rc != NULL) { /* Russian roulette */ + if (minweight <= 0.0) + error(USER, "zero ray weight in Russian roulette"); + if (maxdepth < 0 && r->rlvl > -maxdepth) + return(-1); /* upper reflection limit */ + if (r->rweight >= minweight) + return(0); + if (frandom() < r->rweight/minweight) + return(-1); + rw = minweight/r->rweight; /* promote survivor */ + scalecolor(r->rcoef, rw); + r->rweight = minweight; + return(0); + } return(r->rlvl <= maxdepth && r->rweight >= minweight ? 0 : -1); } @@ -122,10 +149,10 @@ raytrace( /* trace a ray and compute its value */ } else if (sourcehit(r)) rayshade(r, r->ro->omod); /* distant source */ - rayparticipate(r); /* for participating medium */ - if (trace != NULL) (*trace)(r); /* trace execution */ + + rayparticipate(r); /* for participating medium */ } @@ -147,7 +174,7 @@ raytrans( /* transmit ray as is */ { RAY tr; - if (rayorigin(&tr, r, TRANS, 1.0) == 0) { + if (rayorigin(&tr, TRANS, r, NULL) == 0) { VCOPY(tr.rdir, r->rdir); rayvalue(&tr); copycolor(r->rcol, tr.rcol); @@ -162,10 +189,10 @@ rayshade( /* shade ray r with material mod */ int mod ) { - int gotmat; register OBJREC *m; + r->rt = r->rot; /* set effective ray length */ - for (gotmat = 0; !gotmat && mod != OVOID; mod = m->omod) { + for ( ; mod != OVOID; mod = m->omod) { m = objptr(mod); /****** unnecessary test since modifier() is always called if (!ismodifier(m->otype)) { @@ -184,10 +211,10 @@ rayshade( /* shade ray r with material mod */ if (!islight(m->otype)) m = &Lamb; } - /* materials call raytexture */ - gotmat = (*ofun[m->otype].funp)(m, r); + if ((*ofun[m->otype].funp)(m, r)) + return(1); /* materials call raytexture() */ } - return(gotmat); + return(0); /* no material! */ } @@ -209,10 +236,10 @@ rayparticipate( /* compute ray medium participation ge *= 1. - colval(r->albedo,GRN); be *= 1. - colval(r->albedo,BLU); } - setcolor(ce, re<=0. ? 1. : re>92. ? 0. : exp(-re), - ge<=0. ? 1. : ge>92. ? 0. : exp(-ge), - be<=0. ? 1. : be>92. ? 0. : exp(-be)); - multcolor(r->rcol, ce); /* path absorption */ + setcolor(ce, re<=FTINY ? 1. : re>92. ? 0. : exp(-re), + ge<=FTINY ? 1. : ge>92. ? 0. : exp(-ge), + be<=FTINY ? 1. : be>92. ? 0. : exp(-be)); + multcolor(r->rcol, ce); /* path extinction */ if (r->crtype & SHADOW || intens(r->albedo) <= FTINY) return; /* no scattering */ setcolor(ca, @@ -305,7 +332,7 @@ raymixture( /* mix modifiers */ extern double raydist( /* compute (cumulative) ray distance */ - register RAY *r, + register const RAY *r, register int flags ) { @@ -319,6 +346,32 @@ raydist( /* compute (cumulative) ray distance */ } +extern void +raycontrib( /* compute (cumulative) ray contribution */ + double rc[3], + const RAY *r, + int flags +) +{ + double eext[3]; + int i; + + eext[0] = eext[1] = eext[2] = 0.; + rc[0] = rc[1] = rc[2] = 1.; + + while (r != NULL && r->crtype&flags) { + for (i = 3; i--; ) { + rc[i] *= colval(r->rcoef,i); + eext[i] += r->rot * colval(r->cext,i); + } + r = r->parent; + } + for (i = 3; i--; ) + rc[i] *= (eext[i] <= FTINY) ? 1. : + (eext[i] > 300.) ? 0. : exp(-eext[i]); +} + + extern double raynormal( /* compute perturbed normal for ray */ FVECT norm, @@ -365,7 +418,7 @@ newrayxf( /* get new tranformation matrix for ray */ FULLXF xf; } xfseed = { &xfseed }, *xflast = &xfseed; register struct xfn *xp; - register RAY *rp; + register const RAY *rp; /* * Search for transform in circular list that