ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.21
Committed: Fri Oct 5 00:59:38 2012 UTC (11 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.20: +43 -28 lines
Log Message:
Created pmblur2 command to compute better motion blur from ranimove runs

File Contents

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