| 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 |
|
|
| 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 */ |
| 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; |
| 109 |
< |
} |
| 109 |
> |
} |
| 110 |
|
} |
| 111 |
|
} |
| 112 |
|
|
| 131 |
|
/* Photon density estimate. Returns irradiance at ray -> rop. */ |
| 132 |
|
{ |
| 133 |
|
unsigned i; |
| 134 |
< |
float r; |
| 134 |
> |
float r2; |
| 135 |
|
COLOR flux; |
| 136 |
|
Photon *photon; |
| 137 |
|
const PhotonSearchQueueNode *sqn; |
| 163 |
|
/* No bias compensation. Just do a plain vanilla estimate */ |
| 164 |
|
sqn = pmap -> squeue.node + 1; |
| 165 |
|
|
| 166 |
< |
/* Average radius between furthest two photons to improve accuracy */ |
| 167 |
< |
r = max(sqn -> dist2, (sqn + 1) -> dist2); |
| 168 |
< |
r = 0.25 * (pmap -> maxDist2 + r + 2 * sqrt(pmap -> maxDist2 * r)); |
| 166 |
> |
/* Average radius^2 between furthest two photons to improve accuracy */ |
| 167 |
> |
r2 = max(sqn -> dist2, (sqn + 1) -> dist2); |
| 168 |
> |
r2 = 0.25 * (pmap -> maxDist2 + r2 + 2 * sqrt(pmap -> maxDist2 * r2)); |
| 169 |
|
|
| 170 |
|
/* Skip the extra photon */ |
| 171 |
|
for (i = 1 ; i < pmap -> squeue.tail; i++, sqn++) { |
| 173 |
|
getPhotonFlux(photon, flux); |
| 174 |
|
#ifdef PMAP_EPANECHNIKOV |
| 175 |
|
/* Apply Epanechnikov kernel to photon flux based on photon dist */ |
| 176 |
< |
scalecolor(flux, 2 * (1 - sqn -> dist2 / r)); |
| 176 |
> |
scalecolor(flux, 2 * (1 - sqn -> dist2 / r2)); |
| 177 |
|
#endif |
| 178 |
|
addcolor(irrad, flux); |
| 179 |
|
} |
| 180 |
|
|
| 181 |
|
/* Divide by search area PI * r^2, 1 / PI required as ambient |
| 182 |
|
normalisation factor */ |
| 183 |
< |
scalecolor(irrad, 1 / (PI * PI * r)); |
| 183 |
> |
scalecolor(irrad, 1 / (PI * PI * r2)); |
| 184 |
|
|
| 185 |
|
return; |
| 186 |
|
} |
| 203 |
|
if (r -> ro && islight(objptr(r -> ro -> omod) -> otype)) |
| 204 |
|
return; |
| 205 |
|
|
| 206 |
< |
find1Photon(preCompPmap, r, &p); |
| 207 |
< |
getPhotonFlux(&p, irrad); |
| 206 |
> |
if (find1Photon(preCompPmap, r, &p)) |
| 207 |
> |
/* p contains a found photon, so get its irradiance, otherwise it |
| 208 |
> |
* remains zero under the assumption all photons are too distant |
| 209 |
> |
* to contribute significantly */ |
| 210 |
> |
getPhotonFlux(&p, irrad); |
| 211 |
|
} |
| 212 |
|
|
| 213 |
|
|
| 217 |
|
/* Photon volume density estimate. Returns irradiance at ray -> rop. */ |
| 218 |
|
{ |
| 219 |
|
unsigned i; |
| 220 |
< |
float r, gecc2, ph; |
| 220 |
> |
float r2, gecc2, ph; |
| 221 |
|
COLOR flux; |
| 222 |
|
Photon *photon; |
| 223 |
|
const PhotonSearchQueueNode *sqn; |
| 242 |
|
gecc2 = ray -> gecc * ray -> gecc; |
| 243 |
|
sqn = pmap -> squeue.node + 1; |
| 244 |
|
|
| 245 |
< |
/* Average radius between furthest two photons to improve accuracy */ |
| 246 |
< |
r = max(sqn -> dist2, (sqn + 1) -> dist2); |
| 247 |
< |
r = 0.25 * (pmap -> maxDist2 + r + 2 * sqrt(pmap -> maxDist2 * r)); |
| 245 |
> |
/* Average radius^2 between furthest two photons to improve accuracy */ |
| 246 |
> |
r2 = max(sqn -> dist2, (sqn + 1) -> dist2); |
| 247 |
> |
r2 = 0.25 * (pmap -> maxDist2 + r2 + 2 * sqrt(pmap -> maxDist2 * r2)); |
| 248 |
|
|
| 249 |
|
/* Skip the extra photon */ |
| 250 |
|
for (i = 1; i < pmap -> squeue.tail; i++, sqn++) { |
| 266 |
|
|
| 267 |
|
/* Divide by search volume 4 / 3 * PI * r^3 and phase function |
| 268 |
|
normalization factor 1 / (4 * PI) */ |
| 269 |
< |
scalecolor(irrad, 3 / (16 * PI * PI * r * sqrt(r))); |
| 269 |
> |
scalecolor(irrad, 3 / (16 * PI * PI * r2 * sqrt(r2))); |
| 270 |
|
return; |
| 271 |
|
} |
| 272 |
|
#if 0 |