| 4 |
|
|
| 5 |
|
Roland Schregle (roland.schregle@{hslu.ch, gmail.com}) |
| 6 |
|
(c) Fraunhofer Institute for Solar Energy Systems, |
| 7 |
< |
Lucerne University of Applied Sciences & Arts |
| 7 |
> |
(c) Lucerne University of Applied Sciences and Arts, |
| 8 |
> |
supported by the Swiss National Science Foundation (SNSF, #147053) |
| 9 |
|
================================================================== |
| 10 |
|
|
| 11 |
|
$Id$ |
| 19 |
|
#include "otypes.h" |
| 20 |
|
#include "source.h" |
| 21 |
|
#include "rcontrib.h" |
| 22 |
+ |
#include "random.h" |
| 23 |
|
|
| 24 |
|
|
| 25 |
|
|
| 67 |
|
const PhotonPrimary* addPhotonPrimary (PhotonMap *pmap, const RAY *ray) |
| 68 |
|
{ |
| 69 |
|
PhotonPrimary *prim = NULL; |
| 70 |
+ |
FVECT dvec; |
| 71 |
|
|
| 72 |
|
if (!pmap || !ray) |
| 73 |
|
return NULL; |
| 100 |
|
prim -> srcIdx = -1; |
| 101 |
|
|
| 102 |
|
/* Reverse incident direction to point to light source */ |
| 103 |
< |
prim -> dir [0] = -ray -> rdir [0]; |
| 104 |
< |
prim -> dir [1] = -ray -> rdir [1]; |
| 105 |
< |
prim -> dir [2] = -ray -> rdir [2]; |
| 103 |
> |
dvec [0] = -ray -> rdir [0]; |
| 104 |
> |
dvec [1] = -ray -> rdir [1]; |
| 105 |
> |
dvec [2] = -ray -> rdir [2]; |
| 106 |
> |
prim -> dir = encodedir(dvec); |
| 107 |
|
|
| 108 |
< |
VCOPY(prim -> org, ray -> rorg); |
| 108 |
> |
VCOPY(prim -> pos, ray -> rop); |
| 109 |
|
|
| 110 |
|
return prim; |
| 111 |
|
} |
| 230 |
|
} |
| 231 |
|
|
| 232 |
|
/* Reject photon if normal faces away (ignored for volume photons) */ |
| 233 |
< |
if (norm && DOT(norm, p -> norm) <= 0) |
| 233 |
> |
if (norm && DOT(norm, p -> norm) <= 0.5 * frandom()) |
| 234 |
|
return; |
| 235 |
|
|
| 236 |
|
if (isContribPmap(pmap) && pmap -> srcContrib) { |
| 241 |
|
if (srcIdx < 0 || srcIdx >= nsources) |
| 242 |
|
error(INTERNAL, "invalid light source index in photon map"); |
| 243 |
|
|
| 244 |
< |
srcMod = objptr(source [srcIdx].so -> omod); |
| 244 |
> |
srcMod = findmaterial(source [srcIdx].so); |
| 245 |
|
|
| 246 |
|
/* Reject photon if contributions from light source which emitted it |
| 247 |
|
* are not sought */ |
| 312 |
|
/* Threshold below which we assume increasing max radius won't help */ |
| 313 |
|
#define PMAP_SHORT_LOOKUP_THRESH 1 |
| 314 |
|
|
| 315 |
+ |
/* Coefficient for adaptive maximum search radius */ |
| 316 |
+ |
#define PMAP_MAXDIST_COEFF 100 |
| 317 |
+ |
|
| 318 |
+ |
|
| 319 |
|
void findPhotons (PhotonMap* pmap, const RAY* ray) |
| 320 |
|
{ |
| 321 |
|
float pos [3], norm [3]; |
| 337 |
|
pmap -> minError = FHUGE; |
| 338 |
|
pmap -> maxError = -FHUGE; |
| 339 |
|
pmap -> rmsError = 0; |
| 340 |
< |
/* Maximum search radius limit based on avg photon distance to |
| 341 |
< |
* centre of gravity */ |
| 340 |
> |
/* SQUARED max search radius limit is based on avg photon distance to |
| 341 |
> |
* centre of gravity, unless fixed by user (maxDistFix > 0) */ |
| 342 |
|
pmap -> maxDist0 = pmap -> maxDistLimit = |
| 343 |
< |
maxDistCoeff * pmap -> squeueSize * pmap -> CoGdist / |
| 344 |
< |
pmap -> heapSize; |
| 343 |
> |
maxDistFix > 0 ? maxDistFix * maxDistFix |
| 344 |
> |
: PMAP_MAXDIST_COEFF * pmap -> squeueSize * |
| 345 |
> |
pmap -> CoGdist / pmap -> heapSize; |
| 346 |
|
} |
| 347 |
|
|
| 348 |
|
do { |
| 361 |
|
VCOPY(norm, ray -> ron); |
| 362 |
|
nearestNeighbours(pmap, pos, norm, 1); |
| 363 |
|
} |
| 364 |
< |
|
| 364 |
> |
|
| 365 |
> |
if (pmap -> maxDist < FTINY) { |
| 366 |
> |
sprintf(errmsg, "itsy bitsy teeny weeny photon search radius %e", |
| 367 |
> |
sqrt(pmap -> maxDist)); |
| 368 |
> |
error(WARNING, errmsg); |
| 369 |
> |
} |
| 370 |
> |
|
| 371 |
|
if (pmap -> squeueEnd < pmap -> squeueSize * pmap -> gatherTolerance) { |
| 372 |
|
/* Short lookup; too few photons found */ |
| 373 |
|
if (pmap -> squeueEnd > PMAP_SHORT_LOOKUP_THRESH) { |
| 383 |
|
ray -> ro ? ray -> ro -> oname : "<null>"); |
| 384 |
|
error(WARNING, errmsg); |
| 385 |
|
#endif |
| 386 |
< |
|
| 386 |
> |
|
| 387 |
> |
/* Bail out after warning if maxDist is fixed */ |
| 388 |
> |
if (maxDistFix > 0) |
| 389 |
> |
return; |
| 390 |
> |
|
| 391 |
|
if (pmap -> maxDist0 < pmap -> maxDistLimit) { |
| 392 |
|
/* Increase max search radius if below limit & redo search */ |
| 393 |
|
pmap -> maxDist0 *= PMAP_MAXDIST_INC; |
| 394 |
|
#ifdef PMAP_LOOKUP_REDO |
| 395 |
|
redo = 1; |
| 396 |
|
#endif |
| 378 |
– |
|
| 397 |
|
#ifdef PMAP_LOOKUP_WARN |
| 398 |
|
sprintf(errmsg, |
| 399 |
|
redo ? "restarting photon lookup with max radius %.1e" |
| 400 |
|
: "max photon lookup radius adjusted to %.1e", |
| 401 |
< |
pmap -> maxDist0); |
| 401 |
> |
sqrt(pmap -> maxDist0)); |
| 402 |
|
error(WARNING, errmsg); |
| 403 |
|
#endif |
| 404 |
|
} |
| 405 |
|
#ifdef PMAP_LOOKUP_REDO |
| 406 |
|
else { |
| 407 |
|
sprintf(errmsg, "max photon lookup radius clamped to %.1e", |
| 408 |
< |
pmap -> maxDist0); |
| 408 |
> |
sqrt(pmap -> maxDist0)); |
| 409 |
|
error(WARNING, errmsg); |
| 410 |
|
} |
| 411 |
|
#endif |
| 413 |
|
|
| 414 |
|
/* Reset successful lookup counter */ |
| 415 |
|
pmap -> numLookups = 0; |
| 416 |
< |
} |
| 416 |
> |
} |
| 417 |
|
else { |
| 418 |
+ |
/* Bail out after warning if maxDist is fixed */ |
| 419 |
+ |
if (maxDistFix > 0) |
| 420 |
+ |
return; |
| 421 |
+ |
|
| 422 |
|
/* Increment successful lookup counter and reduce max search radius if |
| 423 |
|
* wraparound */ |
| 424 |
|
pmap -> numLookups = (pmap -> numLookups + 1) % PMAP_MAXDIST_CNT; |
| 427 |
|
|
| 428 |
|
redo = 0; |
| 429 |
|
} |
| 430 |
+ |
|
| 431 |
|
} while (redo); |
| 432 |
|
} |
| 433 |
|
|
| 467 |
|
dv [2] = pos [2] - p -> pos [2]; |
| 468 |
|
d2 = DOT(dv, dv); |
| 469 |
|
|
| 470 |
< |
if (d2 < pmap -> maxDist && DOT(norm, p -> norm) > 0) { |
| 470 |
> |
if (d2 < pmap -> maxDist && DOT(norm, p -> norm) > 0.5 * frandom()) { |
| 471 |
|
/* Closest photon so far with similar normal */ |
| 472 |
|
pmap -> maxDist = d2; |
| 473 |
|
*photon = p; |