ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/srcobstr.c
Revision: 2.2
Committed: Thu Jan 1 19:31:46 2004 UTC (20 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +2 -2 lines
Log Message:
Renamed rview, lam, calc, and neat to rvu, rlam, icalc, and neaten

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: srcobstr.c,v 2.1 2003/12/31 19:38:27 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 = 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 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 sd[2]/sd1m);
232 ondx += (int)(SHADCACHE*(.5-FTINY) *
233 (1. + sd[0]/sd1m));
234 }
235 } else /* spherical distribution */ {
236 int ax, ax1, ax2;
237 RREAL amax = 0;
238 for (ax1 = 3; ax1--; )
239 if (ABS(r->rdir[ax1]) > amax) {
240 amax = ABS(r->rdir[ax1]);
241 ax = ax1;
242 }
243 if ((ax1 = ax+1) >= 3) ax1 -= 3;
244 if ((ax2 = ax+2) >= 3) ax2 -= 3;
245 ondx = 2*SHADCACHE*SHADCACHE * ax;
246 if (r->rdir[ax] < 0)
247 ondx += SHADCACHE*SHADCACHE;
248 ondx += SHADCACHE*(int)(SHADCACHE*(.5-FTINY) *
249 (1. + r->rdir[ax1]/amax));
250 ondx += (int)(SHADCACHE*(.5-FTINY) *
251 (1. + r->rdir[ax2]/amax));
252 }
253 /* return cache pointer */
254 return(&srcp->obscache->obs[ondx]);
255 }
256
257
258 void /* free obstruction cache */
259 freeobscache(SRCREC *srcp)
260 {
261 if (srcp->obscache == NULL)
262 return;
263 free((void *)srcp->obscache);
264 srcp->obscache = NULL;
265 }
266
267
268 void /* record a source blocker */
269 srcblocker(register RAY *r)
270 {
271 OBJREC *m;
272
273 if (r->robj == OVOID || objptr(r->robj) != r->ro ||
274 isvolume(r->ro->otype))
275 return; /* don't record complex blockers */
276 m = findmaterial(r->ro);
277 if (m == NULL)
278 return; /* no material?! */
279 if (!(ofun[m->otype].flags & T_OPAQUE))
280 return; /* material not a reliable blocker */
281 *srcobstructp(r) = r->robj; /* else record obstructor */
282 }
283
284
285 int /* check ray against cached blocker */
286 srcblocked(RAY *r)
287 {
288 OBJECT obs = *srcobstructp(r);
289 OBJREC *op;
290
291 if (obs == OVOID)
292 return(0);
293 op = objptr(obs); /* check for intersection */
294 return((*ofun[op->otype].funp)(op, r));
295 }
296
297
298 #endif /* SHADCACHE */