ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/pmcontrib2.c
Revision: 2.1
Committed: Thu Sep 29 21:51:58 2016 UTC (8 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Separated creation from use of contribution photon maps

File Contents

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