ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/ambient.c
Revision: 2.4
Committed: Fri Apr 10 16:14:34 1992 UTC (32 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.3: +2 -0 lines
Log Message:
avoid zero maxarad for scenes with no local objects

File Contents

# Content
1 /* Copyright (c) 1991 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * ambient.c - routines dealing with ambient (inter-reflected) component.
9 *
10 * The macro AMBFLUSH (if defined) is the number of ambient values
11 * to wait before flushing to the ambient file.
12 *
13 * 5/9/86
14 */
15
16 #include "ray.h"
17
18 #include "octree.h"
19
20 #include "otypes.h"
21
22 #include "ambient.h"
23
24 #include "random.h"
25
26 #define OCTSCALE 0.5 /* ceil((valid rad.)/(cube size)) */
27
28 typedef struct ambtree {
29 AMBVAL *alist; /* ambient value list */
30 struct ambtree *kid; /* 8 child nodes */
31 } AMBTREE; /* ambient octree */
32
33 extern CUBE thescene; /* contains space boundaries */
34
35 #define MAXASET 511 /* maximum number of elements in ambient set */
36 OBJECT ambset[MAXASET+1]={0}; /* ambient include/exclude set */
37
38 double maxarad; /* maximum ambient radius */
39 double minarad; /* minimum ambient radius */
40
41 static AMBTREE atrunk; /* our ambient trunk node */
42
43 static FILE *ambfp = NULL; /* ambient file pointer */
44
45 #define newambval() (AMBVAL *)bmalloc(sizeof(AMBVAL))
46
47 #define newambtree() (AMBTREE *)calloc(8, sizeof(AMBTREE))
48
49
50 setambres(ar) /* set ambient resolution */
51 int ar;
52 {
53 /* set min & max radii */
54 if (ar <= 0) {
55 minarad = 0.0;
56 maxarad = thescene.cusize / 2.0;
57 } else {
58 minarad = thescene.cusize / ar;
59 maxarad = 16.0 * minarad; /* heuristic */
60 if (maxarad > thescene.cusize / 2.0)
61 maxarad = thescene.cusize / 2.0;
62 }
63 if (maxarad <= FTINY)
64 maxarad = .001;
65 }
66
67
68 setambient(afile) /* initialize calculation */
69 char *afile;
70 {
71 long ftell();
72 AMBVAL amb;
73 /* init ambient limits */
74 setambres(ambres);
75 /* open ambient file */
76 if (afile != NULL)
77 if ((ambfp = fopen(afile, "r+")) != NULL) {
78 while (fread((char *)&amb,sizeof(AMBVAL),1,ambfp) == 1)
79 avinsert(&amb, &atrunk, thescene.cuorg,
80 thescene.cusize);
81 /* align */
82 fseek(ambfp, -(ftell(ambfp)%sizeof(AMBVAL)), 1);
83 } else if ((ambfp = fopen(afile, "w")) == NULL) {
84 sprintf(errmsg, "cannot open ambient file \"%s\"",
85 afile);
86 error(SYSTEM, errmsg);
87 }
88 }
89
90
91 ambnotify(obj) /* record new modifier */
92 OBJECT obj;
93 {
94 static int hitlimit = 0;
95 register OBJREC *o = objptr(obj);
96 register char **amblp;
97
98 if (hitlimit || !ismodifier(o->otype))
99 return;
100 for (amblp = amblist; *amblp != NULL; amblp++)
101 if (!strcmp(o->oname, *amblp)) {
102 if (ambset[0] >= MAXASET) {
103 error(WARNING, "too many modifiers in ambient list");
104 hitlimit++;
105 return; /* should this be fatal? */
106 }
107 insertelem(ambset, obj);
108 return;
109 }
110 }
111
112
113 ambient(acol, r) /* compute ambient component for ray */
114 COLOR acol;
115 register RAY *r;
116 {
117 static int rdepth = 0; /* ambient recursion */
118 double d;
119
120 if (ambdiv <= 0) /* no ambient calculation */
121 goto dumbamb;
122 /* check number of bounces */
123 if (rdepth >= ambounce)
124 goto dumbamb;
125 /* check ambient list */
126 if (ambincl != -1 && r->ro != NULL &&
127 ambincl != inset(ambset, r->ro->omod))
128 goto dumbamb;
129
130 if (ambacc <= FTINY) { /* no ambient storage */
131 rdepth++;
132 d = doambient(acol, r, r->rweight, NULL, NULL);
133 rdepth--;
134 if (d == 0.0)
135 goto dumbamb;
136 return;
137 }
138 /* get ambient value */
139 setcolor(acol, 0.0, 0.0, 0.0);
140 d = sumambient(acol, r, rdepth,
141 &atrunk, thescene.cuorg, thescene.cusize);
142 if (d > FTINY)
143 scalecolor(acol, 1.0/d);
144 else {
145 d = makeambient(acol, r, rdepth++);
146 rdepth--;
147 }
148 if (d > FTINY)
149 return;
150 dumbamb: /* return global value */
151 copycolor(acol, ambval);
152 }
153
154
155 double
156 sumambient(acol, r, al, at, c0, s) /* get interpolated ambient value */
157 COLOR acol;
158 register RAY *r;
159 int al;
160 AMBTREE *at;
161 FVECT c0;
162 double s;
163 {
164 extern double sqrt();
165 double d, e1, e2, wt, wsum;
166 COLOR ct;
167 FVECT ck0;
168 int i;
169 register int j;
170 register AMBVAL *av;
171 /* do this node */
172 wsum = 0.0;
173 for (av = at->alist; av != NULL; av = av->next) {
174 /*
175 * Ambient level test.
176 */
177 if (av->lvl > al || av->weight < r->rweight-FTINY)
178 continue;
179 /*
180 * Ambient radius test.
181 */
182 e1 = 0.0;
183 for (j = 0; j < 3; j++) {
184 d = av->pos[j] - r->rop[j];
185 e1 += d * d;
186 }
187 e1 /= av->rad * av->rad;
188 if (e1 > ambacc*ambacc*1.21)
189 continue;
190 /*
191 * Normal direction test.
192 */
193 e2 = (1.0 - DOT(av->dir, r->ron)) * r->rweight;
194 if (e2 < 0.0) e2 = 0.0;
195 if (e1 + e2 > ambacc*ambacc*1.21)
196 continue;
197 /*
198 * Ray behind test.
199 */
200 d = 0.0;
201 for (j = 0; j < 3; j++)
202 d += (r->rop[j] - av->pos[j]) *
203 (av->dir[j] + r->ron[j]);
204 if (d*0.5 < -minarad*ambacc-.001)
205 continue;
206 /*
207 * Jittering final test reduces image artifacts.
208 */
209 wt = sqrt(e1) + sqrt(e2);
210 wt *= .9 + .2*urand(9015+samplendx);
211 if (wt > ambacc)
212 continue;
213 if (wt <= 1e-3)
214 wt = 1e3;
215 else
216 wt = 1.0 / wt;
217 wsum += wt;
218 extambient(ct, av, r->rop, r->ron);
219 scalecolor(ct, wt);
220 addcolor(acol, ct);
221 }
222 if (at->kid == NULL)
223 return(wsum);
224 /* do children */
225 s *= 0.5;
226 for (i = 0; i < 8; i++) {
227 for (j = 0; j < 3; j++) {
228 ck0[j] = c0[j];
229 if (1<<j & i)
230 ck0[j] += s;
231 if (r->rop[j] < ck0[j] - OCTSCALE*s)
232 break;
233 if (r->rop[j] > ck0[j] + (1.0+OCTSCALE)*s)
234 break;
235 }
236 if (j == 3)
237 wsum += sumambient(acol, r, al, at->kid+i, ck0, s);
238 }
239 return(wsum);
240 }
241
242
243 double
244 makeambient(acol, r, al) /* make a new ambient value */
245 COLOR acol;
246 register RAY *r;
247 int al;
248 {
249 AMBVAL amb;
250 FVECT gp, gd;
251 /* compute weight */
252 amb.weight = pow(AVGREFL, (double)al);
253 if (r->rweight < 0.2*amb.weight) /* heuristic */
254 amb.weight = r->rweight;
255 /* compute ambient */
256 amb.rad = doambient(acol, r, amb.weight, gp, gd);
257 if (amb.rad == 0.0)
258 return(0.0);
259 /* store it */
260 VCOPY(amb.pos, r->rop);
261 VCOPY(amb.dir, r->ron);
262 amb.lvl = al;
263 copycolor(amb.val, acol);
264 VCOPY(amb.gpos, gp);
265 VCOPY(amb.gdir, gd);
266 /* insert into tree */
267 avinsert(&amb, &atrunk, thescene.cuorg, thescene.cusize);
268 avsave(&amb); /* write to file */
269 return(amb.rad);
270 }
271
272
273 extambient(cr, ap, pv, nv) /* extrapolate value at pv, nv */
274 COLOR cr;
275 register AMBVAL *ap;
276 FVECT pv, nv;
277 {
278 FVECT v1, v2;
279 register int i;
280 double d;
281
282 d = 1.0; /* zeroeth order */
283 /* gradient due to translation */
284 for (i = 0; i < 3; i++)
285 d += ap->gpos[i]*(pv[i]-ap->pos[i]);
286 /* gradient due to rotation */
287 VCOPY(v1, ap->dir);
288 fcross(v2, v1, nv);
289 d += DOT(ap->gdir, v2);
290 if (d <= 0.0) {
291 setcolor(cr, 0.0, 0.0, 0.0);
292 return;
293 }
294 copycolor(cr, ap->val);
295 scalecolor(cr, d);
296 }
297
298
299 static
300 avsave(av) /* save an ambient value */
301 AMBVAL *av;
302 {
303 #ifdef AMBFLUSH
304 static int nunflshed = 0;
305 #endif
306 if (ambfp == NULL)
307 return;
308 if (fwrite((char *)av, sizeof(AMBVAL), 1, ambfp) != 1)
309 goto writerr;
310 #ifdef AMBFLUSH
311 if (++nunflshed >= AMBFLUSH) {
312 if (fflush(ambfp) == EOF)
313 goto writerr;
314 nunflshed = 0;
315 }
316 #endif
317 return;
318 writerr:
319 error(SYSTEM, "error writing ambient file");
320 }
321
322
323 static
324 avinsert(aval, at, c0, s) /* insert ambient value in a tree */
325 AMBVAL *aval;
326 register AMBTREE *at;
327 FVECT c0;
328 double s;
329 {
330 FVECT ck0;
331 int branch;
332 register AMBVAL *av;
333 register int i;
334
335 if ((av = newambval()) == NULL)
336 goto memerr;
337 copystruct(av, aval);
338 VCOPY(ck0, c0);
339 while (s*(OCTSCALE/2) > av->rad*ambacc) {
340 if (at->kid == NULL)
341 if ((at->kid = newambtree()) == NULL)
342 goto memerr;
343 s *= 0.5;
344 branch = 0;
345 for (i = 0; i < 3; i++)
346 if (av->pos[i] > ck0[i] + s) {
347 ck0[i] += s;
348 branch |= 1 << i;
349 }
350 at = at->kid + branch;
351 }
352 av->next = at->alist;
353 at->alist = av;
354 return;
355 memerr:
356 error(SYSTEM, "out of memory in avinsert");
357 }