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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: srcobstr.c,v 2.5 2004/06/22 13:40:54 greg Exp $";
3 #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 d = 1. - 2./SHADCACHE*(j+.5);
140 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 unsigned long lastrno = ~0;
173 static OBJECT noobs;
174 static OBJECT *lastobjp;
175 SRCREC *srcp;
176 int ondx;
177
178 noobs = OVOID;
179 if (r->rno == lastrno)
180 return lastobjp; /* just recall last pointer */
181 DCHECK(r->rsrc < 0, CONSISTENCY,
182 "srcobstructp() called with unaimed ray");
183 lastrno = r->rno;
184 lastobjp = &noobs;
185 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 if ((ondx < 0) | (ondx >= 4*SHADCACHE*SHADCACHE))
207 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 (1. - sd[2]/sd0m));
229 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 (1. - sd[2]/sd1m));
238 ondx += (int)(SHADCACHE*(.5-FTINY) *
239 (1. + sd[0]/sd1m));
240 }
241 DCHECK((ondx < 0) | (ondx >= SHADCACHE*SHADCACHE*3 +
242 (SHADCACHE&1)*SHADCACHE*4), CONSISTENCY,
243 "flat source cache index out of bounds");
244 } 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 DCHECK((ondx < 0) | (ondx >= SHADCACHE*SHADCACHE*6), CONSISTENCY,
262 "radial source cache index out of bounds");
263 }
264 /* return cache pointer */
265 return(lastobjp = &srcp->obscache->obs[ondx]);
266 }
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 if (!isopaque(m->otype))
291 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 return((*ofun[op->otype].funp)(op, r));
306 }
307
308
309 #endif /* SHADCACHE */