ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.7
Committed: Tue Oct 21 19:19:29 2003 UTC (20 years, 6 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.6: +5 -3 lines
Log Message:
Various platform compatibility fixes.

File Contents

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