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

File Contents

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