ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.1
Committed: Sat Feb 22 02:07:30 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

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