22 |
|
|
23 |
|
#define MAXVERT 10 |
24 |
|
|
25 |
+ |
typedef struct splist { |
26 |
+ |
struct splist *next; /* next source in list */ |
27 |
+ |
int sn; /* source number */ |
28 |
+ |
short nv; /* number of vertices */ |
29 |
+ |
FLOAT vl[3][2]; /* vertex array (last) */ |
30 |
+ |
} SPLIST; /* source polygon list */ |
31 |
|
|
32 |
+ |
extern VIEW ourview; /* our view parameters */ |
33 |
+ |
extern int hres, vres; /* our image resolution */ |
34 |
+ |
static SPLIST *sphead = NULL; /* our list of source polys */ |
35 |
+ |
|
36 |
+ |
|
37 |
|
static int |
38 |
|
inregion(p, cv, crit) /* check if vertex is in region */ |
39 |
|
FLOAT p[2]; |
231 |
|
} |
232 |
|
|
233 |
|
|
234 |
+ |
static |
235 |
+ |
spinsert(sn, vl, nv) /* insert new source polygon */ |
236 |
+ |
int sn; |
237 |
+ |
FLOAT vl[][2]; |
238 |
+ |
int nv; |
239 |
+ |
{ |
240 |
+ |
register SPLIST *spn; |
241 |
+ |
register int i; |
242 |
+ |
|
243 |
+ |
if (nv < 3) |
244 |
+ |
return; |
245 |
+ |
if (nv > 3) |
246 |
+ |
spn = (SPLIST *)malloc(sizeof(SPLIST)+sizeof(FLOAT)*2*(nv-3)); |
247 |
+ |
else |
248 |
+ |
spn = (SPLIST *)malloc(sizeof(SPLIST)); |
249 |
+ |
if (spn == NULL) |
250 |
+ |
error(SYSTEM, "out of memory in spinsert"); |
251 |
+ |
spn->sn = sn; |
252 |
+ |
for (i = spn->nv = nv; i--; ) { |
253 |
+ |
spn->vl[i][0] = vl[i][0]; spn->vl[i][1] = vl[i][1]; |
254 |
+ |
} |
255 |
+ |
spn->next = sphead; /* push onto global list */ |
256 |
+ |
sphead = spn; |
257 |
+ |
} |
258 |
+ |
|
259 |
+ |
|
260 |
|
int |
261 |
< |
sourcepoly(vw, sn, sp) /* compute image polygon for source */ |
225 |
< |
VIEW *vw; |
261 |
> |
sourcepoly(sn, sp) /* compute image polygon for source */ |
262 |
|
int sn; |
263 |
|
FLOAT sp[MAXVERT][2]; |
264 |
|
{ |
273 |
|
register int i, j; |
274 |
|
|
275 |
|
if (s->sflags & (SDISTANT|SFLAT)) { |
276 |
< |
if (s->sflags & SDISTANT && vw->type == VT_PAR) |
276 |
> |
if (s->sflags & SDISTANT && ourview.type == VT_PAR) |
277 |
|
return(0); /* all or nothing case */ |
278 |
|
if (s->sflags & SFLAT) { |
279 |
|
for (i = 0; i < 3; i++) |
280 |
< |
ap[i] = s->sloc[i] - vw->vp[i]; |
280 |
> |
ap[i] = s->sloc[i] - ourview.vp[i]; |
281 |
|
if (DOT(ap, s->snorm) >= 0.) |
282 |
|
return(0); /* source faces away */ |
283 |
|
} |
289 |
|
if (j==2|j==3) ap[i] += s->ss[SV][i]; |
290 |
|
else ap[i] -= s->ss[SV][i]; |
291 |
|
if (s->sflags & SDISTANT) { |
292 |
< |
ap[i] *= 1. + vw->vfore; |
293 |
< |
ap[i] += vw->vp[i]; |
292 |
> |
ap[i] *= 1. + ourview.vfore; |
293 |
> |
ap[i] += ourview.vp[i]; |
294 |
|
} |
295 |
|
} |
296 |
< |
viewloc(ip, vw, ap); /* find image point */ |
296 |
> |
viewloc(ip, &ourview, ap); /* find image point */ |
297 |
|
if (ip[2] <= 0.) |
298 |
|
return(0); /* in front of view */ |
299 |
|
sp[j][0] = ip[0]; sp[j][1] = ip[1]; |
302 |
|
} |
303 |
|
/* identify furthest corner */ |
304 |
|
for (i = 0; i < 3; i++) |
305 |
< |
ap[i] = s->sloc[i] - vw->vp[i]; |
305 |
> |
ap[i] = s->sloc[i] - ourview.vp[i]; |
306 |
|
dir = (DOT(ap,s->ss[SU])>0.) | |
307 |
|
(DOT(ap,s->ss[SV])>0.)<<1 | |
308 |
|
(DOT(ap,s->ss[SW])>0.)<<2 ; |
317 |
|
if (cubeord[dir][j] & 4) ap[i] += s->ss[SW][i]; |
318 |
|
else ap[i] -= s->ss[SW][i]; |
319 |
|
} |
320 |
< |
viewloc(ip, vw, ap); /* find image point */ |
320 |
> |
viewloc(ip, &ourview, ap); /* find image point */ |
321 |
|
if (ip[2] <= 0.) |
322 |
|
return(0); /* in front of view */ |
323 |
|
pt[j][0] = ip[0]; pt[j][1] = ip[1]; |
326 |
|
} |
327 |
|
|
328 |
|
|
329 |
+ |
/* initialize by finding sources smaller than rad */ |
330 |
+ |
init_drawsources(rad) |
331 |
+ |
int rad; /* source sample size */ |
332 |
+ |
{ |
333 |
+ |
FLOAT spoly[MAXVERT][2]; |
334 |
+ |
int nsv; |
335 |
+ |
register SPLIST *sp; |
336 |
+ |
register int i; |
337 |
+ |
/* free old source list if one */ |
338 |
+ |
for (sp = sphead; sp != NULL; sp = sphead) { |
339 |
+ |
sphead = sp->next; |
340 |
+ |
free((char *)sp); |
341 |
+ |
} |
342 |
+ |
/* loop through all sources */ |
343 |
+ |
for (i = nsources; i--; ) { |
344 |
+ |
/* compute image polygon for source */ |
345 |
+ |
if (!(nsv = sourcepoly(i, spoly))) |
346 |
+ |
continue; |
347 |
+ |
/* clip to image boundaries */ |
348 |
+ |
if (!(nsv = box_clip_poly(spoly, nsv, 0., 1., 0., 1., spoly))) |
349 |
+ |
continue; |
350 |
+ |
/* big enough for standard sampling? */ |
351 |
+ |
if (minw2(spoly, nsv, ourview.vn2/ourview.hn2) > |
352 |
+ |
(double)rad*rad/hres/hres) |
353 |
+ |
continue; |
354 |
+ |
/* OK, add to our list */ |
355 |
+ |
spinsert(i, spoly, nsv); |
356 |
+ |
} |
357 |
+ |
} |
358 |
+ |
|
359 |
|
/* add sources smaller than rad to computed subimage */ |
360 |
< |
drawsources(vw, xr, yr, pic, zbf, x0, xsiz, y0, ysiz, rad) |
295 |
< |
VIEW *vw; /* full image view */ |
296 |
< |
int xr, yr; /* full image dimensions */ |
360 |
> |
drawsources(pic, zbf, x0, xsiz, y0, ysiz) |
361 |
|
COLOR *pic[]; /* subimage pixel value array */ |
362 |
|
float *zbf[]; /* subimage distance array (opt.) */ |
363 |
|
int x0, xsiz, y0, ysiz; /* origin and size of subimage */ |
300 |
– |
int rad; /* source sample size */ |
364 |
|
{ |
302 |
– |
int sn; |
365 |
|
FLOAT spoly[MAXVERT][2], ppoly[MAXVERT][2]; |
366 |
|
int nsv, npv; |
367 |
< |
int xmin, xmax, ymin, ymax, x, y, i; |
367 |
> |
int xmin, xmax, ymin, ymax, x, y; |
368 |
|
FLOAT cxy[2]; |
369 |
|
double pa; |
370 |
|
RAY sr; |
371 |
< |
/* loop through all sources */ |
372 |
< |
for (sn = 0; sn < nsources; sn++) { |
373 |
< |
/* compute image polygon for source */ |
374 |
< |
if (!(nsv = sourcepoly(vw, sn, spoly))) |
313 |
< |
continue; |
371 |
> |
register SPLIST *sp; |
372 |
> |
register int i; |
373 |
> |
/* check each source in our list */ |
374 |
> |
for (sp = sphead; sp != NULL; sp = sp->next) { |
375 |
|
/* clip source poly to subimage */ |
376 |
< |
nsv = box_clip_poly(spoly, nsv, |
377 |
< |
(double)x0/xr, (double)(x0+xsiz)/xr, |
378 |
< |
(double)y0/yr, (double)(y0+ysiz)/yr, spoly); |
376 |
> |
nsv = box_clip_poly(sp->vl, sp->nv, |
377 |
> |
(double)x0/hres, (double)(x0+xsiz)/hres, |
378 |
> |
(double)y0/vres, (double)(y0+ysiz)/vres, spoly); |
379 |
|
if (!nsv) |
380 |
|
continue; |
320 |
– |
/* is it big so sampling found it? */ |
321 |
– |
if (minw2(spoly, nsv, vw->vn2/vw->hn2) > (double)rad*rad/xr/xr) |
322 |
– |
continue; |
381 |
|
/* find common subimage (BBox) */ |
382 |
|
xmin = x0 + xsiz; xmax = x0; |
383 |
|
ymin = y0 + ysiz; ymax = y0; |
384 |
|
for (i = 0; i < nsv; i++) { |
385 |
< |
if ((double)xmin/xr > spoly[i][0]) |
386 |
< |
xmin = spoly[i][0]*xr + FTINY; |
387 |
< |
if ((double)xmax/xr < spoly[i][0]) |
388 |
< |
xmax = spoly[i][0]*xr - FTINY; |
389 |
< |
if ((double)ymin/yr > spoly[i][1]) |
390 |
< |
ymin = spoly[i][1]*yr + FTINY; |
391 |
< |
if ((double)ymax/yr < spoly[i][1]) |
392 |
< |
ymax = spoly[i][1]*yr - FTINY; |
385 |
> |
if ((double)xmin/hres > spoly[i][0]) |
386 |
> |
xmin = spoly[i][0]*hres + FTINY; |
387 |
> |
if ((double)xmax/hres < spoly[i][0]) |
388 |
> |
xmax = spoly[i][0]*hres - FTINY; |
389 |
> |
if ((double)ymin/vres > spoly[i][1]) |
390 |
> |
ymin = spoly[i][1]*vres + FTINY; |
391 |
> |
if ((double)ymax/vres < spoly[i][1]) |
392 |
> |
ymax = spoly[i][1]*vres - FTINY; |
393 |
|
} |
394 |
|
/* evaluate each pixel in BBox */ |
395 |
|
for (y = ymin; y <= ymax; y++) |
396 |
|
for (x = xmin; x <= xmax; x++) { |
397 |
|
/* subarea for pixel */ |
398 |
|
npv = box_clip_poly(spoly, nsv, |
399 |
< |
(double)x/xr, (x+1.)/xr, |
400 |
< |
(double)y/yr, (y+1.)/yr, ppoly); |
399 |
> |
(double)x/hres, (x+1.)/hres, |
400 |
> |
(double)y/vres, (y+1.)/vres, |
401 |
> |
ppoly); |
402 |
|
if (!npv) |
403 |
|
continue; /* no overlap */ |
404 |
|
convex_center(ppoly, npv, cxy); |
405 |
< |
if ((sr.rmax = viewray(sr.rorg, sr.rdir, vw, |
406 |
< |
cxy[0], cxy[1])) < -FTINY) |
405 |
> |
if ((sr.rmax = viewray(sr.rorg,sr.rdir,&ourview, |
406 |
> |
cxy[0],cxy[1])) < -FTINY) |
407 |
|
continue; /* not in view */ |
408 |
< |
if (source[sn].sflags & SSPOT && |
409 |
< |
spotout(sr, source[sn].sl.s)) |
408 |
> |
if (source[sp->sn].sflags & SSPOT && |
409 |
> |
spotout(&sr, source[sp->sn].sl.s)) |
410 |
|
continue; /* outside spot */ |
411 |
|
rayorigin(&sr, NULL, SHADOW, 1.0); |
412 |
< |
sr.rsrc = sn; |
412 |
> |
sr.rsrc = sp->sn; |
413 |
|
rayvalue(&sr); /* compute value */ |
414 |
|
if (bright(sr.rcol) <= FTINY) |
415 |
|
continue; /* missed/blocked */ |
418 |
|
sr.rt < zbf[y-y0][x-x0]) |
419 |
|
zbf[y-y0][x-x0] = sr.rt; |
420 |
|
pa = poly_area(ppoly, npv); |
421 |
< |
scalecolor(sr.rcol, pa*xr*yr); |
422 |
< |
scalecolor(pic[y-y0][x-x0], (1.-pa*xr*yr)); |
421 |
> |
scalecolor(sr.rcol, pa*hres*vres); |
422 |
> |
scalecolor(pic[y-y0][x-x0], (1.-pa*hres*vres)); |
423 |
|
addcolor(pic[y-y0][x-x0], sr.rcol); |
424 |
|
} |
425 |
|
} |