ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.14
Committed: Thu Apr 17 14:49:59 2008 UTC (16 years ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R9
Changes since 3.13: +5 -8 lines
Log Message:
Eliminated unnecessary bits of code

File Contents

# User Rev Content
1 greg 3.1 #ifndef lint
2 greg 3.14 static const char RCSid[] = "$Id: ranimove1.c,v 3.13 2008/04/17 14:44:25 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 greg 3.14 #if 0
58 schorsch 3.8 extern void
59     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     /* compute resolution and allocate */
111     switch (sscanf(vval(RESOLUTION), "%d %d %lf",
112     &hres, &vres, &pixaspect)) {
113     case 1:
114     vres = hres;
115     /* fall through */
116     case 2:
117     pixaspect = 1.;
118     /* fall through */
119     case 3:
120 schorsch 3.6 if ((hres > 0) & (vres > 0))
121 greg 3.1 break;
122     /* fall through */
123     default:
124     sprintf(errmsg, "bad %s value", vnam(RESOLUTION));
125     error(USER, errmsg);
126     }
127     normaspect(viewaspect(&vw), &pixaspect, &hres, &vres);
128     cbuffer = (COLOR *)malloc(sizeof(COLOR)*hres*vres);
129     zbuffer = (float *)malloc(sizeof(float)*hres*vres);
130     obuffer = (OBJECT *)malloc(sizeof(OBJECT)*hres*vres);
131     xmbuffer = (short *)malloc(sizeof(short)*hres*vres);
132     ymbuffer = (short *)malloc(sizeof(short)*hres*vres);
133     abuffer = (BYTE *)calloc(hres*vres, sizeof(BYTE));
134     sbuffer = (BYTE *)calloc(hres*vres, sizeof(BYTE));
135     cprev = (COLOR *)malloc(sizeof(COLOR)*hres*vres);
136     zprev = (float *)malloc(sizeof(float)*hres*vres);
137     oprev = (OBJECT *)malloc(sizeof(OBJECT)*hres*vres);
138     aprev = (BYTE *)malloc(sizeof(BYTE)*hres*vres);
139 schorsch 3.6 if ((cbuffer==NULL) | (zbuffer==NULL) | (obuffer==NULL) |
140     (xmbuffer==NULL) | (ymbuffer==NULL) |
141     (abuffer==NULL) | (sbuffer==NULL) |
142     (cprev==NULL) | (zprev == NULL) |
143     (oprev==NULL) | (aprev==NULL))
144 greg 3.1 error(SYSTEM, "out of memory in init_frame");
145     frm_stop = getTime() + rtperfrm;
146     } else {
147     COLOR *cp; /* else just swap buffers */
148     float *fp;
149     OBJECT *op;
150     BYTE *bp;
151     cp = cprev; cprev = cbuffer; cbuffer = cp;
152     fp = zprev; zprev = zbuffer; zbuffer = fp;
153     op = oprev; oprev = obuffer; obuffer = op;
154     bp = aprev; aprev = abuffer; abuffer = bp;
155 schorsch 3.4 memset(abuffer, '\0', sizeof(BYTE)*hres*vres);
156     memset(sbuffer, '\0', sizeof(BYTE)*hres*vres);
157 greg 3.1 frm_stop += rtperfrm;
158     }
159     cerrmap = NULL;
160     val2map = NULL;
161     }
162    
163    
164     #define SAMPDIST 3 /* Maximum distance to neighbor sample */
165     #define SAMPDIST2 (SAMPDIST*SAMPDIST)
166    
167    
168     static int
169 schorsch 3.8 sample_here( /* 4x4 quincunx sample at this pixel? */
170     register int x,
171     register int y
172     )
173 greg 3.1 {
174     if (y & 0x1) /* every other row has samples */
175     return(0);
176     if (y & 0x3) /* every fourth row is offset */
177     x += 2;
178     return((x & 0x3) == 0); /* every fourth column is sampled */
179     }
180    
181    
182 schorsch 3.8 extern void
183     sample_pos( /* compute jittered sample position */
184     double hv[2],
185     int x,
186     int y,
187     int sn
188     )
189 greg 3.1 {
190     int hl[2];
191    
192     hl[0] = x; hl[1] = y;
193     multisamp(hv, 2, urand(ilhash(hl,2) + sn));
194     hv[0] = ((double)x + hv[0]) / (double)hres;
195     hv[1] = ((double)y + hv[1]) / (double)vres;
196     }
197    
198    
199 schorsch 3.8 extern double
200     sample_wt( /* compute interpolant sample weight */
201     int xo,
202     int yo
203     )
204 greg 3.1 {
205     static double etab[400];
206 schorsch 3.7 /* we can't use the name rad2 here, for some reason Visual C
207     thinks that is a constant (compiler bug?) */
208     int rad_2 = xo*xo + yo*yo;
209 greg 3.1 int i;
210    
211     if (etab[0] <= FTINY) /* initialize exponent table */
212     for (i = 400; i--; )
213     etab[i] = exp(-0.1*i);
214    
215     /* look up Gaussian */
216 schorsch 3.7 i = (int)((10.*3./(double)SAMPDIST2)*rad_2 + .5);
217 greg 3.1 if (i >= 400)
218     return(0.0);
219     return(etab[i]);
220     }
221    
222    
223     static int
224 schorsch 3.8 offset_cmp( /* compare offset distances */
225     const void *p1,
226     const void *p2
227     )
228 greg 3.1 {
229     return(*(const int *)p1 - *(const int *)p2);
230     }
231    
232    
233 schorsch 3.8 extern int
234     getclosest( /* get nc closest neighbors on same object */
235     int *iarr,
236     int nc,
237     int x,
238     int y
239     )
240 greg 3.1 {
241     #define NSCHECK ((2*SAMPDIST+1)*(2*SAMPDIST+1))
242     static int hro, vro;
243     static int ioffs[NSCHECK];
244     OBJECT myobj;
245     int i0, nf;
246     register int i, j;
247     /* get our object number */
248     myobj = obuffer[fndx(x, y)];
249     /* special case for borders */
250 schorsch 3.6 if ((x < SAMPDIST) | (x >= hres-SAMPDIST) |
251     (y < SAMPDIST) | (y >= vres-SAMPDIST)) {
252 greg 3.1 int tndx[NSCHECK][2];
253     nf = 0;
254     for (j = y - SAMPDIST; j <= y + SAMPDIST; j++) {
255     if (j >= vres) break;
256     if (j < 0) j = 0;
257     for (i = x - SAMPDIST; i <= x + SAMPDIST; i++) {
258     if (i >= hres) break;
259     if (i < 0) i = 0;
260     i0 = fndx(i, j);
261     if (!sbuffer[i0])
262     continue;
263 schorsch 3.6 if ((myobj != OVOID) & (obuffer[i0] != myobj))
264 greg 3.1 continue;
265     tndx[nf][0] = (i-x)*(i-x) + (j-y)*(j-y);
266     tndx[nf][1] = i0;
267     nf++;
268     }
269     }
270     qsort((void *)tndx, nf, 2*sizeof(int), offset_cmp);
271     if (nf > nc)
272     nf = nc;
273     for (i = nf; i--; )
274     iarr[i] = tndx[i][1];
275     return(nf);
276     }
277     /* initialize offset array */
278 schorsch 3.6 if ((hres != hro) | (vres != vro)) {
279 greg 3.1 int toffs[NSCHECK][2];
280     i0 = fndx(SAMPDIST, SAMPDIST);
281     nf = 0;
282     for (i = 0; i <= 2*SAMPDIST; i++)
283     for (j = 0; j <= 2*SAMPDIST; j++) {
284     toffs[nf][0] = (i-SAMPDIST)*(i-SAMPDIST) +
285     (j-SAMPDIST)*(j-SAMPDIST);
286     toffs[nf][1] = fndx(i, j) - i0;
287     nf++;
288     }
289     qsort((void *)toffs, nf, 2*sizeof(int), offset_cmp);
290     for (i = NSCHECK; i--; )
291     ioffs[i] = toffs[i][1];
292     hro = hres;
293     vro = vres;
294     }
295     /* find up to nc neighbors */
296     i0 = fndx(x, y);
297 schorsch 3.6 for (j = 0, nf = 0; (j < NSCHECK) & (nf < nc); j++) {
298 greg 3.1 i = i0 + ioffs[j];
299 schorsch 3.6 if (sbuffer[i] && (myobj == OVOID) | (obuffer[i] == myobj))
300 greg 3.1 iarr[nf++] = i;
301     }
302     /* return number found */
303     return(nf);
304     #undef NSCHECK
305     }
306    
307    
308     static void
309 schorsch 3.8 setmotion( /* compute motion vector for this pixel */
310     register int n,
311     FVECT wpos
312     )
313 greg 3.1 {
314     FVECT ovp;
315     int moi;
316     int xp, yp;
317     /* ID object and update maximum HLS */
318     moi = getmove(obuffer[n]);
319     if (moi >= 0 && obj_move[moi].cprio > hlsmax)
320     hlsmax = obj_move[moi].cprio;
321     if (vwprev.type == 0) /* return leaves MO_UNK */
322     return;
323     if (moi >= 0) { /* move object point back */
324     multp3(ovp, wpos, obj_move[moi].bxfm);
325     wpos = ovp;
326     }
327     viewloc(ovp, &vwprev, wpos);
328     if (ovp[2] <= FTINY)
329     return;
330     xp = (int)(ovp[0]*hres);
331     yp = (int)(ovp[1]*vres);
332     xmbuffer[n] = xp - (n % hres);
333     ymbuffer[n] = yp - (n / hres);
334 schorsch 3.6 if ((xp < 0) | (xp >= hres))
335 greg 3.1 return;
336 schorsch 3.6 if ((yp < 0) | (yp >= vres))
337 greg 3.1 return;
338     n = fndx(xp, yp);
339 schorsch 3.6 if ((zprev[n] < 0.97*ovp[2]) | (zprev[n] > 1.03*ovp[2]))
340 greg 3.1 oprev[n] = OVOID; /* assume it's a bad match */
341     }
342    
343    
344     static void
345 schorsch 3.8 init_frame_sample(void) /* sample our initial frame */
346 greg 3.1 {
347     RAY ir;
348     int x, y;
349     register int n;
350    
351     if (!silent) {
352     printf("\tComputing initial samples...");
353     fflush(stdout);
354     }
355     hlsmax = CSF_SMN;
356     for (y = vres; y--; )
357     for (x = hres; x--; ) {
358     double hv[2];
359     n = fndx(x, y);
360     xmbuffer[n] = MO_UNK;
361     ymbuffer[n] = MO_UNK;
362     sample_pos(hv, x, y, 0);
363     ir.rmax = viewray(ir.rorg, ir.rdir, &vw, hv[0], hv[1]);
364     if (ir.rmax < -FTINY) {
365     setcolor(cbuffer[n], 0., 0., 0.);
366     zbuffer[n] = FHUGE;
367     obuffer[n] = OVOID;
368     abuffer[n] = ADISTANT;
369     continue;
370     }
371     if (!sample_here(x, y)) { /* just cast */
372 greg 3.10 rayorigin(&ir, PRIMARY, NULL, NULL);
373 greg 3.1 if (!localhit(&ir, &thescene)) {
374     if (ir.ro != &Aftplane)
375     sourcehit(&ir);
376     copycolor(cbuffer[n], ir.rcol);
377     zbuffer[n] = ir.rot;
378     obuffer[n] = ir.robj;
379     abuffer[n] = ADISTANT;
380     sbuffer[n] = 1;
381     } else {
382     zbuffer[n] = ir.rot;
383     obuffer[n] = ir.robj;
384     setmotion(n, ir.rop);
385     }
386     continue;
387     }
388     if (nprocs > 1) { /* get sample */
389     int rval;
390 greg 3.10 rayorigin(&ir, PRIMARY, NULL, NULL);
391 greg 3.1 ir.rno = n;
392     rval = ray_pqueue(&ir);
393     if (!rval)
394     continue;
395     if (rval < 0)
396     quit(1);
397     n = ir.rno;
398     } else
399     ray_trace(&ir);
400     copycolor(cbuffer[n], ir.rcol);
401     zbuffer[n] = ir.rot;
402     obuffer[n] = ir.robj;
403     sbuffer[n] = 1;
404     if (ir.rot >= FHUGE)
405     abuffer[n] = ADISTANT;
406     else {
407     abuffer[n] = ALOWQ;
408     setmotion(n, ir.rop);
409     }
410     }
411     if (nprocs > 1) /* get stragglers */
412     while (ray_presult(&ir, 0)) {
413     n = ir.rno;
414     copycolor(cbuffer[n], ir.rcol);
415     zbuffer[n] = ir.rot;
416     obuffer[n] = ir.robj;
417     sbuffer[n] = 1;
418     if (ir.rot >= FHUGE)
419     abuffer[n] = ADISTANT;
420     else {
421     abuffer[n] = ALOWQ;
422     setmotion(n, ir.rop);
423     }
424     }
425     /* ambiguate object boundaries */
426     for (y = vres-1; y--; )
427     for (x = hres-1; x--; ) {
428     OBJECT obj;
429     n = fndx(x, y);
430     if ((obj = obuffer[n]) == OVOID)
431     continue;
432 schorsch 3.6 if ((obuffer[n+1] != OVOID) & (obuffer[n+1] != obj)) {
433 greg 3.1 obuffer[n] = OVOID;
434     obuffer[n+1] = OVOID;
435     }
436 schorsch 3.6 if ((obuffer[n+hres] != OVOID) & (obuffer[n+hres] != obj)) {
437 greg 3.1 obuffer[n] = OVOID;
438     obuffer[n+hres] = OVOID;
439     }
440     }
441    
442     if (!silent)
443     printf("done\n");
444     }
445    
446    
447 schorsch 3.8 extern int
448     getambcolor( /* get ambient color for object if we can */
449     COLOR clr,
450     int obj
451     )
452 greg 3.1 {
453     register OBJREC *op;
454    
455     if (obj == OVOID)
456     return(0);
457     op = objptr(obj);
458 schorsch 3.6 if ((op->otype == OBJ_INSTANCE) & (op->omod == OVOID))
459 greg 3.1 return(0);
460     /* search for material */
461     do {
462     if (op->omod == OVOID || ofun[op->otype].flags & T_X)
463     return(0);
464     op = objptr(op->omod);
465     } while (!ismaterial(op->otype));
466     /*
467     * Since this routine is called to compute the difference
468     * from rendering with and without interreflections,
469     * we don't want to return colors for materials that are
470     * explicitly excluded from the HQ ambient calculation.
471     */
472     if (hirendparams.ambincl >= 0) {
473     int i;
474     char *lv;
475     for (i = 0; (lv = rpambmod(&hirendparams,i)) != NULL; i++)
476     if (lv[0] == op->oname[0] &&
477     !strcmp(lv+1, op->oname+1))
478     break;
479     if ((lv != NULL) != hirendparams.ambincl)
480     return(0);
481     }
482     switch (op->otype) {
483     case MAT_PLASTIC:
484     case MAT_METAL:
485     case MAT_PLASTIC2:
486     case MAT_METAL2:
487     case MAT_PFUNC:
488     case MAT_MFUNC:
489     case MAT_PDATA:
490     case MAT_MDATA:
491     case MAT_TRANS:
492     case MAT_TRANS2:
493     case MAT_TFUNC:
494     case MAT_TDATA:
495     if (op->oargs.nfargs < 3)
496     return(0);
497     setcolor(clr, op->oargs.farg[0], op->oargs.farg[1],
498     op->oargs.farg[2]);
499     return(1);
500     case MAT_BRTDF:
501     if (op->oargs.nfargs < 6)
502     return(0);
503     setcolor(clr, op->oargs.farg[0]+op->oargs.farg[3],
504     op->oargs.farg[1]+op->oargs.farg[4],
505     op->oargs.farg[2]+op->oargs.farg[5]);
506     scalecolor(clr, 0.5);
507     return(1);
508     case MAT_LIGHT:
509     case MAT_GLOW:
510     case MAT_ILLUM:
511     setcolor(clr, 0., 0., 0.);
512     return(1);
513     }
514     return(0);
515     }
516    
517    
518 schorsch 3.8 extern double
519     estimaterr( /* estimate relative error from samples */
520     COLOR cs,
521     COLOR cs2,
522     int ns,
523     int ns0
524     )
525 greg 3.1 {
526     double d, d2, brt;
527    
528     if (ns <= 1 || (brt = bright(cs)/ns) < 1e-14)
529     return(1.0);
530     /* use largest of RGB std. dev. */
531     d2 = colval(cs2,RED) - colval(cs,RED)*colval(cs,RED)/ns;
532     d = colval(cs2,GRN) - colval(cs,GRN)*colval(cs,GRN)/ns;
533     if (d > d2) d2 = d;
534     d = colval(cs2,BLU) - colval(cs,BLU)*colval(cs,BLU)/ns;
535     if (d > d2) d2 = d;
536     /* use s.d. if <= 1 central sample */
537     if (ns0 <= 1)
538     return(sqrt(d2/(ns-1))/brt);
539     /* use s.d./sqrt(ns0) otherwise */
540     return(sqrt(d2/((ns-1)*ns0))/brt);
541     }
542    
543    
544 schorsch 3.8 extern double
545     comperr( /* estimate relative error in neighborhood */
546     int *neigh,
547     int nc,
548     int ns0
549     )
550 greg 3.1 {
551     COLOR csum, csum2;
552     COLOR ctmp;
553     int i;
554     int ns;
555     register int n;
556     /* add together samples */
557     setcolor(csum, 0., 0., 0.);
558     setcolor(csum2, 0., 0., 0.);
559 schorsch 3.6 for (i = 0, ns = 0; (i < nc) & (ns < NSAMPOK); i++) {
560 greg 3.1 n = neigh[i];
561     addcolor(csum, cbuffer[n]);
562     if (val2map != NULL) {
563     addcolor(csum2, val2map[n]);
564     ns += sbuffer[n];
565     continue;
566     }
567     if (sbuffer[n] != 1)
568     error(CONSISTENCY, "bad count in comperr");
569     setcolor(ctmp,
570     colval(cbuffer[n],RED)*colval(cbuffer[n],RED),
571     colval(cbuffer[n],GRN)*colval(cbuffer[n],GRN),
572     colval(cbuffer[n],BLU)*colval(cbuffer[n],BLU));
573     addcolor(csum2, ctmp);
574     ns++;
575     }
576     return(estimaterr(csum, csum2, ns, ns0));
577     }
578    
579    
580 schorsch 3.8 extern void
581     comp_frame_error(void) /* initialize frame error values */
582 greg 3.1 {
583     BYTE *edone = NULL;
584     COLOR objamb;
585     double eest;
586     int neigh[NSAMPOK];
587     int nc;
588 schorsch 3.8 int x, y, i;
589 greg 3.1 register int n;
590    
591     if (!silent) {
592     printf("\tComputing error map\n");
593     fflush(stdout);
594     }
595     if (acctab[0] <= FTINY) /* initialize accuracy table */
596     for (i = 256; i--; )
597     acctab[i] = errorf(i);
598     /* estimate sample error */
599     if (!curparams->ambounce && hirendparams.ambounce) {
600     /*
601     * Our error estimate for the initial value is based
602     * on the assumption that most of it comes from the
603     * lack of an interreflection calculation. The relative
604     * error should be less than the ambient value divided
605     * by the returned ray value -- we take half of this.
606     */
607     edone = (BYTE *)calloc(hres*vres, sizeof(BYTE));
608     for (y = vres; y--; )
609     for (x = hres; x--; ) {
610     n = fndx(x, y);
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     }
628     }
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 schorsch 3.8 extern void
660     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     register int n;
705     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 schorsch 3.8 extern void
717     filter_frame(void) /* interpolation, motion-blur, and exposure */
718 greg 3.1 {
719     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     register int n;
726    
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    
740     if (!silent) {
741     printf("\tFiltering frame\n");
742     fflush(stdout);
743     }
744 greg 3.9 /* normalize samples */
745     for (y = vres; y--; )
746     for (x = hres; x--; ) {
747     n = fndx(x, y);
748     if (sbuffer[n] <= 1)
749     continue;
750     w = 1.0/(double)sbuffer[n];
751     scalecolor(cbuffer[n], w);
752     }
753     /* interpolate samples */
754     for (y = vres; y--; )
755     for (x = hres; x--; ) {
756     n = fndx(x, y);
757     if (sbuffer[n])
758     continue;
759     nc = getclosest(neigh, NPINTERP, x, y);
760     setcolor(cbuffer[n], 0., 0., 0.);
761 greg 3.12 if (nc <= 0) { /* no acceptable neighbors */
762     if (y < vres-1)
763     nc = fndx(x, y+1);
764     else if (x < hres-1)
765     nc = fndx(x+1, y);
766     else
767     continue;
768     copycolor(cbuffer[n], cbuffer[nc]);
769     continue;
770     }
771 greg 3.9 wsum = 0.;
772     while (nc-- > 0) {
773     copycolor(cval, cbuffer[neigh[nc]]);
774     w = sample_wt((neigh[nc]%hres) - x,
775     (neigh[nc]/hres) - y);
776     scalecolor(cval, w);
777     addcolor(cbuffer[n], cval);
778     wsum += w;
779     }
780 greg 3.12 w = 1.0/wsum;
781     scalecolor(cbuffer[n], w);
782 greg 3.9 }
783     /* motion blur if requested */
784 greg 3.1 if (mblur > .02) {
785 greg 3.9 int xs, ys, xl, yl;
786     int rise, run;
787     long rise2, run2;
788     int n2;
789     int cnt;
790     /* sum in motion streaks */
791     memset(outbuffer, '\0', sizeof(COLOR)*hres*vres);
792     memset(wbuffer, '\0', sizeof(float)*hres*vres);
793     for (y = vres; y--; )
794     for (x = hres; x--; ) {
795 greg 3.1 n = fndx(x, y);
796     if (xmbuffer[n] == MO_UNK) {
797     run = rise = 0;
798     } else {
799     run = (int)(mblur*xmbuffer[n]);
800     rise = (int)(mblur*ymbuffer[n]);
801     }
802     if (!(run | rise)) {
803     addcolor(outbuffer[n], cbuffer[n]);
804     wbuffer[n] += 1.;
805     continue;
806     }
807     xl = x - run/4;
808     yl = y - rise/4;
809     if (run < 0) { xs = -1; run = -run; }
810     else xs = 1;
811     if (rise < 0) { ys = -1; rise = -rise; }
812     else ys = 1;
813     rise2 = run2 = 0L;
814     if (rise > run) {
815 greg 3.9 cnt = rise + 1;
816     w = 1./cnt;
817     copycolor(cval, cbuffer[n]);
818     scalecolor(cval, w);
819     while (cnt)
820     if (rise2 >= run2) {
821     if ((xl >= 0) & (xl < hres) &
822 schorsch 3.8 (yl >= 0) & (yl < vres)) {
823 greg 3.9 n2 = fndx(xl, yl);
824     addcolor(outbuffer[n2],
825     cval);
826     wbuffer[n2] += w;
827     }
828     yl += ys;
829     run2 += run;
830     cnt--;
831     } else {
832     xl += xs;
833     rise2 += rise;
834     }
835 greg 3.1 } else {
836     cnt = run + 1;
837     w = 1./cnt;
838     copycolor(cval, cbuffer[n]);
839     scalecolor(cval, w);
840 greg 3.9 while (cnt)
841     if (run2 >= rise2) {
842     if ((xl >= 0) & (xl < hres) &
843 schorsch 3.8 (yl >= 0) & (yl < vres)) {
844 greg 3.9 n2 = fndx(xl, yl);
845     addcolor(outbuffer[n2],
846     cval);
847     wbuffer[n2] += w;
848     }
849     xl += xs;
850     rise2 += rise;
851     cnt--;
852     } else {
853     yl += ys;
854     run2 += run;
855 greg 3.1 }
856 schorsch 3.8 }
857 greg 3.9 }
858     /* compute final results */
859     for (y = vres; y--; )
860     for (x = hres; x--; ) {
861     n = fndx(x, y);
862     if (wbuffer[n] <= FTINY)
863     continue;
864     w = 1./wbuffer[n];
865     scalecolor(outbuffer[n], w);
866     }
867     } else
868     for (n = hres*vres; n--; )
869 greg 3.1 copycolor(outbuffer[n], cbuffer[n]);
870 schorsch 3.8 /*
871     for (n = hres*vres; n--; )
872 greg 3.9 if (!sbuffer[n])
873     setcolor(outbuffer[n], 0., 0., 0.);
874 schorsch 3.8 */
875     /* adjust exposure */
876 schorsch 3.6 if ((expval < 0.99) | (expval > 1.01))
877 greg 3.1 for (n = hres*vres; n--; )
878     scalecolor(outbuffer[n], expval);
879 greg 3.9 #if 0
880 schorsch 3.8 {
881     float *sbuf = (float *)malloc(sizeof(float)*hres*vres);
882     char fnm[256];
883     sprintf(fnm, vval(BASENAME), fcur);
884     strcat(fnm, "_outsamp.pic");
885     for (n = hres*vres; n--; )
886     sbuf[n] = (float)sbuffer[n];
887     write_map(sbuf, fnm);
888     free((void *)sbuf);
889     }
890 greg 3.9 #endif
891 greg 3.1 }
892    
893    
894 schorsch 3.8 extern void
895     send_frame(void) /* send frame to destination */
896 greg 3.1 {
897     char pfname[1024];
898     double d;
899     FILE *fp;
900     int y;
901     /* open output picture */
902     sprintf(pfname, vval(BASENAME), fcur);
903     strcat(pfname, ".pic");
904     fp = fopen(pfname, "w");
905     if (fp == NULL) {
906     sprintf(errmsg, "cannot open output frame \"%s\"", pfname);
907     error(SYSTEM, errmsg);
908     }
909 schorsch 3.3 SET_FILE_BINARY(fp);
910 greg 3.1 if (!silent) {
911     printf("\tWriting to \"%s\"\n", pfname);
912     fflush(stdout);
913     }
914     /* write header */
915     newheader("RADIANCE", fp);
916     printargs(gargc, gargv, fp);
917     fprintf(fp, "SOFTWARE= %s\n", VersionID);
918     fprintf(fp, "FRAME=%d\n", fcur);
919     fputnow(fp);
920     fputs(VIEWSTR, fp); fprintview(&vw, fp); fputc('\n', fp);
921     d = expspec_val(getexp(fcur));
922 schorsch 3.6 if ((d < 0.99) | (d > 1.01))
923 greg 3.1 fputexpos(d, fp);
924     d = viewaspect(&vw) * hres / vres;
925 schorsch 3.6 if ((d < 0.99) | (d > 1.01))
926 greg 3.1 fputaspect(d, fp);
927     fputformat(COLRFMT, fp);
928     fputc('\n', fp); /* end header */
929     fprtresolu(hres, vres, fp);
930     if (fflush(fp) == EOF)
931     goto writerr;
932     #if (PIXSTANDARD != (YMAJOR|YDECR))
933     error(CONSISTENCY, "bad code in send_frame");
934     #endif
935     for (y = vres; y--; ) /* write scanlines */
936     if (fwritescan(outbuffer+y*hres, hres, fp) < 0)
937     goto writerr;
938     if (fclose(fp) == EOF)
939     goto writerr;
940     return; /* all is well */
941     writerr:
942     sprintf(errmsg, "error writing frame \"%s\"", pfname);
943     error(SYSTEM, errmsg);
944     }
945    
946    
947 schorsch 3.8 extern void
948     free_frame(void) /* free frame allocation */
949 greg 3.1 {
950     if (cbuffer == NULL)
951     return;
952     free((void *)cbuffer); cbuffer = NULL;
953     free((void *)zbuffer); zbuffer = NULL;
954     free((void *)obuffer); obuffer = NULL;
955     free((void *)xmbuffer); xmbuffer = NULL;
956     free((void *)ymbuffer); ymbuffer = NULL;
957     free((void *)cprev); cprev = NULL;
958     free((void *)zprev); zprev = NULL;
959     free((void *)oprev); oprev = NULL;
960     cerrmap = NULL;
961     val2map = NULL;
962     hres = vres = 0;
963     vw.type = vwprev.type = 0;
964     frm_stop = 0;
965     }