ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/pmcontrib2.c
Revision: 2.2
Committed: Fri Sep 30 16:51:46 2016 UTC (7 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +2 -4 lines
Log Message:
Removed Unix-only includes I sloppily copied into Windows module

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: pmcontrib2.c,v 2.1 2016/09/29 21:51:58 greg 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.1 2016/09/29 21:51:58 greg 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
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 /* Adjust density estimate bandwidth if lower than modifier
85 * count, otherwise contributions are missing */
86 error(WARNING, "contrib density estimate bandwidth too low, "
87 "adjusting to modifier count");
88 contribPmap -> maxGather = numSrcContrib;
89 }
90
91 /* Sanity check */
92 checkPmapContribs(contribPmap, srcContrib);
93 }
94 }
95
96
97
98 void photonContrib (PhotonMap *pmap, RAY *ray, COLOR irrad)
99 /* Sum up light source contributions from photons in pmap->srcContrib */
100 {
101 unsigned i;
102 PhotonSearchQueueNode *sqn;
103 float r, invArea;
104 RREAL rayCoeff [3];
105 Photon *photon;
106 static char warn = 1;
107
108 setcolor(irrad, 0, 0, 0);
109
110 if (!pmap -> maxGather)
111 return;
112
113 /* Ignore sources */
114 if (ray -> ro && islight(objptr(ray -> ro -> omod) -> otype))
115 return;
116
117 /* Get cumulative path coefficient up to photon lookup point */
118 raycontrib(rayCoeff, ray, PRIMARY);
119
120 /* Lookup photons */
121 pmap -> squeue.tail = 0;
122 findPhotons(pmap, ray);
123
124 /* Need at least 2 photons */
125 if (pmap -> squeue.tail < 2) {
126 #ifdef PMAP_NONEFOUND
127 sprintf(errmsg, "no photons found on %s at (%.3f, %.3f, %.3f)",
128 ray -> ro ? ray -> ro -> oname : "<null>",
129 ray -> rop [0], ray -> rop [1], ray -> rop [2]);
130 error(WARNING, errmsg);
131 #endif
132
133 return;
134 }
135
136 /* Average (squared) radius between furthest two photons to improve
137 * accuracy and get inverse search area 1 / (PI * r^2), with extra
138 * normalisation factor 1 / PI for ambient calculation */
139 sqn = pmap -> squeue.node + 1;
140 r = max(sqn -> dist2, (sqn + 1) -> dist2);
141 r = 0.25 * (pmap -> maxDist2 + r + 2 * sqrt(pmap -> maxDist2 * r));
142 invArea = 1 / (PI * PI * r);
143
144 /* Skip the extra photon */
145 for (i = 1 ; i < pmap -> squeue.tail; i++, sqn++) {
146 COLOR flux;
147
148 /* Get photon's contribution to density estimate */
149 photon = getNearestPhoton(&pmap -> squeue, sqn -> idx);
150 getPhotonFlux(photon, flux);
151 scalecolor(flux, invArea);
152 #ifdef PMAP_EPANECHNIKOV
153 /* Apply Epanechnikov kernel to photon flux based on photon distance */
154 scalecolor(flux, 2 * (1 - sqn -> dist2 / r));
155 #endif
156 addcolor(irrad, flux);
157
158 if (pmap -> srcContrib) {
159 const PhotonPrimary *primary = pmap -> primaries +
160 photon -> primary;
161 const SRCREC *sp = &source [primary -> srcIdx];
162 OBJREC *srcMod = findmaterial(sp -> so);
163 MODCONT *srcContrib = (MODCONT*)lu_find(pmap -> srcContrib,
164 srcMod -> oname) -> data;
165 double srcBinReal;
166 int srcBin;
167 RAY srcRay;
168
169 if (!srcContrib)
170 continue;
171
172 /* Photon's emitting light source has modifier whose contributions
173 * are sought */
174 if (srcContrib -> binv -> type != NUM) {
175 /* Use intersection function to set shadow ray parameters if
176 * it's not simply a constant */
177 rayorigin(&srcRay, SHADOW, NULL, NULL);
178 srcRay.rsrc = primary -> srcIdx;
179 #ifdef PMAP_PRIMARYPOS
180 VCOPY(srcRay.rorg, primary -> pos);
181 #else
182 /* No primary hitpoints; set dummy ray origin and warn once */
183 srcRay.rorg [0] = srcRay.rorg [1] = srcRay.rorg [2] = 0;
184 if (warn) {
185 error(WARNING, "no photon primary hitpoints for bin evaluation;"
186 " using dummy (0,0,0) !");
187 warn = 0;
188 }
189 #endif
190 decodedir(srcRay.rdir, primary -> dir);
191
192 if (!(sp->sflags & SDISTANT
193 ? sourcehit(&srcRay)
194 : (*ofun[sp -> so -> otype].funp)(sp -> so, &srcRay)))
195 continue; /* XXX shouldn't happen! */
196
197 worldfunc(RCCONTEXT, &srcRay);
198 set_eparams((char *)srcContrib -> params);
199 }
200
201 if ((srcBinReal = evalue(srcContrib -> binv)) < -.5)
202 continue; /* silently ignore negative bins */
203
204 if ((srcBin = srcBinReal + .5) >= srcContrib -> nbins) {
205 error(WARNING, "bad bin number (ignored)");
206 continue;
207 }
208
209 if (!contrib) {
210 /* Ray coefficient mode; normalise by light source radiance
211 * after applying distrib pattern */
212 int j;
213
214 raytexture(ray, srcMod -> omod);
215 setcolor(ray -> rcol, srcMod -> oargs.farg [0],
216 srcMod -> oargs.farg [1], srcMod -> oargs.farg [2]);
217 multcolor(ray -> rcol, ray -> pcol);
218 for (j = 0; j < 3; j++)
219 flux [j] = ray -> rcol [j] ? flux [j] / ray -> rcol [j] : 0;
220 }
221
222 multcolor(flux, rayCoeff);
223 addcolor(srcContrib -> cbin [srcBin], flux);
224 }
225 }
226
227 return;
228 }