32 |
|
#define SPA_REFL 01 /* has reflected specular component */ |
33 |
|
#define SPA_FLAT 02 /* reflecting surface is flat */ |
34 |
|
#define SPA_RBLT 010 /* reflection below sample threshold */ |
35 |
– |
#define SPA_BADU 020 /* bad u direction calculation */ |
35 |
|
|
36 |
|
typedef struct { |
37 |
|
OBJREC *mp; /* material pointer */ |
46 |
|
double pdot; /* perturbed dot product */ |
47 |
|
} ASHIKDAT; /* anisotropic material data */ |
48 |
|
|
49 |
< |
static void getacoords_as(RAY *r, ASHIKDAT *np); |
50 |
< |
static void ashiksamp(RAY *r, ASHIKDAT *np); |
49 |
> |
static void getacoords_as(ASHIKDAT *np); |
50 |
> |
static void ashiksamp(ASHIKDAT *np); |
51 |
|
|
52 |
+ |
#undef MAX |
53 |
+ |
#define MAX(a,b) ((a)>(b) ? (a) : (b)) |
54 |
|
|
54 |
– |
static double |
55 |
– |
max(double a, double b) { |
56 |
– |
if (a > b) |
57 |
– |
return(a); |
58 |
– |
return(b); |
59 |
– |
} |
55 |
|
|
61 |
– |
|
56 |
|
static double |
57 |
|
schlick_fres(double dprod) |
58 |
|
{ |
92 |
|
scalecolor(ctmp, dtmp); |
93 |
|
addcolor(cval, ctmp); |
94 |
|
|
95 |
< |
if ((np->specfl & (SPA_REFL|SPA_BADU)) != SPA_REFL) |
95 |
> |
if (!(np->specfl & SPA_REFL)) |
96 |
|
return; |
97 |
|
/* |
98 |
|
* Compute specular reflection coefficient |
109 |
|
dtmp = DOT(np->pnorm, h); |
110 |
|
dtmp = pow(dtmp, (dtmp1+dtmp2)/(1.-dtmp*dtmp)); |
111 |
|
dtmp *= sqrt((np->u_power+1.)*(np->v_power+1.)); |
112 |
< |
dtmp /= 8.*PI * DOT(ldir,h) * max(ldot,np->pdot); |
112 |
> |
dtmp /= 8.*PI * DOT(ldir,h) * MAX(ldot,np->pdot); |
113 |
|
/* worth using? */ |
114 |
|
if (dtmp > FTINY) { |
115 |
|
copycolor(ctmp, np->scolor); |
177 |
|
if (r->ro != NULL && isflat(r->ro->otype)) |
178 |
|
nd.specfl |= SPA_FLAT; |
179 |
|
/* set up coordinates */ |
180 |
< |
getacoords_as(r, &nd); |
180 |
> |
getacoords_as(&nd); |
181 |
|
/* specular sampling? */ |
182 |
|
if ((nd.specfl & (SPA_REFL|SPA_RBLT)) == SPA_REFL) |
183 |
< |
ashiksamp(r, &nd); |
183 |
> |
ashiksamp(&nd); |
184 |
|
/* diffuse interreflection */ |
185 |
|
if (bright(nd.mcolor) > FTINY) { |
186 |
|
copycolor(ctmp, nd.mcolor); /* modified by material color */ |
197 |
|
|
198 |
|
static void |
199 |
|
getacoords_as( /* set up coordinate system */ |
206 |
– |
RAY *r, |
200 |
|
ASHIKDAT *np |
201 |
|
) |
202 |
|
{ |
204 |
|
int i; |
205 |
|
|
206 |
|
mf = getfunc(np->mp, 3, 0x7, 1); |
207 |
< |
setfunc(np->mp, r); |
207 |
> |
setfunc(np->mp, np->rp); |
208 |
|
errno = 0; |
209 |
|
for (i = 0; i < 3; i++) |
210 |
|
np->u[i] = evalue(mf->ep[i]); |
211 |
< |
if ((errno == EDOM) | (errno == ERANGE)) { |
212 |
< |
objerror(np->mp, WARNING, "compute error"); |
220 |
< |
np->specfl |= SPA_BADU; |
221 |
< |
return; |
222 |
< |
} |
211 |
> |
if ((errno == EDOM) | (errno == ERANGE)) |
212 |
> |
np->u[0] = np->u[1] = np->u[2] = 0.0; |
213 |
|
if (mf->fxp != &unitxf) |
214 |
|
multv3(np->u, np->u, mf->fxp->xfm); |
215 |
|
fcross(np->v, np->pnorm, np->u); |
216 |
|
if (normalize(np->v) == 0.0) { |
217 |
< |
objerror(np->mp, WARNING, "illegal orientation vector"); |
218 |
< |
np->specfl |= SPA_BADU; |
219 |
< |
return; |
220 |
< |
} |
221 |
< |
fcross(np->u, np->v, np->pnorm); |
217 |
> |
if (fabs(np->u_power - np->v_power) > 0.1) |
218 |
> |
objerror(np->mp, WARNING, "bad orientation vector"); |
219 |
> |
getperpendicular(np->u, np->pnorm, 1); /* punting */ |
220 |
> |
fcross(np->v, np->pnorm, np->u); |
221 |
> |
np->u_power = np->v_power = |
222 |
> |
2./(1./(np->u_power+1e-5) + 1./(np->v_power+1e-5)); |
223 |
> |
} else |
224 |
> |
fcross(np->u, np->v, np->pnorm); |
225 |
|
} |
226 |
|
|
227 |
|
|
228 |
|
static void |
229 |
|
ashiksamp( /* sample anisotropic Ashikhmin-Shirley specular */ |
237 |
– |
RAY *r, |
230 |
|
ASHIKDAT *np |
231 |
|
) |
232 |
|
{ |
234 |
|
FVECT h; |
235 |
|
double rv[2], dtmp; |
236 |
|
double cosph, sinph, costh, sinth; |
245 |
– |
COLOR scol; |
237 |
|
int maxiter, ntrials, nstarget, nstaken; |
238 |
|
int i; |
239 |
|
|
240 |
< |
if (np->specfl & SPA_BADU || |
250 |
< |
rayorigin(&sr, SPECULAR, r, np->scolor) < 0) |
240 |
> |
if (rayorigin(&sr, SPECULAR, np->rp, np->scolor) < 0) |
241 |
|
return; |
242 |
|
|
243 |
|
nstarget = 1; |
244 |
|
if (specjitter > 1.5) { /* multiple samples? */ |
245 |
< |
nstarget = specjitter*r->rweight + .5; |
245 |
> |
nstarget = specjitter*np->rp->rweight + .5; |
246 |
|
if (sr.rweight <= minweight*nstarget) |
247 |
|
nstarget = sr.rweight/minweight; |
248 |
|
if (nstarget > 1) { |
259 |
|
if (ntrials) |
260 |
|
dtmp = frandom(); |
261 |
|
else |
262 |
< |
dtmp = urand(ilhash(dimlist,ndims)+1823+samplendx); |
262 |
> |
dtmp = urand(ilhash(dimlist,ndims)+647+samplendx); |
263 |
|
multisamp(rv, 2, dtmp); |
264 |
|
dtmp = 2.*PI * rv[0]; |
265 |
< |
cosph = sqrt(np->u_power + 1.) * tcos(dtmp); |
266 |
< |
sinph = sqrt(np->v_power + 1.) * tsin(dtmp); |
267 |
< |
dtmp = 1./(cosph*cosph + sinph*sinph); |
265 |
> |
cosph = sqrt(np->v_power + 1.) * tcos(dtmp); |
266 |
> |
sinph = sqrt(np->u_power + 1.) * tsin(dtmp); |
267 |
> |
dtmp = 1./sqrt(cosph*cosph + sinph*sinph); |
268 |
|
cosph *= dtmp; |
269 |
|
sinph *= dtmp; |
270 |
|
costh = pow(rv[1], 1./(np->u_power*cosph*cosph+np->v_power*sinph*sinph+1.)); |
276 |
|
|
277 |
|
if (nstaken) |
278 |
|
rayclear(&sr); |
279 |
< |
dtmp = -2.*DOT(h, r->rdir); |
280 |
< |
VSUM(sr.rdir, r->rdir, h, dtmp); |
279 |
> |
dtmp = -2.*DOT(h, np->rp->rdir); |
280 |
> |
VSUM(sr.rdir, np->rp->rdir, h, dtmp); |
281 |
|
/* sample rejection test */ |
282 |
< |
if (DOT(sr.rdir, r->ron) <= FTINY) |
282 |
> |
if (DOT(sr.rdir, np->rp->ron) <= FTINY) |
283 |
|
continue; |
284 |
+ |
checknorm(sr.rdir); |
285 |
|
rayvalue(&sr); |
286 |
|
multcolor(sr.rcol, sr.rcoef); |
287 |
< |
addcolor(r->rcol, sr.rcol); |
287 |
> |
addcolor(np->rp->rcol, sr.rcol); |
288 |
|
++nstaken; |
289 |
|
} |
290 |
|
ndims--; |