ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove2.c
Revision: 3.1
Committed: Sat Feb 22 02:07:30 2003 UTC (21 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * ranimove2.c
6 *
7 * Frame refinement routines for ranimate(1).
8 *
9 * Created by Gregory Ward on Wed Jan 08 2003.
10 */
11
12 /* ====================================================================
13 * The Radiance Software License, Version 1.0
14 *
15 * Copyright (c) 1990 - 2002 The Regents of the University of California,
16 * through Lawrence Berkeley National Laboratory. All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
28 * distribution.
29 *
30 * 3. The end-user documentation included with the redistribution,
31 * if any, must include the following acknowledgment:
32 * "This product includes Radiance software
33 * (http://radsite.lbl.gov/)
34 * developed by the Lawrence Berkeley National Laboratory
35 * (http://www.lbl.gov/)."
36 * Alternately, this acknowledgment may appear in the software itself,
37 * if and wherever such third-party acknowledgments normally appear.
38 *
39 * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
40 * and "The Regents of the University of California" must
41 * not be used to endorse or promote products derived from this
42 * software without prior written permission. For written
43 * permission, please contact [email protected].
44 *
45 * 5. Products derived from this software may not be called "Radiance",
46 * nor may "Radiance" appear in their name, without prior written
47 * permission of Lawrence Berkeley National Laboratory.
48 *
49 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
50 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
51 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
52 * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
53 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
55 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
56 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
57 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
58 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
59 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 * ====================================================================
62 *
63 * This software consists of voluntary contributions made by many
64 * individuals on behalf of Lawrence Berkeley National Laboratory. For more
65 * information on Lawrence Berkeley National Laboratory, please see
66 * <http://www.lbl.gov/>.
67 */
68
69 #include "ranimove.h"
70 #include "random.h"
71
72
73 #define HL_ERR 0.32 /* highlight error threshold */
74
75 int cerrzero; /* is cerrmap all zeroes? */
76
77
78 int
79 refine_first() /* initial refinement pass */
80 {
81 int *esamp = (int *)zprev; /* OK to reuse */
82 int hl_erri = errori(HL_ERR);
83 int nextra = 0;
84 int x, y, xp, yp;
85 int neigh;
86 register int n, np;
87
88 if (sizeof(int) < sizeof(*zprev))
89 error(CONSISTENCY, "code error in refine_first");
90 if (!silent) {
91 printf("\tFirst refinement pass...");
92 fflush(stdout);
93 }
94 bzero((void *)esamp, sizeof(int)*hres*vres);
95 /*
96 * In our initial pass, we look for lower error pixels from
97 * the same objects in the previous frame, and copy them here.
98 */
99 for (y = vres; y--; )
100 for (x = hres; x--; ) {
101 n = fndx(x, y);
102 if (obuffer[n] == OVOID)
103 continue;
104 if (xmbuffer[n] == MO_UNK)
105 continue;
106 xp = x + xmbuffer[n];
107 if ((xp < 0 | xp >= hres))
108 continue;
109 yp = y + ymbuffer[n];
110 if ((yp < 0 | yp >= vres))
111 continue;
112 np = fndx(xp, yp);
113 /* make sure we hit same object */
114 if (oprev[np] != obuffer[n])
115 continue;
116 /* is previous frame error lower? */
117 if (aprev[np] < AMIN + ATIDIFF)
118 continue;
119 if (aprev[np] <= abuffer[n] + ATIDIFF)
120 continue;
121 /* shadow & highlight detection */
122 if (abuffer[n] > hl_erri &&
123 getclosest(&neigh, 1, x, y) &&
124 bigdiff(cbuffer[neigh], cprev[np],
125 HL_ERR*(.9+.2*frandom())))
126 continue;
127 abuffer[n] = aprev[np] - ATIDIFF;
128 copycolor(cbuffer[n], cprev[np]);
129 esamp[n] = 1; /* record extrapolated sample */
130 nextra++;
131 }
132 for (n = hres*vres; n--; ) /* update sample counts */
133 if (esamp[n])
134 sbuffer[n] = 1;
135 if (!silent)
136 printf("extrapolated %d pixels\n", nextra);
137 return(1);
138 }
139
140
141 /*
142 * We use a recursive computation of the conspicuity
143 * map to avoid associated memory costs and simplify
144 * coding. We create a virtual image pyramid, pooling
145 * variance calculations, etc. The top of the pyramid
146 * corresponds to the foveal resolution, as there should
147 * not be any interesting mechanisms above this level.
148 */
149
150 #define CSF_C0 1.14
151 #define CSF_C1 0.67
152 #define CSF_C2 1.7
153 #define CSF_S1 6.1
154 #define CSF_S2 7.3
155 #define CSF_P1 45.9
156 #define CSF_PC (30./45.9*CSF_P1)
157 #define CSF_VR0 0.15
158 #define CSF_VRC 80.
159
160 struct ConspSum {
161 COLOR vsum; /* value sum */
162 COLOR v2sum; /* value^2 sum */
163 long nsamp; /* number of samples */
164 long xmsum; /* x-motion sum */
165 long ymsum; /* y-motion sum */
166 int npix; /* number of pixels */
167 double hls; /* high-level saliency */
168 };
169
170 static double pixel_deg; /* base pixel frequency */
171 static int fhsiz, fvsiz; /* foveal subimage size */
172
173 static void
174 clr_consp(cs) /* initialize a conspicuity sum */
175 register struct ConspSum *cs;
176 {
177 if (cs == NULL)
178 return;
179 setcolor(cs->vsum, 0., 0., 0.);
180 setcolor(cs->v2sum, 0., 0., 0.);
181 cs->nsamp = 0;
182 cs->xmsum = cs->ymsum = 0;
183 cs->npix = 0;
184 cs->hls = 0;
185 }
186
187 static void
188 sum_consp(cdest, cs) /* sum in conspicuity result */
189 register struct ConspSum *cdest, *cs;
190 {
191 if ((cdest == NULL | cs == NULL))
192 return;
193 addcolor(cdest->vsum, cs->vsum);
194 addcolor(cdest->v2sum, cs->v2sum);
195 cdest->nsamp += cs->nsamp;
196 cdest->xmsum += cs->xmsum;
197 cdest->ymsum += cs->ymsum;
198 cdest->npix += cs->npix;
199 if (cs->hls > cdest->hls)
200 cdest->hls = cs->hls;
201 }
202
203 static void
204 est_consp(x0,y0,x1,y1, cs) /* estimate error conspicuity & update */
205 int x0, y0, x1, y1;
206 register struct ConspSum *cs;
207 {
208 double rad2, mtn2, cpd, vm, vr, csf, eest;
209 /* do we care? */
210 if (cs->hls <= FTINY)
211 return;
212 /* get relative error */
213 if (cs->nsamp < NSAMPOK) {
214 int neigh[NSAMPOK]; /* gather neighbors */
215 eest = comperr(neigh,
216 getclosest(neigh, NSAMPOK, (x0+x1)>>1, (y0+y1)>>1),
217 cs->nsamp);
218 } else
219 eest = estimaterr(cs->vsum, cs->v2sum, cs->nsamp, cs->nsamp);
220
221 if ((x0 == x1-1 & y0 == y1-1)) { /* update pixel error */
222 int n = fndx(x0, y0);
223 int ai;
224 int ne;
225 if (sbuffer[n] >= 255) {
226 abuffer[n] = ADISTANT;
227 } else {
228 ai = errori(eest);
229 if (ai < AMIN) ai = AMIN;
230 else if (ai >= ADISTANT) ai = ADISTANT-1;
231 abuffer[n] = ai;
232 /* can't improve on closest */
233 if (!cs->nsamp && getclosest(&ne, 1, x0, y0) &&
234 abuffer[ne] < ai &&
235 abuffer[ne] >= AMIN)
236 abuffer[n] = abuffer[ne];
237 }
238 }
239 /* compute radius^2 */
240 rad2 = 0.125*((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
241
242 /* average motion^2 */
243 mtn2 = (double)cs->xmsum*cs->xmsum + (double)cs->ymsum*cs->ymsum;
244 mtn2 /= (double)(cs->npix*cs->npix);
245 /* motion blur hides us? */
246 if (mblur*mblur*mtn2 >= 4.*rad2)
247 return;
248 /* too small to see? */
249 cpd = pixel_deg * pixel_deg / rad2;
250 if (cpd > CSF_PC*CSF_PC)
251 return;
252 cpd = sqrt(cpd);
253 /* compute CSF [Daley98] */
254 vm = rate * sqrt(mtn2) / pixel_deg;
255 vr = cs->hls/hlsmax*vm + CSF_VR0; /* use hls tracking eff. */
256 if (vr > CSF_VRC) vr = CSF_VRC;
257 vr = vm - vr;
258 if (vr < 0) vr = -vr;
259 csf = log(CSF_C2*(1./3.)*vr);
260 if (csf < 0) csf = -csf;
261 csf = CSF_S1 + CSF_S2*csf*csf*csf;
262 csf *= CSF_C0*CSF_C2*4.*PI*PI*CSF_C1*CSF_C1*cpd*cpd;
263 csf *= exp(-CSF_C1*4.*PI/CSF_P1*(CSF_C2*vr + 2.)*cpd);
264 /* compute visible error */
265 eest = eest*csf/ndthresh - 1.;
266 if (eest <= FTINY)
267 return;
268 /* scale by saleincy */
269 eest *= cs->hls;
270 /* worth the bother? */
271 if (eest <= .01)
272 return;
273 /* sum into map */
274 for ( ; y0 < y1; y0++) {
275 float *em0 = cerrmap + fndx(x0, y0);
276 register float *emp = em0 + (x1-x0);
277 while (emp-- > em0)
278 *emp += eest;
279 }
280 cerrzero = 0;
281 }
282
283 static void
284 subconspicuity(x0,y0,x1,y1, cs) /* compute subportion of conspicuity */
285 int x0, y0, x1, y1;
286 struct ConspSum *cs;
287 {
288 struct ConspSum mysum;
289 int i;
290
291 if ((x0 >= x1 | y0 >= y1))
292 error(CONSISTENCY, "bad call to subconspicuity");
293
294 clr_consp(&mysum); /* prepare sum */
295
296 if ((x0 == x1-1 & y0 == y1-1)) { /* single pixel */
297 double hls;
298 register int n = fndx(x0, y0);
299 if (sbuffer[n]) {
300 copycolor(mysum.vsum, cbuffer[n]);
301 copycolor(mysum.v2sum, val2map[n]);
302 mysum.nsamp = sbuffer[n];
303 }
304 if ((mysum.xmsum = xmbuffer[n]) == MO_UNK)
305 mysum.xmsum = 0;
306 else
307 mysum.ymsum = ymbuffer[n];
308 mysum.npix = 1;
309 /* max. hls in fovea */
310 mysum.hls = obj_prio(obuffer[n]);
311 if (x0 >= fhsiz) {
312 hls = obj_prio(obuffer[fndx(x0-fhsiz,y0)]);
313 if (hls > mysum.hls) mysum.hls = hls;
314 }
315 if (x0 < hres-fhsiz) {
316 hls = obj_prio(obuffer[fndx(x0+fhsiz,y0)]);
317 if (hls > mysum.hls) mysum.hls = hls;
318 }
319 if (y0 >= fvsiz) {
320 hls = obj_prio(obuffer[fndx(x0,y0-fvsiz)]);
321 if (hls > mysum.hls) mysum.hls = hls;
322 }
323 if (y0 < vres-fvsiz) {
324 hls = obj_prio(obuffer[fndx(x0,y0+fvsiz)]);
325 if (hls > mysum.hls) mysum.hls = hls;
326 }
327 } else if (x0 == x1-1) { /* vertical pair */
328 for (i = y0 ; i < y1; i++)
329 subconspicuity(x0, i, x1, i+1, &mysum);
330 } else if (y0 == y1-1) { /* horizontal pair */
331 for (i = x0 ; i < x1; i++)
332 subconspicuity(i, y0, i+1, y1, &mysum);
333 } else { /* rectangle */
334 subconspicuity(x0, y0, (x0+x1)>>1, (y0+y1)>>1, &mysum);
335 subconspicuity((x0+x1)>>1, y0, x1, (y0+y1)>>1, &mysum);
336 subconspicuity(x0, (y0+y1)>>1, (x0+x1)>>1, y1, &mysum);
337 subconspicuity((x0+x1)>>1, (y0+y1)>>1, x1, y1, &mysum);
338 }
339 /* update conspicuity */
340 est_consp(x0, y0, x1, y1, &mysum);
341 /* sum into return value */
342 sum_consp(cs, &mysum);
343 }
344
345 void
346 conspicuity() /* compute conspicuous error map */
347 {
348 int fhres, fvres;
349 int fx, fy;
350 /* reuse previous z-buffer */
351 cerrmap = (float *)zprev;
352 bzero((void *)cerrmap, sizeof(float)*hres*vres);
353 cerrzero = 1;
354 /* compute base pixel frequency */
355 pixel_deg = .5*(hres/vw.horiz + vres/vw.vert);
356 /* compute foveal resolution */
357 fhres = vw.horiz/FOV_DEG + 0.5;
358 if (fhres <= 0) fhres = 1;
359 else if (fhres > hres) fhres = hres;
360 fvres = vw.vert/FOV_DEG + 0.5;
361 if (fvres <= 0) fvres = 1;
362 else if (fvres > vres) fvres = vres;
363 fhsiz = hres/fhres;
364 fvsiz = vres/fvres;
365 /* call our foveal subroutine */
366 for (fy = fvres; fy--; )
367 for (fx = fhres; fx--; )
368 subconspicuity(hres*fx/fhres, vres*fy/fvres,
369 hres*(fx+1)/fhres, vres*(fy+1)/fvres,
370 NULL);
371 }
372
373
374 /*
375 * The following structure is used to collect data on the
376 * initial error in the ambient value estimate, in order
377 * to correct for it in the subsequent frames.
378 */
379 static struct AmbSum {
380 double diffsum[3]; /* sum of (correct - ambval) */
381 long nsamps; /* number of values in sum */
382 } *asump = NULL;
383
384
385 static int
386 ppri_cmp(pp1, pp2) /* pixel priority comparison */
387 const void *pp1, *pp2;
388 {
389 double se1 = cerrmap[*(const int *)pp1];
390 double se2 = cerrmap[*(const int *)pp2];
391 int adiff;
392 /* higher conspicuity to front */
393 if (se1 < se2) return(1);
394 if (se1 > se2) return(-1);
395 /* else higher error to front */
396 adiff = (int)abuffer[*(const int *)pp1] -
397 (int)abuffer[*(const int *)pp2];
398 if (adiff)
399 return(adiff);
400 /* else fewer samples to front */
401 return((int)sbuffer[*(const int *)pp1] -
402 (int)sbuffer[*(const int *)pp2]);
403 }
404
405
406 static int
407 ray_refine(n) /* refine the given pixel by tracing a ray */
408 register int n;
409 {
410 RAY ir;
411 int neigh[NSAMPOK];
412 int nc;
413 COLOR ctmp;
414 int i;
415
416 if (n < 0) { /* fetching stragglers */
417 if (nprocs <= 1 || !ray_presult(&ir, 0))
418 return(-1);
419 n = ir.rno;
420 } else { /* else tracing a new ray */
421 double hv[2];
422 if (sbuffer[n] >= 255) /* reached limit? */
423 return(-1);
424 sample_pos(hv, n%hres, n/hres, sbuffer[n]);
425 ir.rmax = viewray(ir.rorg, ir.rdir, &vw, hv[0], hv[1]);
426 if (ir.rmax < -FTINY)
427 return(-1);
428 if (nprocs > 1) {
429 int rval;
430 rayorigin(&ir, NULL, PRIMARY, 1.0);
431 ir.rno = n;
432 rval = ray_pqueue(&ir);
433 if (!rval)
434 return(-1);
435 if (rval < 0)
436 quit(1);
437 n = ir.rno;
438 } else
439 ray_trace(&ir);
440 }
441 if (abuffer[n] == ALOWQ && asump != NULL) {
442 if (sbuffer[n] != 1)
443 error(CONSISTENCY, "bad code in ray_refine");
444 if (getambcolor(ctmp, obuffer[n]) &&
445 (colval(ctmp,RED) > 0.01 &
446 colval(ctmp,GRN) > 0.01 &
447 colval(ctmp,BLU) > 0.01)) {
448 for (i = 0; i < 3; i++)
449 asump->diffsum[i] +=
450 (colval(ir.rcol,i) - colval(cbuffer[n],i))
451 / colval(ctmp,i);
452 asump->nsamps++;
453 }
454 sbuffer[n] = 0;
455 }
456 setcolor(ctmp,
457 colval(ir.rcol,RED)*colval(ir.rcol,RED),
458 colval(ir.rcol,GRN)*colval(ir.rcol,GRN),
459 colval(ir.rcol,BLU)*colval(ir.rcol,BLU));
460 if (!sbuffer[n]) { /* first sample */
461 copycolor(cbuffer[n], ir.rcol);
462 copycolor(val2map[n], ctmp);
463 abuffer[n] = AHIGHQ;
464 sbuffer[n] = 1;
465 } else { /* else sum in sample */
466 addcolor(cbuffer[n], ir.rcol);
467 addcolor(val2map[n], ctmp);
468 sbuffer[n]++;
469 }
470 return(n);
471 }
472
473
474 static long
475 refine_rays(nrays) /* compute refinement rays */
476 long nrays;
477 {
478 int *pord;
479 int ntodo;
480 long rdone;
481 int i;
482 /* skip if nothing significant */
483 if (ndtset && cerrzero)
484 return;
485 /* initialize priority list */
486 pord = (int *)malloc(sizeof(int)*hres*vres);
487 for (i = hres*vres; i--; )
488 pord[i] = i;
489 /* sort our priorities */
490 ntodo = hres*vres;
491 if (nrays < ntodo)
492 qsort((void *)pord, hres*vres, sizeof(int), ppri_cmp);
493 i = 0;
494 /* trace rays in list */
495 for (rdone = 0; rdone < nrays; rdone++) {
496 if (ndtset && i >= 1000 && cerrmap[pord[i]] <= FTINY)
497 ntodo = i;
498 if (i >= ntodo) { /* redo conspicuity & priority */
499 while (ray_refine(-1) >= 0)
500 ;
501 conspicuity();
502 if (ndtset && cerrzero)
503 break;
504 qsort((void *)pord, hres*vres, sizeof(int), ppri_cmp);
505 ntodo = hres*vres/8;
506 i = 0;
507 }
508 /* sample next pixel */
509 ray_refine(pord[i++]);
510 }
511 /* clean up and return */
512 while (ray_refine(-1) >= 0)
513 ;
514 free((void *)pord);
515 return(rdone);
516 }
517
518
519 int
520 refine_frame(pass) /* refine current frame */
521 int pass;
522 {
523 static double rtime_used = 0;
524 static long ray_cnt = 0;
525 static double ctime_used = 0;
526 static int csp_cnt = 0;
527 int timed = (fcur > fbeg | pass > 0 | quickstart);
528 double time_start, rtime_start, time_done;
529 struct AmbSum myAmbSum;
530 long rays_todo, nr;
531 register int n;
532 /* IBR refinement? */
533 if ((pass == 0 & fcur > fbeg))
534 return(refine_first());
535 /* any time left? */
536 time_start = getTime();
537 if (timed) {
538 if (time_start >= frm_stop)
539 goto nomore;
540 if (csp_cnt > 0 && time_start + ctime_used/csp_cnt >= frm_stop)
541 goto nomore;
542 }
543 asump = NULL; /* use resampling to update ambval? */
544 if (!curparams->ambounce && hirendparams.ambounce) {
545 myAmbSum.diffsum[RED] =
546 myAmbSum.diffsum[GRN] =
547 myAmbSum.diffsum[BLU] = 0;
548 myAmbSum.nsamps = 0;
549 asump = &myAmbSum;
550 }
551 /* initialize value-squared map */
552 if (val2map == NULL) {
553 val2map = cprev; /* OK to reuse at this point */
554 n = (asump == NULL) ? hres*vres : 0;
555 while (n--)
556 if (sbuffer[n])
557 setcolor(val2map[n],
558 colval(cbuffer[n],RED)*colval(cbuffer[n],RED),
559 colval(cbuffer[n],GRN)*colval(cbuffer[n],GRN),
560 colval(cbuffer[n],BLU)*colval(cbuffer[n],BLU));
561 else
562 setcolor(val2map[n], 0., 0., 0.);
563 }
564 /* compute conspicuity */
565 if (!silent) {
566 printf("\tComputing conspicuity map\n");
567 fflush(stdout);
568 }
569 conspicuity();
570 csp_cnt++;
571 #if 0
572 if (pass == 1) {
573 char fnm[256];
574 sprintf(fnm, vval(BASENAME), fcur);
575 strcat(fnm, "_incmap.pic");
576 write_map(cerrmap, fnm);
577 }
578 #endif
579 /* get ray start time */
580 rtime_start = getTime();
581 ctime_used += rtime_start - time_start;
582 if (timed && rtime_start >= frm_stop)
583 return(0); /* error done but out of time */
584 if (rtime_used <= FTINY) {
585 if (quickstart)
586 rays_todo = 1000;
587 else
588 rays_todo = hres*vres;
589 } else {
590 rays_todo = (long)((frm_stop - rtime_start) *
591 ray_cnt / rtime_used);
592 if (rays_todo < 1000)
593 return(0); /* let's call it a frame */
594 }
595 /* set higher rendering quality */
596 if (twolevels && curparams != &hirendparams) {
597 ray_restore(curparams = &hirendparams);
598 if (nprocs > 1) { /* need to update children */
599 if (!silent) {
600 printf("\tRestarting %d processes\n", nprocs);
601 fflush(stdout);
602 }
603 ray_pclose(0);
604 ray_popen(nprocs);
605 }
606 }
607 /* compute refinement rays */
608 if (!silent) {
609 printf("\tRefinement pass %d...",
610 pass+1, rays_todo);
611 fflush(stdout);
612 }
613 if (asump != NULL) /* flag low-quality samples */
614 for (n = hres*vres; n--; )
615 if (sbuffer[n])
616 abuffer[n] = ALOWQ;
617 /* trace those rays */
618 nr = refine_rays(rays_todo);
619 if (!silent)
620 printf("traced %d HQ rays\n", nr);
621 if (nr <= 0)
622 return(0);
623 /* update timing stats */
624 while (ray_cnt >= 1L<<20) {
625 ray_cnt >>= 1;
626 rtime_used *= .5;
627 }
628 ray_cnt += nr;
629 time_done = getTime();
630 rtime_used += time_done - rtime_start;
631 if (!timed && time_done > frm_stop)
632 frm_stop = time_done;
633 /* update ambient value */
634 if (asump != NULL && asump->nsamps >= 1000) {
635 double sf = 1./(double)asump->nsamps;
636 for (n = 3; n--; ) {
637 asump->diffsum[n] *= sf;
638 asump->diffsum[n] += colval(lorendparams.ambval,n);
639 if (asump->diffsum[n] < 0) asump->diffsum[n] = 0;
640 }
641 setcolor(lorendparams.ambval,
642 asump->diffsum[RED],
643 asump->diffsum[GRN],
644 asump->diffsum[BLU]);
645 if (!silent)
646 printf("\tUpdated parameter: -av %f %f %f\n",
647 asump->diffsum[RED],
648 asump->diffsum[GRN],
649 asump->diffsum[BLU]);
650 asump = NULL;
651 }
652 return(1);
653 nomore:
654 /* make sure error map is updated */
655 if ((fcur == fbeg | pass > 1))
656 comp_frame_error();
657 return(0);
658 }