23 |
|
|
24 |
|
#ifdef NEWAMB |
25 |
|
|
26 |
+ |
/* #define HEM_MULT 4.0 /* hem multiplier (bigger => sparser cache) */ |
27 |
+ |
|
28 |
|
extern void SDsquare2disk(double ds[2], double seedx, double seedy); |
29 |
|
|
30 |
|
/* vertex direction bit positions */ |
52 |
|
|
53 |
|
typedef struct { |
54 |
|
COLOR v; /* hemisphere sample value */ |
55 |
+ |
float d; /* reciprocal distance (1/rt) */ |
56 |
|
FVECT p; /* intersection point */ |
57 |
|
} AMBSAMP; /* sample value */ |
58 |
|
|
210 |
|
AMBSAMP *ap = &ambsam(hp,i,j); |
211 |
|
RAY ar; |
212 |
|
/* generate hemispherical sample */ |
213 |
< |
if (!getambsamp(&ar, hp, i, j, 0)) |
214 |
< |
goto badsample; |
215 |
< |
/* limit vertex distance */ |
213 |
> |
if (!getambsamp(&ar, hp, i, j, 0) || ar.rt <= FTINY) { |
214 |
> |
memset(ap, 0, sizeof(AMBSAMP)); |
215 |
> |
return(NULL); |
216 |
> |
} |
217 |
> |
ap->d = 1.0/ar.rt; /* limit vertex distance */ |
218 |
|
if (ar.rt > 10.0*thescene.cusize) |
219 |
|
ar.rt = 10.0*thescene.cusize; |
215 |
– |
else if (ar.rt <= FTINY) /* should never happen! */ |
216 |
– |
goto badsample; |
220 |
|
VSUM(ap->p, ar.rorg, ar.rdir, ar.rt); |
221 |
|
copycolor(ap->v, ar.rcol); |
222 |
|
return(ap); |
220 |
– |
badsample: |
221 |
– |
setcolor(ap->v, 0., 0., 0.); |
222 |
– |
VCOPY(ap->p, hp->rp->rop); |
223 |
– |
return(NULL); |
223 |
|
} |
224 |
|
|
225 |
|
|
316 |
|
vertex_flags(AMBHEMI *hp) |
317 |
|
{ |
318 |
|
uby8 *vflags = (uby8 *)calloc(hp->ns*hp->ns, sizeof(uby8)); |
320 |
– |
double *dist2a = (double *)malloc(sizeof(double)*hp->ns); |
319 |
|
uby8 *vf; |
320 |
+ |
AMBSAMP *ap; |
321 |
|
int i, j; |
322 |
|
|
323 |
< |
if ((vflags == NULL) | (dist2a == NULL)) |
323 |
> |
if (vflags == NULL) |
324 |
|
error(SYSTEM, "out of memory in vertex_flags()"); |
325 |
< |
vf = vflags; /* compute distances along first row */ |
326 |
< |
for (j = 0; j < hp->ns; j++) { |
327 |
< |
dist2a[j] = dist2(ambsam(hp,0,j).p, hp->rp->rop); |
328 |
< |
++vf; |
329 |
< |
if (!j) continue; |
331 |
< |
if (dist2a[j] >= dist2a[j-1]) |
332 |
< |
vf[0] |= 1<<VDB_x; |
325 |
> |
vf = vflags; |
326 |
> |
ap = hp->sa; /* compute farthest along first row */ |
327 |
> |
for (j = 0; j < hp->ns-1; j++, vf++, ap++) |
328 |
> |
if (ap[0].d <= ap[1].d) |
329 |
> |
vf[0] |= 1<<VDB_X; |
330 |
|
else |
331 |
< |
vf[-1] |= 1<<VDB_X; |
332 |
< |
} |
331 |
> |
vf[1] |= 1<<VDB_x; |
332 |
> |
++vf; ++ap; |
333 |
|
/* flag subsequent rows */ |
334 |
|
for (i = 1; i < hp->ns; i++) { |
335 |
< |
double d2n = dist2(ambsam(hp,i,0).p, hp->rp->rop); |
336 |
< |
for (j = 0; j < hp->ns-1; j++) { |
340 |
< |
double d2 = d2n; |
341 |
< |
if (d2 >= dist2a[j]) /* row before */ |
335 |
> |
for (j = 0; j < hp->ns-1; j++, vf++, ap++) { |
336 |
> |
if (ap[0].d <= ap[-hp->ns].d) /* row before */ |
337 |
|
vf[0] |= 1<<VDB_y; |
338 |
|
else |
339 |
|
vf[-hp->ns] |= 1<<VDB_Y; |
340 |
< |
dist2a[j] = d2n; |
346 |
< |
if (d2 >= dist2a[j+1]) /* diagonal we care about */ |
340 |
> |
if (ap[0].d <= ap[1-hp->ns].d) /* diagonal we care about */ |
341 |
|
vf[0] |= 1<<VDB_Xy; |
342 |
|
else |
343 |
|
vf[1-hp->ns] |= 1<<VDB_xY; |
344 |
< |
d2n = dist2(ambsam(hp,i,j+1).p, hp->rp->rop); |
351 |
< |
if (d2 >= d2n) /* column after */ |
344 |
> |
if (ap[0].d <= ap[1].d) /* column after */ |
345 |
|
vf[0] |= 1<<VDB_X; |
346 |
|
else |
347 |
|
vf[1] |= 1<<VDB_x; |
355 |
– |
++vf; |
348 |
|
} |
349 |
< |
if (d2n >= dist2a[j]) /* final column edge */ |
349 |
> |
if (ap[0].d <= ap[-hp->ns].d) /* final column edge */ |
350 |
|
vf[0] |= 1<<VDB_y; |
351 |
|
else |
352 |
|
vf[-hp->ns] |= 1<<VDB_Y; |
353 |
< |
dist2a[j] = d2n; |
362 |
< |
++vf; |
353 |
> |
++vf; ++ap; |
354 |
|
} |
364 |
– |
free(dist2a); |
355 |
|
return(vflags); |
356 |
|
} |
357 |
|
|
720 |
|
} |
721 |
|
|
722 |
|
|
723 |
+ |
/* Make sure radii don't extend beyond what we see in our periphery */ |
724 |
+ |
static void |
725 |
+ |
hem_radii(AMBHEMI *hp, FVECT uv[2], float ra[2]) |
726 |
+ |
{ |
727 |
+ |
#ifdef HEM_MULT |
728 |
+ |
double udsum = 0, vdsum = 0; |
729 |
+ |
double uwsum = 0, vwsum = 0; |
730 |
+ |
int i, j; |
731 |
+ |
/* circle around perimeter */ |
732 |
+ |
for (i = 0; i < hp->ns; i++) |
733 |
+ |
for (j = 0; j < hp->ns; j += !i|(i==hp->ns-1) ? 1 : hp->ns-1) { |
734 |
+ |
AMBSAMP *ap = &ambsam(hp,i,j); |
735 |
+ |
FVECT vec; |
736 |
+ |
double us2, vs2; |
737 |
+ |
VSUB(vec, ap->p, hp->rp->rop); |
738 |
+ |
us2 = DOT(vec, uv[0]) * ap->d; |
739 |
+ |
us2 *= us2; |
740 |
+ |
vs2 = DOT(vec, uv[1]) * ap->d; |
741 |
+ |
vs2 *= vs2; |
742 |
+ |
udsum += us2 * ap->d; |
743 |
+ |
uwsum += us2; |
744 |
+ |
vdsum += vs2 * ap->d; |
745 |
+ |
vwsum += vs2; |
746 |
+ |
} |
747 |
+ |
uwsum *= HEM_MULT; /* adjust effective hem size */ |
748 |
+ |
vwsum *= HEM_MULT; |
749 |
+ |
/* cap radii (recall d=1/rt) */ |
750 |
+ |
if (ra[0]*udsum > uwsum) |
751 |
+ |
ra[0] = uwsum/udsum; |
752 |
+ |
if (ra[1]*vdsum > vwsum) |
753 |
+ |
ra[1] = vwsum/vdsum; |
754 |
+ |
#endif |
755 |
+ |
} |
756 |
+ |
|
757 |
+ |
|
758 |
|
int |
759 |
|
doambient( /* compute ambient component */ |
760 |
|
COLOR rcol, /* input/output color */ |
836 |
|
ra[0] = 1.0/d; |
837 |
|
if (ra[1]*(d = fabs(pg[1])) > 1.0) |
838 |
|
ra[1] = 1.0/d; |
814 |
– |
if (ra[0] > ra[1]) |
815 |
– |
ra[0] = ra[1]; |
839 |
|
} |
840 |
+ |
hem_radii(hp, uv, ra); |
841 |
+ |
if (ra[0] > ra[1]) |
842 |
+ |
ra[0] = ra[1]; |
843 |
|
if (ra[0] < minarad) { |
844 |
|
ra[0] = minarad; |
845 |
|
if (ra[1] < minarad) |