ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/srcobstr.c
Revision: 2.10
Committed: Fri Sep 10 17:08:36 2004 UTC (19 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R6
Changes since 2.9: +9 -8 lines
Log Message:
Fixed bug in last fix -- distant sources weren't working

File Contents

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