--- ray/src/rt/dielectric.c 2004/03/30 16:13:01 2.18 +++ ray/src/rt/dielectric.c 2013/08/07 05:10:09 2.23 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: dielectric.c,v 2.18 2004/03/30 16:13:01 schorsch Exp $"; +static const char RCSid[] = "$Id: dielectric.c,v 2.23 2013/08/07 05:10:09 greg Exp $"; #endif /* * dielectric.c - shading function for transparent materials. @@ -74,6 +74,9 @@ m_dielectric( /* color a ray which hit a dielectric in COLOR ctrans; COLOR talb; int hastexture; + double transdist=0, transtest=0; + double mirdist=0, mirtest=0; + int flatsurface; double refl, trans; FVECT dnorm; double d1, d2; @@ -91,6 +94,8 @@ m_dielectric( /* color a ray which hit a dielectric in VCOPY(dnorm, r->ron); cos1 = r->rod; } + flatsurface = !hastexture && r->ro != NULL && isflat(r->ro->otype); + /* index of refraction */ if (m->otype == MAT_DIELECTRIC) nratio = m->oargs.farg[3] + m->oargs.farg[4]/MLAMBDA; @@ -159,8 +164,10 @@ m_dielectric( /* color a ray which hit a dielectric in trans *= nratio*nratio; /* solid angle ratio */ - if (rayorigin(&p, r, REFRACTED, trans) == 0) { + setcolor(p.rcoef, trans, trans, trans); + if (rayorigin(&p, REFRACTED, r, p.rcoef) == 0) { + /* compute refracted ray */ d1 = nratio*cos1 - cos2; for (i = 0; i < 3; i++) @@ -173,7 +180,8 @@ m_dielectric( /* color a ray which hit a dielectric in p.rdir[i] = nratio*r->rdir[i] + d1*r->ron[i]; normalize(p.rdir); /* not exact */ - } + } else + checknorm(p.rdir); #ifdef DISPERSE if (m->otype != MAT_DIELECTRIC || r->rod > 0.0 @@ -187,30 +195,45 @@ m_dielectric( /* color a ray which hit a dielectric in copycolor(p.cext, ctrans); copycolor(p.albedo, talb); rayvalue(&p); - scalecolor(p.rcol, trans); + multcolor(p.rcol, p.rcoef); addcolor(r->rcol, p.rcol); - if (nratio >= 1.0-FTINY && nratio <= 1.0+FTINY) - r->rt = r->rot + p.rt; + /* virtual distance */ + if (flatsurface || + (1.-FTINY <= nratio && + nratio <= 1.+FTINY)) { + transtest = 2*bright(p.rcol); + transdist = r->rot + p.rt; + } } } } - + setcolor(p.rcoef, refl, refl, refl); + if (!(r->crtype & SHADOW) && - rayorigin(&p, r, REFLECTED, refl) == 0) { + rayorigin(&p, REFLECTED, r, p.rcoef) == 0) { /* compute reflected ray */ - for (i = 0; i < 3; i++) - p.rdir[i] = r->rdir[i] + 2.0*cos1*dnorm[i]; + VSUM(p.rdir, r->rdir, dnorm, 2.*cos1); /* accidental penetration? */ if (hastexture && DOT(p.rdir,r->ron)*hastexture <= FTINY) - for (i = 0; i < 3; i++) /* ignore texture */ - p.rdir[i] = r->rdir[i] + 2.0*r->rod*r->ron[i]; - + VSUM(p.rdir, r->rdir, r->ron, 2.*r->rod); + checknorm(p.rdir); rayvalue(&p); /* reflected ray value */ - scalecolor(p.rcol, refl); /* color contribution */ + multcolor(p.rcol, p.rcoef); /* color contribution */ addcolor(r->rcol, p.rcol); + /* virtual distance */ + if (flatsurface) { + mirtest = 2*bright(p.rcol); + mirdist = r->rot + p.rt; + } } + /* check distance to return */ + d1 = bright(r->rcol); + if (transtest > d1) + r->rt = transdist; + else if (mirtest > d1) + r->rt = mirdist; /* rayvalue() computes absorption */ return(1); } @@ -228,7 +251,8 @@ disperse( /* check light sources for dispersion */ COLOR abt ) { - RAY sray, *entray; + RAY sray; + const RAY *entray; FVECT v1, v2, n1, n2; FVECT dv, v2Xdv; double v2Xdvv2Xdv; @@ -283,10 +307,10 @@ disperse( /* check light sources for dispersion */ VCOPY(n2, r->ron); /* first order dispersion approx. */ - dtmp1 = DOT(n1, v1); - dtmp2 = DOT(n2, v2); + dtmp1 = 1./DOT(n1, v1); + dtmp2 = 1./DOT(n2, v2); for (i = 0; i < 3; i++) - dv[i] = v1[i] + v2[i] - n1[i]/dtmp1 - n2[i]/dtmp2; + dv[i] = v1[i] + v2[i] - n1[i]*dtmp1 - n2[i]*dtmp2; if (DOT(dv, dv) <= FTINY) /* null effect */ return(0); @@ -329,15 +353,13 @@ disperse( /* check light sources for dispersion */ dtmp1 = sqrt(si.dom / v2Xdvv2Xdv / PI); /* compute first ray */ - for (i = 0; i < 3; i++) - vtmp2[i] = sray.rdir[i] + dtmp1*vtmp1[i]; + VSUM(vtmp2, sray.rdir, vtmp1, dtmp1); l1 = lambda(m, v2, dv, vtmp2); /* first lambda */ if (l1 < 0) continue; /* compute second ray */ - for (i = 0; i < 3; i++) - vtmp2[i] = sray.rdir[i] - dtmp1*vtmp1[i]; + VSUM(vtmp2, sray.rdir, vtmp1, -dtmp1); l2 = lambda(m, v2, dv, vtmp2); /* second lambda */ if (l2 < 0) @@ -370,7 +392,7 @@ lambda( /* compute lambda for material */ fcross(lrXdv, lr, dv); for (i = 0; i < 3; i++) - if (lrXdv[i] > FTINY || lrXdv[i] < -FTINY) + if ((lrXdv[i] > FTINY) | (lrXdv[i] < -FTINY)) break; if (i >= 3) return(-1);