ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.11
Committed: Sun Jul 24 21:11:53 2005 UTC (18 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1
Changes since 3.10: +2 -2 lines
Log Message:
Fixed comments

File Contents

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