--- ray/src/rt/virtuals.c 1991/10/01 14:29:16 1.27 +++ ray/src/rt/virtuals.c 2003/04/23 00:52:34 2.9 @@ -1,18 +1,17 @@ -/* Copyright (c) 1991 Regents of the University of California */ - #ifndef lint -static char SCCSid[] = "$SunId$ LBL"; +static const char RCSid[] = "$Id: virtuals.c,v 2.9 2003/04/23 00:52:34 greg Exp $"; #endif - /* * Routines for simulating virtual light sources * Thus far, we only support planar mirrors. + * + * External symbols declared in source.h */ +#include "copyright.h" + #include "ray.h" -#include "octree.h" - #include "otypes.h" #include "source.h" @@ -23,12 +22,11 @@ static char SCCSid[] = "$SunId$ LBL"; #define STESTMAX 32 /* maximum seeks per sample */ -double getdisk(); - static OBJECT *vobject; /* virtual source objects */ static int nvobjects = 0; /* number of virtual source objects */ +void markvirtuals() /* find and mark virtual sources */ { register OBJREC *o; @@ -41,7 +39,7 @@ markvirtuals() /* find and mark virtual sources */ o = objptr(i); if (!issurface(o->otype) || o->omod == OVOID) continue; - if (!isvlight(objptr(o->omod)->otype)) + if (!isvlight(vsmaterial(o)->otype)) continue; if (sfun[o->otype].of == NULL || sfun[o->otype].of->getpleq == NULL) { @@ -51,7 +49,7 @@ markvirtuals() /* find and mark virtual sources */ if (nvobjects == 0) vobject = (OBJECT *)malloc(sizeof(OBJECT)); else - vobject = (OBJECT *)realloc((char *)vobject, + vobject = (OBJECT *)realloc((void *)vobject, (unsigned)(nvobjects+1)*sizeof(OBJECT)); if (vobject == NULL) error(SYSTEM, "out of memory in addvirtuals"); @@ -66,11 +64,12 @@ markvirtuals() /* find and mark virtual sources */ for (i = nsources; i-- > 0; ) addvirtuals(i, directrelay); /* done with our object list */ - free((char *)vobject); + free((void *)vobject); nvobjects = 0; } +void addvirtuals(sn, nr) /* add virtuals associated with source */ int sn; int nr; @@ -88,6 +87,7 @@ int nr; } +void vproject(o, sn, n) /* create projected source(s) if they exist */ OBJREC *o; int sn; @@ -101,7 +101,7 @@ int n; if (o == source[sn].so) /* objects cannot project themselves */ return; /* get virtual source material */ - vsmat = sfun[objptr(o->omod)->otype].mf; + vsmat = sfun[vsmaterial(o)->otype].mf; /* project virtual sources */ for (i = 0; i < vsmat->nproj; i++) if ((*vsmat->vproj)(proj, o, &source[sn], i)) @@ -115,6 +115,23 @@ int n; } +OBJREC * +vsmaterial(o) /* get virtual source material pointer */ +OBJREC *o; +{ + register int i; + register OBJREC *m; + + i = o->omod; + m = objptr(i); + if (m->otype != MAT_ILLUM || m->oargs.nsargs < 1 || + !strcmp(m->oargs.sarg[0], VOIDID) || + (i = lastmod(objndx(m), m->oargs.sarg[0])) == OVOID) + return(m); /* direct modifier */ + return(objptr(i)); /* illum alternate */ +} + + int makevsrc(op, sn, pm) /* make virtual source if reasonable */ OBJREC *op; @@ -140,11 +157,12 @@ MAT4 pm; normalize(nsloc); VCOPY(ourspot.aim, ocent); ourspot.siz = PI*maxrad2; - ourspot.flen = 0.; + ourspot.flen = -1.; if (source[sn].sflags & SSPOT) { multp3(theirspot.aim, source[sn].sl.s->aim, pm); + /* adjust for source size */ d = sqrt(dist2(ourspot.aim, theirspot.aim)); - d = sqrt(source[sn].sl.s->siz/PI) + d*source[sn].ss; + d = sqrt(source[sn].sl.s->siz/PI) + d*source[sn].srad; theirspot.siz = PI*d*d; ourspot.flen = theirspot.flen = source[sn].sl.s->flen; d = ourspot.siz; @@ -169,7 +187,8 @@ MAT4 pm; if (source[sn].sflags & SPROX && d > source[sn].sl.prox) return(-1); /* too far away */ ourspot.flen = 0.; - d = (sqrt(maxrad2) + source[sn].ss) / d; + /* adjust for source size */ + d = (sqrt(maxrad2) + source[sn].srad) / d; if (d < 1.-FTINY) ourspot.siz = 2.*PI*(1. - sqrt(1.-d*d)); else @@ -214,9 +233,14 @@ MAT4 pm; goto memerr; source[i].sflags = nsflags; VCOPY(source[i].sloc, nsloc); + multv3(source[i].ss[SU], source[sn].ss[SU], pm); + multv3(source[i].ss[SV], source[sn].ss[SV], pm); if (nsflags & SFLAT) VCOPY(source[i].snorm, nsnorm); - source[i].ss = source[sn].ss; source[i].ss2 = source[sn].ss2; + else + multv3(source[i].ss[SW], source[sn].ss[SW], pm); + source[i].srad = source[sn].srad; + source[i].ss2 = source[sn].ss2; if (nsflags & SSPOT) { if ((source[i].sl.s = (SPOT *)malloc(sizeof(SPOT))) == NULL) goto memerr; @@ -275,8 +299,8 @@ register int sn; /* target source number */ RAY sr; FVECT onorm; FVECT offsdir; + SRCINDEX si; double or, d; - int infront; int stestlim, ssn; int nhit, nok; register int i, n; @@ -289,7 +313,6 @@ register int sn; /* target source number */ if (source[sn].sflags & SDISTANT) { /* 32. == heuristic constant */ n = 32.*or2/(thescene.cusize*thescene.cusize)*vspretest + .5; - infront = DOT(onorm, source[sn].sloc) > 0.; } else { for (i = 0; i < 3; i++) offsdir[i] = source[sn].sloc[i] - oc[i]; @@ -298,7 +321,6 @@ register int sn; /* target source number */ n = 2.*PI * vspretest + .5; else n = 2.*PI * (1.-sqrt(1./(1.+or2/d)))*vspretest + .5; - infront = DOT(onorm, offsdir) > 0.; } if (n < MINSAMPLES) n = MINSAMPLES; #ifdef DEBUG @@ -310,6 +332,7 @@ register int sn; /* target source number */ stestlim = n*STESTMAX; ssn = 0; nhit = nok = 0; + initsrcindex(&si); while (n-- > 0) { /* get sample point */ do { @@ -323,31 +346,29 @@ register int sn; /* target source number */ for (i = 0; i < 3; i++) offsdir[i] = or*(1. - 2.*offsdir[i]); ssn++; - for (i = 0; i < 3; i++) - sr.rorg[i] = oc[i] + offsdir[i]; - d = DOT(offsdir,onorm); - if (infront) - for (i = 0; i < 3; i++) { - sr.rorg[i] -= (d-.0001)*onorm[i]; - sr.rdir[i] = -onorm[i]; - } - else - for (i = 0; i < 3; i++) { - sr.rorg[i] -= (d+.0001)*onorm[i]; - sr.rdir[i] = onorm[i]; - } + d = 1. - DOT(offsdir, onorm); + for (i = 0; i < 3; i++) { + sr.rorg[i] = oc[i] + offsdir[i] + d*onorm[i]; + sr.rdir[i] = -onorm[i]; + } + sr.rmax = 0.0; rayorigin(&sr, NULL, PRIMARY, 1.0); } while (!(*ofun[o->otype].funp)(o, &sr)); /* check against source */ + VCOPY(sr.rorg, sr.rop); /* starting from intersection */ samplendx++; - if (srcray(&sr, NULL, sn) == 0.) - continue; + if (si.sp >= si.np-1 || + !srcray(&sr, NULL, &si) || sr.rsrc != sn) { + si.sn = sn-1; /* reset index to our source */ + si.np = 0; + if (!srcray(&sr, NULL, &si) || sr.rsrc != sn) + continue; /* can't get there from here */ + } sr.revf = srcvalue; - rayvalue(&sr); + rayvalue(&sr); /* check sample validity */ if (bright(sr.rcol) <= FTINY) continue; - nok++; - /* check against obstructions */ + nok++; /* got sample; check obstructions */ rayclear(&sr); sr.revf = raytrace; rayvalue(&sr); @@ -374,6 +395,7 @@ register int sn; /* target source number */ #ifdef DEBUG +void virtverb(sn, fp) /* print verbose description of virtual source */ register int sn; FILE *fp;