ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/srcobstr.c
Revision: 2.5
Committed: Tue Jun 22 13:40:54 2004 UTC (19 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.4: +2 -2 lines
Log Message:
Added isopaque() macro to otspecial.h

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.5 static const char RCSid[] = "$Id: srcobstr.c,v 2.4 2004/03/30 16:13:01 schorsch 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     static OBJECT noobs;
173     SRCREC *srcp;
174     int ondx;
175    
176     DCHECK(r->rsrc < 0, CONSISTENCY,
177     "srcobstructp() called with unaimed ray");
178     noobs = OVOID;
179     srcp = &source[r->rsrc];
180     if (srcp->sflags & (SSKIP|SPROX|SSPOT|SVIRTUAL))
181     return(&noobs); /* don't cache these */
182     if (srcp->obscache == NULL) /* initialize cache */
183     initobscache(r->rsrc);
184     /* compute cache index */
185     if (srcp->sflags & SDISTANT) {
186     int ax, ax1, ax2;
187     double t;
188     ax = srcp->obscache->p.d.ax;
189     if ((ax1 = ax+1) >= 3) ax1 -= 3;
190     if ((ax2 = ax+2) >= 3) ax2 -= 3;
191     t = (srcp->obscache->p.d.o[ax] - r->rorg[ax]) / srcp->sloc[ax];
192     if (t <= FTINY)
193     return(&noobs); /* could happen if ray is outside */
194     ondx = 2*SHADCACHE*(int)(2*SHADCACHE*srcp->obscache->p.d.e1 *
195     (r->rorg[ax1] + t*srcp->sloc[ax1] -
196     srcp->obscache->p.d.o[ax1]));
197     ondx += (int)(2*SHADCACHE*srcp->obscache->p.d.e2 *
198     (r->rorg[ax2] + t*srcp->sloc[ax2] -
199     srcp->obscache->p.d.o[ax2]));
200 schorsch 2.4 if ((ondx < 0) | (ondx >= 4*SHADCACHE*SHADCACHE))
201 greg 2.1 return(&noobs); /* could happen if ray is outside */
202     } else if (srcp->sflags & SFLAT) {
203     FVECT sd;
204     RREAL sd0m, sd1m;
205     sd[0] = -DOT(r->rdir, srcp->obscache->p.f.u);
206     sd[1] = -DOT(r->rdir, srcp->obscache->p.f.v);
207     sd[2] = -DOT(r->rdir, srcp->snorm);
208     if (sd[2] < 0)
209     return(&noobs); /* shouldn't happen */
210     sd0m = ABS(sd[0]);
211     sd1m = ABS(sd[1]);
212     if (sd[2] >= sd0m && sd[2] >= sd1m) {
213     ondx = SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
214     (1. + sd[0]/sd[2]));
215     ondx += (int)(SHADCACHE*(.5-FTINY) *
216     (1. + sd[1]/sd[2]));
217     } else if (sd0m >= sd1m) {
218     ondx = SHADCACHE*SHADCACHE;
219     if (sd[0] < 0)
220     ondx += ((SHADCACHE+1)>>1)*SHADCACHE;
221     ondx += SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
222 greg 2.3 (1. - sd[2]/sd0m));
223 greg 2.1 ondx += (int)(SHADCACHE*(.5-FTINY) *
224     (1. + sd[1]/sd0m));
225     } else /* sd1m > sd0m */ {
226     ondx = SHADCACHE*SHADCACHE +
227     ((SHADCACHE+1)>>1)*SHADCACHE*2;
228     if (sd[1] < 0)
229     ondx += ((SHADCACHE+1)>>1)*SHADCACHE;
230     ondx += SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
231 greg 2.3 (1. - sd[2]/sd1m));
232 greg 2.1 ondx += (int)(SHADCACHE*(.5-FTINY) *
233     (1. + sd[0]/sd1m));
234     }
235 greg 2.3 DCHECK(ondx < 0 | ondx >= SHADCACHE*SHADCACHE*3 +
236     (SHADCACHE&1)*SHADCACHE*4, CONSISTENCY,
237     "flat source cache index out of bounds");
238 greg 2.1 } else /* spherical distribution */ {
239     int ax, ax1, ax2;
240     RREAL amax = 0;
241     for (ax1 = 3; ax1--; )
242     if (ABS(r->rdir[ax1]) > amax) {
243     amax = ABS(r->rdir[ax1]);
244     ax = ax1;
245     }
246     if ((ax1 = ax+1) >= 3) ax1 -= 3;
247     if ((ax2 = ax+2) >= 3) ax2 -= 3;
248     ondx = 2*SHADCACHE*SHADCACHE * ax;
249     if (r->rdir[ax] < 0)
250     ondx += SHADCACHE*SHADCACHE;
251     ondx += SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
252     (1. + r->rdir[ax1]/amax));
253     ondx += (int)(SHADCACHE*(.5-FTINY) *
254     (1. + r->rdir[ax2]/amax));
255 greg 2.3 DCHECK(ondx < 0 | ondx >= SHADCACHE*SHADCACHE*6, CONSISTENCY,
256     "radial source cache index out of bounds");
257 greg 2.1 }
258     /* return cache pointer */
259     return(&srcp->obscache->obs[ondx]);
260     }
261    
262    
263     void /* free obstruction cache */
264     freeobscache(SRCREC *srcp)
265     {
266     if (srcp->obscache == NULL)
267     return;
268     free((void *)srcp->obscache);
269     srcp->obscache = NULL;
270     }
271    
272    
273     void /* record a source blocker */
274     srcblocker(register RAY *r)
275     {
276     OBJREC *m;
277    
278     if (r->robj == OVOID || objptr(r->robj) != r->ro ||
279     isvolume(r->ro->otype))
280     return; /* don't record complex blockers */
281     m = findmaterial(r->ro);
282     if (m == NULL)
283     return; /* no material?! */
284 greg 2.5 if (!isopaque(m->otype))
285 greg 2.1 return; /* material not a reliable blocker */
286     *srcobstructp(r) = r->robj; /* else record obstructor */
287     }
288    
289    
290     int /* check ray against cached blocker */
291     srcblocked(RAY *r)
292     {
293     OBJECT obs = *srcobstructp(r);
294     OBJREC *op;
295    
296     if (obs == OVOID)
297     return(0);
298     op = objptr(obs); /* check for intersection */
299 greg 2.2 return((*ofun[op->otype].funp)(op, r));
300 greg 2.1 }
301    
302    
303     #endif /* SHADCACHE */