19 |
|
#if SHADCACHE /* preemptive shadow checking */ |
20 |
|
|
21 |
|
|
22 |
< |
static void /* cast source ray to first blocker */ |
22 |
> |
static int /* cast source ray to first blocker */ |
23 |
|
castshadow(int sn, FVECT rorg, FVECT rdir) |
24 |
|
{ |
25 |
|
RAY rt; |
28 |
|
VCOPY(rt.rdir, rdir); |
29 |
|
rt.rmax = 0; |
30 |
|
rayorigin(&rt, NULL, PRIMARY, 1.0); |
31 |
< |
if (!localhit(&rt, &thescene)) |
32 |
< |
return; |
33 |
< |
/* pretend we were aimed at source */ |
34 |
< |
rt.crtype |= rt.rtype = SHADOW; |
35 |
< |
rt.rdir[0] = -rt.rdir[0]; |
36 |
< |
rt.rdir[1] = -rt.rdir[1]; |
37 |
< |
rt.rdir[2] = -rt.rdir[2]; |
38 |
< |
rt.rod = -rt.rod; |
39 |
< |
VSUB(rt.rorg, rt.rop, rt.rdir); |
40 |
< |
rt.rot = 1.; |
41 |
< |
rt.rsrc = sn; |
31 |
> |
/* check for intersection */ |
32 |
> |
while (localhit(&rt, &thescene)) { |
33 |
> |
RAY rt1 = rt; /* pretend we were aimed at source */ |
34 |
> |
rt1.crtype |= rt1.rtype = SHADOW; |
35 |
> |
rt1.rdir[0] = -rt.rdir[0]; |
36 |
> |
rt1.rdir[1] = -rt.rdir[1]; |
37 |
> |
rt1.rdir[2] = -rt.rdir[2]; |
38 |
> |
rt1.rod = -rt.rod; |
39 |
> |
VSUB(rt1.rorg, rt.rop, rt.rdir); |
40 |
> |
rt1.rot = 1.; |
41 |
> |
rt1.rsrc = sn; |
42 |
|
/* record blocker */ |
43 |
< |
srcblocker(&rt); |
43 |
> |
if (srcblocker(&rt1)) |
44 |
> |
return(1); |
45 |
> |
/* move past failed blocker */ |
46 |
> |
VSUM(rt.rorg, rt.rop, rt.rdir, FTINY); |
47 |
> |
rayclear(&rt); /* & try again... */ |
48 |
> |
} |
49 |
> |
return(0); /* found no blockers */ |
50 |
|
} |
51 |
|
|
52 |
|
|
53 |
< |
static void /* initialize occlusion cache */ |
53 |
> |
void /* initialize occlusion cache */ |
54 |
|
initobscache(int sn) |
55 |
|
{ |
56 |
|
register SRCREC *srcp = &source[sn]; |
60 |
|
int i, j, k; |
61 |
|
int ax, ax1, ax2; |
62 |
|
|
63 |
+ |
if (srcp->sflags & (SSKIP|SPROX|SSPOT|SVIRTUAL)) |
64 |
+ |
return; /* don't cache these */ |
65 |
|
if (srcp->sflags & SDISTANT) |
66 |
|
cachelen = 4*SHADCACHE*SHADCACHE; |
67 |
|
else if (srcp->sflags & SFLAT) |
69 |
|
else /* spherical distribution */ |
70 |
|
cachelen = SHADCACHE*SHADCACHE*6; |
71 |
|
/* allocate cache */ |
64 |
– |
DCHECK(srcp->obscache != NULL, |
65 |
– |
CONSISTENCY, "initobscache() called twice"); |
72 |
|
srcp->obscache = (OBSCACHE *)malloc(sizeof(OBSCACHE) + |
73 |
|
sizeof(OBJECT)*(cachelen-1)); |
74 |
|
if (srcp->obscache == NULL) |
175 |
|
static OBJECT * /* return occluder cache entry */ |
176 |
|
srcobstructp(register RAY *r) |
177 |
|
{ |
178 |
+ |
static unsigned long lastrno = ~0; |
179 |
|
static OBJECT noobs; |
180 |
+ |
static OBJECT *lastobjp; |
181 |
|
SRCREC *srcp; |
182 |
|
int ondx; |
183 |
|
|
184 |
+ |
noobs = OVOID; |
185 |
+ |
if (r->rno == lastrno) |
186 |
+ |
return lastobjp; /* just recall last pointer */ |
187 |
|
DCHECK(r->rsrc < 0, CONSISTENCY, |
188 |
|
"srcobstructp() called with unaimed ray"); |
189 |
< |
noobs = OVOID; |
189 |
> |
lastrno = r->rno; |
190 |
> |
lastobjp = &noobs; |
191 |
|
srcp = &source[r->rsrc]; |
192 |
|
if (srcp->sflags & (SSKIP|SPROX|SSPOT|SVIRTUAL)) |
193 |
|
return(&noobs); /* don't cache these */ |
244 |
|
ondx += (int)(SHADCACHE*(.5-FTINY) * |
245 |
|
(1. + sd[0]/sd1m)); |
246 |
|
} |
247 |
< |
DCHECK(ondx < 0 | ondx >= SHADCACHE*SHADCACHE*3 + |
248 |
< |
(SHADCACHE&1)*SHADCACHE*4, CONSISTENCY, |
247 |
> |
DCHECK((ondx < 0) | (ondx >= SHADCACHE*SHADCACHE*3 + |
248 |
> |
(SHADCACHE&1)*SHADCACHE*4), CONSISTENCY, |
249 |
|
"flat source cache index out of bounds"); |
250 |
|
} else /* spherical distribution */ { |
251 |
|
int ax, ax1, ax2; |
264 |
|
(1. + r->rdir[ax1]/amax)); |
265 |
|
ondx += (int)(SHADCACHE*(.5-FTINY) * |
266 |
|
(1. + r->rdir[ax2]/amax)); |
267 |
< |
DCHECK(ondx < 0 | ondx >= SHADCACHE*SHADCACHE*6, CONSISTENCY, |
267 |
> |
DCHECK((ondx < 0) | (ondx >= SHADCACHE*SHADCACHE*6), CONSISTENCY, |
268 |
|
"radial source cache index out of bounds"); |
269 |
|
} |
270 |
|
/* return cache pointer */ |
271 |
< |
return(&srcp->obscache->obs[ondx]); |
271 |
> |
return(lastobjp = &srcp->obscache->obs[ondx]); |
272 |
|
} |
273 |
|
|
274 |
|
|
282 |
|
} |
283 |
|
|
284 |
|
|
285 |
< |
void /* record a source blocker */ |
285 |
> |
int /* record a source blocker */ |
286 |
|
srcblocker(register RAY *r) |
287 |
|
{ |
288 |
|
OBJREC *m; |
289 |
|
|
290 |
|
if (r->robj == OVOID || objptr(r->robj) != r->ro || |
291 |
|
isvolume(r->ro->otype)) |
292 |
< |
return; /* don't record complex blockers */ |
292 |
> |
return(0); /* don't record complex blockers */ |
293 |
|
m = findmaterial(r->ro); |
294 |
|
if (m == NULL) |
295 |
< |
return; /* no material?! */ |
296 |
< |
if (!(ofun[m->otype].flags & T_OPAQUE)) |
297 |
< |
return; /* material not a reliable blocker */ |
295 |
> |
return(0); /* no material?! */ |
296 |
> |
if (!isopaque(m->otype)) |
297 |
> |
return(0); /* material not a reliable blocker */ |
298 |
|
*srcobstructp(r) = r->robj; /* else record obstructor */ |
299 |
+ |
return(1); |
300 |
|
} |
301 |
|
|
302 |
|
|