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