| 50 |
|
|
| 51 |
|
typedef struct { |
| 52 |
|
COLOR v; /* hemisphere sample value */ |
| 53 |
+ |
float d; /* reciprocal distance (1/rt) */ |
| 54 |
|
FVECT p; /* intersection point */ |
| 55 |
|
} AMBSAMP; /* sample value */ |
| 56 |
|
|
| 208 |
|
AMBSAMP *ap = &ambsam(hp,i,j); |
| 209 |
|
RAY ar; |
| 210 |
|
/* generate hemispherical sample */ |
| 211 |
< |
if (!getambsamp(&ar, hp, i, j, 0)) |
| 212 |
< |
goto badsample; |
| 213 |
< |
/* limit vertex distance */ |
| 211 |
> |
if (!getambsamp(&ar, hp, i, j, 0) || ar.rt <= FTINY) { |
| 212 |
> |
memset(ap, 0, sizeof(AMBSAMP)); |
| 213 |
> |
return(NULL); |
| 214 |
> |
} |
| 215 |
> |
ap->d = 1.0/ar.rt; /* limit vertex distance */ |
| 216 |
|
if (ar.rt > 10.0*thescene.cusize) |
| 217 |
|
ar.rt = 10.0*thescene.cusize; |
| 215 |
– |
else if (ar.rt <= FTINY) /* should never happen! */ |
| 216 |
– |
goto badsample; |
| 218 |
|
VSUM(ap->p, ar.rorg, ar.rdir, ar.rt); |
| 219 |
|
copycolor(ap->v, ar.rcol); |
| 220 |
|
return(ap); |
| 220 |
– |
badsample: |
| 221 |
– |
setcolor(ap->v, 0., 0., 0.); |
| 222 |
– |
VCOPY(ap->p, hp->rp->rop); |
| 223 |
– |
return(NULL); |
| 221 |
|
} |
| 222 |
|
|
| 223 |
|
|
| 314 |
|
vertex_flags(AMBHEMI *hp) |
| 315 |
|
{ |
| 316 |
|
uby8 *vflags = (uby8 *)calloc(hp->ns*hp->ns, sizeof(uby8)); |
| 320 |
– |
double *dist2a = (double *)malloc(sizeof(double)*hp->ns); |
| 317 |
|
uby8 *vf; |
| 318 |
+ |
AMBSAMP *ap; |
| 319 |
|
int i, j; |
| 320 |
|
|
| 321 |
< |
if ((vflags == NULL) | (dist2a == NULL)) |
| 321 |
> |
if (vflags == NULL) |
| 322 |
|
error(SYSTEM, "out of memory in vertex_flags()"); |
| 323 |
< |
vf = vflags; /* compute distances along first row */ |
| 324 |
< |
for (j = 0; j < hp->ns; j++) { |
| 325 |
< |
dist2a[j] = dist2(ambsam(hp,0,j).p, hp->rp->rop); |
| 326 |
< |
++vf; |
| 327 |
< |
if (!j) continue; |
| 331 |
< |
if (dist2a[j] >= dist2a[j-1]) |
| 332 |
< |
vf[0] |= 1<<VDB_x; |
| 323 |
> |
vf = vflags; |
| 324 |
> |
ap = hp->sa; /* compute farthest along first row */ |
| 325 |
> |
for (j = 0; j < hp->ns-1; j++, vf++, ap++) |
| 326 |
> |
if (ap[0].d <= ap[1].d) |
| 327 |
> |
vf[0] |= 1<<VDB_X; |
| 328 |
|
else |
| 329 |
< |
vf[-1] |= 1<<VDB_X; |
| 330 |
< |
} |
| 329 |
> |
vf[1] |= 1<<VDB_x; |
| 330 |
> |
++vf; ++ap; |
| 331 |
|
/* flag subsequent rows */ |
| 332 |
|
for (i = 1; i < hp->ns; i++) { |
| 333 |
< |
double d2n = dist2(ambsam(hp,i,0).p, hp->rp->rop); |
| 334 |
< |
for (j = 0; j < hp->ns-1; j++) { |
| 340 |
< |
double d2 = d2n; |
| 341 |
< |
if (d2 >= dist2a[j]) /* row before */ |
| 333 |
> |
for (j = 0; j < hp->ns-1; j++, vf++, ap++) { |
| 334 |
> |
if (ap[0].d <= ap[-hp->ns].d) /* row before */ |
| 335 |
|
vf[0] |= 1<<VDB_y; |
| 336 |
|
else |
| 337 |
|
vf[-hp->ns] |= 1<<VDB_Y; |
| 338 |
< |
dist2a[j] = d2n; |
| 346 |
< |
if (d2 >= dist2a[j+1]) /* diagonal we care about */ |
| 338 |
> |
if (ap[0].d <= ap[1-hp->ns].d) /* diagonal we care about */ |
| 339 |
|
vf[0] |= 1<<VDB_Xy; |
| 340 |
|
else |
| 341 |
|
vf[1-hp->ns] |= 1<<VDB_xY; |
| 342 |
< |
d2n = dist2(ambsam(hp,i,j+1).p, hp->rp->rop); |
| 351 |
< |
if (d2 >= d2n) /* column after */ |
| 342 |
> |
if (ap[0].d <= ap[1].d) /* column after */ |
| 343 |
|
vf[0] |= 1<<VDB_X; |
| 344 |
|
else |
| 345 |
|
vf[1] |= 1<<VDB_x; |
| 355 |
– |
++vf; |
| 346 |
|
} |
| 347 |
< |
if (d2n >= dist2a[j]) /* final column edge */ |
| 347 |
> |
if (ap[0].d <= ap[-hp->ns].d) /* final column edge */ |
| 348 |
|
vf[0] |= 1<<VDB_y; |
| 349 |
|
else |
| 350 |
|
vf[-hp->ns] |= 1<<VDB_Y; |
| 351 |
< |
dist2a[j] = d2n; |
| 362 |
< |
++vf; |
| 351 |
> |
++vf; ++ap; |
| 352 |
|
} |
| 364 |
– |
free(dist2a); |
| 353 |
|
return(vflags); |
| 354 |
|
} |
| 355 |
|
|
| 718 |
|
} |
| 719 |
|
|
| 720 |
|
|
| 721 |
+ |
/* Compute potential light leak direction flags for cache value */ |
| 722 |
+ |
static uint32 |
| 723 |
+ |
ambcorral(AMBHEMI *hp, FVECT uv[2], const double r0, const double r1) |
| 724 |
+ |
{ |
| 725 |
+ |
uint32 flgs = 0; |
| 726 |
+ |
int i, j; |
| 727 |
+ |
/* circle around perimeter */ |
| 728 |
+ |
for (i = 0; i < hp->ns; i++) |
| 729 |
+ |
for (j = 0; j < hp->ns; j += !i|(i==hp->ns-1) ? 1 : hp->ns-1) { |
| 730 |
+ |
AMBSAMP *ap = &ambsam(hp,i,j); |
| 731 |
+ |
FVECT vec; |
| 732 |
+ |
double u, v; |
| 733 |
+ |
double ang; |
| 734 |
+ |
int abp; |
| 735 |
+ |
if (ap->d <= FTINY) |
| 736 |
+ |
continue; |
| 737 |
+ |
VSUB(vec, ap->p, hp->rp->rop); |
| 738 |
+ |
u = DOT(vec, uv[0]) * ap->d; |
| 739 |
+ |
v = DOT(vec, uv[1]) * ap->d; |
| 740 |
+ |
if ((r0*r0*u*u + r1*r1*v*v) * ap->d*ap->d <= 1.0) |
| 741 |
+ |
continue; /* occluder outside ellipse */ |
| 742 |
+ |
ang = atan2a(v, u); /* else set direction flags */ |
| 743 |
+ |
ang += 2.0*PI*(ang < 0); |
| 744 |
+ |
ang *= 16./PI; |
| 745 |
+ |
if ((ang < .5) | (ang >= 31.5)) |
| 746 |
+ |
flgs |= 0x80000001; |
| 747 |
+ |
else |
| 748 |
+ |
flgs |= 3L<<(int)(ang-.5); |
| 749 |
+ |
} |
| 750 |
+ |
return(flgs); |
| 751 |
+ |
} |
| 752 |
+ |
|
| 753 |
+ |
|
| 754 |
|
int |
| 755 |
|
doambient( /* compute ambient component */ |
| 756 |
|
COLOR rcol, /* input/output color */ |
| 759 |
|
FVECT uv[2], /* returned (optional) */ |
| 760 |
|
float ra[2], /* returned (optional) */ |
| 761 |
|
float pg[2], /* returned (optional) */ |
| 762 |
< |
float dg[2] /* returned (optional) */ |
| 762 |
> |
float dg[2], /* returned (optional) */ |
| 763 |
> |
uint32 *crlp /* returned (optional) */ |
| 764 |
|
) |
| 765 |
|
{ |
| 766 |
|
AMBHEMI *hp = inithemi(rcol, r, wt); |
| 780 |
|
pg[0] = pg[1] = 0.0; |
| 781 |
|
if (dg != NULL) |
| 782 |
|
dg[0] = dg[1] = 0.0; |
| 783 |
+ |
if (crlp != NULL) |
| 784 |
+ |
*crlp = 0; |
| 785 |
|
/* sample the hemisphere */ |
| 786 |
|
acol[0] = acol[1] = acol[2] = 0.0; |
| 787 |
|
cnt = 0; |
| 851 |
|
if (ra[0] > maxarad) |
| 852 |
|
ra[0] = maxarad; |
| 853 |
|
} |
| 854 |
+ |
if (crlp != NULL) /* flag encroached directions */ |
| 855 |
+ |
*crlp = ambcorral(hp, uv, ra[0]*ambacc, ra[1]*ambacc); |
| 856 |
|
if (pg != NULL) { /* cap gradient if necessary */ |
| 857 |
|
d = pg[0]*pg[0]*ra[0]*ra[0] + pg[1]*pg[1]*ra[1]*ra[1]; |
| 858 |
|
if (d > 1.0) { |