Back to index

radiance  4R0+20100331
ranimove1.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: ranimove1.c,v 3.15 2008/11/10 19:08:20 greg Exp $";
00003 #endif
00004 /*
00005  *  ranimove1.c
00006  *
00007  *  Basic frame rendering routines for ranimove(1).
00008  *
00009  *  Created by Gregory Ward on Wed Jan 08 2003.
00010  */
00011 
00012 #include "copyright.h"
00013 
00014 #include <string.h>
00015 
00016 #include "platform.h"
00017 #include "ranimove.h"
00018 #include "otypes.h"
00019 #include "source.h"
00020 #include "random.h"
00021 
00022 double        acctab[256];  /* accuracy value table */
00023 
00024 int           hres, vres;   /* frame resolution (fcur) */
00025 double        pixaspect;    /* pixel aspect ratio */
00026 
00027 VIEW          vw;           /* view for this frame */
00028 COLOR         *cbuffer;     /* color at each pixel */
00029 float         *zbuffer;     /* depth at each pixel */
00030 OBJECT        *obuffer;     /* object id at each pixel */
00031 short         *xmbuffer;    /* x motion at each pixel */
00032 short         *ymbuffer;    /* y motion at each pixel */
00033 BYTE          *abuffer;     /* accuracy at each pixel */
00034 BYTE          *sbuffer;     /* sample count per pixel */
00035 
00036 VIEW          vwprev;              /* last frame's view */
00037 COLOR         *cprev;              /* last frame colors */
00038 float         *zprev;              /* last frame depth */
00039 OBJECT        *oprev;              /* last frame objects */
00040 BYTE          *aprev;              /* last frame accuracy */
00041 
00042 float         *cerrmap;     /* conspicuous error map */
00043 COLOR         *val2map;     /* value-squared map for variance */
00044 
00045 double        frm_stop;     /* when to stop rendering this frame */
00046 
00047 double        hlsmax;              /* maximum high-level saliency this frame */
00048 
00049 
00050 static void next_frame(void);
00051 static int sample_here(int  x, int y);
00052 static int offset_cmp(const void   *p1, const void      *p2);
00053 static void setmotion(int   n, FVECT      wpos);
00054 static void init_frame_sample(void);
00055 
00056 
00057 #if 0
00058 extern void
00059 write_map(           /* write out float map (debugging) */
00060        float  *mp,
00061        char   *fn
00062 )
00063 {
00064        FILE   *fp = fopen(fn, "w");
00065        COLOR  scanbuf[2048];
00066        int    x, y;
00067 
00068        if (fp == NULL)
00069               return;
00070        newheader("RADIANCE", fp);
00071        fputformat(COLRFMT, fp);
00072        fputc('\n', fp);            /* end header */
00073        fprtresolu(hres, vres, fp);
00074        for (y = vres; y--; ) {            /* write scanlines */
00075               float  *bp = mp + (y+1)*hres - 1;
00076               for (x = hres; x--; bp--)
00077                      setcolor(scanbuf[x], *bp, *bp, *bp);
00078               if (fwritescan(scanbuf, hres, fp) < 0)
00079                      break;
00080        }
00081        fclose(fp);
00082 }
00083 #endif
00084 
00085 
00086 static void
00087 next_frame(void)                   /* prepare next frame buffer */
00088 {
00089        VIEW   *fv;
00090        char   *err;
00091                                    /* get previous view */
00092        if (vw.type != 0)
00093               vwprev = vw;
00094        else if (fcur > 1 && (fv = getview(fcur-1)) != NULL) {
00095               vwprev = *fv;
00096               if (setview(&vwprev) != NULL)
00097                      vwprev.type = 0;
00098        }
00099                                    /* get current view */
00100        if ((fv = getview(fcur)) == NULL) {
00101               sprintf(errmsg, "cannot get view for frame %d", fcur);
00102               error(USER, errmsg);
00103        }
00104        vw = *fv;
00105        if ((err = setview(&vw)) != NULL) {
00106               sprintf(errmsg, "view error at frame %d: %s", fcur, err);
00107               error(USER, errmsg);
00108        }
00109        if (cbuffer == NULL) {
00110                                    /* compute resolution and allocate */
00111               switch (sscanf(vval(RESOLUTION), "%d %d %lf",
00112                             &hres, &vres, &pixaspect)) {
00113               case 1:
00114                      vres = hres;
00115                      /* fall through */
00116               case 2:
00117                      pixaspect = 1.;
00118                      /* fall through */
00119               case 3:
00120                      if ((hres > 0) & (vres > 0))
00121                             break;
00122                      /* fall through */
00123               default:
00124                      sprintf(errmsg, "bad %s value", vnam(RESOLUTION));
00125                      error(USER, errmsg);
00126               }
00127               normaspect(viewaspect(&vw), &pixaspect, &hres, &vres);
00128               cbuffer = (COLOR *)malloc(sizeof(COLOR)*hres*vres);
00129               zbuffer = (float *)malloc(sizeof(float)*hres*vres);
00130               obuffer = (OBJECT *)malloc(sizeof(OBJECT)*hres*vres);
00131               xmbuffer = (short *)malloc(sizeof(short)*hres*vres);
00132               ymbuffer = (short *)malloc(sizeof(short)*hres*vres);
00133               abuffer = (BYTE *)calloc(hres*vres, sizeof(BYTE));
00134               sbuffer = (BYTE *)calloc(hres*vres, sizeof(BYTE));
00135               cprev = (COLOR *)malloc(sizeof(COLOR)*hres*vres);
00136               zprev = (float *)malloc(sizeof(float)*hres*vres);
00137               oprev = (OBJECT *)malloc(sizeof(OBJECT)*hres*vres);
00138               aprev = (BYTE *)malloc(sizeof(BYTE)*hres*vres);
00139               if ((cbuffer==NULL) | (zbuffer==NULL) | (obuffer==NULL) |
00140                             (xmbuffer==NULL) | (ymbuffer==NULL) |
00141                             (abuffer==NULL) | (sbuffer==NULL) |
00142                             (cprev==NULL) | (zprev == NULL) |
00143                             (oprev==NULL) | (aprev==NULL))
00144                      error(SYSTEM, "out of memory in init_frame");
00145               frm_stop = getTime() + rtperfrm;
00146        } else {
00147               COLOR  *cp;          /* else just swap buffers */
00148               float  *fp;
00149               OBJECT *op;
00150               BYTE   *bp;
00151               cp = cprev; cprev = cbuffer; cbuffer = cp;
00152               fp = zprev; zprev = zbuffer; zbuffer = fp;
00153               op = oprev; oprev = obuffer; obuffer = op;
00154               bp = aprev; aprev = abuffer; abuffer = bp;
00155               memset(abuffer, '\0', sizeof(BYTE)*hres*vres);
00156               memset(sbuffer, '\0', sizeof(BYTE)*hres*vres);
00157               frm_stop += rtperfrm;
00158        }
00159        cerrmap = NULL;
00160        val2map = NULL;
00161 }
00162 
00163 
00164 #define SAMPDIST     3      /* Maximum distance to neighbor sample */
00165 #define       SAMPDIST2     (SAMPDIST*SAMPDIST)
00166 
00167 
00168 static int
00169 sample_here(         /* 4x4 quincunx sample at this pixel? */
00170        register int  x,
00171        register int  y
00172 )
00173 {
00174        if (y & 0x1)         /* every other row has samples */
00175               return(0);
00176        if (y & 0x3)         /* every fourth row is offset */
00177               x += 2;
00178        return((x & 0x3) == 0);     /* every fourth column is sampled */
00179 }
00180 
00181 
00182 extern void
00183 sample_pos(   /* compute jittered sample position */
00184        double hv[2],
00185        int    x,
00186        int    y,
00187        int    sn
00188 )
00189 {
00190        int    hl[2];
00191 
00192        hl[0] = x; hl[1] = y;
00193        multisamp(hv, 2, urand(ilhash(hl,2) + sn));
00194        hv[0] = ((double)x + hv[0]) / (double)hres;
00195        hv[1] = ((double)y + hv[1]) / (double)vres;
00196 }
00197 
00198 
00199 extern double
00200 sample_wt(           /* compute interpolant sample weight */
00201        int    xo,
00202        int yo
00203 )
00204 {
00205        static double etab[400];
00206        /* we can't use the name rad2 here, for some reason Visual C
00207           thinks that is a constant (compiler bug?) */
00208        int    rad_2 = xo*xo + yo*yo;
00209        int    i;
00210 
00211        if (etab[0] <= FTINY)              /* initialize exponent table */
00212               for (i = 400; i--; )
00213                      etab[i] = exp(-0.1*i);
00214 
00215                                    /* look up Gaussian */
00216        i = (int)((10.*3./(double)SAMPDIST2)*rad_2 + .5);
00217        if (i >= 400)
00218               return(0.0);
00219        return(etab[i]);
00220 }
00221 
00222 
00223 static int
00224 offset_cmp(          /* compare offset distances */
00225        const void    *p1,
00226        const void    *p2
00227 )
00228 {
00229        return(*(const int *)p1 - *(const int *)p2);
00230 }
00231 
00232 
00233 extern int
00234 getclosest(   /* get nc closest neighbors on same object */
00235        int    *iarr,
00236        int    nc,
00237        int    x,
00238        int    y
00239 )
00240 {
00241 #define       NSCHECK              ((2*SAMPDIST+1)*(2*SAMPDIST+1))
00242        static int    hro, vro;
00243        static int    ioffs[NSCHECK];
00244        OBJECT myobj;
00245        int    i0, nf;
00246        register int  i, j;
00247                                    /* get our object number */
00248        myobj = obuffer[fndx(x, y)];
00249                                    /* special case for borders */
00250        if ((x < SAMPDIST) | (x >= hres-SAMPDIST) |
00251                      (y < SAMPDIST) | (y >= vres-SAMPDIST)) {
00252               int    tndx[NSCHECK][2];
00253               nf = 0;
00254               for (j = y - SAMPDIST; j <= y + SAMPDIST; j++) {
00255                   if (j >= vres) break;
00256                   if (j < 0) j = 0;
00257                   for (i = x - SAMPDIST; i <= x + SAMPDIST; i++) {
00258                      if (i >= hres) break;
00259                      if (i < 0) i = 0;
00260                      i0 = fndx(i, j);
00261                      if (!sbuffer[i0])
00262                             continue;
00263                      if ((myobj != OVOID) & (obuffer[i0] != myobj))
00264                             continue;
00265                      tndx[nf][0] = (i-x)*(i-x) + (j-y)*(j-y);
00266                      tndx[nf][1] = i0;
00267                      nf++;
00268                   }
00269               }
00270               qsort((void *)tndx, nf, 2*sizeof(int), offset_cmp);
00271               if (nf > nc)
00272                      nf = nc;
00273               for (i = nf; i--; )
00274                      iarr[i] = tndx[i][1];
00275               return(nf);
00276        }
00277                                    /* initialize offset array */
00278        if ((hres != hro) | (vres != vro)) {
00279               int    toffs[NSCHECK][2];
00280               i0 = fndx(SAMPDIST, SAMPDIST);
00281               nf = 0;
00282               for (i = 0; i <= 2*SAMPDIST; i++)
00283                   for (j = 0; j <= 2*SAMPDIST; j++) {
00284                      toffs[nf][0] = (i-SAMPDIST)*(i-SAMPDIST) +
00285                                    (j-SAMPDIST)*(j-SAMPDIST);
00286                      toffs[nf][1] = fndx(i, j) - i0;
00287                      nf++;
00288                   }
00289               qsort((void *)toffs, nf, 2*sizeof(int), offset_cmp);
00290               for (i = NSCHECK; i--; )
00291                      ioffs[i] = toffs[i][1];
00292               hro = hres;
00293               vro = vres;
00294        }
00295                                    /* find up to nc neighbors */
00296        i0 = fndx(x, y);
00297        for (j = 0, nf = 0; (j < NSCHECK) & (nf < nc); j++) {
00298               i = i0 + ioffs[j];
00299               if (sbuffer[i] && (myobj == OVOID) | (obuffer[i] == myobj))
00300                      iarr[nf++] = i;
00301        }
00302                                    /* return number found */
00303        return(nf);
00304 #undef NSCHECK
00305 }
00306 
00307 
00308 static void
00309 setmotion(           /* compute motion vector for this pixel */
00310               register int  n,
00311               FVECT  wpos
00312 )
00313 {
00314        FVECT  ovp;
00315        int    moi;
00316        int    xp, yp;
00317                                    /* ID object and update maximum HLS */
00318        moi = getmove(obuffer[n]);
00319        if (moi >= 0 && obj_move[moi].cprio > hlsmax)
00320               hlsmax = obj_move[moi].cprio;
00321        if (vwprev.type == 0)              /* return leaves MO_UNK */
00322               return;
00323        if (moi >= 0) {                    /* move object point back */
00324               multp3(ovp, wpos, obj_move[moi].bxfm);
00325               wpos = ovp;
00326        }
00327        viewloc(ovp, &vwprev, wpos);
00328        if (ovp[2] <= FTINY)
00329               return;
00330        xp = (int)(ovp[0]*hres);
00331        yp = (int)(ovp[1]*vres);
00332        xmbuffer[n] = xp - (n % hres);
00333        ymbuffer[n] = yp - (n / hres);
00334        if ((xp < 0) | (xp >= hres))
00335               return;
00336        if ((yp < 0) | (yp >= vres))
00337               return;
00338        n = fndx(xp, yp);
00339        if ((zprev[n] < 0.97*ovp[2]) | (zprev[n] > 1.03*ovp[2]))
00340               oprev[n] = OVOID;    /* assume it's a bad match */
00341 }
00342 
00343 
00344 static void
00345 init_frame_sample(void)            /* sample our initial frame */
00346 {
00347        RAY    ir;
00348        int    x, y;
00349        register int  n;
00350 
00351        if (!silent) {
00352               printf("\tComputing initial samples...");
00353               fflush(stdout);
00354        }
00355        hlsmax = CSF_SMN;
00356        for (y = vres; y--; )
00357            for (x = hres; x--; ) {
00358               double hv[2];
00359               n = fndx(x, y);
00360               xmbuffer[n] = MO_UNK;
00361               ymbuffer[n] = MO_UNK;
00362               sample_pos(hv, x, y, 0);
00363               ir.rmax = viewray(ir.rorg, ir.rdir, &vw, hv[0], hv[1]);
00364               if (ir.rmax < -FTINY) {
00365                      setcolor(cbuffer[n], 0., 0., 0.);
00366                      zbuffer[n] = FHUGE;
00367                      obuffer[n] = OVOID;
00368                      abuffer[n] = ADISTANT;
00369                      continue;
00370               }
00371               if (!sample_here(x, y)) {   /* just cast */
00372                      rayorigin(&ir, PRIMARY, NULL, NULL);
00373                      if (!localhit(&ir, &thescene)) {
00374                             if (ir.ro != &Aftplane)
00375                                    sourcehit(&ir);
00376                             copycolor(cbuffer[n], ir.rcol);
00377                             zbuffer[n] = ir.rot;
00378                             obuffer[n] = ir.robj;
00379                             abuffer[n] = ADISTANT;
00380                             sbuffer[n] = 1;
00381                      } else {
00382                             zbuffer[n] = ir.rot;
00383                             obuffer[n] = ir.robj;
00384                             setmotion(n, ir.rop);
00385                      }      
00386                      continue;
00387               }
00388               if (nprocs > 1) {           /* get sample */
00389                      int    rval;
00390                      rayorigin(&ir, PRIMARY, NULL, NULL);
00391                      ir.rno = n;
00392                      rval = ray_pqueue(&ir);
00393                      if (!rval)
00394                             continue;
00395                      if (rval < 0)
00396                             quit(1);
00397                      n = ir.rno;
00398               } else
00399                      ray_trace(&ir);
00400               copycolor(cbuffer[n], ir.rcol);
00401               zbuffer[n] = ir.rot;
00402               obuffer[n] = ir.robj;
00403               sbuffer[n] = 1;
00404               if (ir.rot >= FHUGE)
00405                      abuffer[n] = ADISTANT;
00406               else {
00407                      abuffer[n] = ALOWQ;
00408                      setmotion(n, ir.rop);
00409               }
00410            }
00411        if (nprocs > 1)                    /* get stragglers */
00412               while (ray_presult(&ir, 0)) {
00413                      n = ir.rno;
00414                      copycolor(cbuffer[n], ir.rcol);
00415                      zbuffer[n] = ir.rot;
00416                      obuffer[n] = ir.robj;
00417                      sbuffer[n] = 1;
00418                      if (ir.rot >= FHUGE)
00419                             abuffer[n] = ADISTANT;
00420                      else {
00421                             abuffer[n] = ALOWQ;
00422                             setmotion(n, ir.rop);
00423                      }
00424               }
00425                                    /* ambiguate object boundaries */
00426        for (y = vres-1; y--; )
00427            for (x = hres-1; x--; ) {
00428               OBJECT obj;
00429               n = fndx(x, y);
00430               if ((obj = obuffer[n]) == OVOID)
00431                      continue;
00432               if ((obuffer[n+1] != OVOID) & (obuffer[n+1] != obj)) {
00433                      obuffer[n] = OVOID;
00434                      obuffer[n+1] = OVOID;
00435               }
00436               if ((obuffer[n+hres] != OVOID) & (obuffer[n+hres] != obj)) {
00437                      obuffer[n] = OVOID;
00438                      obuffer[n+hres] = OVOID;
00439               }
00440            }
00441 
00442        if (!silent)
00443               printf("done\n");
00444 }
00445 
00446 
00447 extern int
00448 getambcolor(         /* get ambient color for object if we can */
00449               COLOR  clr,
00450               int    obj
00451 )
00452 {
00453        register OBJREC      *op;
00454 
00455        if (obj == OVOID)
00456               return(0);
00457        op = objptr(obj);
00458        if ((op->otype == OBJ_INSTANCE) & (op->omod == OVOID))
00459               return(0);
00460                                    /* search for material */
00461        do {
00462               if (op->omod == OVOID || ofun[op->otype].flags & T_X)
00463                      return(0);
00464               op = objptr(op->omod);
00465        } while (!ismaterial(op->otype));
00466        /*
00467         * Since this routine is called to compute the difference
00468         * from rendering with and without interreflections,
00469         * we don't want to return colors for materials that are
00470         * explicitly excluded from the HQ ambient calculation.
00471         */
00472        if (hirendparams.ambincl >= 0) {
00473               int    i;
00474               char   *lv;
00475               for (i = 0; (lv = rpambmod(&hirendparams,i)) != NULL; i++)
00476                      if (lv[0] == op->oname[0] &&
00477                                    !strcmp(lv+1, op->oname+1))
00478                             break;
00479               if ((lv != NULL) != hirendparams.ambincl)
00480                      return(0);
00481        }
00482        switch (op->otype) {
00483        case MAT_PLASTIC:
00484        case MAT_METAL:
00485        case MAT_PLASTIC2:
00486        case MAT_METAL2:
00487        case MAT_PFUNC:
00488        case MAT_MFUNC:
00489        case MAT_PDATA:
00490        case MAT_MDATA:
00491        case MAT_TRANS:
00492        case MAT_TRANS2:
00493        case MAT_TFUNC:
00494        case MAT_TDATA:
00495               if (op->oargs.nfargs < 3)
00496                      return(0);
00497               setcolor(clr, op->oargs.farg[0], op->oargs.farg[1],
00498                             op->oargs.farg[2]);
00499               return(1);
00500        case MAT_BRTDF:
00501               if (op->oargs.nfargs < 6)
00502                      return(0);
00503               setcolor(clr, op->oargs.farg[0]+op->oargs.farg[3],
00504                             op->oargs.farg[1]+op->oargs.farg[4],
00505                             op->oargs.farg[2]+op->oargs.farg[5]);
00506               scalecolor(clr, 0.5);
00507               return(1);
00508        case MAT_LIGHT:
00509        case MAT_GLOW:
00510        case MAT_ILLUM:
00511               setcolor(clr, 0., 0., 0.);
00512               return(1);
00513        }
00514        return(0);
00515 }
00516 
00517 
00518 extern double
00519 estimaterr(          /* estimate relative error from samples */
00520               COLOR  cs,
00521               COLOR  cs2,
00522               int    ns,
00523               int ns0
00524 )
00525 {
00526        double d, d2, brt;
00527 
00528        if (ns <= 1 || (brt = bright(cs)/ns) < 1e-14)
00529               return(1.0);
00530                                    /* use largest of RGB std. dev. */
00531        d2 = colval(cs2,RED) - colval(cs,RED)*colval(cs,RED)/ns;
00532        d = colval(cs2,GRN) - colval(cs,GRN)*colval(cs,GRN)/ns;
00533        if (d > d2) d2 = d;
00534        d = colval(cs2,BLU) - colval(cs,BLU)*colval(cs,BLU)/ns;
00535        if (d > d2) d2 = d;
00536                                    /* use s.d. if <= 1 central sample */
00537        if (ns0 <= 1)
00538               return(sqrt(d2/(ns-1))/brt);
00539                                    /* use s.d./sqrt(ns0) otherwise */
00540        return(sqrt(d2/((ns-1)*ns0))/brt);
00541 }
00542 
00543 
00544 extern double
00545 comperr(             /* estimate relative error in neighborhood */
00546               int    *neigh,
00547               int    nc,
00548               int    ns0
00549 )
00550 {
00551        COLOR  csum, csum2;
00552        COLOR  ctmp;
00553        int    i;
00554        int    ns;
00555        register int  n;
00556                                    /* add together samples */
00557        setcolor(csum, 0., 0., 0.);
00558        setcolor(csum2, 0., 0., 0.);
00559        for (i = 0, ns = 0; (i < nc) & (ns < NSAMPOK); i++) {
00560               n = neigh[i];
00561               addcolor(csum, cbuffer[n]);
00562               if (val2map != NULL) {
00563                      addcolor(csum2, val2map[n]);
00564                      ns += sbuffer[n];
00565                      continue;
00566               }
00567               if (sbuffer[n] != 1)
00568                      error(CONSISTENCY, "bad count in comperr");
00569               setcolor(ctmp,
00570                      colval(cbuffer[n],RED)*colval(cbuffer[n],RED),
00571                      colval(cbuffer[n],GRN)*colval(cbuffer[n],GRN),
00572                      colval(cbuffer[n],BLU)*colval(cbuffer[n],BLU));
00573               addcolor(csum2, ctmp);
00574               ns++;
00575        }
00576        return(estimaterr(csum, csum2, ns, ns0));
00577 }
00578 
00579 
00580 extern void
00581 comp_frame_error(void)             /* initialize frame error values */
00582 {
00583        BYTE   *edone = NULL;
00584        COLOR  objamb;
00585        double eest;
00586        int    neigh[NSAMPOK];
00587        int    nc;
00588        int    x, y, i;
00589        register int  n;
00590 
00591        if (!silent) {
00592               printf("\tComputing error map\n");
00593               fflush(stdout);
00594        }
00595        if (acctab[0] <= FTINY)            /* initialize accuracy table */
00596               for (i = 256; i--; )
00597                      acctab[i] = errorf(i);
00598                                    /* estimate sample error */
00599        if (!curparams->ambounce && hirendparams.ambounce) {
00600               /*
00601                * Our error estimate for the initial value is based
00602                * on the assumption that most of it comes from the
00603                * lack of an interreflection calculation.  The relative
00604                * error should be less than the ambient value divided
00605                * by the returned ray value -- we take half of this.
00606                */
00607               edone = (BYTE *)calloc(hres*vres, sizeof(BYTE));
00608               for (y = vres; y--; )
00609                   for (x = hres; x--; ) {
00610                      n = fndx(x, y);
00611                      if ((abuffer[n] != ALOWQ) | (obuffer[n] == OVOID))
00612                             continue;
00613                      if (!getambcolor(objamb, obuffer[n]))
00614                             continue;
00615                      multcolor(objamb, ambval);
00616                      if ((eest = bright(cbuffer[n])) <= FTINY)
00617                             continue;
00618                      eest = bright(objamb) / eest;
00619                      if (eest > 1.)       /* should we report this? */
00620                             continue;
00621                      eest *= 0.50; /* use 50% ambient error */
00622                      i = errori(eest);
00623                      if (i < AMIN) i = AMIN;
00624                      else if (i >= ADISTANT/2) i = ADISTANT/2-1;
00625                      abuffer[n] = i;
00626                      edone[n] = 1;
00627                   }
00628        }
00629                                    /* final statistical estimate */
00630        for (y = vres; y--; )
00631            for (x = hres; x--; ) {
00632               n = fndx(x, y);
00633               if (abuffer[n] == ADISTANT)
00634                      continue;     /* don't update these */
00635               if (edone != NULL && edone[n])
00636                      continue;     /* already done this */
00637               if (sbuffer[n] >= 255) {
00638                      abuffer[n] = ADISTANT;
00639                      continue;     /* can't take any more */
00640               }
00641               nc = getclosest(neigh, NSAMPOK, x, y);
00642               if (nc <= 0) {
00643                      abuffer[n] = ANOVAL;
00644                      continue;     /* no clue what to do for him */
00645               }
00646               i = errori(comperr(neigh, nc, sbuffer[n]));
00647               if (i < AMIN) i = AMIN;
00648               else if (i >= ADISTANT) i = ADISTANT-1;
00649               abuffer[n] = i;
00650                                    /* can't be better than closest */
00651               if (i < abuffer[neigh[0]] && abuffer[neigh[0]] >= AMIN)
00652                      abuffer[n] = abuffer[neigh[0]];
00653            }
00654        if (edone != NULL)
00655               free((void *)edone);
00656 }
00657 
00658 
00659 extern void
00660 init_frame(void)                   /* render base (low quality) frame */
00661 {
00662        int    restart;
00663                                    /* allocate/swap buffers */
00664        next_frame();
00665                                    /* check rendering status */
00666        restart = (!nobjects || vdef(MOVE));
00667        if (!restart && curparams != &lorendparams && nprocs > 1)
00668               restart = -1;
00669                                    /* post low quality parameters */
00670        if (curparams != &lorendparams)
00671               ray_restore(curparams = &lorendparams);
00672        if (restart > 0) {          /* load new octree */
00673               char   *oct = getoctspec(fcur);
00674               if (oct == NULL) {
00675                      sprintf(errmsg, "cannot get scene for frame %d", fcur);
00676                      error(USER, errmsg);
00677               }
00678               if (!silent) {
00679                      printf("\tLoading octree...");
00680                      fflush(stdout);
00681               }
00682               if (nprocs > 1)
00683                      ray_pinit(oct, nprocs);
00684               else
00685                      ray_init(oct);
00686        } else if (restart < 0) {   /* update children */
00687               if (!silent) {
00688                      printf("\tRestarting %d processes...", nprocs);
00689                      fflush(stdout);
00690               }
00691               ray_pclose(0);
00692               ray_popen(nprocs);
00693        }
00694        if (restart && !silent)
00695               printf("done\n");
00696                                    /* sample frame buffer */
00697        init_frame_sample();
00698                                    /* initialize frame error */
00699        comp_frame_error();
00700 #if 0
00701 {
00702        float  *ebuf = (float *)malloc(sizeof(float)*hres*vres);
00703        char   fnm[256];
00704        register int  n;
00705        for (n = hres*vres; n--; )
00706               ebuf[n] = acctab[abuffer[n]];
00707        sprintf(fnm, vval(BASENAME), fcur);
00708        strcat(fnm, "_inerr.pic");
00709        write_map(ebuf, fnm);
00710        free((void *)ebuf);
00711 }
00712 #endif
00713 }
00714 
00715 
00716 extern void
00717 filter_frame(void)                 /* interpolation, motion-blur, and exposure */
00718 {
00719        double expval = expspec_val(getexp(fcur));
00720        int    x, y;
00721        int    neigh[NPINTERP];
00722        int    nc;
00723        COLOR  cval;
00724        double w, wsum;
00725        register int  n;
00726 
00727 #if 0
00728        /* XXX TEMPORARY!! */
00729        conspicuity();
00730        write_map(cerrmap, "outcmap.pic");
00731        {
00732               float  *ebuf = (float *)malloc(sizeof(float)*hres*vres);
00733               for (n = hres*vres; n--; )
00734                      ebuf[n] = acctab[abuffer[n]];
00735               write_map(ebuf, "outerr.pic");
00736               free((void *)ebuf);
00737        }
00738 #endif
00739 
00740        if (!silent) {
00741               printf("\tFiltering frame\n");
00742               fflush(stdout);
00743        }
00744                                    /* normalize samples */
00745        for (y = vres; y--; )
00746            for (x = hres; x--; ) {
00747               n = fndx(x, y);
00748               if (sbuffer[n] <= 1)
00749                      continue;
00750               w = 1.0/(double)sbuffer[n];
00751               scalecolor(cbuffer[n], w);
00752            }
00753                                    /* interpolate samples */
00754        for (y = vres; y--; )
00755            for (x = hres; x--; ) {
00756               n = fndx(x, y);
00757               if (sbuffer[n])
00758                      continue;
00759               nc = getclosest(neigh, NPINTERP, x, y);
00760               setcolor(cbuffer[n], 0., 0., 0.);
00761               if (nc <= 0) {              /* no acceptable neighbors */
00762                      if (y < vres-1)
00763                             nc = fndx(x, y+1);
00764                      else if (x < hres-1)
00765                             nc = fndx(x+1, y);
00766                      else
00767                             continue;
00768                      copycolor(cbuffer[n], cbuffer[nc]);
00769                      continue;
00770               }
00771               wsum = 0.;
00772               while (nc-- > 0) {
00773                      copycolor(cval, cbuffer[neigh[nc]]);
00774                      w = sample_wt((neigh[nc]%hres) - x,
00775                                    (neigh[nc]/hres) - y);
00776                      scalecolor(cval, w);
00777                      addcolor(cbuffer[n], cval);
00778                      wsum += w;
00779               }
00780               w = 1.0/wsum;
00781               scalecolor(cbuffer[n], w);
00782            }
00783                                    /* motion blur if requested */
00784        if (mblur > .02) {
00785               int    xs, ys, xl, yl;
00786               int    rise, run;
00787               long   rise2, run2;
00788               int    n2;
00789               int    cnt;
00790                                    /* sum in motion streaks */
00791               memset(outbuffer, '\0', sizeof(COLOR)*hres*vres);
00792               memset(wbuffer, '\0', sizeof(float)*hres*vres);
00793               for (y = vres; y--; )
00794                   for (x = hres; x--; ) {
00795                      n = fndx(x, y);
00796                      if (xmbuffer[n] == MO_UNK) {
00797                             run = rise = 0;
00798                      } else {
00799                             run = (int)(mblur*xmbuffer[n]);
00800                             rise = (int)(mblur*ymbuffer[n]);
00801                      }
00802                      if (!(run | rise)) {
00803                             addcolor(outbuffer[n], cbuffer[n]);
00804                             wbuffer[n] += 1.;
00805                             continue;
00806                      }
00807                      xl = x - run/4;
00808                      yl = y - rise/4;
00809                      if (run < 0) { xs = -1; run = -run; }
00810                      else xs = 1;
00811                      if (rise < 0) { ys = -1; rise = -rise; }
00812                      else ys = 1;
00813                      rise2 = run2 = 0L;
00814                      if (rise > run) {
00815                             cnt = rise + 1;
00816                             w = 1./cnt;
00817                             copycolor(cval, cbuffer[n]);
00818                             scalecolor(cval, w);
00819                             while (cnt)
00820                                    if (rise2 >= run2) {
00821                                           if ((xl >= 0) & (xl < hres) &
00822                                               (yl >= 0) & (yl < vres)) {
00823                                                  n2 = fndx(xl, yl);
00824                                                  addcolor(outbuffer[n2],
00825                                                                cval);
00826                                                  wbuffer[n2] += w;
00827                                           }
00828                                           yl += ys;
00829                                           run2 += run;
00830                                           cnt--;
00831                                    } else {
00832                                           xl += xs;
00833                                           rise2 += rise;
00834                                    }
00835                      } else {
00836                             cnt = run + 1;
00837                             w = 1./cnt;
00838                             copycolor(cval, cbuffer[n]);
00839                             scalecolor(cval, w);
00840                             while (cnt)
00841                                    if (run2 >= rise2) {
00842                                           if ((xl >= 0) & (xl < hres) &
00843                                               (yl >= 0) & (yl < vres)) {
00844                                                  n2 = fndx(xl, yl);
00845                                                  addcolor(outbuffer[n2],
00846                                                                cval);
00847                                                  wbuffer[n2] += w;
00848                                           }
00849                                           xl += xs;
00850                                           rise2 += rise;
00851                                           cnt--;
00852                                    } else {
00853                                           yl += ys;
00854                                           run2 += run;
00855                                    }
00856                      }
00857                   }
00858                                    /* compute final results */
00859               for (y = vres; y--; )
00860                   for (x = hres; x--; ) {
00861                      n = fndx(x, y);
00862                      if (wbuffer[n] <= FTINY)
00863                             continue;
00864                      w = 1./wbuffer[n];
00865                      scalecolor(outbuffer[n], w);
00866                   }
00867        } else
00868               for (n = hres*vres; n--; )
00869                      copycolor(outbuffer[n], cbuffer[n]);
00870        /*
00871           for (n = hres*vres; n--; )
00872                  if (!sbuffer[n])
00873                         setcolor(outbuffer[n], 0., 0., 0.);
00874         */
00875        /* adjust exposure */
00876        if ((expval < 0.99) | (expval > 1.01))
00877               for (n = hres*vres; n--; )
00878                      scalecolor(outbuffer[n], expval);
00879 #if 0
00880        {
00881               float  *sbuf = (float *)malloc(sizeof(float)*hres*vres);
00882               char   fnm[256];
00883               sprintf(fnm, vval(BASENAME), fcur);
00884               strcat(fnm, "_outsamp.pic");
00885               for (n = hres*vres; n--; )
00886                      sbuf[n] = (float)sbuffer[n];
00887               write_map(sbuf, fnm);
00888               free((void *)sbuf);
00889        }
00890 #endif
00891 }
00892 
00893 
00894 extern void
00895 send_frame(void)                   /* send frame to destination */
00896 {
00897        char   pfname[1024];
00898        double d;
00899        FILE   *fp;
00900        int    y;
00901                                    /* open output picture */
00902        sprintf(pfname, vval(BASENAME), fcur);
00903        strcat(pfname, ".hdr");
00904        fp = fopen(pfname, "w");
00905        if (fp == NULL) {
00906               sprintf(errmsg, "cannot open output frame \"%s\"", pfname);
00907               error(SYSTEM, errmsg);
00908        }
00909        SET_FILE_BINARY(fp);
00910        if (!silent) {
00911               printf("\tWriting to \"%s\"\n", pfname);
00912               fflush(stdout);
00913        }
00914                                    /* write header */
00915        newheader("RADIANCE", fp);
00916        printargs(gargc, gargv, fp);
00917        fprintf(fp, "SOFTWARE= %s\n", VersionID);
00918        fprintf(fp, "FRAME=%d\n", fcur);
00919        fputnow(fp);
00920        fputs(VIEWSTR, fp); fprintview(&vw, fp); fputc('\n', fp);
00921        d = expspec_val(getexp(fcur));
00922        if ((d < 0.99) | (d > 1.01))
00923               fputexpos(d, fp);
00924        d = viewaspect(&vw) * hres / vres;
00925        if ((d < 0.99) | (d > 1.01))
00926               fputaspect(d, fp);
00927        fputformat(COLRFMT, fp);
00928        fputc('\n', fp);            /* end header */
00929        fprtresolu(hres, vres, fp);
00930        if (fflush(fp) == EOF)
00931               goto writerr;
00932 #if (PIXSTANDARD != (YMAJOR|YDECR))
00933        error(CONSISTENCY, "bad code in send_frame");
00934 #endif
00935        for (y = vres; y--; )              /* write scanlines */
00936               if (fwritescan(outbuffer+y*hres, hres, fp) < 0)
00937                      goto writerr;
00938        if (fclose(fp) == EOF)
00939               goto writerr;
00940        return;                            /* all is well */
00941 writerr:
00942        sprintf(errmsg, "error writing frame \"%s\"", pfname);
00943        error(SYSTEM, errmsg);
00944 }
00945 
00946 
00947 extern void
00948 free_frame(void)                   /* free frame allocation */
00949 {
00950        if (cbuffer == NULL)
00951               return;
00952        free((void *)cbuffer); cbuffer = NULL;
00953        free((void *)zbuffer); zbuffer = NULL;
00954        free((void *)obuffer); obuffer = NULL;
00955        free((void *)xmbuffer); xmbuffer = NULL;
00956        free((void *)ymbuffer); ymbuffer = NULL;
00957        free((void *)cprev); cprev = NULL;
00958        free((void *)zprev); zprev = NULL;
00959        free((void *)oprev); oprev = NULL;
00960        cerrmap = NULL;
00961        val2map = NULL;
00962        hres = vres = 0;
00963        vw.type = vwprev.type = 0;
00964        frm_stop = 0;
00965 }