ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/pmutil.c
Revision: 2.1
Committed: Mon Sep 26 20:19:30 2016 UTC (7 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R1
Log Message:
Pulled pmap routines needed during rendering from pmap.c into pmutil.c

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #endif
4    
5     /*
6     ======================================================================
7     Photon map utilities
8    
9     Roland Schregle (roland.schregle@{hslu.ch, gmail.com})
10     (c) Fraunhofer Institute for Solar Energy Systems,
11     (c) Lucerne University of Applied Sciences and Arts,
12     supported by the Swiss National Science Foundation (SNSF, #147053)
13     ======================================================================
14    
15     $Id: pmap.c,v 2.11 2016/05/17 17:39:47 rschregle Exp $
16     */
17    
18     #include "pmap.h"
19     #include "pmapio.h"
20     #include "pmapbias.h"
21     #include "otypes.h"
22     #include <sys/stat.h>
23    
24    
25     extern char *octname;
26    
27    
28     /* Photon map lookup functions per type */
29     void (*pmapLookup [NUM_PMAP_TYPES])(PhotonMap*, RAY*, COLOR) = {
30     photonDensity, photonPreCompDensity, photonDensity, volumePhotonDensity,
31     photonDensity, NULL
32     };
33    
34    
35    
36    
37     void colorNorm (COLOR c)
38     /* Normalise colour channels to average of 1 */
39     {
40     const float avg = colorAvg(c);
41    
42     if (!avg)
43     return;
44    
45     c [0] /= avg;
46     c [1] /= avg;
47     c [2] /= avg;
48     }
49    
50    
51    
52    
53     void loadPmaps (PhotonMap **pmaps, const PhotonMapParams *parm)
54     {
55     unsigned t;
56     struct stat octstat, pmstat;
57     PhotonMap *pm;
58     PhotonMapType type;
59    
60     for (t = 0; t < NUM_PMAP_TYPES; t++)
61     if (setPmapParam(&pm, parm + t)) {
62     /* Check if photon map newer than octree */
63     if (pm -> fileName && octname &&
64     !stat(pm -> fileName, &pmstat) && !stat(octname, &octstat) &&
65     octstat.st_mtime > pmstat.st_mtime) {
66     sprintf(errmsg, "photon map in file %s may be stale",
67     pm -> fileName);
68     error(USER, errmsg);
69     }
70    
71     /* Load photon map from file and get its type */
72     if ((type = loadPhotonMap(pm, pm -> fileName)) == PMAP_TYPE_NONE)
73     error(USER, "failed loading photon map");
74    
75     /* Assign to appropriate photon map type (deleting previously
76     * loaded photon map of same type if necessary) */
77     if (pmaps [type]) {
78     deletePhotons(pmaps [type]);
79     free(pmaps [type]);
80     }
81     pmaps [type] = pm;
82    
83     /* Check for invalid density estimate bandwidth */
84     if (pm -> maxGather > pm -> numPhotons) {
85     error(WARNING, "adjusting density estimate bandwidth");
86     pm -> minGather = pm -> maxGather = pm -> numPhotons;
87     }
88     }
89     }
90    
91    
92    
93     void cleanUpPmaps (PhotonMap **pmaps)
94     {
95     unsigned t;
96    
97     for (t = 0; t < NUM_PMAP_TYPES; t++) {
98     if (pmaps [t]) {
99     deletePhotons(pmaps [t]);
100     free(pmaps [t]);
101     }
102     }
103     }
104    
105    
106    
107    
108     void photonDensity (PhotonMap *pmap, RAY *ray, COLOR irrad)
109     /* Photon density estimate. Returns irradiance at ray -> rop. */
110     {
111     unsigned i;
112     float r;
113     COLOR flux;
114     Photon *photon;
115     const PhotonSearchQueueNode *sqn;
116    
117     setcolor(irrad, 0, 0, 0);
118    
119     if (!pmap -> maxGather)
120     return;
121    
122     /* Ignore sources */
123     if (ray -> ro && islight(objptr(ray -> ro -> omod) -> otype))
124     return;
125    
126     findPhotons(pmap, ray);
127    
128     /* Need at least 2 photons */
129     if (pmap -> squeue.tail < 2) {
130     #ifdef PMAP_NONEFOUND
131     sprintf(errmsg, "no photons found on %s at (%.3f, %.3f, %.3f)",
132     ray -> ro ? ray -> ro -> oname : "<null>",
133     ray -> rop [0], ray -> rop [1], ray -> rop [2]);
134     error(WARNING, errmsg);
135     #endif
136    
137     return;
138     }
139    
140     if (pmap -> minGather == pmap -> maxGather) {
141     /* No bias compensation. Just do a plain vanilla estimate */
142     sqn = pmap -> squeue.node + 1;
143    
144     /* Average radius between furthest two photons to improve accuracy */
145     r = max(sqn -> dist2, (sqn + 1) -> dist2);
146     r = 0.25 * (pmap -> maxDist2 + r + 2 * sqrt(pmap -> maxDist2 * r));
147    
148     /* Skip the extra photon */
149     for (i = 1 ; i < pmap -> squeue.tail; i++, sqn++) {
150     photon = getNearestPhoton(&pmap -> squeue, sqn -> idx);
151     getPhotonFlux(photon, flux);
152     #ifdef PMAP_EPANECHNIKOV
153     /* Apply Epanechnikov kernel to photon flux based on photon dist */
154     scalecolor(flux, 2 * (1 - sqn -> dist2 / r));
155     #endif
156     addcolor(irrad, flux);
157     }
158    
159     /* Divide by search area PI * r^2, 1 / PI required as ambient
160     normalisation factor */
161     scalecolor(irrad, 1 / (PI * PI * r));
162    
163     return;
164     }
165     else
166     /* Apply bias compensation to density estimate */
167     biasComp(pmap, irrad);
168     }
169    
170    
171    
172    
173     void photonPreCompDensity (PhotonMap *pmap, RAY *r, COLOR irrad)
174     /* Returns precomputed photon density estimate at ray -> rop. */
175     {
176     Photon p;
177    
178     setcolor(irrad, 0, 0, 0);
179    
180     /* Ignore sources */
181     if (r -> ro && islight(objptr(r -> ro -> omod) -> otype))
182     return;
183    
184     find1Photon(preCompPmap, r, &p);
185     getPhotonFlux(&p, irrad);
186     }
187    
188    
189    
190    
191     void volumePhotonDensity (PhotonMap *pmap, RAY *ray, COLOR irrad)
192     /* Photon volume density estimate. Returns irradiance at ray -> rop. */
193     {
194     unsigned i;
195     float r, gecc2, ph;
196     COLOR flux;
197     Photon *photon;
198     const PhotonSearchQueueNode *sqn;
199    
200     setcolor(irrad, 0, 0, 0);
201    
202     if (!pmap -> maxGather)
203     return;
204    
205     findPhotons(pmap, ray);
206    
207     /* Need at least 2 photons */
208     if (pmap -> squeue.tail < 2)
209     return;
210    
211     #if 0
212     /* Volume biascomp disabled (probably redundant) */
213     if (pmap -> minGather == pmap -> maxGather)
214     #endif
215     {
216     /* No bias compensation. Just do a plain vanilla estimate */
217     gecc2 = ray -> gecc * ray -> gecc;
218     sqn = pmap -> squeue.node + 1;
219    
220     /* Average radius between furthest two photons to improve accuracy */
221     r = max(sqn -> dist2, (sqn + 1) -> dist2);
222     r = 0.25 * (pmap -> maxDist2 + r + 2 * sqrt(pmap -> maxDist2 * r));
223    
224     /* Skip the extra photon */
225     for (i = 1; i < pmap -> squeue.tail; i++, sqn++) {
226     photon = getNearestPhoton(&pmap -> squeue, sqn -> idx);
227    
228     /* Compute phase function for inscattering from photon */
229     if (gecc2 <= FTINY)
230     ph = 1;
231     else {
232     ph = DOT(ray -> rdir, photon -> norm) / 127;
233     ph = 1 + gecc2 - 2 * ray -> gecc * ph;
234     ph = (1 - gecc2) / (ph * sqrt(ph));
235     }
236    
237     getPhotonFlux(photon, flux);
238     scalecolor(flux, ph);
239     addcolor(irrad, flux);
240     }
241    
242     /* Divide by search volume 4 / 3 * PI * r^3 and phase function
243     normalization factor 1 / (4 * PI) */
244     scalecolor(irrad, 3 / (16 * PI * PI * r * sqrt(r)));
245     return;
246     }
247     #if 0
248     else
249     /* Apply bias compensation to density estimate */
250     volumeBiasComp(pmap, ray, irrad);
251     #endif
252     }