ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.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

# User Rev Content
1 greg 3.1 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #endif
4     /*
5     * ranimove1.c
6     *
7     * Basic frame rendering 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 "otypes.h"
71     #include "random.h"
72    
73     double acctab[256]; /* accuracy value table */
74    
75     int hres, vres; /* frame resolution (fcur) */
76     double pixaspect; /* pixel aspect ratio */
77    
78     VIEW vw; /* view for this frame */
79     COLOR *cbuffer; /* color at each pixel */
80     float *zbuffer; /* depth at each pixel */
81     OBJECT *obuffer; /* object id at each pixel */
82     short *xmbuffer; /* x motion at each pixel */
83     short *ymbuffer; /* y motion at each pixel */
84     BYTE *abuffer; /* accuracy at each pixel */
85     BYTE *sbuffer; /* sample count per pixel */
86    
87     VIEW vwprev; /* last frame's view */
88     COLOR *cprev; /* last frame colors */
89     float *zprev; /* last frame depth */
90     OBJECT *oprev; /* last frame objects */
91     BYTE *aprev; /* last frame accuracy */
92    
93     float *cerrmap; /* conspicuous error map */
94     COLOR *val2map; /* value-squared map for variance */
95    
96     double frm_stop; /* when to stop rendering this frame */
97    
98     double hlsmax; /* maximum high-level saliency this frame */
99    
100    
101     void
102     write_map(mp, fn) /* write out float map (debugging) */
103     float *mp;
104     char *fn;
105     {
106     FILE *fp = fopen(fn, "w");
107     COLOR scanbuf[2048];
108     int x, y;
109    
110     if (fp == NULL)
111     return;
112     newheader("RADIANCE", fp);
113     fputformat(COLRFMT, fp);
114     fputc('\n', fp); /* end header */
115     fprtresolu(hres, vres, fp);
116     for (y = vres; y--; ) { /* write scanlines */
117     float *bp = mp + (y+1)*hres - 1;
118     for (x = hres; x--; bp--)
119     setcolor(scanbuf[x], *bp, *bp, *bp);
120     if (fwritescan(scanbuf, hres, fp) < 0)
121     break;
122     }
123     fclose(fp);
124     }
125    
126    
127     static void
128     next_frame() /* prepare next frame buffer */
129     {
130     VIEW *fv;
131     char *err;
132     /* get previous view */
133     if (vw.type != 0)
134     copystruct(&vwprev, &vw);
135     else if (fcur > 1 && (fv = getview(fcur-1)) != NULL) {
136     copystruct(&vwprev, fv);
137     if (setview(&vwprev) != NULL)
138     vwprev.type = 0;
139     }
140     /* get current view */
141     if ((fv = getview(fcur)) == NULL) {
142     sprintf(errmsg, "cannot get view for frame %d", fcur);
143     error(USER, errmsg);
144     }
145     copystruct(&vw, fv);
146     if ((err = setview(&vw)) != NULL) {
147     sprintf(errmsg, "view error at frame %d: %s", fcur, err);
148     error(USER, errmsg);
149     }
150     if (cbuffer == NULL) {
151     /* compute resolution and allocate */
152     switch (sscanf(vval(RESOLUTION), "%d %d %lf",
153     &hres, &vres, &pixaspect)) {
154     case 1:
155     vres = hres;
156     /* fall through */
157     case 2:
158     pixaspect = 1.;
159     /* fall through */
160     case 3:
161     if ((hres > 0 & vres > 0))
162     break;
163     /* fall through */
164     default:
165     sprintf(errmsg, "bad %s value", vnam(RESOLUTION));
166     error(USER, errmsg);
167     }
168     normaspect(viewaspect(&vw), &pixaspect, &hres, &vres);
169     cbuffer = (COLOR *)malloc(sizeof(COLOR)*hres*vres);
170     zbuffer = (float *)malloc(sizeof(float)*hres*vres);
171     obuffer = (OBJECT *)malloc(sizeof(OBJECT)*hres*vres);
172     xmbuffer = (short *)malloc(sizeof(short)*hres*vres);
173     ymbuffer = (short *)malloc(sizeof(short)*hres*vres);
174     abuffer = (BYTE *)calloc(hres*vres, sizeof(BYTE));
175     sbuffer = (BYTE *)calloc(hres*vres, sizeof(BYTE));
176     cprev = (COLOR *)malloc(sizeof(COLOR)*hres*vres);
177     zprev = (float *)malloc(sizeof(float)*hres*vres);
178     oprev = (OBJECT *)malloc(sizeof(OBJECT)*hres*vres);
179     aprev = (BYTE *)malloc(sizeof(BYTE)*hres*vres);
180     if ((cbuffer==NULL | zbuffer==NULL | obuffer==NULL |
181     xmbuffer==NULL | ymbuffer==NULL |
182     abuffer==NULL | sbuffer==NULL |
183     cprev==NULL | zprev == NULL |
184     oprev==NULL | aprev==NULL))
185     error(SYSTEM, "out of memory in init_frame");
186     frm_stop = getTime() + rtperfrm;
187     } else {
188     COLOR *cp; /* else just swap buffers */
189     float *fp;
190     OBJECT *op;
191     BYTE *bp;
192     cp = cprev; cprev = cbuffer; cbuffer = cp;
193     fp = zprev; zprev = zbuffer; zbuffer = fp;
194     op = oprev; oprev = obuffer; obuffer = op;
195     bp = aprev; aprev = abuffer; abuffer = bp;
196     bzero(abuffer, sizeof(BYTE)*hres*vres);
197     bzero(sbuffer, sizeof(BYTE)*hres*vres);
198     frm_stop += rtperfrm;
199     }
200     cerrmap = NULL;
201     val2map = NULL;
202     }
203    
204    
205     #define SAMPDIST 3 /* Maximum distance to neighbor sample */
206     #define SAMPDIST2 (SAMPDIST*SAMPDIST)
207    
208    
209     static int
210     sample_here(x, y) /* 4x4 quincunx sample at this pixel? */
211     register int x, y;
212     {
213     if (y & 0x1) /* every other row has samples */
214     return(0);
215     if (y & 0x3) /* every fourth row is offset */
216     x += 2;
217     return((x & 0x3) == 0); /* every fourth column is sampled */
218     }
219    
220    
221     void
222     sample_pos(hv, x, y, sn) /* compute jittered sample position */
223     double hv[2];
224     int x, y;
225     int sn;
226     {
227     int hl[2];
228    
229     hl[0] = x; hl[1] = y;
230     multisamp(hv, 2, urand(ilhash(hl,2) + sn));
231     hv[0] = ((double)x + hv[0]) / (double)hres;
232     hv[1] = ((double)y + hv[1]) / (double)vres;
233     }
234    
235    
236     double
237     sample_wt(xo, yo) /* compute interpolant sample weight */
238     int xo, yo;
239     {
240     static double etab[400];
241     int rad2 = xo*xo + yo*yo;
242     int i;
243    
244     if (etab[0] <= FTINY) /* initialize exponent table */
245     for (i = 400; i--; )
246     etab[i] = exp(-0.1*i);
247    
248     /* look up Gaussian */
249     i = (int)((10.*3./(double)SAMPDIST2)*rad2 + .5);
250     if (i >= 400)
251     return(0.0);
252     return(etab[i]);
253     }
254    
255    
256     static int
257     offset_cmp(p1, p2) /* compare offset distances */
258     const void *p1, *p2;
259     {
260     return(*(const int *)p1 - *(const int *)p2);
261     }
262    
263    
264     int
265     getclosest(iarr, nc, x, y) /* get nc closest neighbors on same object */
266     int *iarr;
267     int nc;
268     int x, y;
269     {
270     #define NSCHECK ((2*SAMPDIST+1)*(2*SAMPDIST+1))
271     static int hro, vro;
272     static int ioffs[NSCHECK];
273     OBJECT myobj;
274     int i0, nf;
275     register int i, j;
276     /* get our object number */
277     myobj = obuffer[fndx(x, y)];
278     /* special case for borders */
279     if ((x < SAMPDIST | x >= hres-SAMPDIST |
280     y < SAMPDIST | y >= vres-SAMPDIST)) {
281     int tndx[NSCHECK][2];
282     nf = 0;
283     for (j = y - SAMPDIST; j <= y + SAMPDIST; j++) {
284     if (j >= vres) break;
285     if (j < 0) j = 0;
286     for (i = x - SAMPDIST; i <= x + SAMPDIST; i++) {
287     if (i >= hres) break;
288     if (i < 0) i = 0;
289     i0 = fndx(i, j);
290     if (!sbuffer[i0])
291     continue;
292     if ((myobj != OVOID & obuffer[i0] != myobj))
293     continue;
294     tndx[nf][0] = (i-x)*(i-x) + (j-y)*(j-y);
295     tndx[nf][1] = i0;
296     nf++;
297     }
298     }
299     qsort((void *)tndx, nf, 2*sizeof(int), offset_cmp);
300     if (nf > nc)
301     nf = nc;
302     for (i = nf; i--; )
303     iarr[i] = tndx[i][1];
304     return(nf);
305     }
306     /* initialize offset array */
307     if ((hres != hro | vres != vro)) {
308     int toffs[NSCHECK][2];
309     i0 = fndx(SAMPDIST, SAMPDIST);
310     nf = 0;
311     for (i = 0; i <= 2*SAMPDIST; i++)
312     for (j = 0; j <= 2*SAMPDIST; j++) {
313     toffs[nf][0] = (i-SAMPDIST)*(i-SAMPDIST) +
314     (j-SAMPDIST)*(j-SAMPDIST);
315     toffs[nf][1] = fndx(i, j) - i0;
316     nf++;
317     }
318     qsort((void *)toffs, nf, 2*sizeof(int), offset_cmp);
319     for (i = NSCHECK; i--; )
320     ioffs[i] = toffs[i][1];
321     hro = hres;
322     vro = vres;
323     }
324     /* find up to nc neighbors */
325     i0 = fndx(x, y);
326     for (j = 0, nf = 0; (j < NSCHECK & nf < nc); j++) {
327     i = i0 + ioffs[j];
328     if (sbuffer[i] && (myobj == OVOID | obuffer[i] == myobj))
329     iarr[nf++] = i;
330     }
331     /* return number found */
332     return(nf);
333     #undef NSCHECK
334     }
335    
336    
337     static void
338     setmotion(n, wpos) /* compute motion vector for this pixel */
339     register int n;
340     FVECT wpos;
341     {
342     FVECT ovp;
343     MAT4 xfm;
344     double d;
345     int moi;
346     int xp, yp;
347     /* ID object and update maximum HLS */
348     moi = getmove(obuffer[n]);
349     if (moi >= 0 && obj_move[moi].cprio > hlsmax)
350     hlsmax = obj_move[moi].cprio;
351     if (vwprev.type == 0) /* return leaves MO_UNK */
352     return;
353     if (moi >= 0) { /* move object point back */
354     multp3(ovp, wpos, obj_move[moi].bxfm);
355     wpos = ovp;
356     }
357     viewloc(ovp, &vwprev, wpos);
358     if (ovp[2] <= FTINY)
359     return;
360     xp = (int)(ovp[0]*hres);
361     yp = (int)(ovp[1]*vres);
362     xmbuffer[n] = xp - (n % hres);
363     ymbuffer[n] = yp - (n / hres);
364     if ((xp < 0 | xp >= hres))
365     return;
366     if ((yp < 0 | yp >= vres))
367     return;
368     n = fndx(xp, yp);
369     if ((zprev[n] < 0.97*ovp[2] | zprev[n] > 1.03*ovp[2]))
370     oprev[n] = OVOID; /* assume it's a bad match */
371     }
372    
373    
374     static void
375     init_frame_sample() /* sample our initial frame */
376     {
377     RAY ir;
378     int x, y;
379     register int n;
380    
381     if (!silent) {
382     printf("\tComputing initial samples...");
383     fflush(stdout);
384     }
385     hlsmax = CSF_SMN;
386     for (y = vres; y--; )
387     for (x = hres; x--; ) {
388     double hv[2];
389     n = fndx(x, y);
390     xmbuffer[n] = MO_UNK;
391     ymbuffer[n] = MO_UNK;
392     sample_pos(hv, x, y, 0);
393     ir.rmax = viewray(ir.rorg, ir.rdir, &vw, hv[0], hv[1]);
394     if (ir.rmax < -FTINY) {
395     setcolor(cbuffer[n], 0., 0., 0.);
396     zbuffer[n] = FHUGE;
397     obuffer[n] = OVOID;
398     abuffer[n] = ADISTANT;
399     continue;
400     }
401     if (!sample_here(x, y)) { /* just cast */
402     rayorigin(&ir, NULL, PRIMARY, 1.0);
403     if (!localhit(&ir, &thescene)) {
404     if (ir.ro != &Aftplane)
405     sourcehit(&ir);
406     copycolor(cbuffer[n], ir.rcol);
407     zbuffer[n] = ir.rot;
408     obuffer[n] = ir.robj;
409     abuffer[n] = ADISTANT;
410     sbuffer[n] = 1;
411     } else {
412     zbuffer[n] = ir.rot;
413     obuffer[n] = ir.robj;
414     setmotion(n, ir.rop);
415     }
416     continue;
417     }
418     if (nprocs > 1) { /* get sample */
419     int rval;
420     rayorigin(&ir, NULL, PRIMARY, 1.0);
421     ir.rno = n;
422     rval = ray_pqueue(&ir);
423     if (!rval)
424     continue;
425     if (rval < 0)
426     quit(1);
427     n = ir.rno;
428     } else
429     ray_trace(&ir);
430     copycolor(cbuffer[n], ir.rcol);
431     zbuffer[n] = ir.rot;
432     obuffer[n] = ir.robj;
433     sbuffer[n] = 1;
434     if (ir.rot >= FHUGE)
435     abuffer[n] = ADISTANT;
436     else {
437     abuffer[n] = ALOWQ;
438     setmotion(n, ir.rop);
439     }
440     }
441     if (nprocs > 1) /* get stragglers */
442     while (ray_presult(&ir, 0)) {
443     n = ir.rno;
444     copycolor(cbuffer[n], ir.rcol);
445     zbuffer[n] = ir.rot;
446     obuffer[n] = ir.robj;
447     sbuffer[n] = 1;
448     if (ir.rot >= FHUGE)
449     abuffer[n] = ADISTANT;
450     else {
451     abuffer[n] = ALOWQ;
452     setmotion(n, ir.rop);
453     }
454     }
455     /* ambiguate object boundaries */
456     for (y = vres-1; y--; )
457     for (x = hres-1; x--; ) {
458     OBJECT obj;
459     n = fndx(x, y);
460     if ((obj = obuffer[n]) == OVOID)
461     continue;
462     if ((obuffer[n+1] != OVOID & obuffer[n+1] != obj)) {
463     obuffer[n] = OVOID;
464     obuffer[n+1] = OVOID;
465     }
466     if ((obuffer[n+hres] != OVOID & obuffer[n+hres] != obj)) {
467     obuffer[n] = OVOID;
468     obuffer[n+hres] = OVOID;
469     }
470     }
471    
472     if (!silent)
473     printf("done\n");
474     }
475    
476    
477     int
478     getambcolor(clr, obj) /* get ambient color for object if we can */
479     COLOR clr;
480     int obj;
481     {
482     register OBJREC *op;
483    
484     if (obj == OVOID)
485     return(0);
486     op = objptr(obj);
487     if ((op->otype == OBJ_INSTANCE & op->omod == OVOID))
488     return(0);
489     /* search for material */
490     do {
491     if (op->omod == OVOID || ofun[op->otype].flags & T_X)
492     return(0);
493     op = objptr(op->omod);
494     } while (!ismaterial(op->otype));
495     /*
496     * Since this routine is called to compute the difference
497     * from rendering with and without interreflections,
498     * we don't want to return colors for materials that are
499     * explicitly excluded from the HQ ambient calculation.
500     */
501     if (hirendparams.ambincl >= 0) {
502     int i;
503     char *lv;
504     for (i = 0; (lv = rpambmod(&hirendparams,i)) != NULL; i++)
505     if (lv[0] == op->oname[0] &&
506     !strcmp(lv+1, op->oname+1))
507     break;
508     if ((lv != NULL) != hirendparams.ambincl)
509     return(0);
510     }
511     switch (op->otype) {
512     case MAT_PLASTIC:
513     case MAT_METAL:
514     case MAT_PLASTIC2:
515     case MAT_METAL2:
516     case MAT_PFUNC:
517     case MAT_MFUNC:
518     case MAT_PDATA:
519     case MAT_MDATA:
520     case MAT_TRANS:
521     case MAT_TRANS2:
522     case MAT_TFUNC:
523     case MAT_TDATA:
524     if (op->oargs.nfargs < 3)
525     return(0);
526     setcolor(clr, op->oargs.farg[0], op->oargs.farg[1],
527     op->oargs.farg[2]);
528     return(1);
529     case MAT_BRTDF:
530     if (op->oargs.nfargs < 6)
531     return(0);
532     setcolor(clr, op->oargs.farg[0]+op->oargs.farg[3],
533     op->oargs.farg[1]+op->oargs.farg[4],
534     op->oargs.farg[2]+op->oargs.farg[5]);
535     scalecolor(clr, 0.5);
536     return(1);
537     case MAT_LIGHT:
538     case MAT_GLOW:
539     case MAT_ILLUM:
540     setcolor(clr, 0., 0., 0.);
541     return(1);
542     }
543     return(0);
544     }
545    
546    
547     double
548     estimaterr(cs, cs2, ns, ns0) /* estimate relative error from samples */
549     COLOR cs, cs2;
550     int ns;
551     {
552     double d, d2, brt;
553    
554     if (ns <= 1 || (brt = bright(cs)/ns) < 1e-14)
555     return(1.0);
556     /* use largest of RGB std. dev. */
557     d2 = colval(cs2,RED) - colval(cs,RED)*colval(cs,RED)/ns;
558     d = colval(cs2,GRN) - colval(cs,GRN)*colval(cs,GRN)/ns;
559     if (d > d2) d2 = d;
560     d = colval(cs2,BLU) - colval(cs,BLU)*colval(cs,BLU)/ns;
561     if (d > d2) d2 = d;
562     /* use s.d. if <= 1 central sample */
563     if (ns0 <= 1)
564     return(sqrt(d2/(ns-1))/brt);
565     /* use s.d./sqrt(ns0) otherwise */
566     return(sqrt(d2/((ns-1)*ns0))/brt);
567     }
568    
569    
570     double
571     comperr(neigh, nc, ns0) /* estimate relative error in neighborhood */
572     int *neigh;
573     int nc;
574     int ns0;
575     {
576     COLOR csum, csum2;
577     COLOR ctmp;
578     int i;
579     int ns;
580     register int n;
581     /* add together samples */
582     setcolor(csum, 0., 0., 0.);
583     setcolor(csum2, 0., 0., 0.);
584     for (i = 0, ns = 0; (i < nc & ns < NSAMPOK); i++) {
585     n = neigh[i];
586     addcolor(csum, cbuffer[n]);
587     if (val2map != NULL) {
588     addcolor(csum2, val2map[n]);
589     ns += sbuffer[n];
590     continue;
591     }
592     if (sbuffer[n] != 1)
593     error(CONSISTENCY, "bad count in comperr");
594     setcolor(ctmp,
595     colval(cbuffer[n],RED)*colval(cbuffer[n],RED),
596     colval(cbuffer[n],GRN)*colval(cbuffer[n],GRN),
597     colval(cbuffer[n],BLU)*colval(cbuffer[n],BLU));
598     addcolor(csum2, ctmp);
599     ns++;
600     }
601     return(estimaterr(csum, csum2, ns, ns0));
602     }
603    
604    
605     void
606     comp_frame_error() /* initialize frame error values */
607     {
608     BYTE *edone = NULL;
609     COLOR objamb;
610     double eest;
611     int neigh[NSAMPOK];
612     int nc;
613     int x, y, i, j;
614     register int n;
615    
616     if (!silent) {
617     printf("\tComputing error map\n");
618     fflush(stdout);
619     }
620     if (acctab[0] <= FTINY) /* initialize accuracy table */
621     for (i = 256; i--; )
622     acctab[i] = errorf(i);
623     /* estimate sample error */
624     if (!curparams->ambounce && hirendparams.ambounce) {
625     /*
626     * Our error estimate for the initial value is based
627     * on the assumption that most of it comes from the
628     * lack of an interreflection calculation. The relative
629     * error should be less than the ambient value divided
630     * by the returned ray value -- we take half of this.
631     */
632     edone = (BYTE *)calloc(hres*vres, sizeof(BYTE));
633     for (y = vres; y--; )
634     for (x = hres; x--; ) {
635     n = fndx(x, y);
636     if ((abuffer[n] != ALOWQ | obuffer[n] == OVOID))
637     continue;
638     if (!getambcolor(objamb, obuffer[n]))
639     continue;
640     multcolor(objamb, ambval);
641     if ((eest = bright(cbuffer[n])) <= FTINY)
642     continue;
643     eest = bright(objamb) / eest;
644     if (eest > 1.) /* should we report this? */
645     continue;
646     eest *= 0.50; /* use 50% ambient error */
647     i = errori(eest);
648     if (i < AMIN) i = AMIN;
649     else if (i >= ADISTANT/2) i = ADISTANT/2-1;
650     abuffer[n] = i;
651     edone[n] = 1;
652     }
653     }
654     /* final statistical estimate */
655     for (y = vres; y--; )
656     for (x = hres; x--; ) {
657     n = fndx(x, y);
658     if (abuffer[n] == ADISTANT)
659     continue; /* don't update these */
660     if (edone != NULL && edone[n])
661     continue; /* already done this */
662     if (sbuffer[n] >= 255) {
663     abuffer[n] = ADISTANT;
664     continue; /* can't take any more */
665     }
666     nc = getclosest(neigh, NSAMPOK, x, y);
667     if (nc <= 0) {
668     abuffer[n] = ANOVAL;
669     continue; /* no clue what to do for him */
670     }
671     i = errori(comperr(neigh, nc, sbuffer[n]));
672     if (i < AMIN) i = AMIN;
673     else if (i >= ADISTANT) i = ADISTANT-1;
674     abuffer[n] = i;
675     /* can't be better than closest */
676     if (i < abuffer[neigh[0]] && abuffer[neigh[0]] >= AMIN)
677     abuffer[n] = abuffer[neigh[0]];
678     }
679     if (edone != NULL)
680     free((void *)edone);
681     }
682    
683    
684     void
685     init_frame() /* render base (low quality) frame */
686     {
687     int restart;
688    
689     /* allocate/swap buffers */
690     next_frame();
691     /* check rendering status */
692     restart = (!nobjects || vdef(MOVE));
693     if (!restart && curparams != &lorendparams && nprocs > 1)
694     restart = -1;
695     if (restart > 0)
696     if (nprocs > 1)
697     ray_pdone(1);
698     else
699     ray_done(1);
700     /* post low quality parameters */
701     if (curparams != &lorendparams)
702     ray_restore(curparams = &lorendparams);
703     if (restart > 0) { /* load new octree */
704     char *oct = getoctspec(fcur);
705     if (oct == NULL) {
706     sprintf(errmsg, "cannot get scene for frame %d", fcur);
707     error(USER, errmsg);
708     }
709     if (!silent) {
710     printf("\tLoading octree...");
711     fflush(stdout);
712     }
713     if (nprocs > 1)
714     ray_pinit(oct, nprocs);
715     else
716     ray_init(oct);
717     } else if (restart < 0) { /* update children */
718     if (!silent) {
719     printf("\tRestarting %d processes...", nprocs);
720     fflush(stdout);
721     }
722     ray_pclose(0);
723     ray_popen(nprocs);
724     }
725     if (restart && !silent)
726     printf("done\n");
727     /* sample frame buffer */
728     init_frame_sample();
729     /* initialize frame error */
730     comp_frame_error();
731     return;
732     {
733     float *ebuf = (float *)malloc(sizeof(float)*hres*vres);
734     char fnm[256];
735     register int n;
736     for (n = hres*vres; n--; )
737     ebuf[n] = acctab[abuffer[n]];
738     sprintf(fnm, vval(BASENAME), fcur);
739     strcat(fnm, "_inerr.pic");
740     write_map(ebuf, fnm);
741     free((void *)ebuf);
742     }
743     }
744    
745    
746     void
747     filter_frame() /* interpolation, motion-blur, and exposure */
748     {
749     double expval = expspec_val(getexp(fcur));
750     int x, y;
751     int neigh[NPINTERP];
752     int nc;
753     COLOR cval;
754     double w, wsum;
755     register int n;
756    
757     #if 0
758     /* XXX TEMPORARY!! */
759     conspicuity();
760     write_map(cerrmap, "outcmap.pic");
761     {
762     float *ebuf = (float *)malloc(sizeof(float)*hres*vres);
763     for (n = hres*vres; n--; )
764     ebuf[n] = acctab[abuffer[n]];
765     write_map(ebuf, "outerr.pic");
766     free((void *)ebuf);
767     }
768     #endif
769    
770     if (!silent) {
771     printf("\tFiltering frame\n");
772     fflush(stdout);
773     }
774     /* normalize samples */
775     for (y = vres; y--; )
776     for (x = hres; x--; ) {
777     n = fndx(x, y);
778     if (sbuffer[n] <= 1)
779     continue;
780     w = 1.0/(double)sbuffer[n];
781     scalecolor(cbuffer[n], w);
782     }
783     /* interpolate samples */
784     for (y = vres; y--; )
785     for (x = hres; x--; ) {
786     n = fndx(x, y);
787     if (sbuffer[n])
788     continue;
789     nc = getclosest(neigh, NPINTERP, x, y);
790     setcolor(cbuffer[n], 0., 0., 0.);
791     wsum = 0.;
792     while (nc-- > 0) {
793     copycolor(cval, cbuffer[neigh[nc]]);
794     w = sample_wt((neigh[nc]%hres) - x,
795     (neigh[nc]/hres) - y);
796     scalecolor(cval, w);
797     addcolor(cbuffer[n], cval);
798     wsum += w;
799     }
800     if (wsum > FTINY) {
801     w = 1.0/wsum;
802     scalecolor(cbuffer[n], w);
803     }
804     }
805     /* motion blur if requested */
806     if (mblur > .02) {
807     int len;
808     int xs, ys, xl, yl;
809     int rise, run;
810     long rise2, run2;
811     int n2;
812     int cnt;
813     /* sum in motion streaks */
814     bzero(outbuffer, sizeof(COLOR)*hres*vres);
815     bzero(wbuffer, sizeof(float)*hres*vres);
816     for (y = vres; y--; )
817     for (x = hres; x--; ) {
818     n = fndx(x, y);
819     if (xmbuffer[n] == MO_UNK) {
820     run = rise = 0;
821     } else {
822     run = (int)(mblur*xmbuffer[n]);
823     rise = (int)(mblur*ymbuffer[n]);
824     }
825     if (!(run | rise)) {
826     addcolor(outbuffer[n], cbuffer[n]);
827     wbuffer[n] += 1.;
828     continue;
829     }
830     xl = x - run/4;
831     yl = y - rise/4;
832     if (run < 0) { xs = -1; run = -run; }
833     else xs = 1;
834     if (rise < 0) { ys = -1; rise = -rise; }
835     else ys = 1;
836     rise2 = run2 = 0L;
837     if (rise > run) {
838     cnt = rise + 1;
839     w = 1./cnt;
840     copycolor(cval, cbuffer[n]);
841     scalecolor(cval, w);
842     while (cnt)
843     if (rise2 >= run2) {
844     if ((xl >= 0 & xl < hres &
845     yl >= 0 & yl < vres)) {
846     n2 = fndx(xl, yl);
847     addcolor(outbuffer[n2],
848     cval);
849     wbuffer[n2] += w;
850     }
851     yl += ys;
852     run2 += run;
853     cnt--;
854     } else {
855     xl += xs;
856     rise2 += rise;
857     }
858     } else {
859     cnt = run + 1;
860     w = 1./cnt;
861     copycolor(cval, cbuffer[n]);
862     scalecolor(cval, w);
863     while (cnt)
864     if (run2 >= rise2) {
865     if ((xl >= 0 & xl < hres &
866     yl >= 0 & yl < vres)) {
867     n2 = fndx(xl, yl);
868     addcolor(outbuffer[n2],
869     cval);
870     wbuffer[n2] += w;
871     }
872     xl += xs;
873     rise2 += rise;
874     cnt--;
875     } else {
876     yl += ys;
877     run2 += run;
878     }
879     }
880     }
881     /* compute final results */
882     for (y = vres; y--; )
883     for (x = hres; x--; ) {
884     n = fndx(x, y);
885     if (wbuffer[n] <= FTINY)
886     continue;
887     w = 1./wbuffer[n];
888     scalecolor(outbuffer[n], w);
889     }
890     } else
891     for (n = hres*vres; n--; )
892     copycolor(outbuffer[n], cbuffer[n]);
893     /*
894     for (n = hres*vres; n--; )
895     if (!sbuffer[n])
896     setcolor(outbuffer[n], 0., 0., 0.);
897     */
898     /* adjust exposure */
899     if ((expval < 0.99 | expval > 1.01))
900     for (n = hres*vres; n--; )
901     scalecolor(outbuffer[n], expval);
902     return;
903     {
904     float *sbuf = (float *)malloc(sizeof(float)*hres*vres);
905     char fnm[256];
906     sprintf(fnm, vval(BASENAME), fcur);
907     strcat(fnm, "_outsamp.pic");
908     for (n = hres*vres; n--; )
909     sbuf[n] = (float)sbuffer[n];
910     write_map(sbuf, fnm);
911     free((void *)sbuf);
912     }
913     }
914    
915    
916     void
917     send_frame() /* send frame to destination */
918     {
919     char pfname[1024];
920     double d;
921     FILE *fp;
922     int y;
923     /* open output picture */
924     sprintf(pfname, vval(BASENAME), fcur);
925     strcat(pfname, ".pic");
926     fp = fopen(pfname, "w");
927     if (fp == NULL) {
928     sprintf(errmsg, "cannot open output frame \"%s\"", pfname);
929     error(SYSTEM, errmsg);
930     }
931     #ifdef MSDOS
932     setmode(fileno(fp), O_BINARY);
933     #endif
934     if (!silent) {
935     printf("\tWriting to \"%s\"\n", pfname);
936     fflush(stdout);
937     }
938     /* write header */
939     newheader("RADIANCE", fp);
940     printargs(gargc, gargv, fp);
941     fprintf(fp, "SOFTWARE= %s\n", VersionID);
942     fprintf(fp, "FRAME=%d\n", fcur);
943     fputnow(fp);
944     fputs(VIEWSTR, fp); fprintview(&vw, fp); fputc('\n', fp);
945     d = expspec_val(getexp(fcur));
946     if ((d < 0.99 | d > 1.01))
947     fputexpos(d, fp);
948     d = viewaspect(&vw) * hres / vres;
949     if ((d < 0.99 | d > 1.01))
950     fputaspect(d, fp);
951     fputformat(COLRFMT, fp);
952     fputc('\n', fp); /* end header */
953     fprtresolu(hres, vres, fp);
954     if (fflush(fp) == EOF)
955     goto writerr;
956     #if (PIXSTANDARD != (YMAJOR|YDECR))
957     error(CONSISTENCY, "bad code in send_frame");
958     #endif
959     for (y = vres; y--; ) /* write scanlines */
960     if (fwritescan(outbuffer+y*hres, hres, fp) < 0)
961     goto writerr;
962     if (fclose(fp) == EOF)
963     goto writerr;
964     return; /* all is well */
965     writerr:
966     sprintf(errmsg, "error writing frame \"%s\"", pfname);
967     error(SYSTEM, errmsg);
968     }
969    
970    
971     void
972     free_frame() /* free frame allocation */
973     {
974     if (cbuffer == NULL)
975     return;
976     free((void *)cbuffer); cbuffer = NULL;
977     free((void *)zbuffer); zbuffer = NULL;
978     free((void *)obuffer); obuffer = NULL;
979     free((void *)xmbuffer); xmbuffer = NULL;
980     free((void *)ymbuffer); ymbuffer = NULL;
981     free((void *)cprev); cprev = NULL;
982     free((void *)zprev); zprev = NULL;
983     free((void *)oprev); oprev = NULL;
984     cerrmap = NULL;
985     val2map = NULL;
986     hres = vres = 0;
987     vw.type = vwprev.type = 0;
988     frm_stop = 0;
989     }