94 |
|
RAY *rp; /* ray pointer */ |
95 |
|
OBJREC *mtp; /* material pointer */ |
96 |
|
MFUNC *mf; /* pointer to expression list */ |
97 |
+ |
OBJECT mto; /* material object index (or -2) */ |
98 |
|
int specfl; /* specularity flags, defined above */ |
99 |
|
FVECT ulocal; /* u-vector in local coordinates */ |
100 |
|
DCOMP rd, td; /* diffuse component params */ |
102 |
|
FVECT prdir; /* vector in transmitted direction */ |
103 |
|
} WGMDDAT; /* WGMD material data */ |
104 |
|
|
105 |
< |
#define clr_comps(wp) ((wp)->specfl = 0, \ |
105 |
> |
#define clr_comps(wp) ((wp)->specfl = 0, (wp)->mto = OVOID-1, \ |
106 |
|
(wp)->rd.mo.nam = (wp)->td.mo.nam = \ |
107 |
|
(wp)->rs.mo.nam = (wp)->ts.mo.nam = "") |
108 |
|
|
134 |
|
|
135 |
|
/* fill modifier values, using previous setting if found */ |
136 |
|
static int |
137 |
< |
fill_modval(MODVAL *mp, const WGMDDAT *wp) |
137 |
> |
fill_modval(MODVAL *mp, WGMDDAT *wp) |
138 |
|
{ |
139 |
|
if (mp == &wp->rd.mo) { /* special case (should be first) */ |
140 |
|
set_modval(mp, wp->mtp->omod, wp->rp); |
155 |
|
if (mp != &wp->ts.mo && !strcmp(mp->nam, wp->ts.mo.nam)) { |
156 |
|
*mp = wp->ts.mo; |
157 |
|
return(1); |
158 |
< |
} /* new modifier */ |
159 |
< |
return(set_modval(mp, lastmod(objndx(wp->mtp), mp->nam), wp->rp)); |
158 |
> |
} |
159 |
> |
if (wp->mto < OVOID) |
160 |
> |
wp->mto = objndx(wp->mtp); |
161 |
> |
/* new modifier */ |
162 |
> |
return(set_modval(mp, lastmod(wp->mto, mp->nam), wp->rp)); |
163 |
|
} |
164 |
|
|
165 |
+ |
/* set calculation context for given component of MAT_WGMDF */ |
166 |
+ |
static int |
167 |
+ |
setWGMDfunc(MODVAL *mp, const WGMDDAT *wp) |
168 |
+ |
{ |
169 |
+ |
static char lastMod[MAXSTR]; |
170 |
+ |
double sf; |
171 |
+ |
FVECT vec; |
172 |
+ |
|
173 |
+ |
if (setfunc(wp->mtp, wp->rp) == 0 && |
174 |
+ |
!strcmp(mp->nam, lastMod)) |
175 |
+ |
return(0); /* already set */ |
176 |
+ |
strcpy(lastMod, mp->nam); |
177 |
+ |
/* else (re)assign special variables */ |
178 |
+ |
sf = 1 - 2*(wp->rp->rod < 0); |
179 |
+ |
varset("RdotP`", '=', mp->pdot*sf); |
180 |
+ |
multv3(vec, mp->pnorm, funcxf.xfm); |
181 |
+ |
sf /= funcxf.sca; |
182 |
+ |
varset("NxP`", '=', vec[0]*sf); |
183 |
+ |
varset("NyP`", '=', vec[1]*sf); |
184 |
+ |
varset("NzP`", '=', vec[2]*sf); |
185 |
+ |
return(1); |
186 |
+ |
} |
187 |
+ |
|
188 |
|
/* assign indicated diffuse component (do !trans first) */ |
189 |
|
static void |
190 |
|
set_dcomp(WGMDDAT *wp, int trans) |
217 |
|
static void |
218 |
|
set_scomp(WGMDDAT *wp, int trans) |
219 |
|
{ |
220 |
< |
SCOMP *sp = trans ? &wp->ts : &wp->rs; |
221 |
< |
const int eoff = 3*(trans != 0); |
222 |
< |
double coef; |
223 |
< |
|
224 |
< |
setfunc(wp->mtp, wp->rp); /* get coefficient, first */ |
225 |
< |
errno = 0; |
226 |
< |
coef = evalue(wp->mf->ep[eoff]); |
200 |
< |
if ((errno == EDOM) | (errno == ERANGE)) { |
201 |
< |
objerror(wp->mtp, WARNING, "specular compute error"); |
202 |
< |
scolorblack(sp->scol); |
203 |
< |
return; |
204 |
< |
} |
205 |
< |
if (coef <= FTINY) { /* negligible value? */ |
206 |
< |
scolorblack(sp->scol); |
207 |
< |
return; |
208 |
< |
} /* else get modifier */ |
220 |
> |
SCOMP *sp = trans ? &wp->ts : &wp->rs; |
221 |
> |
EPNODE **exa = wp->mf->ep + 3*(trans != 0); |
222 |
> |
double coef; |
223 |
> |
/* constant zero check */ |
224 |
> |
if (exa[0]->type == NUM && exa[0]->v.num <= FTINY) |
225 |
> |
goto blackout; |
226 |
> |
/* need modifier */ |
227 |
|
sp->mo.nam = wp->mtp->oargs.sarg[4*(trans != 0)]; |
228 |
|
if (!fill_modval(&sp->mo, wp)) { |
229 |
|
sprintf(errmsg, "unknown specular %s modifier '%s'", |
230 |
|
trans ? "transmission" : "reflection", sp->mo.nam); |
231 |
|
objerror(wp->mtp, USER, errmsg); |
232 |
|
} |
233 |
+ |
if (sintens(sp->mo.pcol) <= FTINY) |
234 |
+ |
goto blackout; /* got black pattern */ |
235 |
+ |
setWGMDfunc(&sp->mo, wp); /* else compute coefficient */ |
236 |
+ |
errno = 0; |
237 |
+ |
coef = evalue(exa[0]); |
238 |
+ |
if ((errno == EDOM) | (errno == ERANGE)) { |
239 |
+ |
objerror(wp->mtp, WARNING, "specular compute error"); |
240 |
+ |
goto blackout; |
241 |
+ |
} |
242 |
+ |
if (coef <= FTINY) /* negligible value? */ |
243 |
+ |
goto blackout; |
244 |
|
copyscolor(sp->scol, sp->mo.pcol); |
245 |
|
scalescolor(sp->scol, coef); |
246 |
< |
if (sintens(sp->scol) <= FTINY) { |
247 |
< |
scolorblack(sp->scol); |
248 |
< |
return; /* got black pattern */ |
220 |
< |
} |
221 |
< |
setfunc(wp->mtp, wp->rp); /* else get roughness */ |
222 |
< |
errno = 0; |
223 |
< |
sp->u_alpha = evalue(wp->mf->ep[eoff+1]); |
224 |
< |
sp->v_alpha = (sp->u_alpha > FTINY) ? evalue(wp->mf->ep[eoff+2]) : 0.0; |
246 |
> |
errno = 0; /* else get roughness */ |
247 |
> |
sp->u_alpha = evalue(exa[1]); |
248 |
> |
sp->v_alpha = (sp->u_alpha > FTINY) ? evalue(exa[2]) : 0.0; |
249 |
|
if ((errno == EDOM) | (errno == ERANGE)) { |
250 |
|
objerror(wp->mtp, WARNING, "roughness compute error"); |
251 |
< |
scolorblack(sp->scol); |
228 |
< |
return; |
251 |
> |
goto blackout; |
252 |
|
} /* we have something... */ |
253 |
|
wp->specfl |= trans ? SP_TRAN : SP_REFL; |
254 |
|
if (sp->v_alpha <= FTINY) { /* is it pure specular? */ |
255 |
|
wp->specfl |= trans ? SP_TPURE : SP_RPURE; |
256 |
|
sp->u_alpha = sp->v_alpha = 0.0; |
257 |
|
return; |
258 |
< |
} |
236 |
< |
/* get anisotropic coordinates */ |
258 |
> |
} /* else get aniso coordinates */ |
259 |
|
fcross(sp->v, sp->mo.pnorm, wp->ulocal); |
260 |
|
if (normalize(sp->v) == 0.0) { /* orientation vector==normal? */ |
261 |
|
if (fabs(sp->u_alpha - sp->v_alpha) > 0.001) |
262 |
|
objerror(wp->mtp, WARNING, "bad orientation vector"); |
263 |
< |
getperpendicular(sp->u, sp->mo.pnorm, 1); /* punting */ |
263 |
> |
getperpendicular(sp->u, sp->mo.pnorm, 0); /* punting */ |
264 |
|
fcross(sp->v, sp->mo.pnorm, sp->u); |
265 |
|
sp->u_alpha = sp->v_alpha = sqrt( 0.5 * |
266 |
|
(sp->u_alpha*sp->u_alpha + sp->v_alpha*sp->v_alpha) ); |
267 |
|
} else |
268 |
|
fcross(sp->u, sp->v, sp->mo.pnorm); |
269 |
+ |
return; |
270 |
+ |
blackout: |
271 |
+ |
scolorblack(sp->scol); /* zero out component */ |
272 |
|
} |
273 |
|
|
274 |
|
/* sample anisotropic Gaussian specular */ |
298 |
|
nstarget = 1; |
299 |
|
} |
300 |
|
scolorblack(scol); |
301 |
< |
dimlist[ndims++] = (int)(size_t)wp->mtp; |
301 |
> |
dimlist[ndims_inc] = (int)(size_t)wp->mtp; |
302 |
|
maxiter = MAXITER*nstarget; |
303 |
|
for (nstaken = ntrials = 0; (nstaken < nstarget) & |
304 |
|
(ntrials < maxiter); ntrials++) { |
364 |
|
} else |
365 |
|
nstarget = 1; |
366 |
|
} |
367 |
< |
dimlist[ndims++] = (int)(size_t)wp->mtp; |
367 |
> |
dimlist[ndims_inc] = (int)(size_t)wp->mtp; |
368 |
|
maxiter = MAXITER*nstarget; |
369 |
|
for (nstaken = ntrials = 0; (nstaken < nstarget) & |
370 |
|
(ntrials < maxiter); ntrials++) { |
456 |
|
*/ |
457 |
|
/* add source width if flat */ |
458 |
|
if (wp->specfl & SP_FLAT) |
459 |
< |
au2 = av2 = omega * (0.25/PI); |
459 |
> |
au2 = av2 = (1. - dstrsrc) * omega * (0.25/PI); |
460 |
|
else |
461 |
|
au2 = av2 = 0.0; |
462 |
|
au2 += wp->rs.u_alpha*wp->rs.u_alpha; |
542 |
|
wd.rp = r; |
543 |
|
wd.mtp = m; |
544 |
|
wd.mf = getfunc(m, 12, 0xEEE, 1); |
545 |
< |
set_dcomp(&wd, 0); /* calls main modifier */ |
546 |
< |
setfunc(m, r); /* get local u vector */ |
545 |
> |
set_dcomp(&wd, 0); /* gets main modifier */ |
546 |
> |
setWGMDfunc(&wd.rd.mo, &wd); /* get local u vector */ |
547 |
|
errno = 0; |
548 |
|
for (i = 0; i < 3; i++) |
549 |
|
wd.ulocal[i] = evalue(wd.mf->ep[6+i]); |
557 |
|
return(1); /* second shadow test */ |
558 |
|
set_dcomp(&wd, 1); |
559 |
|
set_scomp(&wd, 0); |
560 |
< |
wd.specfl |= SP_FLAT*(r->ro != NULL && isflat(r->ro->otype)); |
560 |
> |
wd.specfl |= SP_FLAT*(!wd.rs.mo.hastexture && |
561 |
> |
r->ro != NULL && isflat(r->ro->otype)); |
562 |
|
/* apply Fresnel adjustments? */ |
563 |
|
if (wd.specfl & SP_RPURE && pbright(wd.rs.scol) >= FRESTHRESH) { |
564 |
|
const double fest = FRESNE(fabs(wd.rs.mo.pdot)); |
565 |
|
for (i = NCSAMP; i--; ) |
566 |
|
wd.rs.scol[i] += fest*(1. - wd.rs.scol[i]); |
567 |
+ |
scalescolor(wd.rd.scol, 1.-fest); |
568 |
|
scalescolor(wd.ts.scol, 1.-fest); |
569 |
|
scalescolor(wd.td.scol, 1.-fest); |
570 |
|
} |
617 |
|
copyscolor(r->mcol, lr.rcol); |
618 |
|
saddscolor(r->rcol, lr.rcol); |
619 |
|
r->rmt = r->rot; |
620 |
< |
if (wd.specfl & SP_FLAT && |
594 |
< |
!wd.rs.mo.hastexture | (r->crtype & AMBIENT)) |
620 |
> |
if (wd.specfl & SP_FLAT && r->crtype & AMBIENT) |
621 |
|
r->rmt += raydistance(&lr); |
622 |
|
} |
623 |
|
if (wd.specfl & (SP_REFL|SP_TRAN)) /* specularly scattered rays */ |