--- ray/src/rt/raytrace.c 1991/10/23 13:43:45 1.23 +++ ray/src/rt/raytrace.c 1993/12/09 09:34:08 2.8 @@ -18,20 +18,24 @@ static char SCCSid[] = "$SunId$ LBL"; #include "otspecial.h" +#define MAXCSET ((MAXSET+1)*2-1) /* maximum check set size */ + extern CUBE thescene; /* our scene */ extern int maxdepth; /* maximum recursion depth */ extern double minweight; /* minimum ray weight */ extern int do_irrad; /* compute irradiance? */ -long raynum = 0L; /* next unique ray number */ -long nrays = 0L; /* number of calls to localhit */ +unsigned long raynum = 0; /* next unique ray number */ +unsigned long nrays = 0; /* number of calls to localhit */ static FLOAT Lambfa[5] = {PI, PI, PI, 0.0, 0.0}; OBJREC Lamb = { OVOID, MAT_PLASTIC, "Lambertian", - {0, 5, NULL, Lambfa}, NULL, -1, + {0, 5, NULL, Lambfa}, NULL, }; /* a Lambertian surface */ +static int raymove(), checkset(), checkhit(); + #define MAXLOOP 128 /* modifier loop detection */ #define RAYHIT (-1) /* return value for intercepted ray */ @@ -101,7 +105,8 @@ RAY *r; raycont(r) /* check for clipped object and continue */ register RAY *r; { - if (r->clipset != NULL && inset(r->clipset, r->ro->omod)) + if ((r->clipset != NULL && inset(r->clipset, r->ro->omod)) || + r->ro->omod == OVOID) raytrans(r); else rayshade(r, r->ro->omod); @@ -151,7 +156,6 @@ int mod; m = &Lamb; } (*ofun[m->otype].funp)(m, r); /* execute function */ - m->lastrno = r->rno; if (ismaterial(m->otype)) { /* materials call raytexture */ depth--; return; /* we're done */ @@ -178,7 +182,6 @@ int mod; error(USER, errmsg); } (*ofun[m->otype].funp)(m, r); - m->lastrno = r->rno; } depth--; /* end here */ } @@ -318,6 +321,7 @@ localhit(r, scene) /* check for hit in the octree */ register RAY *r; register CUBE *scene; { + OBJECT cxset[MAXCSET+1]; /* set of checked objects */ FVECT curpos; /* current cube position */ int sflags; /* sign flags */ double t, dt; @@ -327,9 +331,9 @@ register CUBE *scene; sflags = 0; for (i = 0; i < 3; i++) { curpos[i] = r->rorg[i]; - if (r->rdir[i] > FTINY) + if (r->rdir[i] > 1e-7) sflags |= 1 << i; - else if (r->rdir[i] < -FTINY) + else if (r->rdir[i] < -1e-7) sflags |= 0x10 << i; } if (sflags == 0) @@ -358,13 +362,15 @@ register CUBE *scene; if (!incube(scene, curpos)) /* non-intersecting ray */ return(0); } - return(raymove(curpos, sflags, r, scene) == RAYHIT); + cxset[0] = 0; + return(raymove(curpos, cxset, sflags, r, scene) == RAYHIT); } static int -raymove(pos, dirf, r, cu) /* check for hit as we move */ -FVECT pos; /* modified */ +raymove(pos, cxs, dirf, r, cu) /* check for hit as we move */ +FVECT pos; /* current position, modified herein */ +OBJECT *cxs; /* checked objects, modified by checkhit */ int dirf; /* direction indicators to speed tests */ register RAY *r; register CUBE *cu; @@ -393,7 +399,7 @@ register CUBE *cu; } for ( ; ; ) { cukid.cutree = octkid(cu->cutree, br); - if ((ax = raymove(pos,dirf,r,&cukid)) == RAYHIT) + if ((ax = raymove(pos,cxs,dirf,r,&cukid)) == RAYHIT) return(RAYHIT); sgn = 1 << ax; if (sgn & dirf) /* positive axis? */ @@ -412,7 +418,7 @@ register CUBE *cu; } /*NOTREACHED*/ } - if (isfull(cu->cutree) && checkhit(r, cu)) + if (isfull(cu->cutree) && checkhit(r, cu, cxs)) return(RAYHIT); /* advance to next cube */ if (dirf&0x11) { @@ -445,24 +451,55 @@ register CUBE *cu; static -checkhit(r, cu) /* check for hit in full cube */ +checkhit(r, cu, cxs) /* check for hit in full cube */ register RAY *r; CUBE *cu; +OBJECT *cxs; { OBJECT oset[MAXSET+1]; register OBJREC *o; register int i; objset(oset, cu->cutree); + checkset(oset, cxs); /* eliminate double-checking */ for (i = oset[0]; i > 0; i--) { o = objptr(oset[i]); - if (o->lastrno == r->rno) /* checked already? */ - continue; (*ofun[o->otype].funp)(o, r); - o->lastrno = r->rno; } if (r->ro == NULL) return(0); /* no scores yet */ return(incube(cu, r->rop)); /* hit OK if in current cube */ +} + + +static +checkset(os, cs) /* modify checked set and set to check */ +register OBJECT *os; /* os' = os - cs */ +register OBJECT *cs; /* cs' = cs + os */ +{ + OBJECT cset[MAXCSET+MAXSET+1]; + register int i, j; + int k; + /* copy os in place, cset <- cs */ + cset[0] = 0; + k = 0; + for (i = j = 1; i <= os[0]; i++) { + while (j <= cs[0] && cs[j] < os[i]) + cset[++cset[0]] = cs[j++]; + if (j > cs[0] || os[i] != cs[j]) { /* object to check */ + os[++k] = os[i]; + cset[++cset[0]] = os[i]; + } + } + if (!(os[0] = k)) /* new "to check" set size */ + return; /* special case */ + while (j <= cs[0]) /* get the rest of cs */ + cset[++cset[0]] = cs[j++]; + if (cset[0] > MAXCSET) /* truncate "checked" set if nec. */ + cset[0] = MAXCSET; + /* setcopy(cs, cset); */ /* copy cset back to cs */ + os = cset; + for (i = os[0]; i-- >= 0; ) + *cs++ = *os++; }