| 23 |
|
|
| 24 |
|
#ifdef NEWAMB |
| 25 |
|
|
| 26 |
– |
/* #define AHEM_MARG 1.2 /* hem margin */ |
| 27 |
– |
|
| 26 |
|
extern void SDsquare2disk(double ds[2], double seedx, double seedy); |
| 27 |
|
|
| 28 |
|
/* vertex direction bit positions */ |
| 718 |
|
} |
| 719 |
|
|
| 720 |
|
|
| 721 |
< |
/* Make sure radii don't extend beyond what we see in our periphery */ |
| 722 |
< |
static int |
| 723 |
< |
hem_radii(AMBHEMI *hp, FVECT uv[2], float ra[2]) |
| 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 |
< |
#ifdef AHEM_MARG |
| 726 |
< |
#define MAXDACCUM 47 |
| 729 |
< |
const double hemarg = AHEM_MARG*ambacc; /* hem margin */ |
| 730 |
< |
float radivisor2[MAXDACCUM+1]; |
| 731 |
< |
int i, j, k = hp->ns/10 + 1; /* around 5%ile */ |
| 732 |
< |
const int n2accum = (k < MAXDACCUM) ? k : MAXDACCUM ; |
| 733 |
< |
int na = 0; |
| 734 |
< |
double d; |
| 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); |
| 739 |
– |
double radiv2 = 0; |
| 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 |
< |
for (k = 2; k--; ) { |
| 739 |
< |
d = ap->d * DOT(vec, uv[k]) * ra[k]; |
| 740 |
< |
radiv2 += d*d; |
| 741 |
< |
} |
| 742 |
< |
radiv2 *= hemarg*hemarg * ap->d * ap->d; |
| 743 |
< |
if (radiv2 <= 1.0) |
| 744 |
< |
continue; |
| 745 |
< |
/* insert in percentile list */ |
| 746 |
< |
for (k = na; k && radiv2 > radivisor2[k-1]; k--) |
| 747 |
< |
radivisor2[k] = radivisor2[k-1]; |
| 748 |
< |
radivisor2[k] = radiv2; |
| 755 |
< |
na += (na < n2accum); |
| 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 |
< |
if (na < n2accum) /* current radii are OK? */ |
| 758 |
< |
return(0); |
| 759 |
< |
/* else apply divisor */ |
| 760 |
< |
d = 1.0/sqrt(radivisor2[na-1]); |
| 761 |
< |
ra[0] *= d; |
| 762 |
< |
ra[1] *= d; |
| 763 |
< |
return(1); |
| 764 |
< |
#undef MAXDACCUM |
| 765 |
< |
#else |
| 766 |
< |
return(0); |
| 767 |
< |
#endif |
| 750 |
> |
return(flgs); |
| 751 |
|
} |
| 752 |
|
|
| 753 |
|
|
| 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; |
| 838 |
|
if (ra[0] > ra[1]) |
| 839 |
|
ra[0] = ra[1]; |
| 840 |
|
} |
| 855 |
– |
hem_radii(hp, uv, ra); |
| 841 |
|
if (ra[0] < minarad) { |
| 842 |
|
ra[0] = minarad; |
| 843 |
|
if (ra[1] < minarad) |
| 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) { |