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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: srcobstr.c,v 2.14 2007/10/08 18:07:57 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 "rtotypes.h"
15
16 #include "source.h"
17
18 #define ABS(x) ((x)>0 ? (x) : -(x))
19
20
21 #if SHADCACHE /* preemptive shadow checking */
22
23
24 OBJECT * antimodlist = NULL; /* set of clipped materials */
25
26
27 static int /* cast source ray to first blocker */
28 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 rayorigin(&rt, PRIMARY, NULL, NULL);
36 /* 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 /* record blocker */
48 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 }
56
57
58 void /* initialize occlusion cache */
59 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 if (srcp->sflags & (SSKIP|SPROX|SSPOT|SVIRTUAL))
69 return; /* don't cache these */
70 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 d = 1. - 2./SHADCACHE*(j+.5);
151 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 static RNUMBER lastrno = ~0;
184 static OBJECT noobs;
185 static OBJECT *lastobjp;
186 SRCREC *srcp;
187 int ondx;
188
189 noobs = OVOID;
190 if (r->rno == lastrno)
191 return lastobjp; /* just recall last pointer */
192 DCHECK(r->rsrc < 0, CONSISTENCY,
193 "srcobstructp() called with unaimed ray");
194 lastrno = r->rno;
195 lastobjp = &noobs;
196 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 if ((ondx < 0) | (ondx >= 4*SHADCACHE*SHADCACHE))
218 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 (1. - sd[2]/sd0m));
240 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 (1. - sd[2]/sd1m));
249 ondx += (int)(SHADCACHE*(.5-FTINY) *
250 (1. + sd[0]/sd1m));
251 }
252 DCHECK((ondx < 0) | (ondx >= SHADCACHE*SHADCACHE*3 +
253 (SHADCACHE&1)*SHADCACHE*4), CONSISTENCY,
254 "flat source cache index out of bounds");
255 } 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 DCHECK((ondx < 0) | (ondx >= SHADCACHE*SHADCACHE*6), CONSISTENCY,
273 "radial source cache index out of bounds");
274 }
275 /* return cache pointer */
276 return(lastobjp = &srcp->obscache->obs[ondx]);
277 }
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 int /* record a source blocker */
291 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 return(0); /* don't record complex blockers */
298 if (r->rsrc < 0 || source[r->rsrc].so == r->ro)
299 return(0); /* just a mistake, that's all */
300 if (antimodlist != NULL && inset(antimodlist, r->ro->omod))
301 return(0); /* could be clipped */
302 m = findmaterial(r->ro);
303 if (m == NULL)
304 return(0); /* no material?! */
305 if (!isopaque(m->otype))
306 return(0); /* material not a reliable blocker */
307 *srcobstructp(r) = r->robj; /* else record obstructor */
308 return(1);
309 }
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 op = objptr(obs); /* check blocker intersection */
321 if (!(*ofun[op->otype].funp)(op, r))
322 return(0);
323 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 }
331
332
333 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 #endif /* SHADCACHE */