ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/ambient.c
Revision: 2.6
Committed: Thu Jul 16 12:09:08 1992 UTC (31 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.5: +34 -7 lines
Log Message:
added header and magic number to ambient value file

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 static int ambheadlen; /* length of ambient file header */
45
46 #define AMBFLUSH (BUFSIZ/AMBVALSIZ)
47
48 #define newambval() (AMBVAL *)bmalloc(sizeof(AMBVAL))
49
50 #define newambtree() (AMBTREE *)calloc(8, sizeof(AMBTREE))
51
52
53 setambres(ar) /* set ambient resolution */
54 int ar;
55 {
56 /* set min & max radii */
57 if (ar <= 0) {
58 minarad = 0.0;
59 maxarad = thescene.cusize / 2.0;
60 } else {
61 minarad = thescene.cusize / ar;
62 maxarad = 16.0 * minarad; /* heuristic */
63 if (maxarad > thescene.cusize / 2.0)
64 maxarad = thescene.cusize / 2.0;
65 }
66 if (maxarad <= FTINY)
67 maxarad = .001;
68 }
69
70
71 setambient(afile) /* initialize calculation */
72 char *afile;
73 {
74 extern long ftell();
75 AMBVAL amb;
76 /* init ambient limits */
77 setambres(ambres);
78 /* open ambient file */
79 if (afile != NULL)
80 if ((ambfp = fopen(afile, "r+")) != NULL) {
81 initambfile(0);
82 while (readambval(&amb, ambfp))
83 avinsert(&amb, &atrunk, thescene.cuorg,
84 thescene.cusize);
85 /* align */
86 fseek(ambfp, -((ftell(ambfp)-ambheadlen)%AMBVALSIZ), 1);
87 } else if ((ambfp = fopen(afile, "w")) != NULL)
88 initambfile(1);
89 else {
90 sprintf(errmsg, "cannot open ambient file \"%s\"",
91 afile);
92 error(SYSTEM, errmsg);
93 }
94 }
95
96
97 initambfile(creat) /* initialize ambient file */
98 int creat;
99 {
100 extern char *progname, *octname;
101
102 setbuf(ambfp, bmalloc(BUFSIZ));
103 if (creat) { /* new file */
104 fprintf(ambfp, "%s -av %g %g %g -ab %d -aa %g ",
105 progname, colval(ambval,RED),
106 colval(ambval,GRN), colval(ambval,BLU),
107 ambounce, ambacc);
108 fprintf(ambfp, "-ad %d -as %d -ar %d %s\n",
109 ambdiv, ambssamp, ambres,
110 octname==NULL ? "" : octname);
111 fputformat(AMBFMT, ambfp);
112 putc('\n', ambfp);
113 putambmagic(ambfp);
114 fflush(ambfp);
115 } else if (checkheader(ambfp, AMBFMT, NULL) < 0 || !hasambmagic(ambfp))
116 error(USER, "ambient file format error");
117 ambheadlen = ftell(ambfp);
118 }
119
120
121 ambnotify(obj) /* record new modifier */
122 OBJECT obj;
123 {
124 static int hitlimit = 0;
125 register OBJREC *o = objptr(obj);
126 register char **amblp;
127
128 if (hitlimit || !ismodifier(o->otype))
129 return;
130 for (amblp = amblist; *amblp != NULL; amblp++)
131 if (!strcmp(o->oname, *amblp)) {
132 if (ambset[0] >= MAXASET) {
133 error(WARNING, "too many modifiers in ambient list");
134 hitlimit++;
135 return; /* should this be fatal? */
136 }
137 insertelem(ambset, obj);
138 return;
139 }
140 }
141
142
143 ambient(acol, r) /* compute ambient component for ray */
144 COLOR acol;
145 register RAY *r;
146 {
147 static int rdepth = 0; /* ambient recursion */
148 double d;
149
150 if (ambdiv <= 0) /* no ambient calculation */
151 goto dumbamb;
152 /* check number of bounces */
153 if (rdepth >= ambounce)
154 goto dumbamb;
155 /* check ambient list */
156 if (ambincl != -1 && r->ro != NULL &&
157 ambincl != inset(ambset, r->ro->omod))
158 goto dumbamb;
159
160 if (ambacc <= FTINY) { /* no ambient storage */
161 rdepth++;
162 d = doambient(acol, r, r->rweight, NULL, NULL);
163 rdepth--;
164 if (d == 0.0)
165 goto dumbamb;
166 return;
167 }
168 /* get ambient value */
169 setcolor(acol, 0.0, 0.0, 0.0);
170 d = sumambient(acol, r, rdepth,
171 &atrunk, thescene.cuorg, thescene.cusize);
172 if (d > FTINY)
173 scalecolor(acol, 1.0/d);
174 else {
175 d = makeambient(acol, r, rdepth++);
176 rdepth--;
177 }
178 if (d > FTINY)
179 return;
180 dumbamb: /* return global value */
181 copycolor(acol, ambval);
182 }
183
184
185 double
186 sumambient(acol, r, al, at, c0, s) /* get interpolated ambient value */
187 COLOR acol;
188 register RAY *r;
189 int al;
190 AMBTREE *at;
191 FVECT c0;
192 double s;
193 {
194 extern double sqrt();
195 double d, e1, e2, wt, wsum;
196 COLOR ct;
197 FVECT ck0;
198 int i;
199 register int j;
200 register AMBVAL *av;
201 /* do this node */
202 wsum = 0.0;
203 for (av = at->alist; av != NULL; av = av->next) {
204 /*
205 * Ambient level test.
206 */
207 if (av->lvl > al || av->weight < r->rweight-FTINY)
208 continue;
209 /*
210 * Ambient radius test.
211 */
212 e1 = 0.0;
213 for (j = 0; j < 3; j++) {
214 d = av->pos[j] - r->rop[j];
215 e1 += d * d;
216 }
217 e1 /= av->rad * av->rad;
218 if (e1 > ambacc*ambacc*1.21)
219 continue;
220 /*
221 * Normal direction test.
222 */
223 e2 = (1.0 - DOT(av->dir, r->ron)) * r->rweight;
224 if (e2 < 0.0) e2 = 0.0;
225 if (e1 + e2 > ambacc*ambacc*1.21)
226 continue;
227 /*
228 * Ray behind test.
229 */
230 d = 0.0;
231 for (j = 0; j < 3; j++)
232 d += (r->rop[j] - av->pos[j]) *
233 (av->dir[j] + r->ron[j]);
234 if (d*0.5 < -minarad*ambacc-.001)
235 continue;
236 /*
237 * Jittering final test reduces image artifacts.
238 */
239 wt = sqrt(e1) + sqrt(e2);
240 wt *= .9 + .2*urand(9015+samplendx);
241 if (wt > ambacc)
242 continue;
243 if (wt <= 1e-3)
244 wt = 1e3;
245 else
246 wt = 1.0 / wt;
247 wsum += wt;
248 extambient(ct, av, r->rop, r->ron);
249 scalecolor(ct, wt);
250 addcolor(acol, ct);
251 }
252 if (at->kid == NULL)
253 return(wsum);
254 /* do children */
255 s *= 0.5;
256 for (i = 0; i < 8; i++) {
257 for (j = 0; j < 3; j++) {
258 ck0[j] = c0[j];
259 if (1<<j & i)
260 ck0[j] += s;
261 if (r->rop[j] < ck0[j] - OCTSCALE*s)
262 break;
263 if (r->rop[j] > ck0[j] + (1.0+OCTSCALE)*s)
264 break;
265 }
266 if (j == 3)
267 wsum += sumambient(acol, r, al, at->kid+i, ck0, s);
268 }
269 return(wsum);
270 }
271
272
273 double
274 makeambient(acol, r, al) /* make a new ambient value */
275 COLOR acol;
276 register RAY *r;
277 int al;
278 {
279 AMBVAL amb;
280 FVECT gp, gd;
281 /* compute weight */
282 amb.weight = pow(AVGREFL, (double)al);
283 if (r->rweight < 0.2*amb.weight) /* heuristic */
284 amb.weight = r->rweight;
285 /* compute ambient */
286 amb.rad = doambient(acol, r, amb.weight, gp, gd);
287 if (amb.rad == 0.0)
288 return(0.0);
289 /* store it */
290 VCOPY(amb.pos, r->rop);
291 VCOPY(amb.dir, r->ron);
292 amb.lvl = al;
293 copycolor(amb.val, acol);
294 VCOPY(amb.gpos, gp);
295 VCOPY(amb.gdir, gd);
296 /* insert into tree */
297 avinsert(&amb, &atrunk, thescene.cuorg, thescene.cusize);
298 avsave(&amb); /* write to file */
299 return(amb.rad);
300 }
301
302
303 extambient(cr, ap, pv, nv) /* extrapolate value at pv, nv */
304 COLOR cr;
305 register AMBVAL *ap;
306 FVECT pv, nv;
307 {
308 FVECT v1, v2;
309 register int i;
310 double d;
311
312 d = 1.0; /* zeroeth order */
313 /* gradient due to translation */
314 for (i = 0; i < 3; i++)
315 d += ap->gpos[i]*(pv[i]-ap->pos[i]);
316 /* gradient due to rotation */
317 VCOPY(v1, ap->dir);
318 fcross(v2, v1, nv);
319 d += DOT(ap->gdir, v2);
320 if (d <= 0.0) {
321 setcolor(cr, 0.0, 0.0, 0.0);
322 return;
323 }
324 copycolor(cr, ap->val);
325 scalecolor(cr, d);
326 }
327
328
329 static
330 avsave(av) /* save an ambient value */
331 AMBVAL *av;
332 {
333 static int nunflshed = 0;
334
335 if (ambfp == NULL)
336 return;
337 if (writambval(av, ambfp) < 0)
338 goto writerr;
339 if (++nunflshed >= AMBFLUSH) {
340 if (fflush(ambfp) == EOF)
341 goto writerr;
342 nunflshed = 0;
343 }
344 return;
345 writerr:
346 error(SYSTEM, "error writing ambient file");
347 }
348
349
350 static
351 avinsert(aval, at, c0, s) /* insert ambient value in a tree */
352 AMBVAL *aval;
353 register AMBTREE *at;
354 FVECT c0;
355 double s;
356 {
357 FVECT ck0;
358 int branch;
359 register AMBVAL *av;
360 register int i;
361
362 if ((av = newambval()) == NULL)
363 goto memerr;
364 copystruct(av, aval);
365 VCOPY(ck0, c0);
366 while (s*(OCTSCALE/2) > av->rad*ambacc) {
367 if (at->kid == NULL)
368 if ((at->kid = newambtree()) == NULL)
369 goto memerr;
370 s *= 0.5;
371 branch = 0;
372 for (i = 0; i < 3; i++)
373 if (av->pos[i] > ck0[i] + s) {
374 ck0[i] += s;
375 branch |= 1 << i;
376 }
377 at = at->kid + branch;
378 }
379 av->next = at->alist;
380 at->alist = av;
381 return;
382 memerr:
383 error(SYSTEM, "out of memory in avinsert");
384 }