2 |
|
static const char RCSid[] = "$Id$"; |
3 |
|
#endif |
4 |
|
/* |
5 |
< |
================================================================== |
5 |
> |
|
6 |
> |
====================================================================== |
7 |
|
Photon map support routines for scattering by materials. |
8 |
|
|
9 |
|
Roland Schregle (roland.schregle@{hslu.ch, gmail.com}) |
10 |
|
(c) Fraunhofer Institute for Solar Energy Systems, |
11 |
+ |
supported by the German Research Foundation |
12 |
+ |
(DFG LU-204/10-2, "Fassadenintegrierte Regelsysteme FARESYS") |
13 |
|
(c) Lucerne University of Applied Sciences and Arts, |
14 |
< |
supported by the Swiss National Science Foundation (SNSF, #147053) |
15 |
< |
================================================================== |
14 |
> |
supported by the Swiss National Science Foundation |
15 |
> |
(SNSF #147053, "Daylight Redirecting Components") |
16 |
> |
====================================================================== |
17 |
|
|
18 |
|
*/ |
19 |
|
|
149 |
|
} |
150 |
|
|
151 |
|
|
148 |
– |
|
152 |
|
static void addPhotons (const RAY *r) |
153 |
|
/* Insert photon hits, where applicable */ |
154 |
|
{ |
155 |
|
if (!r -> rlvl) |
156 |
< |
/* Add direct photon map at primary hitpoint */ |
156 |
> |
/* Add direct photon at primary hitpoint */ |
157 |
|
newPhoton(directPmap, r); |
158 |
|
else { |
159 |
< |
/* Add global or precomputed photon map at indirect hitpoint */ |
159 |
> |
/* Add global or precomputed photon at indirect hitpoint */ |
160 |
|
newPhoton(preCompPmap ? preCompPmap : globalPmap, r); |
161 |
|
|
162 |
|
/* Store caustic photon if specular flag set */ |
322 |
|
} |
323 |
|
else raytexture(rayIn, mat -> omod); |
324 |
|
|
325 |
+ |
nd.mp = mat; |
326 |
|
nd.rp = rayIn; |
327 |
|
|
328 |
|
/* Get material color */ |
335 |
|
if ((nd.alpha2 *= nd.alpha2) <= FTINY) |
336 |
|
nd.specfl |= SP_PURE; |
337 |
|
|
334 |
– |
if (rayIn -> ro != NULL && isflat(rayIn -> ro -> otype)) |
335 |
– |
nd.specfl |= SP_FLAT; |
336 |
– |
|
338 |
|
/* Perturb normal */ |
339 |
|
if ((hastexture = (DOT(rayIn -> pert, rayIn -> pert) > sqr(FTINY)) )) |
340 |
|
nd.pdot = raynormal(nd.pnorm, rayIn); |
343 |
|
nd.pdot = rayIn -> rod; |
344 |
|
} |
345 |
|
|
346 |
< |
nd.pdot = max(nd.pdot, .001); |
346 |
> |
if (!hastexture && rayIn -> ro != NULL && isflat(rayIn -> ro -> otype)) |
347 |
> |
nd.specfl |= SP_FLAT; |
348 |
> |
|
349 |
> |
nd.pdot = max(nd.pdot, .001); |
350 |
|
|
351 |
|
/* Modify material color */ |
352 |
|
multcolor(nd.mcolor, rayIn -> pcol); |
484 |
|
|
485 |
|
|
486 |
|
|
487 |
< |
static void getacoords (ANISODAT *np) |
487 |
> |
static void getacoords (ANISODAT *nd) |
488 |
|
/* Set up coordinate system for anisotropic sampling; cloned from aniso.c */ |
489 |
|
{ |
490 |
< |
MFUNC *mf; |
491 |
< |
int i; |
490 |
> |
MFUNC *mf; |
491 |
> |
int i; |
492 |
|
|
493 |
< |
mf = getfunc(np->mp, 3, 0x7, 1); |
494 |
< |
setfunc(np->mp, np->rp); |
493 |
> |
mf = getfunc(nd -> mp, 3, 0x7, 1); |
494 |
> |
setfunc(nd -> mp, nd -> rp); |
495 |
|
errno = 0; |
496 |
|
|
497 |
|
for (i = 0; i < 3; i++) |
498 |
< |
np->u[i] = evalue(mf->ep[i]); |
498 |
> |
nd -> u [i] = evalue(mf -> ep [i]); |
499 |
|
|
500 |
< |
if ((errno == EDOM) | (errno == ERANGE)) { |
501 |
< |
objerror(np->mp, WARNING, "compute error"); |
498 |
< |
np->specfl |= SP_BADU; |
499 |
< |
return; |
500 |
< |
} |
501 |
< |
|
502 |
< |
if (mf->fxp != &unitxf) |
503 |
< |
multv3(np->u, np->u, mf->fxp->xfm); |
500 |
> |
if ((errno == EDOM) | (errno == ERANGE)) |
501 |
> |
nd -> u [0] = nd -> u [1] = nd -> u [2] = 0.0; |
502 |
|
|
503 |
< |
fcross(np->v, np->pnorm, np->u); |
503 |
> |
if (mf -> fxp != &unitxf) |
504 |
> |
multv3(nd -> u, nd -> u, mf -> fxp -> xfm); |
505 |
|
|
506 |
< |
if (normalize(np->v) == 0.0) { |
508 |
< |
objerror(np->mp, WARNING, "illegal orientation vector"); |
509 |
< |
np->specfl |= SP_BADU; |
510 |
< |
return; |
511 |
< |
} |
506 |
> |
fcross(nd -> v, nd -> pnorm, nd -> u); |
507 |
|
|
508 |
< |
fcross(np->u, np->v, np->pnorm); |
508 |
> |
if (normalize(nd -> v) == 0.0) { |
509 |
> |
if (fabs(nd -> u_alpha - nd -> v_alpha) > 0.001) |
510 |
> |
objerror(nd -> mp, WARNING, "illegal orientation vector"); |
511 |
> |
getperpendicular(nd -> u, nd -> pnorm, 1); |
512 |
> |
fcross(nd -> v, nd -> pnorm, nd -> u); |
513 |
> |
nd -> u_alpha = nd -> v_alpha = |
514 |
> |
sqrt(0.5 * (sqr(nd -> u_alpha) + sqr(nd -> v_alpha))); |
515 |
> |
} |
516 |
> |
else fcross(nd -> u, nd -> v, nd -> pnorm); |
517 |
|
} |
518 |
|
|
519 |
|
|
619 |
|
if (mat -> oargs.nfargs != (mat -> otype == MAT_TRANS2 ? 8 : 6)) |
620 |
|
objerror(mat, USER, "bad number of real arguments"); |
621 |
|
|
622 |
+ |
nd.mp = mat; |
623 |
|
nd.rp = rayIn; |
620 |
– |
nd.mp = objptr(rayIn -> ro -> omod); |
624 |
|
|
625 |
|
/* get material color */ |
626 |
|
copycolor(nd.mcolor, mat -> oargs.farg); |
664 |
|
if (nd.rspec > FTINY) { |
665 |
|
nd.specfl |= SP_REFL; |
666 |
|
|
667 |
< |
/* comput e specular color */ |
667 |
> |
/* compute specular color */ |
668 |
|
if (mat -> otype == MAT_METAL2) |
669 |
|
copycolor(nd.scolor, nd.mcolor); |
670 |
|
else setcolor(nd.scolor, 1, 1, 1); |
1036 |
|
/* Replacement scattering routine */ |
1037 |
|
photonScatter [aliasRec.otype] (&aliasRec, rayIn); |
1038 |
|
|
1036 |
– |
#if 0 |
1039 |
|
/* Avoid potential memory leak? */ |
1040 |
|
if (aliasRec.os != aliasPtr -> os) { |
1041 |
< |
if (aliasObj -> os) |
1042 |
< |
free_os(aliasObj); |
1041 |
> |
if (aliasPtr -> os) |
1042 |
> |
free_os(aliasPtr); |
1043 |
|
aliasPtr -> os = aliasRec.os; |
1044 |
|
} |
1043 |
– |
#endif |
1045 |
|
|
1046 |
|
return 0; |
1047 |
|
} |
1491 |
|
/* Check argz */ |
1492 |
|
if (mat -> oargs.nsargs < 10 || mat -> oargs.nfargs < 9) |
1493 |
|
objerror(mat, USER, "bad # arguments"); |
1494 |
+ |
|
1495 |
|
nd.mp = mat; |
1496 |
|
nd.pr = rayIn; |
1497 |
|
/* Dummiez */ |
1546 |
|
evalue(mf->ep[0]), evalue(mf->ep[1]), evalue(mf->ep[2])); |
1547 |
|
setcolor(tspecCol, |
1548 |
|
evalue(mf->ep[3]), evalue(mf->ep[4]), evalue(mf->ep[5])); |
1549 |
< |
if (errno == EDOM || errno == ERANGE) |
1549 |
> |
if ((errno == EDOM) | (errno == ERANGE)) |
1550 |
|
objerror(mat, WARNING, "compute error"); |
1551 |
|
else { |
1552 |
|
/* Set up probz */ |
1582 |
|
objerror(mat, WARNING, "illegal perturbation"); |
1583 |
|
VCOPY(rayOut.rdir, rayIn -> rdir); |
1584 |
|
} |
1583 |
– |
else VCOPY(rayOut.rdir, rayIn -> rdir); |
1585 |
|
} |
1586 |
+ |
else VCOPY(rayOut.rdir, rayIn -> rdir); |
1587 |
|
} |
1588 |
|
else if (xi > (albedo -= prDiff)) { |
1589 |
|
/* Diffuz reflekzion */ |
1640 |
|
|
1641 |
|
nd.mp = mat; |
1642 |
|
nd.pr = rayIn; |
1643 |
+ |
|
1644 |
|
/* Material kolour */ |
1645 |
|
setcolor(nd.mcolor, mat -> oargs.farg [0], mat -> oargs.farg [1], |
1646 |
|
mat -> oargs.farg [2]); |
1715 |
|
|
1716 |
|
|
1717 |
|
/* |
1718 |
< |
================================================================== |
1718 |
> |
====================================================================== |
1719 |
|
The following code is |
1720 |
|
(c) Lucerne University of Applied Sciences and Arts, |
1721 |
< |
supported by the Swiss National Science Foundation (SNSF, #147053) |
1722 |
< |
================================================================== |
1721 |
> |
supported by the Swiss National Science Foundation |
1722 |
> |
(SNSF #147053, "Daylight Redirecting Components") |
1723 |
> |
====================================================================== |
1724 |
|
*/ |
1725 |
|
|
1726 |
|
static int bsdfPhotonScatter (OBJREC *mat, RAY *rayIn) |
1727 |
|
/* Generate new photon ray for BSDF modifier and recurse. */ |
1728 |
|
{ |
1729 |
< |
int hasthick = (mat->otype == MAT_BSDF); |
1730 |
< |
int hitFront; |
1731 |
< |
SDError err; |
1732 |
< |
SDValue bsdfVal; |
1733 |
< |
FVECT upvec; |
1734 |
< |
MFUNC *mf; |
1735 |
< |
BSDFDAT nd; |
1736 |
< |
RAY rayOut; |
1737 |
< |
COLOR bsdfRGB; |
1738 |
< |
int transmitted; |
1739 |
< |
double prDiff, ptDiff, prDiffSD, ptDiffSD, prSpecSD, ptSpecSD, |
1740 |
< |
albedo, xi; |
1741 |
< |
const double patAlb = bright(rayIn -> pcol); |
1729 |
> |
int hasthick = (mat->otype == MAT_BSDF); |
1730 |
> |
int hitFront; |
1731 |
> |
SDError err; |
1732 |
> |
SDValue bsdfVal; |
1733 |
> |
FVECT upvec; |
1734 |
> |
MFUNC *mf; |
1735 |
> |
BSDFDAT nd; |
1736 |
> |
RAY rayOut; |
1737 |
> |
COLOR bsdfRGB; |
1738 |
> |
int transmitted; |
1739 |
> |
double prDiff, ptDiff, prDiffSD, ptDiffSD, prSpecSD, ptSpecSD, |
1740 |
> |
albedo, xi; |
1741 |
> |
const double patAlb = bright(rayIn -> pcol); |
1742 |
|
|
1743 |
|
/* Following code adapted from m_bsdf() */ |
1744 |
|
/* Check arguments */ |
1745 |
< |
if (mat -> oargs.nsargs < hasthick+5 || mat -> oargs.nfargs > 9 || |
1746 |
< |
mat -> oargs.nfargs % 3) |
1745 |
> |
if ( |
1746 |
> |
mat -> oargs.nsargs < hasthick+5 || |
1747 |
> |
mat -> oargs.nfargs > 9 || mat -> oargs.nfargs % 3 |
1748 |
> |
) |
1749 |
|
objerror(mat, USER, "bad # arguments"); |
1750 |
|
|
1751 |
|
hitFront = (rayIn -> rod > 0); |
1756 |
|
/* Get thickness */ |
1757 |
|
nd.thick = 0; |
1758 |
|
if (hasthick) { |
1759 |
< |
nd.thick = evalue(mf -> ep [0]); |
1760 |
< |
if ((-FTINY <= nd.thick) & (nd.thick <= FTINY)) |
1761 |
< |
nd.thick = .0; |
1759 |
> |
nd.thick = evalue(mf -> ep [0]); |
1760 |
> |
if ((-FTINY <= nd.thick) & (nd.thick <= FTINY)) |
1761 |
> |
nd.thick = .0; |
1762 |
|
} |
1763 |
|
|
1764 |
|
/* Get BSDF data */ |
1768 |
|
if (hitFront) { |
1769 |
|
if (mat -> oargs.nfargs < 3) |
1770 |
|
setcolor(nd.rdiff, .0, .0, .0); |
1771 |
< |
else setcolor(nd.rdiff, mat -> oargs.farg [0], mat -> oargs.farg [1], |
1772 |
< |
mat -> oargs.farg [2]); |
1771 |
> |
else setcolor( |
1772 |
> |
nd.rdiff, |
1773 |
> |
mat -> oargs.farg [0], mat -> oargs.farg [1], mat -> oargs.farg [2] |
1774 |
> |
); |
1775 |
|
} |
1776 |
|
else if (mat -> oargs.nfargs < 6) { |
1777 |
|
/* Check for absorbing backside */ |
1782 |
|
|
1783 |
|
setcolor(nd.rdiff, .0, .0, .0); |
1784 |
|
} |
1785 |
< |
else setcolor(nd.rdiff, mat -> oargs.farg [3], mat -> oargs.farg [4], |
1786 |
< |
mat -> oargs.farg [5]); |
1785 |
> |
else setcolor( |
1786 |
> |
nd.rdiff, |
1787 |
> |
mat -> oargs.farg [3], mat -> oargs.farg [4], mat -> oargs.farg [5] |
1788 |
> |
); |
1789 |
|
|
1790 |
|
/* Extra diffuse transmittance from material def */ |
1791 |
|
if (mat -> oargs.nfargs < 9) |
1792 |
|
setcolor(nd.tdiff, .0, .0, .0); |
1793 |
< |
else setcolor(nd.tdiff, mat -> oargs.farg [6], mat -> oargs.farg [7], |
1794 |
< |
mat -> oargs.farg [8]); |
1793 |
> |
else setcolor( |
1794 |
> |
nd.tdiff, |
1795 |
> |
mat -> oargs.farg [6], mat -> oargs.farg [7], mat -> oargs.farg [8] |
1796 |
> |
); |
1797 |
|
|
1798 |
|
nd.mp = mat; |
1799 |
|
nd.pr = rayIn; |
1842 |
|
} |
1843 |
|
|
1844 |
|
/* Determine BSDF resolution */ |
1845 |
< |
err = SDsizeBSDF(nd.sr_vpsa, nd.vray, NULL, |
1846 |
< |
SDqueryMin + SDqueryMax, nd.sd); |
1845 |
> |
err = SDsizeBSDF( |
1846 |
> |
nd.sr_vpsa, nd.vray, NULL, SDqueryMin + SDqueryMax, nd.sd |
1847 |
> |
); |
1848 |
|
|
1849 |
|
if (err) |
1850 |
|
objerror(mat, USER, transSDError(err)); |
1905 |
|
else { /* Sample SDF */ |
1906 |
|
if ((xi -= prDiffSD) <= 0) { |
1907 |
|
/* Diffuse SDF reflection (constant component) */ |
1908 |
< |
if ((err = SDsampBSDF(&bsdfVal, nd.vray, pmapRandom(scatterState), |
1909 |
< |
SDsampDf | SDsampR, nd.sd))) |
1908 |
> |
if ((err = SDsampBSDF( |
1909 |
> |
&bsdfVal, nd.vray, pmapRandom(scatterState), |
1910 |
> |
SDsampDf | SDsampR, nd.sd |
1911 |
> |
))) |
1912 |
|
objerror(mat, USER, transSDError(err)); |
1913 |
|
|
1914 |
|
/* Apply pattern to spectral component */ |
1919 |
|
|
1920 |
|
else if ((xi -= ptDiffSD) <= 0) { |
1921 |
|
/* Diffuse SDF transmission (constant component) */ |
1922 |
< |
if ((err = SDsampBSDF(&bsdfVal, nd.vray, pmapRandom(scatterState), |
1923 |
< |
SDsampDf | SDsampT, nd.sd))) |
1922 |
> |
if ((err = SDsampBSDF( |
1923 |
> |
&bsdfVal, nd.vray, pmapRandom(scatterState), |
1924 |
> |
SDsampDf | SDsampT, nd.sd |
1925 |
> |
))) |
1926 |
|
objerror(mat, USER, transSDError(err)); |
1927 |
|
|
1928 |
|
/* Apply pattern to spectral component */ |
1935 |
|
|
1936 |
|
else if ((xi -= prSpecSD) <= 0) { |
1937 |
|
/* Non-diffuse ("specular") SDF reflection */ |
1938 |
< |
if ((err = SDsampBSDF(&bsdfVal, nd.vray, pmapRandom(scatterState), |
1939 |
< |
SDsampSp | SDsampR, nd.sd))) |
1938 |
> |
if ((err = SDsampBSDF( |
1939 |
> |
&bsdfVal, nd.vray, pmapRandom(scatterState), |
1940 |
> |
SDsampSp | SDsampR, nd.sd |
1941 |
> |
))) |
1942 |
|
objerror(mat, USER, transSDError(err)); |
1943 |
|
|
1944 |
|
ccy2rgb(&bsdfVal.spec, bsdfVal.cieY, bsdfRGB); |
1947 |
|
|
1948 |
|
else { |
1949 |
|
/* Non-diffuse ("specular") SDF transmission */ |
1950 |
< |
if ((err = SDsampBSDF(&bsdfVal, nd.vray, pmapRandom(scatterState), |
1951 |
< |
SDsampSp | SDsampT, nd.sd))) |
1950 |
> |
if ((err = SDsampBSDF( |
1951 |
> |
&bsdfVal, nd.vray, pmapRandom(scatterState), |
1952 |
> |
SDsampSp | SDsampT, nd.sd |
1953 |
> |
))) |
1954 |
|
objerror(mat, USER, transSDError(err)); |
1955 |
|
|
1956 |
|
/* Apply pattern to spectral component */ |