ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/srcobstr.c
Revision: 2.6
Committed: Wed Sep 8 01:48:50 2004 UTC (19 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.5: +12 -6 lines
Log Message:
Added local caching of obstruction index

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.6 static const char RCSid[] = "$Id: srcobstr.c,v 2.5 2004/06/22 13:40:54 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     #include "source.h"
15    
16     #define ABS(x) ((x)>0 ? (x) : -(x))
17    
18    
19     #if SHADCACHE /* preemptive shadow checking */
20    
21    
22     static void /* cast source ray to first blocker */
23     castshadow(int sn, FVECT rorg, FVECT rdir)
24     {
25     RAY rt;
26    
27     VCOPY(rt.rorg, rorg);
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;
42     /* record blocker */
43     srcblocker(&rt);
44     }
45    
46    
47     static void /* initialize occlusion cache */
48     initobscache(int sn)
49     {
50     register SRCREC *srcp = &source[sn];
51     int cachelen;
52     FVECT rorg, rdir;
53     RREAL d;
54     int i, j, k;
55     int ax, ax1, ax2;
56    
57     if (srcp->sflags & SDISTANT)
58     cachelen = 4*SHADCACHE*SHADCACHE;
59     else if (srcp->sflags & SFLAT)
60     cachelen = SHADCACHE*SHADCACHE*3 + (SHADCACHE&1)*SHADCACHE*4;
61     else /* spherical distribution */
62     cachelen = SHADCACHE*SHADCACHE*6;
63     /* allocate cache */
64     DCHECK(srcp->obscache != NULL,
65     CONSISTENCY, "initobscache() called twice");
66     srcp->obscache = (OBSCACHE *)malloc(sizeof(OBSCACHE) +
67     sizeof(OBJECT)*(cachelen-1));
68     if (srcp->obscache == NULL)
69     error(SYSTEM, "out of memory in initobscache()");
70     /* set parameters */
71     if (srcp->sflags & SDISTANT) {
72     RREAL amax = 0;
73     for (ax1 = 3; ax1--; )
74     if (ABS(srcp->sloc[ax1]) > amax) {
75     amax = ABS(srcp->sloc[ax1]);
76     ax = ax1;
77     }
78     srcp->obscache->p.d.ax = ax;
79     ax1 = (ax+1)%3;
80     ax2 = (ax+2)%3;
81     VCOPY(srcp->obscache->p.d.o, thescene.cuorg);
82     if (srcp->sloc[ax] > 0)
83     srcp->obscache->p.d.o[ax] += thescene.cusize;
84     if (srcp->sloc[ax1] < 0)
85     srcp->obscache->p.d.o[ax1] += thescene.cusize *
86     srcp->sloc[ax1] / amax;
87     if (srcp->sloc[ax2] < 0)
88     srcp->obscache->p.d.o[ax2] += thescene.cusize *
89     srcp->sloc[ax2] / amax;
90     srcp->obscache->p.d.e1 = 1. / (thescene.cusize*(1. +
91     fabs(srcp->sloc[ax1])/amax));
92     srcp->obscache->p.d.e2 = 1. / (thescene.cusize*(1. +
93     fabs(srcp->sloc[ax2])/amax));
94     } else if (srcp->sflags & SFLAT) {
95     VCOPY(srcp->obscache->p.f.u, srcp->ss[SU]);
96     normalize(srcp->obscache->p.f.u);
97     fcross(srcp->obscache->p.f.v,
98     srcp->snorm, srcp->obscache->p.f.u);
99     }
100     /* clear cache */
101     for (i = cachelen; i--; )
102     srcp->obscache->obs[i] = OVOID;
103     /* cast shadow rays */
104     if (srcp->sflags & SDISTANT) {
105     for (k = 3; k--; )
106     rdir[k] = -srcp->sloc[k];
107     for (i = 2*SHADCACHE; i--; )
108     for (j = 2*SHADCACHE; j--; ) {
109     VCOPY(rorg, srcp->obscache->p.d.o);
110     rorg[ax1] += (i+.5) /
111     (2*SHADCACHE*srcp->obscache->p.d.e1);
112     rorg[ax2] += (j+.5) /
113     (2*SHADCACHE*srcp->obscache->p.d.e2);
114     castshadow(sn, rorg, rdir);
115     }
116     } else if (srcp->sflags & SFLAT) {
117     d = 0.01*srcp->srad;
118     VSUM(rorg, srcp->sloc, srcp->snorm, d);
119     for (i = SHADCACHE; i--; )
120     for (j = SHADCACHE; j--; ) {
121     d = 2./SHADCACHE*(i+.5) - 1.;
122     VSUM(rdir, srcp->snorm,
123     srcp->obscache->p.f.u, d);
124     d = 2./SHADCACHE*(j+.5) - 1.;
125     VSUM(rdir, rdir, srcp->obscache->p.f.v, d);
126     normalize(rdir);
127     castshadow(sn, rorg, rdir);
128     }
129     for (k = 2; k--; )
130     for (i = SHADCACHE; i--; )
131     for (j = SHADCACHE>>1; j--; ) {
132     d = 2./SHADCACHE*(i+.5) - 1.;
133     if (k)
134     VSUM(rdir, srcp->obscache->p.f.u,
135     srcp->obscache->p.f.v, d);
136     else
137     VSUM(rdir, srcp->obscache->p.f.v,
138     srcp->obscache->p.f.u, d);
139 greg 2.3 d = 1. - 2./SHADCACHE*(j+.5);
140 greg 2.1 VSUM(rdir, rdir, srcp->snorm, d);
141     normalize(rdir);
142     castshadow(sn, rorg, rdir);
143     d = 2.*DOT(rdir, srcp->snorm);
144     rdir[0] = d*srcp->snorm[0] - rdir[0];
145     rdir[1] = d*srcp->snorm[1] - rdir[1];
146     rdir[2] = d*srcp->snorm[2] - rdir[2];
147     castshadow(sn, rorg, rdir);
148     }
149     } else /* spherical distribution */
150     for (k = 6; k--; ) {
151     ax = k%3;
152     ax1 = (k+1)%3;
153     ax2 = (k+2)%3;
154     for (i = SHADCACHE; i--; )
155     for (j = SHADCACHE; j--; ) {
156     rdir[0]=rdir[1]=rdir[2] = 0.;
157     rdir[ax] = k<3 ? 1. : -1.;
158     rdir[ax1] = 2./SHADCACHE*(i+.5) - 1.;
159     rdir[ax2] = 2./SHADCACHE*(j+.5) - 1.;
160     normalize(rdir);
161     d = 1.05*srcp->srad;
162     VSUM(rorg, srcp->sloc, rdir, d);
163     castshadow(sn, rorg, rdir);
164     }
165     }
166     }
167    
168    
169     static OBJECT * /* return occluder cache entry */
170     srcobstructp(register RAY *r)
171     {
172 greg 2.6 static unsigned long lastrno = ~0;
173 greg 2.1 static OBJECT noobs;
174 greg 2.6 static OBJECT *lastobjp;
175 greg 2.1 SRCREC *srcp;
176     int ondx;
177    
178 greg 2.6 noobs = OVOID;
179     if (r->rno == lastrno)
180     return lastobjp; /* just recall last pointer */
181 greg 2.1 DCHECK(r->rsrc < 0, CONSISTENCY,
182     "srcobstructp() called with unaimed ray");
183 greg 2.6 lastrno = r->rno;
184     lastobjp = &noobs;
185 greg 2.1 srcp = &source[r->rsrc];
186     if (srcp->sflags & (SSKIP|SPROX|SSPOT|SVIRTUAL))
187     return(&noobs); /* don't cache these */
188     if (srcp->obscache == NULL) /* initialize cache */
189     initobscache(r->rsrc);
190     /* compute cache index */
191     if (srcp->sflags & SDISTANT) {
192     int ax, ax1, ax2;
193     double t;
194     ax = srcp->obscache->p.d.ax;
195     if ((ax1 = ax+1) >= 3) ax1 -= 3;
196     if ((ax2 = ax+2) >= 3) ax2 -= 3;
197     t = (srcp->obscache->p.d.o[ax] - r->rorg[ax]) / srcp->sloc[ax];
198     if (t <= FTINY)
199     return(&noobs); /* could happen if ray is outside */
200     ondx = 2*SHADCACHE*(int)(2*SHADCACHE*srcp->obscache->p.d.e1 *
201     (r->rorg[ax1] + t*srcp->sloc[ax1] -
202     srcp->obscache->p.d.o[ax1]));
203     ondx += (int)(2*SHADCACHE*srcp->obscache->p.d.e2 *
204     (r->rorg[ax2] + t*srcp->sloc[ax2] -
205     srcp->obscache->p.d.o[ax2]));
206 schorsch 2.4 if ((ondx < 0) | (ondx >= 4*SHADCACHE*SHADCACHE))
207 greg 2.1 return(&noobs); /* could happen if ray is outside */
208     } else if (srcp->sflags & SFLAT) {
209     FVECT sd;
210     RREAL sd0m, sd1m;
211     sd[0] = -DOT(r->rdir, srcp->obscache->p.f.u);
212     sd[1] = -DOT(r->rdir, srcp->obscache->p.f.v);
213     sd[2] = -DOT(r->rdir, srcp->snorm);
214     if (sd[2] < 0)
215     return(&noobs); /* shouldn't happen */
216     sd0m = ABS(sd[0]);
217     sd1m = ABS(sd[1]);
218     if (sd[2] >= sd0m && sd[2] >= sd1m) {
219     ondx = SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
220     (1. + sd[0]/sd[2]));
221     ondx += (int)(SHADCACHE*(.5-FTINY) *
222     (1. + sd[1]/sd[2]));
223     } else if (sd0m >= sd1m) {
224     ondx = SHADCACHE*SHADCACHE;
225     if (sd[0] < 0)
226     ondx += ((SHADCACHE+1)>>1)*SHADCACHE;
227     ondx += SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
228 greg 2.3 (1. - sd[2]/sd0m));
229 greg 2.1 ondx += (int)(SHADCACHE*(.5-FTINY) *
230     (1. + sd[1]/sd0m));
231     } else /* sd1m > sd0m */ {
232     ondx = SHADCACHE*SHADCACHE +
233     ((SHADCACHE+1)>>1)*SHADCACHE*2;
234     if (sd[1] < 0)
235     ondx += ((SHADCACHE+1)>>1)*SHADCACHE;
236     ondx += SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
237 greg 2.3 (1. - sd[2]/sd1m));
238 greg 2.1 ondx += (int)(SHADCACHE*(.5-FTINY) *
239     (1. + sd[0]/sd1m));
240     }
241 greg 2.6 DCHECK((ondx < 0) | (ondx >= SHADCACHE*SHADCACHE*3 +
242     (SHADCACHE&1)*SHADCACHE*4), CONSISTENCY,
243 greg 2.3 "flat source cache index out of bounds");
244 greg 2.1 } else /* spherical distribution */ {
245     int ax, ax1, ax2;
246     RREAL amax = 0;
247     for (ax1 = 3; ax1--; )
248     if (ABS(r->rdir[ax1]) > amax) {
249     amax = ABS(r->rdir[ax1]);
250     ax = ax1;
251     }
252     if ((ax1 = ax+1) >= 3) ax1 -= 3;
253     if ((ax2 = ax+2) >= 3) ax2 -= 3;
254     ondx = 2*SHADCACHE*SHADCACHE * ax;
255     if (r->rdir[ax] < 0)
256     ondx += SHADCACHE*SHADCACHE;
257     ondx += SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
258     (1. + r->rdir[ax1]/amax));
259     ondx += (int)(SHADCACHE*(.5-FTINY) *
260     (1. + r->rdir[ax2]/amax));
261 greg 2.6 DCHECK((ondx < 0) | (ondx >= SHADCACHE*SHADCACHE*6), CONSISTENCY,
262 greg 2.3 "radial source cache index out of bounds");
263 greg 2.1 }
264     /* return cache pointer */
265 greg 2.6 return(lastobjp = &srcp->obscache->obs[ondx]);
266 greg 2.1 }
267    
268    
269     void /* free obstruction cache */
270     freeobscache(SRCREC *srcp)
271     {
272     if (srcp->obscache == NULL)
273     return;
274     free((void *)srcp->obscache);
275     srcp->obscache = NULL;
276     }
277    
278    
279     void /* record a source blocker */
280     srcblocker(register RAY *r)
281     {
282     OBJREC *m;
283    
284     if (r->robj == OVOID || objptr(r->robj) != r->ro ||
285     isvolume(r->ro->otype))
286     return; /* don't record complex blockers */
287     m = findmaterial(r->ro);
288     if (m == NULL)
289     return; /* no material?! */
290 greg 2.5 if (!isopaque(m->otype))
291 greg 2.1 return; /* material not a reliable blocker */
292     *srcobstructp(r) = r->robj; /* else record obstructor */
293     }
294    
295    
296     int /* check ray against cached blocker */
297     srcblocked(RAY *r)
298     {
299     OBJECT obs = *srcobstructp(r);
300     OBJREC *op;
301    
302     if (obs == OVOID)
303     return(0);
304     op = objptr(obs); /* check for intersection */
305 greg 2.2 return((*ofun[op->otype].funp)(op, r));
306 greg 2.1 }
307    
308    
309     #endif /* SHADCACHE */