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 */ |
105 |
|
case VDB_xY: return(db2==VDB_x ? VDB_y : VDB_X); |
106 |
|
case VDB_Xy: return(db2==VDB_y ? VDB_x : VDB_Y); |
107 |
|
} |
108 |
< |
error(INTERNAL, "forbidden diagonal in vdb_edge()"); |
108 |
> |
error(CONSISTENCY, "forbidden diagonal in vdb_edge()"); |
109 |
|
return(-1); |
110 |
|
} |
111 |
|
|
272 |
|
ambsupersamp(double acol[3], AMBHEMI *hp, int cnt) |
273 |
|
{ |
274 |
|
float *earr = getambdiffs(hp); |
275 |
< |
double e2sum = 0; |
275 |
> |
double e2sum = 0.0; |
276 |
|
AMBSAMP *ap; |
277 |
|
RAY ar; |
278 |
< |
COLOR asum; |
278 |
> |
double asum[3]; |
279 |
|
float *ep; |
280 |
|
int i, j, n; |
281 |
|
|
288 |
|
for (ap = hp->sa, i = 0; i < hp->ns; i++) |
289 |
|
for (j = 0; j < hp->ns; j++, ap++) { |
290 |
|
int nss = *ep/e2sum*cnt + frandom(); |
291 |
< |
setcolor(asum, 0., 0., 0.); |
291 |
> |
asum[0] = asum[1] = asum[2] = 0.0; |
292 |
|
for (n = 1; n <= nss; n++) { |
293 |
|
if (!getambsamp(&ar, hp, i, j, n)) { |
294 |
|
nss = n-1; |
299 |
|
if (nss) { /* update returned ambient value */ |
300 |
|
const double ssf = 1./(nss + 1); |
301 |
|
for (n = 3; n--; ) |
302 |
< |
acol[n] += ssf*colval(asum,n) + |
302 |
> |
acol[n] += ssf*asum[n] + |
303 |
|
(ssf - 1.)*colval(ap->v,n); |
304 |
|
} |
305 |
|
e2sum -= *ep++; /* update remainders */ |
537 |
|
|
538 |
|
|
539 |
|
/* Compute anisotropic radii and eigenvector directions */ |
540 |
< |
static int |
540 |
> |
static void |
541 |
|
eigenvectors(FVECT uv[2], float ra[2], FVECT hessian[3]) |
542 |
|
{ |
543 |
|
double hess2[2][2]; |
559 |
|
if (i == 1) /* double-root (circle) */ |
560 |
|
evalue[1] = evalue[0]; |
561 |
|
if (!i || ((evalue[0] = fabs(evalue[0])) <= FTINY*FTINY) | |
562 |
< |
((evalue[1] = fabs(evalue[1])) <= FTINY*FTINY) ) |
563 |
< |
error(INTERNAL, "bad eigenvalue calculation"); |
564 |
< |
|
562 |
> |
((evalue[1] = fabs(evalue[1])) <= FTINY*FTINY) ) { |
563 |
> |
ra[0] = ra[1] = maxarad; |
564 |
> |
return; |
565 |
> |
} |
566 |
|
if (evalue[0] > evalue[1]) { |
567 |
|
ra[0] = sqrt(sqrt(4.0/evalue[0])); |
568 |
|
ra[1] = sqrt(sqrt(4.0/evalue[1])); |
719 |
|
} |
720 |
|
|
721 |
|
|
722 |
< |
/* Make sure radii don't extend beyond what we see in our periphery */ |
723 |
< |
static int |
724 |
< |
hem_radii(AMBHEMI *hp, FVECT uv[2], float ra[2]) |
722 |
> |
/* Compute potential light leak direction flags for cache value */ |
723 |
> |
static uint32 |
724 |
> |
ambcorral(AMBHEMI *hp, FVECT uv[2], const double r0, const double r1) |
725 |
|
{ |
726 |
< |
#ifdef AHEM_MARG |
727 |
< |
#define MAXDACCUM 47 |
728 |
< |
const double hemarg = AHEM_MARG*ambacc; /* hem margin */ |
729 |
< |
float radivisor2[MAXDACCUM+1]; |
730 |
< |
int i, j, k = hp->ns/10 + 1; /* around 5%ile */ |
731 |
< |
const int n2accum = (k < MAXDACCUM) ? k : MAXDACCUM ; |
732 |
< |
int na = 0; |
733 |
< |
double d; |
734 |
< |
/* circle around perimeter */ |
726 |
> |
const double max_d = 1.0/(minarad*ambacc + 0.001); |
727 |
> |
const double ang_res = 0.5*PI/(hp->ns-1); |
728 |
> |
const double ang_step = ang_res/((int)(16/PI*ang_res) + (1+FTINY)); |
729 |
> |
double avg_d = 0; |
730 |
> |
uint32 flgs = 0; |
731 |
> |
int i, j; |
732 |
> |
/* don't bother for a few samples */ |
733 |
> |
if (hp->ns < 12) |
734 |
> |
return(0); |
735 |
> |
/* check distances overhead */ |
736 |
> |
for (i = hp->ns*3/4; i-- > hp->ns>>2; ) |
737 |
> |
for (j = hp->ns*3/4; j-- > hp->ns>>2; ) |
738 |
> |
avg_d += ambsam(hp,i,j).d; |
739 |
> |
avg_d *= 4.0/(hp->ns*hp->ns); |
740 |
> |
if (avg_d*r0 >= 1.0) /* ceiling too low for corral? */ |
741 |
> |
return(0); |
742 |
> |
if (avg_d >= max_d) /* insurance */ |
743 |
> |
return(0); |
744 |
> |
/* else circle around perimeter */ |
745 |
|
for (i = 0; i < hp->ns; i++) |
746 |
|
for (j = 0; j < hp->ns; j += !i|(i==hp->ns-1) ? 1 : hp->ns-1) { |
747 |
|
AMBSAMP *ap = &ambsam(hp,i,j); |
739 |
– |
double radiv2 = 0; |
748 |
|
FVECT vec; |
749 |
< |
if (ap->d <= FTINY) |
750 |
< |
continue; |
749 |
> |
double u, v; |
750 |
> |
double ang, a1; |
751 |
> |
int abp; |
752 |
> |
if ((ap->d <= FTINY) | (ap->d >= max_d)) |
753 |
> |
continue; /* too far or too near */ |
754 |
|
VSUB(vec, ap->p, hp->rp->rop); |
755 |
< |
for (k = 2; k--; ) { |
756 |
< |
d = ap->d * DOT(vec, uv[k]) * ra[k]; |
757 |
< |
radiv2 += d*d; |
758 |
< |
} |
759 |
< |
radiv2 *= hemarg*hemarg * ap->d * ap->d; |
760 |
< |
if (radiv2 <= 1.0) |
761 |
< |
continue; |
751 |
< |
/* insert in percentile list */ |
752 |
< |
for (k = na; k && radiv2 > radivisor2[k-1]; k--) |
753 |
< |
radivisor2[k] = radivisor2[k-1]; |
754 |
< |
radivisor2[k] = radiv2; |
755 |
< |
na += (na < n2accum); |
755 |
> |
u = DOT(vec, uv[0]) * ap->d; |
756 |
> |
v = DOT(vec, uv[1]) * ap->d; |
757 |
> |
if ((r0*r0*u*u + r1*r1*v*v) * ap->d*ap->d <= 1.0) |
758 |
> |
continue; /* occluder outside ellipse */ |
759 |
> |
ang = atan2a(v, u); /* else set direction flags */ |
760 |
> |
for (a1 = ang-.5*ang_res; a1 <= ang+.5*ang_res; a1 += ang_step) |
761 |
> |
flgs |= 1L<<(int)(16/PI*(a1 + 2.*PI*(a1 < 0))); |
762 |
|
} |
763 |
< |
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 |
763 |
> |
return(flgs); |
764 |
|
} |
765 |
|
|
766 |
|
|
772 |
|
FVECT uv[2], /* returned (optional) */ |
773 |
|
float ra[2], /* returned (optional) */ |
774 |
|
float pg[2], /* returned (optional) */ |
775 |
< |
float dg[2] /* returned (optional) */ |
775 |
> |
float dg[2], /* returned (optional) */ |
776 |
> |
uint32 *crlp /* returned (optional) */ |
777 |
|
) |
778 |
|
{ |
779 |
|
AMBHEMI *hp = inithemi(rcol, r, wt); |
793 |
|
pg[0] = pg[1] = 0.0; |
794 |
|
if (dg != NULL) |
795 |
|
dg[0] = dg[1] = 0.0; |
796 |
+ |
if (crlp != NULL) |
797 |
+ |
*crlp = 0; |
798 |
|
/* sample the hemisphere */ |
799 |
|
acol[0] = acol[1] = acol[2] = 0.0; |
800 |
|
cnt = 0; |
815 |
|
return(-1); /* return value w/o Hessian */ |
816 |
|
} |
817 |
|
cnt = ambssamp*wt + 0.5; /* perform super-sampling? */ |
818 |
< |
if (cnt > 0) |
818 |
> |
if (cnt > 8) |
819 |
|
ambsupersamp(acol, hp, cnt); |
820 |
|
copycolor(rcol, acol); /* final indirect irradiance/PI */ |
821 |
|
if ((ra == NULL) & (pg == NULL) & (dg == NULL)) { |
829 |
|
K = 1.0; |
830 |
|
pg = NULL; |
831 |
|
dg = NULL; |
832 |
+ |
crlp = NULL; |
833 |
|
} |
834 |
|
ap = hp->sa; /* relative Y channel from here on... */ |
835 |
|
for (i = hp->ns*hp->ns; i--; ap++) |
852 |
|
if (ra[0] > ra[1]) |
853 |
|
ra[0] = ra[1]; |
854 |
|
} |
855 |
– |
hem_radii(hp, uv, ra); |
855 |
|
if (ra[0] < minarad) { |
856 |
|
ra[0] = minarad; |
857 |
|
if (ra[1] < minarad) |
865 |
|
if (ra[0] > maxarad) |
866 |
|
ra[0] = maxarad; |
867 |
|
} |
868 |
+ |
/* flag encroached directions */ |
869 |
+ |
if ((wt >= 0.5-FTINY) & (crlp != NULL)) |
870 |
+ |
*crlp = ambcorral(hp, uv, ra[0]*ambacc, ra[1]*ambacc); |
871 |
|
if (pg != NULL) { /* cap gradient if necessary */ |
872 |
|
d = pg[0]*pg[0]*ra[0]*ra[0] + pg[1]*pg[1]*ra[1]*ra[1]; |
873 |
|
if (d > 1.0) { |