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

# Content
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 }