ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.23
Committed: Wed Jan 24 04:39:52 2018 UTC (6 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2
Changes since 3.22: +2 -3 lines
Log Message:
Further tweaked viewloc() output to be 1 only if in view frame

File Contents

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