ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.18
Committed: Fri Sep 28 22:20:49 2012 UTC (11 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.17: +72 -18 lines
Log Message:
Added MNAME and ZNAME variables to ranimove

File Contents

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