ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/ambient.c
(Generate patch)

Comparing ray/src/rt/ambient.c (file contents):
Revision 1.14 by greg, Fri Jun 7 10:04:29 1991 UTC vs.
Revision 2.18 by greg, Fri Jan 29 12:02:23 1993 UTC

# Line 1 | Line 1
1 < /* Copyright (c) 1991 Regents of the University of California */
1 > /* Copyright (c) 1993 Regents of the University of California */
2  
3   #ifndef lint
4   static char SCCSid[] = "$SunId$ LBL";
# Line 6 | Line 6 | static char SCCSid[] = "$SunId$ LBL";
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
9   */
10  
11   #include  "ray.h"
# Line 23 | Line 18 | static char SCCSid[] = "$SunId$ LBL";
18  
19   #include  "random.h"
20  
21 < #define  OCTSCALE       0.5     /* ceil((valid rad.)/(cube size)) */
21 > #define  OCTSCALE       0.5     /* ceil((valid rad.)/(cube size)) */
22  
23   typedef struct ambtree {
24 <        AMBVAL  *alist;         /* ambient value list */
25 <        struct ambtree  *kid;   /* 8 child nodes */
24 >        AMBVAL  *alist;         /* ambient value list */
25 >        struct ambtree  *kid;   /* 8 child nodes */
26   }  AMBTREE;                     /* ambient octree */
27  
28   extern CUBE  thescene;          /* contains space boundaries */
29  
30 < #define  MAXASET        511     /* maximum number of elements in ambient set */
31 < OBJECT  ambset[MAXASET+1]={0};  /* ambient include/exclude set */
30 > #define  MAXASET        511     /* maximum number of elements in ambient set */
31 > OBJECT  ambset[MAXASET+1]={0};  /* ambient include/exclude set */
32  
33 < double  maxarad;                /* maximum ambient radius */
34 < double  minarad;                /* minimum ambient radius */
33 > double  maxarad;                /* maximum ambient radius */
34 > double  minarad;                /* minimum ambient radius */
35  
36 < static AMBTREE  atrunk;         /* our ambient trunk node */
36 > static AMBTREE  atrunk;         /* our ambient trunk node */
37  
38   static FILE  *ambfp = NULL;     /* ambient file pointer */
39 + static int  nunflshed = 0;      /* number of unflushed ambient values */
40  
41 < #define  newambval()    (AMBVAL *)bmalloc(sizeof(AMBVAL))
41 > #define  AMBFLUSH       (BUFSIZ/AMBVALSIZ)
42  
43 < #define  newambtree()   (AMBTREE *)calloc(8, sizeof(AMBTREE))
43 > #define  newambval()    (AMBVAL *)bmalloc(sizeof(AMBVAL))
44  
45 + #define  newambtree()   (AMBTREE *)calloc(8, sizeof(AMBTREE))
46  
47 < setambient(afile)                       /* initialize calculation */
48 < char  *afile;
47 > extern long  ftell(), lseek();
48 > static int  initambfile(), avsave(), avinsert();
49 >
50 >
51 > setambres(ar)                           /* set ambient resolution */
52 > int  ar;
53   {
54 <        long  ftell();
55 <        AMBVAL  amb;
54 >                                                /* set min & max radii */
55 >        if (ar <= 0) {
56 >                minarad = 0.0;
57 >                maxarad = thescene.cusize / 2.0;
58 >        } else {
59 >                minarad = thescene.cusize / ar;
60 >                maxarad = 16.0 * minarad;               /* heuristic */
61 >                if (maxarad > thescene.cusize / 2.0)
62 >                        maxarad = thescene.cusize / 2.0;
63 >        }
64 >        if (maxarad <= FTINY)
65 >                maxarad = .001;
66 > }
67  
56        maxarad = thescene.cusize / 2.0;                /* maximum radius */
57                                                        /* minimum radius */
58        minarad = ambres > 0 ? thescene.cusize/ambres : 0.0;
68  
69 <                                        /* open ambient file */
70 <        if (afile != NULL)
69 > setambient(afile)                       /* initialize calculation */
70 > char  *afile;
71 > {
72 >        long  headlen;
73 >        AMBVAL  amb;
74 >                                                /* init ambient limits */
75 >        setambres(ambres);
76 >                                                /* open ambient file */
77 >        if (afile != NULL) {
78                  if ((ambfp = fopen(afile, "r+")) != NULL) {
79 <                        while (fread((char *)&amb,sizeof(AMBVAL),1,ambfp) == 1)
79 >                        initambfile(0);
80 >                        headlen = ftell(ambfp);
81 >                        while (readambval(&amb, ambfp))
82                                  avinsert(&amb, &atrunk, thescene.cuorg,
83                                                  thescene.cusize);
84                                                          /* align */
85 <                        fseek(ambfp, -(ftell(ambfp)%sizeof(AMBVAL)), 1);
86 <                } else if ((ambfp = fopen(afile, "w")) == NULL) {
85 >                        fseek(ambfp, -((ftell(ambfp)-headlen)%AMBVALSIZ), 1);
86 >                } else if ((ambfp = fopen(afile, "w+")) != NULL)
87 >                        initambfile(1);
88 >                else {
89                          sprintf(errmsg, "cannot open ambient file \"%s\"",
90                                          afile);
91                          error(SYSTEM, errmsg);
92                  }
93 +                nunflshed++;    /* lie */
94 +                ambsync();
95 +        }
96   }
97  
98  
99   ambnotify(obj)                  /* record new modifier */
100 < OBJECT  obj;
100 > OBJECT  obj;
101   {
102          static int  hitlimit = 0;
103 <        register OBJREC  *o = objptr(obj);
103 >        register OBJREC  *o = objptr(obj);
104          register char  **amblp;
105  
106          if (hitlimit || !ismodifier(o->otype))
# Line 100 | Line 123 | COLOR  acol;
123   register RAY  *r;
124   {
125          static int  rdepth = 0;                 /* ambient recursion */
126 <        double  wsum;
126 >        double  d;
127  
105        rdepth++;                               /* increment level */
106
128          if (ambdiv <= 0)                        /* no ambient calculation */
129                  goto dumbamb;
130                                                  /* check number of bounces */
131 <        if (rdepth > ambounce)
131 >        if (rdepth >= ambounce)
132                  goto dumbamb;
133                                                  /* check ambient list */
134          if (ambincl != -1 && r->ro != NULL &&
# Line 115 | Line 136 | register RAY  *r;
136                  goto dumbamb;
137  
138          if (ambacc <= FTINY) {                  /* no ambient storage */
139 <                if (doambient(acol, r, NULL, NULL) == 0.0)
139 >                rdepth++;
140 >                d = doambient(acol, r, r->rweight, NULL, NULL);
141 >                rdepth--;
142 >                if (d == 0.0)
143                          goto dumbamb;
144 <                goto done;
144 >                return;
145          }
146                                                  /* get ambient value */
147          setcolor(acol, 0.0, 0.0, 0.0);
148 <        wsum = sumambient(acol, r, &atrunk, thescene.cuorg, thescene.cusize);
149 <        if (wsum > FTINY)
150 <                scalecolor(acol, 1.0/wsum);
151 <        else if (makeambient(acol, r) == 0.0)
152 <                goto dumbamb;
153 <        goto done;
154 <
148 >        d = sumambient(acol, r, rdepth,
149 >                        &atrunk, thescene.cuorg, thescene.cusize);
150 >        if (d > FTINY)
151 >                scalecolor(acol, 1.0/d);
152 >        else {
153 >                d = makeambient(acol, r, rdepth++);
154 >                rdepth--;
155 >        }
156 >        if (d > FTINY)
157 >                return;
158   dumbamb:                                        /* return global value */
159          copycolor(acol, ambval);
133 done:                                           /* must finish here! */
134        rdepth--;
160   }
161  
162  
163   double
164 < sumambient(acol, r, at, c0, s)          /* get interpolated ambient value */
164 > sumambient(acol, r, al, at, c0, s)      /* get interpolated ambient value */
165   COLOR  acol;
166   register RAY  *r;
167 < AMBTREE  *at;
167 > int  al;
168 > AMBTREE  *at;
169   FVECT  c0;
170 < double  s;
170 > double  s;
171   {
172 <        extern double  sqrt();
147 <        double  d, e1, e2, wt, wsum;
172 >        double  d, e1, e2, wt, wsum;
173          COLOR  ct;
174          FVECT  ck0;
175          int  i;
176          register int  j;
177 <        register AMBVAL  *av;
177 >        register AMBVAL  *av;
178                                          /* do this node */
179          wsum = 0.0;
180          for (av = at->alist; av != NULL; av = av->next) {
181                  /*
182 <                 *  Ray strength test.
182 >                 *  Ambient level test.
183                   */
184 <                if (av->lvl > r->rlvl || av->weight < r->rweight-FTINY)
184 >                if (av->lvl > al || av->weight < r->rweight-FTINY)
185                          continue;
186                  /*
187                   *  Ambient radius test.
# Line 183 | Line 208 | double  s;
208                  for (j = 0; j < 3; j++)
209                          d += (r->rop[j] - av->pos[j]) *
210                                          (av->dir[j] + r->ron[j]);
211 <                if (d*0.5 < -minarad*ambacc)
211 >                if (d*0.5 < -minarad*ambacc-.001)
212                          continue;
213                  /*
214                   *  Jittering final test reduces image artifacts.
215                   */
216                  wt = sqrt(e1) + sqrt(e2);
217 <                wt *= .9 + .2*frandom();
217 >                wt *= .9 + .2*urand(9015+samplendx);
218                  if (wt > ambacc)
219                          continue;
220                  if (wt <= 1e-3)
# Line 197 | Line 222 | double  s;
222                  else
223                          wt = 1.0 / wt;
224                  wsum += wt;
225 <                copycolor(ct, av->val);
225 >                extambient(ct, av, r->rop, r->ron);
226                  scalecolor(ct, wt);
227                  addcolor(acol, ct);
228          }
# Line 216 | Line 241 | double  s;
241                                  break;
242                  }
243                  if (j == 3)
244 <                        wsum += sumambient(acol, r, at->kid+i, ck0, s);
244 >                        wsum += sumambient(acol, r, al, at->kid+i, ck0, s);
245          }
246          return(wsum);
247   }
248  
249  
250   double
251 < makeambient(acol, r)            /* make a new ambient value */
251 > makeambient(acol, r, al)        /* make a new ambient value */
252   COLOR  acol;
253   register RAY  *r;
254 + int  al;
255   {
256 <        AMBVAL  amb;
256 >        AMBVAL  amb;
257          FVECT   gp, gd;
258 <
259 <        amb.rad = doambient(acol, r, gp, gd);   /* compute ambient */
258 >                                                /* compute weight */
259 >        amb.weight = pow(AVGREFL, (double)al);
260 >        if (r->rweight < 0.2*amb.weight)        /* heuristic */
261 >                amb.weight = r->rweight;
262 >                                                /* compute ambient */
263 >        amb.rad = doambient(acol, r, amb.weight, gp, gd);
264          if (amb.rad == 0.0)
265                  return(0.0);
266                                                  /* store it */
267          VCOPY(amb.pos, r->rop);
268          VCOPY(amb.dir, r->ron);
269 <        amb.lvl = r->rlvl;
240 <        amb.weight = r->rweight;
269 >        amb.lvl = al;
270          copycolor(amb.val, acol);
271          VCOPY(amb.gpos, gp);
272          VCOPY(amb.gdir, gd);
273                                                  /* insert into tree */
274 <        avinsert(&amb, &atrunk, thescene.cuorg, thescene.cusize);
246 <        avsave(&amb);                           /* write to file */
274 >        avsave(&amb);                           /* and save to file */
275          return(amb.rad);
276   }
277  
278  
279 + extambient(cr, ap, pv, nv)              /* extrapolate value at pv, nv */
280 + COLOR  cr;
281 + register AMBVAL  *ap;
282 + FVECT  pv, nv;
283 + {
284 +        FVECT  v1, v2;
285 +        register int  i;
286 +        double  d;
287 +
288 +        d = 1.0;                        /* zeroeth order */
289 +                                        /* gradient due to translation */
290 +        for (i = 0; i < 3; i++)
291 +                d += ap->gpos[i]*(pv[i]-ap->pos[i]);
292 +                                        /* gradient due to rotation */
293 +        VCOPY(v1, ap->dir);
294 +        fcross(v2, v1, nv);
295 +        d += DOT(ap->gdir, v2);
296 +        if (d <= 0.0) {
297 +                setcolor(cr, 0.0, 0.0, 0.0);
298 +                return;
299 +        }
300 +        copycolor(cr, ap->val);
301 +        scalecolor(cr, d);
302 + }
303 +
304 +
305   static
306 < avsave(av)                              /* save an ambient value */
307 < AMBVAL  *av;
306 > initambfile(creat)              /* initialize ambient file */
307 > int  creat;
308   {
309 < #ifdef  AMBFLUSH
310 <        static int  nunflshed = 0;
309 >        extern char  *progname, *octname, VersionID[];
310 >
311 > #ifdef MSDOS
312 >        setmode(fileno(ambfp), O_BINARY);
313   #endif
314 +        setbuf(ambfp, bmalloc(BUFSIZ));
315 +        if (creat) {                    /* new file */
316 +                fprintf(ambfp, "%s -av %g %g %g -ab %d -aa %g ",
317 +                                progname, colval(ambval,RED),
318 +                                colval(ambval,GRN), colval(ambval,BLU),
319 +                                ambounce, ambacc);
320 +                fprintf(ambfp, "-ad %d -as %d -ar %d %s\n",
321 +                                ambdiv, ambssamp, ambres,
322 +                                octname==NULL ? "" : octname);
323 +                fprintf(ambfp, "SOFTWARE= %s\n", VersionID);
324 +                fputformat(AMBFMT, ambfp);
325 +                putc('\n', ambfp);
326 +                putambmagic(ambfp);
327 +        } else if (checkheader(ambfp, AMBFMT, NULL) < 0 || !hasambmagic(ambfp))
328 +                error(USER, "bad ambient file");
329 + }
330 +
331 +
332 + static
333 + avsave(av)                              /* insert and save an ambient value */
334 + AMBVAL  *av;
335 + {
336 +        avinsert(av, &atrunk, thescene.cuorg, thescene.cusize);
337          if (ambfp == NULL)
338                  return;
339 <        if (fwrite((char *)av, sizeof(AMBVAL), 1, ambfp) != 1)
339 >        if (writambval(av, ambfp) < 0)
340                  goto writerr;
341 < #ifdef  AMBFLUSH
342 <        if (++nunflshed >= AMBFLUSH) {
264 <                if (fflush(ambfp) == EOF)
341 >        if (++nunflshed >= AMBFLUSH)
342 >                if (ambsync() == EOF)
343                          goto writerr;
266                nunflshed = 0;
267        }
268 #endif
344          return;
345   writerr:
346          error(SYSTEM, "error writing ambient file");
# Line 274 | Line 349 | writerr:
349  
350   static
351   avinsert(aval, at, c0, s)               /* insert ambient value in a tree */
352 < AMBVAL  *aval;
352 > AMBVAL  *aval;
353   register AMBTREE  *at;
354   FVECT  c0;
355 < double  s;
355 > double  s;
356   {
357          FVECT  ck0;
358          int  branch;
359 <        register AMBVAL  *av;
359 >        register AMBVAL  *av;
360          register int  i;
361  
362          if ((av = newambval()) == NULL)
# Line 307 | Line 382 | double  s;
382   memerr:
383          error(SYSTEM, "out of memory in avinsert");
384   }
385 +
386 +
387 + #ifdef  F_SETLKW
388 +
389 + int
390 + ambsync()                       /* synchronize ambient file */
391 + {
392 +        static FILE  *ambinp = NULL;
393 +        static long  lastpos = -1;
394 +        struct flock  fls;
395 +        long  flen;
396 +        AMBVAL  avs;
397 +        register int  n;
398 +
399 +        if (nunflshed == 0)
400 +                return(0);
401 +                                /* gain exclusive access */
402 +        fls.l_type = F_WRLCK;
403 +        fls.l_whence = 0;
404 +        fls.l_start = 0L;
405 +        fls.l_len = 0L;
406 +        if (fcntl(fileno(ambfp), F_SETLKW, &fls) < 0)
407 +                error(SYSTEM, "cannot lock ambient file");
408 +        if (lastpos < 0)        /* initializing */
409 +                goto syncend;
410 +                                /* see if file has grown */
411 +        if ((flen = lseek(fileno(ambfp), 0L, 2)) < 0)
412 +                error(SYSTEM, "cannot seek on ambient file");
413 +        if (n = flen - lastpos) {               /* file has grown */
414 +                if (ambinp == NULL) {           /* use duplicate filedes */
415 +                        ambinp = fdopen(dup(fileno(ambfp)), "r");
416 +                        if (ambinp == NULL)
417 +                                error(SYSTEM, "fdopen failed in ambsync");
418 +                }
419 +                if (fseek(ambinp, lastpos, 0) < 0)
420 +                        error(SYSTEM, "fseek failed in ambsync");
421 +                while (n >= AMBVALSIZ) {        /* load contributed values */
422 +                        readambval(&avs, ambinp);
423 +                        avinsert(&avs,&atrunk,thescene.cuorg,thescene.cusize);
424 +                        n -= AMBVALSIZ;
425 +                }
426 +                if (n)                          /* alignment */
427 +                        lseek(fileno(ambfp), flen-n, 0);
428 +        }
429 + syncend:
430 +        n = fflush(ambfp);                      /* calls write() at last */
431 +        lastpos = lseek(fileno(ambfp), 0L, 1);
432 +        fls.l_type = F_UNLCK;                   /* release file */
433 +        fcntl(fileno(ambfp), F_SETLKW, &fls);
434 +        nunflshed = 0;
435 +        return(n);
436 + }
437 +
438 + #else
439 +
440 + int
441 + ambsync()                       /* flush ambient file */
442 + {
443 +        if (nunflshed == 0)
444 +                return(0);
445 +        nunflshed = 0;
446 +        return(fflush(ambfp));
447 + }
448 +
449 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines