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 (7 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Separated creation from use of contribution photon maps

File Contents

# User Rev Content
1 greg 2.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     }