ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/srcobstr.c
Revision: 2.15
Committed: Sat Dec 12 00:03:42 2009 UTC (14 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R0
Changes since 2.14: +2 -2 lines
Log Message:
Created RNUMBER type (#define) in preparation for 64-bit compiling

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.15 static const char RCSid[] = "$Id: srcobstr.c,v 2.14 2007/10/08 18:07:57 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Source occlusion caching routines
6     */
7    
8     #include "ray.h"
9    
10     #include "otypes.h"
11    
12     #include "otspecial.h"
13    
14 greg 2.14 #include "rtotypes.h"
15    
16 greg 2.1 #include "source.h"
17    
18     #define ABS(x) ((x)>0 ? (x) : -(x))
19    
20    
21     #if SHADCACHE /* preemptive shadow checking */
22    
23    
24 greg 2.13 OBJECT * antimodlist = NULL; /* set of clipped materials */
25    
26    
27 greg 2.7 static int /* cast source ray to first blocker */
28 greg 2.1 castshadow(int sn, FVECT rorg, FVECT rdir)
29     {
30     RAY rt;
31    
32     VCOPY(rt.rorg, rorg);
33     VCOPY(rt.rdir, rdir);
34     rt.rmax = 0;
35 greg 2.12 rayorigin(&rt, PRIMARY, NULL, NULL);
36 greg 2.7 /* check for intersection */
37     while (localhit(&rt, &thescene)) {
38     RAY rt1 = rt; /* pretend we were aimed at source */
39     rt1.crtype |= rt1.rtype = SHADOW;
40     rt1.rdir[0] = -rt.rdir[0];
41     rt1.rdir[1] = -rt.rdir[1];
42     rt1.rdir[2] = -rt.rdir[2];
43     rt1.rod = -rt.rod;
44     VSUB(rt1.rorg, rt.rop, rt.rdir);
45     rt1.rot = 1.;
46     rt1.rsrc = sn;
47 greg 2.1 /* record blocker */
48 greg 2.7 if (srcblocker(&rt1))
49     return(1);
50     /* move past failed blocker */
51     VSUM(rt.rorg, rt.rop, rt.rdir, FTINY);
52     rayclear(&rt); /* & try again... */
53     }
54     return(0); /* found no blockers */
55 greg 2.1 }
56    
57    
58 greg 2.8 void /* initialize occlusion cache */
59 greg 2.1 initobscache(int sn)
60     {
61     register SRCREC *srcp = &source[sn];
62     int cachelen;
63     FVECT rorg, rdir;
64     RREAL d;
65     int i, j, k;
66     int ax, ax1, ax2;
67    
68 greg 2.8 if (srcp->sflags & (SSKIP|SPROX|SSPOT|SVIRTUAL))
69     return; /* don't cache these */
70 greg 2.1 if (srcp->sflags & SDISTANT)
71     cachelen = 4*SHADCACHE*SHADCACHE;
72     else if (srcp->sflags & SFLAT)
73     cachelen = SHADCACHE*SHADCACHE*3 + (SHADCACHE&1)*SHADCACHE*4;
74     else /* spherical distribution */
75     cachelen = SHADCACHE*SHADCACHE*6;
76     /* allocate cache */
77     srcp->obscache = (OBSCACHE *)malloc(sizeof(OBSCACHE) +
78     sizeof(OBJECT)*(cachelen-1));
79     if (srcp->obscache == NULL)
80     error(SYSTEM, "out of memory in initobscache()");
81     /* set parameters */
82     if (srcp->sflags & SDISTANT) {
83     RREAL amax = 0;
84     for (ax1 = 3; ax1--; )
85     if (ABS(srcp->sloc[ax1]) > amax) {
86     amax = ABS(srcp->sloc[ax1]);
87     ax = ax1;
88     }
89     srcp->obscache->p.d.ax = ax;
90     ax1 = (ax+1)%3;
91     ax2 = (ax+2)%3;
92     VCOPY(srcp->obscache->p.d.o, thescene.cuorg);
93     if (srcp->sloc[ax] > 0)
94     srcp->obscache->p.d.o[ax] += thescene.cusize;
95     if (srcp->sloc[ax1] < 0)
96     srcp->obscache->p.d.o[ax1] += thescene.cusize *
97     srcp->sloc[ax1] / amax;
98     if (srcp->sloc[ax2] < 0)
99     srcp->obscache->p.d.o[ax2] += thescene.cusize *
100     srcp->sloc[ax2] / amax;
101     srcp->obscache->p.d.e1 = 1. / (thescene.cusize*(1. +
102     fabs(srcp->sloc[ax1])/amax));
103     srcp->obscache->p.d.e2 = 1. / (thescene.cusize*(1. +
104     fabs(srcp->sloc[ax2])/amax));
105     } else if (srcp->sflags & SFLAT) {
106     VCOPY(srcp->obscache->p.f.u, srcp->ss[SU]);
107     normalize(srcp->obscache->p.f.u);
108     fcross(srcp->obscache->p.f.v,
109     srcp->snorm, srcp->obscache->p.f.u);
110     }
111     /* clear cache */
112     for (i = cachelen; i--; )
113     srcp->obscache->obs[i] = OVOID;
114     /* cast shadow rays */
115     if (srcp->sflags & SDISTANT) {
116     for (k = 3; k--; )
117     rdir[k] = -srcp->sloc[k];
118     for (i = 2*SHADCACHE; i--; )
119     for (j = 2*SHADCACHE; j--; ) {
120     VCOPY(rorg, srcp->obscache->p.d.o);
121     rorg[ax1] += (i+.5) /
122     (2*SHADCACHE*srcp->obscache->p.d.e1);
123     rorg[ax2] += (j+.5) /
124     (2*SHADCACHE*srcp->obscache->p.d.e2);
125     castshadow(sn, rorg, rdir);
126     }
127     } else if (srcp->sflags & SFLAT) {
128     d = 0.01*srcp->srad;
129     VSUM(rorg, srcp->sloc, srcp->snorm, d);
130     for (i = SHADCACHE; i--; )
131     for (j = SHADCACHE; j--; ) {
132     d = 2./SHADCACHE*(i+.5) - 1.;
133     VSUM(rdir, srcp->snorm,
134     srcp->obscache->p.f.u, d);
135     d = 2./SHADCACHE*(j+.5) - 1.;
136     VSUM(rdir, rdir, srcp->obscache->p.f.v, d);
137     normalize(rdir);
138     castshadow(sn, rorg, rdir);
139     }
140     for (k = 2; k--; )
141     for (i = SHADCACHE; i--; )
142     for (j = SHADCACHE>>1; j--; ) {
143     d = 2./SHADCACHE*(i+.5) - 1.;
144     if (k)
145     VSUM(rdir, srcp->obscache->p.f.u,
146     srcp->obscache->p.f.v, d);
147     else
148     VSUM(rdir, srcp->obscache->p.f.v,
149     srcp->obscache->p.f.u, d);
150 greg 2.3 d = 1. - 2./SHADCACHE*(j+.5);
151 greg 2.1 VSUM(rdir, rdir, srcp->snorm, d);
152     normalize(rdir);
153     castshadow(sn, rorg, rdir);
154     d = 2.*DOT(rdir, srcp->snorm);
155     rdir[0] = d*srcp->snorm[0] - rdir[0];
156     rdir[1] = d*srcp->snorm[1] - rdir[1];
157     rdir[2] = d*srcp->snorm[2] - rdir[2];
158     castshadow(sn, rorg, rdir);
159     }
160     } else /* spherical distribution */
161     for (k = 6; k--; ) {
162     ax = k%3;
163     ax1 = (k+1)%3;
164     ax2 = (k+2)%3;
165     for (i = SHADCACHE; i--; )
166     for (j = SHADCACHE; j--; ) {
167     rdir[0]=rdir[1]=rdir[2] = 0.;
168     rdir[ax] = k<3 ? 1. : -1.;
169     rdir[ax1] = 2./SHADCACHE*(i+.5) - 1.;
170     rdir[ax2] = 2./SHADCACHE*(j+.5) - 1.;
171     normalize(rdir);
172     d = 1.05*srcp->srad;
173     VSUM(rorg, srcp->sloc, rdir, d);
174     castshadow(sn, rorg, rdir);
175     }
176     }
177     }
178    
179    
180     static OBJECT * /* return occluder cache entry */
181     srcobstructp(register RAY *r)
182     {
183 greg 2.15 static RNUMBER lastrno = ~0;
184 greg 2.1 static OBJECT noobs;
185 greg 2.6 static OBJECT *lastobjp;
186 greg 2.1 SRCREC *srcp;
187     int ondx;
188    
189 greg 2.6 noobs = OVOID;
190     if (r->rno == lastrno)
191     return lastobjp; /* just recall last pointer */
192 greg 2.1 DCHECK(r->rsrc < 0, CONSISTENCY,
193     "srcobstructp() called with unaimed ray");
194 greg 2.6 lastrno = r->rno;
195     lastobjp = &noobs;
196 greg 2.1 srcp = &source[r->rsrc];
197     if (srcp->sflags & (SSKIP|SPROX|SSPOT|SVIRTUAL))
198     return(&noobs); /* don't cache these */
199     if (srcp->obscache == NULL) /* initialize cache */
200     initobscache(r->rsrc);
201     /* compute cache index */
202     if (srcp->sflags & SDISTANT) {
203     int ax, ax1, ax2;
204     double t;
205     ax = srcp->obscache->p.d.ax;
206     if ((ax1 = ax+1) >= 3) ax1 -= 3;
207     if ((ax2 = ax+2) >= 3) ax2 -= 3;
208     t = (srcp->obscache->p.d.o[ax] - r->rorg[ax]) / srcp->sloc[ax];
209     if (t <= FTINY)
210     return(&noobs); /* could happen if ray is outside */
211     ondx = 2*SHADCACHE*(int)(2*SHADCACHE*srcp->obscache->p.d.e1 *
212     (r->rorg[ax1] + t*srcp->sloc[ax1] -
213     srcp->obscache->p.d.o[ax1]));
214     ondx += (int)(2*SHADCACHE*srcp->obscache->p.d.e2 *
215     (r->rorg[ax2] + t*srcp->sloc[ax2] -
216     srcp->obscache->p.d.o[ax2]));
217 schorsch 2.4 if ((ondx < 0) | (ondx >= 4*SHADCACHE*SHADCACHE))
218 greg 2.1 return(&noobs); /* could happen if ray is outside */
219     } else if (srcp->sflags & SFLAT) {
220     FVECT sd;
221     RREAL sd0m, sd1m;
222     sd[0] = -DOT(r->rdir, srcp->obscache->p.f.u);
223     sd[1] = -DOT(r->rdir, srcp->obscache->p.f.v);
224     sd[2] = -DOT(r->rdir, srcp->snorm);
225     if (sd[2] < 0)
226     return(&noobs); /* shouldn't happen */
227     sd0m = ABS(sd[0]);
228     sd1m = ABS(sd[1]);
229     if (sd[2] >= sd0m && sd[2] >= sd1m) {
230     ondx = SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
231     (1. + sd[0]/sd[2]));
232     ondx += (int)(SHADCACHE*(.5-FTINY) *
233     (1. + sd[1]/sd[2]));
234     } else if (sd0m >= sd1m) {
235     ondx = SHADCACHE*SHADCACHE;
236     if (sd[0] < 0)
237     ondx += ((SHADCACHE+1)>>1)*SHADCACHE;
238     ondx += SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
239 greg 2.3 (1. - sd[2]/sd0m));
240 greg 2.1 ondx += (int)(SHADCACHE*(.5-FTINY) *
241     (1. + sd[1]/sd0m));
242     } else /* sd1m > sd0m */ {
243     ondx = SHADCACHE*SHADCACHE +
244     ((SHADCACHE+1)>>1)*SHADCACHE*2;
245     if (sd[1] < 0)
246     ondx += ((SHADCACHE+1)>>1)*SHADCACHE;
247     ondx += SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
248 greg 2.3 (1. - sd[2]/sd1m));
249 greg 2.1 ondx += (int)(SHADCACHE*(.5-FTINY) *
250     (1. + sd[0]/sd1m));
251     }
252 greg 2.6 DCHECK((ondx < 0) | (ondx >= SHADCACHE*SHADCACHE*3 +
253     (SHADCACHE&1)*SHADCACHE*4), CONSISTENCY,
254 greg 2.3 "flat source cache index out of bounds");
255 greg 2.1 } else /* spherical distribution */ {
256     int ax, ax1, ax2;
257     RREAL amax = 0;
258     for (ax1 = 3; ax1--; )
259     if (ABS(r->rdir[ax1]) > amax) {
260     amax = ABS(r->rdir[ax1]);
261     ax = ax1;
262     }
263     if ((ax1 = ax+1) >= 3) ax1 -= 3;
264     if ((ax2 = ax+2) >= 3) ax2 -= 3;
265     ondx = 2*SHADCACHE*SHADCACHE * ax;
266     if (r->rdir[ax] < 0)
267     ondx += SHADCACHE*SHADCACHE;
268     ondx += SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
269     (1. + r->rdir[ax1]/amax));
270     ondx += (int)(SHADCACHE*(.5-FTINY) *
271     (1. + r->rdir[ax2]/amax));
272 greg 2.6 DCHECK((ondx < 0) | (ondx >= SHADCACHE*SHADCACHE*6), CONSISTENCY,
273 greg 2.3 "radial source cache index out of bounds");
274 greg 2.1 }
275     /* return cache pointer */
276 greg 2.6 return(lastobjp = &srcp->obscache->obs[ondx]);
277 greg 2.1 }
278    
279    
280     void /* free obstruction cache */
281     freeobscache(SRCREC *srcp)
282     {
283     if (srcp->obscache == NULL)
284     return;
285     free((void *)srcp->obscache);
286     srcp->obscache = NULL;
287     }
288    
289    
290 greg 2.7 int /* record a source blocker */
291 greg 2.1 srcblocker(register RAY *r)
292     {
293     OBJREC *m;
294    
295     if (r->robj == OVOID || objptr(r->robj) != r->ro ||
296     isvolume(r->ro->otype))
297 greg 2.7 return(0); /* don't record complex blockers */
298 greg 2.11 if (r->rsrc < 0 || source[r->rsrc].so == r->ro)
299     return(0); /* just a mistake, that's all */
300 greg 2.13 if (antimodlist != NULL && inset(antimodlist, r->ro->omod))
301     return(0); /* could be clipped */
302 greg 2.1 m = findmaterial(r->ro);
303     if (m == NULL)
304 greg 2.7 return(0); /* no material?! */
305 greg 2.5 if (!isopaque(m->otype))
306 greg 2.7 return(0); /* material not a reliable blocker */
307 greg 2.1 *srcobstructp(r) = r->robj; /* else record obstructor */
308 greg 2.7 return(1);
309 greg 2.1 }
310    
311    
312     int /* check ray against cached blocker */
313     srcblocked(RAY *r)
314     {
315     OBJECT obs = *srcobstructp(r);
316     OBJREC *op;
317    
318     if (obs == OVOID)
319     return(0);
320 greg 2.10 op = objptr(obs); /* check blocker intersection */
321 greg 2.9 if (!(*ofun[op->otype].funp)(op, r))
322     return(0);
323 greg 2.10 if (source[r->rsrc].sflags & SDISTANT)
324     return(1);
325     op = source[r->rsrc].so; /* check source intersection */
326     if (!(*ofun[op->otype].funp)(op, r))
327     return(1);
328     rayclear(r);
329     return(0); /* source in front */
330 greg 2.1 }
331    
332    
333 greg 2.13 void /* record potentially clipped materials */
334     markclip(OBJREC *m)
335     {
336     OBJECT *set2add, *oldset;
337    
338     m_clip(m, NULL); /* initialize modifier list */
339     if ((set2add = (OBJECT *)m->os) == NULL || !set2add[0])
340     return;
341    
342     if (antimodlist == NULL) { /* start of list */
343     antimodlist = setsave(set2add);
344     return;
345     }
346     /* else add to previous list */
347     oldset = antimodlist;
348     antimodlist = (OBJECT *)malloc((oldset[0]+set2add[0]+1)*sizeof(OBJECT));
349     if (antimodlist == NULL)
350     error(SYSTEM, "out of memory in markclip");
351     setunion(antimodlist, oldset, set2add);
352     free((void *)oldset);
353     }
354    
355    
356     #else /* SHADCACHE */
357    
358    
359     void /* no-op also avoids linker warning */
360     markclip(OBJREC *m)
361     {
362     (void)m;
363     }
364    
365    
366 greg 2.1 #endif /* SHADCACHE */