28 |
|
/* Photon map lookup functions per type */ |
29 |
|
void (*pmapLookup [NUM_PMAP_TYPES])(PhotonMap*, RAY*, COLOR) = { |
30 |
|
photonDensity, photonPreCompDensity, photonDensity, volumePhotonDensity, |
31 |
< |
photonDensity, NULL |
31 |
> |
photonDensity, photonDensity |
32 |
|
}; |
33 |
|
|
34 |
|
|
56 |
|
struct stat octstat, pmstat; |
57 |
|
PhotonMap *pm; |
58 |
|
PhotonMapType type; |
59 |
< |
|
59 |
> |
|
60 |
|
for (t = 0; t < NUM_PMAP_TYPES; t++) |
61 |
< |
if (setPmapParam(&pm, parm + 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) && |
67 |
|
pm -> fileName); |
68 |
|
error(USER, errmsg); |
69 |
|
} |
70 |
< |
|
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"); |
75 |
|
/* Assign to appropriate photon map type (deleting previously |
76 |
|
* loaded photon map of same type if necessary) */ |
77 |
|
if (pmaps [type]) { |
78 |
+ |
sprintf(errmsg, "multiple %s photon maps, dropping previous", |
79 |
+ |
pmapName [type]); |
80 |
+ |
error(WARNING, errmsg); |
81 |
|
deletePhotons(pmaps [type]); |
82 |
|
free(pmaps [type]); |
83 |
|
} |
84 |
|
pmaps [type] = pm; |
85 |
< |
|
86 |
< |
/* Check for invalid density estimate bandwidth */ |
85 |
> |
|
86 |
> |
/* Check for valid density estimate bandwidths */ |
87 |
> |
if ((pm -> minGather > 1 || pm -> maxGather > 1) && |
88 |
> |
(type == PMAP_TYPE_PRECOMP)) { |
89 |
> |
/* Force bwidth to 1 for precomputed pmap */ |
90 |
> |
error(WARNING, "ignoring bandwidth for precomp photon map"); |
91 |
> |
pm -> minGather = pm -> maxGather = 1; |
92 |
> |
} |
93 |
> |
|
94 |
> |
if ((pm -> maxGather > pm -> minGather) && |
95 |
> |
(type == PMAP_TYPE_VOLUME)) { |
96 |
> |
/* Biascomp for volume pmaps (see volumePhotonDensity() below) |
97 |
> |
is considered redundant, and there's probably no point in |
98 |
> |
recovering by using the lower bandwidth, since it's probably |
99 |
> |
not what the user wants, so bail out. */ |
100 |
> |
sprintf(errmsg, |
101 |
> |
"bias compensation is not available with %s photon maps", |
102 |
> |
pmapName [type]); |
103 |
> |
error(USER, errmsg); |
104 |
> |
} |
105 |
> |
|
106 |
|
if (pm -> maxGather > pm -> numPhotons) { |
107 |
< |
error(WARNING, "adjusting density estimate bandwidth"); |
108 |
< |
pm -> minGather = pm -> maxGather = pm -> numPhotons; |
107 |
> |
/* Clamp lookup bandwidth to total number of photons (minus one, |
108 |
> |
since density estimate gets extra photon to obtain averaged |
109 |
> |
radius) */ |
110 |
> |
sprintf( |
111 |
> |
errmsg, "clamping density estimate bandwidth to %ld", |
112 |
> |
pm -> numPhotons |
113 |
> |
); |
114 |
> |
error(WARNING, errmsg); |
115 |
> |
pm -> minGather = pm -> maxGather = pm -> numPhotons - 1; |
116 |
|
} |
117 |
|
} |
118 |
|
} |
138 |
|
/* Photon density estimate. Returns irradiance at ray -> rop. */ |
139 |
|
{ |
140 |
|
unsigned i; |
141 |
< |
float r; |
141 |
> |
float r2; |
142 |
|
COLOR flux; |
143 |
|
Photon *photon; |
144 |
|
const PhotonSearchQueueNode *sqn; |
170 |
|
/* No bias compensation. Just do a plain vanilla estimate */ |
171 |
|
sqn = pmap -> squeue.node + 1; |
172 |
|
|
173 |
< |
/* Average radius between furthest two photons to improve accuracy */ |
174 |
< |
r = max(sqn -> dist2, (sqn + 1) -> dist2); |
175 |
< |
r = 0.25 * (pmap -> maxDist2 + r + 2 * sqrt(pmap -> maxDist2 * r)); |
173 |
> |
/* Average radius^2 between furthest two photons to improve accuracy */ |
174 |
> |
r2 = max(sqn -> dist2, (sqn + 1) -> dist2); |
175 |
> |
r2 = 0.25 * (pmap -> maxDist2 + r2 + 2 * sqrt(pmap -> maxDist2 * r2)); |
176 |
|
|
177 |
|
/* Skip the extra photon */ |
178 |
|
for (i = 1 ; i < pmap -> squeue.tail; i++, sqn++) { |
180 |
|
getPhotonFlux(photon, flux); |
181 |
|
#ifdef PMAP_EPANECHNIKOV |
182 |
|
/* Apply Epanechnikov kernel to photon flux based on photon dist */ |
183 |
< |
scalecolor(flux, 2 * (1 - sqn -> dist2 / r)); |
183 |
> |
scalecolor(flux, 2 * (1 - sqn -> dist2 / r2)); |
184 |
|
#endif |
185 |
|
addcolor(irrad, flux); |
186 |
|
} |
187 |
|
|
188 |
|
/* Divide by search area PI * r^2, 1 / PI required as ambient |
189 |
|
normalisation factor */ |
190 |
< |
scalecolor(irrad, 1 / (PI * PI * r)); |
190 |
> |
scalecolor(irrad, 1 / (PI * PI * r2)); |
191 |
|
|
192 |
|
return; |
193 |
|
} |
210 |
|
if (r -> ro && islight(objptr(r -> ro -> omod) -> otype)) |
211 |
|
return; |
212 |
|
|
213 |
< |
find1Photon(preCompPmap, r, &p); |
214 |
< |
getPhotonFlux(&p, irrad); |
213 |
> |
if (find1Photon(preCompPmap, r, &p)) |
214 |
> |
/* p contains a found photon, so get its irradiance, otherwise it |
215 |
> |
* remains zero under the assumption all photons are too distant |
216 |
> |
* to contribute significantly */ |
217 |
> |
getPhotonFlux(&p, irrad); |
218 |
|
} |
219 |
|
|
220 |
|
|
224 |
|
/* Photon volume density estimate. Returns irradiance at ray -> rop. */ |
225 |
|
{ |
226 |
|
unsigned i; |
227 |
< |
float r, gecc2, ph; |
227 |
> |
float r2, gecc2, ph; |
228 |
|
COLOR flux; |
229 |
|
Photon *photon; |
230 |
|
const PhotonSearchQueueNode *sqn; |
249 |
|
gecc2 = ray -> gecc * ray -> gecc; |
250 |
|
sqn = pmap -> squeue.node + 1; |
251 |
|
|
252 |
< |
/* Average radius between furthest two photons to improve accuracy */ |
253 |
< |
r = max(sqn -> dist2, (sqn + 1) -> dist2); |
254 |
< |
r = 0.25 * (pmap -> maxDist2 + r + 2 * sqrt(pmap -> maxDist2 * r)); |
252 |
> |
/* Average radius^2 between furthest two photons to improve accuracy */ |
253 |
> |
r2 = max(sqn -> dist2, (sqn + 1) -> dist2); |
254 |
> |
r2 = 0.25 * (pmap -> maxDist2 + r2 + 2 * sqrt(pmap -> maxDist2 * r2)); |
255 |
|
|
256 |
|
/* Skip the extra photon */ |
257 |
|
for (i = 1; i < pmap -> squeue.tail; i++, sqn++) { |
273 |
|
|
274 |
|
/* Divide by search volume 4 / 3 * PI * r^3 and phase function |
275 |
|
normalization factor 1 / (4 * PI) */ |
276 |
< |
scalecolor(irrad, 3 / (16 * PI * PI * r * sqrt(r))); |
276 |
> |
scalecolor(irrad, 3 / (16 * PI * PI * r2 * sqrt(r2))); |
277 |
|
return; |
278 |
|
} |
279 |
|
#if 0 |