ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.26
Committed: Thu May 14 20:58:03 2020 UTC (3 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R3
Changes since 3.25: +2 -2 lines
Log Message:
Fixed return-value checking for viewloc()

File Contents

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