ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/pmcontrib2.c
Revision: 2.5
Committed: Thu Nov 8 00:54:07 2018 UTC (5 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R3
Changes since 2.4: +3 -3 lines
Log Message:
Moved findmaterial() from source.c to initotypes.c

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: pmcontrib2.c,v 2.4 2018/02/09 14:59:08 rschregle Exp $";
3 #endif
4
5 /*
6 ======================================================================
7 Photon map support for using light source contributions
8
9 Roland Schregle (roland.schregle@{hslu.ch, gmail.com})
10 (c) Lucerne University of Applied Sciences and Arts,
11 supported by the Swiss National Science Foundation (SNSF, #147053)
12 ======================================================================
13
14 $Id: pmcontrib2.c,v 2.4 2018/02/09 14:59:08 rschregle Exp $
15 */
16
17
18 #include "pmapcontrib.h"
19 #include "pmapmat.h"
20 #include "pmapsrc.h"
21 #include "pmaprand.h"
22 #include "pmapio.h"
23 #include "pmapdiag.h"
24 #include "rcontrib.h"
25 #include "otypes.h"
26 #include "otspecial.h"
27
28
29 static void setPmapContribParams (PhotonMap *pmap, LUTAB *srcContrib)
30 /* Set parameters for light source contributions */
31 {
32 /* Set light source modifier list and appropriate callback to extract
33 * their contributions from the photon map */
34 if (pmap) {
35 pmap -> srcContrib = srcContrib;
36 pmap -> lookup = photonContrib;
37 /* Ensure we get all requested photon contribs during lookups */
38 pmap -> gatherTolerance = 1.0;
39 }
40 }
41
42
43
44 static void checkPmapContribs (const PhotonMap *pmap, LUTAB *srcContrib)
45 /* Check modifiers for light source contributions */
46 {
47 const PhotonPrimary *primary = pmap -> primaries;
48 PhotonPrimaryIdx i, found = 0;
49 OBJREC *srcMod;
50
51 /* Make sure at least one of the modifiers is actually in the pmap,
52 * otherwise findPhotons() winds up in an infinite loop! */
53 for (i = pmap -> numPrimary; i; --i, ++primary) {
54 if (primary -> srcIdx < 0 || primary -> srcIdx >= nsources)
55 error(INTERNAL, "invalid light source index in photon map");
56
57 srcMod = findmaterial(source [primary -> srcIdx].so);
58 if ((MODCONT*)lu_find(srcContrib, srcMod -> oname) -> data)
59 ++found;
60 }
61
62 if (!found)
63 error(USER, "modifiers not in photon map");
64 }
65
66
67
68 void initPmapContrib (LUTAB *srcContrib, unsigned numSrcContrib)
69 {
70 unsigned t;
71
72 for (t = 0; t < NUM_PMAP_TYPES; t++)
73 if (photonMaps [t] && t != PMAP_TYPE_CONTRIB) {
74 sprintf(errmsg, "%s photon map does not support contributions",
75 pmapName [t]);
76 error(USER, errmsg);
77 }
78
79 /* Get params */
80 setPmapContribParams(contribPmap, srcContrib);
81
82 if (contribPhotonMapping) {
83 if (contribPmap -> maxGather < numSrcContrib) {
84 #if 0
85 /* Adjust density estimate bandwidth if lower than modifier
86 * count, otherwise contributions are missing */
87 error(WARNING, "contrib density estimate bandwidth too low, "
88 "adjusting to modifier count");
89 contribPmap -> maxGather = numSrcContrib;
90 #else
91 /* Warn if density estimate bandwidth is lower than modifier
92 * count, since some contributions will be missing */
93 error(WARNING, "photon density estimate bandwidth too low,"
94 " contributions may be underestimated");
95 #endif
96 }
97
98 /* Sanity check */
99 checkPmapContribs(contribPmap, srcContrib);
100 }
101 }
102
103
104
105 void photonContrib (PhotonMap *pmap, RAY *ray, COLOR irrad)
106 /* Sum up light source contributions from photons in pmap->srcContrib */
107 {
108 unsigned i;
109 PhotonSearchQueueNode *sqn;
110 float r2, invArea;
111 RREAL rayCoeff [3];
112 Photon *photon;
113 static char warnPos = 1, warnDir = 1;
114
115 setcolor(irrad, 0, 0, 0);
116
117 if (!pmap -> maxGather)
118 return;
119
120 /* Ignore sources */
121 if (ray -> ro && islight(objptr(ray -> ro -> omod) -> otype))
122 return;
123
124 /* Get cumulative path coefficient up to photon lookup point */
125 raycontrib(rayCoeff, ray, PRIMARY);
126
127 /* Lookup photons */
128 pmap -> squeue.tail = 0;
129 findPhotons(pmap, ray);
130
131 /* Need at least 2 photons */
132 if (pmap -> squeue.tail < 2) {
133 #ifdef PMAP_NONEFOUND
134 sprintf(errmsg, "no photons found on %s at (%.3f, %.3f, %.3f)",
135 ray -> ro ? ray -> ro -> oname : "<null>",
136 ray -> rop [0], ray -> rop [1], ray -> rop [2]);
137 error(WARNING, errmsg);
138 #endif
139
140 return;
141 }
142
143 /* Average radius^2 between furthest two photons to improve accuracy and
144 * get inverse search area 1 / (PI * r^2), with extra normalisation
145 * factor 1 / PI for ambient calculation */
146 sqn = pmap -> squeue.node + 1;
147 r2 = max(sqn -> dist2, (sqn + 1) -> dist2);
148 r2 = 0.25 * (pmap -> maxDist2 + r2 + 2 * sqrt(pmap -> maxDist2 * r2));
149 invArea = 1 / (PI * PI * r2);
150
151 /* Skip the extra photon */
152 for (i = 1 ; i < pmap -> squeue.tail; i++, sqn++) {
153 COLOR flux;
154
155 /* Get photon's contribution to density estimate */
156 photon = getNearestPhoton(&pmap -> squeue, sqn -> idx);
157 getPhotonFlux(photon, flux);
158 scalecolor(flux, invArea);
159 #ifdef PMAP_EPANECHNIKOV
160 /* Apply Epanechnikov kernel to photon flux based on photon distance */
161 scalecolor(flux, 2 * (1 - sqn -> dist2 / r2));
162 #endif
163 addcolor(irrad, flux);
164
165 if (pmap -> srcContrib) {
166 const PhotonPrimary *primary = pmap -> primaries +
167 photon -> primary;
168 const SRCREC *sp = &source [primary -> srcIdx];
169 OBJREC *srcMod = findmaterial(sp -> so);
170 MODCONT *srcContrib = (MODCONT*)lu_find(pmap -> srcContrib,
171 srcMod -> oname) -> data;
172 double srcBinReal;
173 int srcBin;
174 RAY srcRay;
175
176 if (!srcContrib)
177 continue;
178
179 /* Photon's emitting light source has modifier whose contributions
180 * are sought */
181 if (srcContrib -> binv -> type != NUM) {
182 /* Use intersection function to set shadow ray parameters if
183 * it's not simply a constant */
184 rayorigin(&srcRay, SHADOW, NULL, NULL);
185 srcRay.rsrc = primary -> srcIdx;
186 #ifdef PMAP_PRIMARYPOS
187 VCOPY(srcRay.rorg, primary -> pos);
188 #else
189 /* No primary hitpoints; set dummy ray origin and warn once */
190 srcRay.rorg [0] = srcRay.rorg [1] = srcRay.rorg [2] = 0;
191 if (warnPos) {
192 error(WARNING,
193 "no photon primary hitpoints for bin evaluation; "
194 "using dummy (0,0,0)! Recompile with -DPMAP_CBDM.");
195 warnPos = 0;
196 }
197 #endif
198 #ifdef PMAP_PRIMARYDIR
199 decodedir(srcRay.rdir, primary -> dir);
200 #else
201 /* No primary incident direction; set dummy and warn once */
202 if (warnDir) {
203 error(WARNING,
204 "no photon primary directions for bin evaluation; "
205 "using dummy (0,0,0)! Recompile with -DPMAP_CBDM.");
206 warnDir = 0;
207 }
208 srcRay.rdir [0] = srcRay.rdir [1] = srcRay.rdir [2] = 0;
209 #endif
210
211 if (!(sp->sflags & SDISTANT
212 ? sourcehit(&srcRay)
213 : (*ofun[sp -> so -> otype].funp)(sp -> so, &srcRay)))
214 continue; /* XXX shouldn't happen! */
215
216 worldfunc(RCCONTEXT, &srcRay);
217 set_eparams((char *)srcContrib -> params);
218 }
219
220 if ((srcBinReal = evalue(srcContrib -> binv)) < -.5)
221 continue; /* silently ignore negative bins */
222
223 if ((srcBin = srcBinReal + .5) >= srcContrib -> nbins) {
224 error(WARNING, "bad bin number (ignored)");
225 continue;
226 }
227
228 if (!contrib) {
229 /* Ray coefficient mode; normalise by light source radiance
230 * after applying distrib pattern */
231 int j;
232
233 raytexture(ray, srcMod -> omod);
234 setcolor(ray -> rcol, srcMod -> oargs.farg [0],
235 srcMod -> oargs.farg [1], srcMod -> oargs.farg [2]);
236 multcolor(ray -> rcol, ray -> pcol);
237 for (j = 0; j < 3; j++)
238 flux [j] = ray -> rcol [j] ? flux [j] / ray -> rcol [j] : 0;
239 }
240
241 multcolor(flux, rayCoeff);
242 addcolor(srcContrib -> cbin [srcBin], flux);
243 }
244 }
245
246 return;
247 }