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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: srcobstr.c,v 2.4 2004/03/30 16:13:01 schorsch 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 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 if ((ondx < 0) | (ondx >= 4*SHADCACHE*SHADCACHE))
201 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 (1. - sd[2]/sd0m));
223 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 (1. - sd[2]/sd1m));
232 ondx += (int)(SHADCACHE*(.5-FTINY) *
233 (1. + sd[0]/sd1m));
234 }
235 DCHECK(ondx < 0 | ondx >= SHADCACHE*SHADCACHE*3 +
236 (SHADCACHE&1)*SHADCACHE*4, CONSISTENCY,
237 "flat source cache index out of bounds");
238 } 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 DCHECK(ondx < 0 | ondx >= SHADCACHE*SHADCACHE*6, CONSISTENCY,
256 "radial source cache index out of bounds");
257 }
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 if (!isopaque(m->otype))
285 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 return((*ofun[op->otype].funp)(op, r));
300 }
301
302
303 #endif /* SHADCACHE */