--- ray/src/rt/source.c 2020/12/17 03:30:37 2.74 +++ ray/src/rt/source.c 2022/06/08 17:18:41 2.79 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: source.c,v 2.74 2020/12/17 03:30:37 greg Exp $"; +static const char RCSid[] = "$Id: source.c,v 2.79 2022/06/08 17:18:41 greg Exp $"; #endif /* * source.c - routines dealing with illumination sources. @@ -36,8 +36,8 @@ typedef struct { float brt; /* brightness (for comparison) */ } CNTPTR; /* contribution pointer */ -static CONTRIB *srccnt; /* source contributions in direct() */ -static CNTPTR *cntord; /* source ordering in direct() */ +static CONTRIB *srccnt = NULL; /* source contributions in direct() */ +static CNTPTR *cntord = NULL; /* source ordering in direct() */ static int maxcntr = 0; /* size of contribution arrays */ static int cntcmp(const void *p1, const void *p2); @@ -46,10 +46,13 @@ static int cntcmp(const void *p1, const void *p2); void marksources(void) /* find and mark source objects */ { - int foundsource = 0; + int indirect = 0; int i; OBJREC *o, *m; int ns; + /* call us only once! */ + if (nsources) + error(CONSISTENCY, "Multiple calls to marksources!"); /* initialize dispatch table */ initstypes(); /* find direct sources */ @@ -60,7 +63,7 @@ marksources(void) /* find and mark source objects */ if (!issurface(o->otype) || o->omod == OVOID) continue; /* find material */ - m = findmaterial(objptr(o->omod)); + m = findmaterial(o); if (m == NULL) continue; if (m->otype == MAT_CLIP) { @@ -80,7 +83,7 @@ marksources(void) /* find and mark source objects */ if (m->otype == MAT_GLOW && o->otype != OBJ_SOURCE && m->oargs.farg[3] <= FTINY) { - foundsource += (ambounce > 0); + indirect += (ambounce > 0); continue; /* don't track these */ } if (sfun[o->otype].of == NULL || @@ -97,7 +100,7 @@ marksources(void) /* find and mark source objects */ source[ns].sl.prox = m->oargs.farg[3]; if (source[ns].sflags & SDISTANT) { source[ns].sflags |= SSKIP; - foundsource += (ambounce > 0); + indirect += (ambounce > 0); } } else if (m->otype == MAT_SPOT) { if (source[ns].sflags & SDISTANT) @@ -113,11 +116,12 @@ marksources(void) /* find and mark source objects */ source[ns].sflags |= SSKIP; } } - foundsource += !(source[ns].sflags & SSKIP); + maxcntr += !(source[ns].sflags & SSKIP); } - if (!foundsource) { - error(WARNING, "no light sources found"); - return; + if (!maxcntr) { + if (!indirect) + error(WARNING, "no light sources found"); + return; /* no direct calculation, it seems */ } #if SHADCACHE for (ns = 0; ns < nsources; ns++) /* initialize obstructor cache */ @@ -128,7 +132,7 @@ marksources(void) /* find and mark source objects */ markvirtuals(); /* find and add virtual sources */ /* allocate our contribution arrays */ - maxcntr = nsources + MAXSPART; /* start with this many */ + maxcntr += MAXSPART; /* start with this many */ srccnt = (CONTRIB *)malloc(maxcntr*sizeof(CONTRIB)); cntord = (CNTPTR *)malloc(maxcntr*sizeof(CNTPTR)); if ((srccnt != NULL) & (cntord != NULL)) @@ -144,6 +148,9 @@ distantsources(void) /* only mark distant sources */ int i; OBJREC *o, *m; int ns; + /* call us only once! */ + if (nsources) + error(CONSISTENCY, "Multiple calls to distantsources!"); /* initialize dispatch table */ initstypes(); /* sources needed for sourcehit() */ @@ -154,7 +161,7 @@ distantsources(void) /* only mark distant sources */ if ((o->otype != OBJ_SOURCE) | (o->omod == OVOID)) continue; /* find material */ - m = findmaterial(objptr(o->omod)); + m = findmaterial(o); if (m == NULL) continue; if (!islight(m->otype)) @@ -294,11 +301,10 @@ nomat: static int transillum( /* check if material is transparent illum */ - OBJECT obj + OBJREC *m ) { - OBJREC *m = findmaterial(objptr(obj)); - + m = findmaterial(m); if (m == NULL) return(1); if (m->otype != MAT_ILLUM) @@ -331,8 +337,8 @@ sourcehit( /* check to see if ray hit distant source */ if (2.*PI*(1. - DOT(source[i].sloc,r->rdir)) > source[i].ss2) continue; - /* is it the only possibility? */ - if (first == last) { + /* is it what we aimed for? */ + if (i == r->rsrc) { r->ro = source[i].so; break; } @@ -344,7 +350,7 @@ sourcehit( /* check to see if ray hit distant source glowsrc = i; continue; } - if (transillum(source[i].so->omod)) { + if (transillum(source[i].so)) { if (transrc < 0) transrc = i; continue; @@ -364,15 +370,9 @@ sourcehit( /* check to see if ray hit distant source return(0); /* nothing usable */ } /* - * Make assignments. + * Assign object index */ r->robj = objndx(r->ro); - for (i = 0; i < 3; i++) - r->ron[i] = -r->rdir[i]; - r->rod = 1.0; - r->pert[0] = r->pert[1] = r->pert[2] = 0.0; - r->uv[0] = r->uv[1] = 0.0; - r->rox = NULL; return(1); } @@ -415,12 +415,11 @@ direct( /* add direct component */ multDirectPmap(r); return; } - /* NOTE: srccnt and cntord global so no recursion */ - if (nsources <= 0) - return; /* no sources?! */ - /* potential contributions */ - initsrcindex(&si); + if (maxcntr <= 0) + return; /* no direct?! */ + + initsrcindex(&si); /* potential contributions */ for (sn = 0; srcray(&sr, r, &si); sn++) { if (sn >= maxcntr) { maxcntr = sn + MAXSPART; @@ -670,17 +669,16 @@ srcscatter( /* compute source scattering into ray */ */ static int -weaksrcmat(OBJECT obj) /* identify material */ +weaksrcmat(OBJREC *m) /* identify material */ { - OBJREC *m = findmaterial(objptr(obj)); - + m = findmaterial(m); if (m == NULL) return(0); return((m->otype==MAT_ILLUM) | (m->otype==MAT_GLOW)); } #define illumblock(m, r) (!(source[r->rsrc].sflags&SVIRTUAL) && \ r->rod > 0.0 && \ - weaksrcmat(source[r->rsrc].so->omod)) + weaksrcmat(source[r->rsrc].so)) /* wrongsource * * @@ -768,9 +766,11 @@ m_light( /* ray hit a light source */ return(1); } /* otherwise treat as source */ - /* check for behind */ - if (r->rod < 0.0) + if (r->rod < 0.0) { /* check for behind */ + if (!backvis) + raytrans(r); /* used to return black */ return(1); + } /* check for outside spot */ if (m->otype==MAT_SPOT && spotout(r, makespot(m))) return(1);