| 1 |
greg |
2.1 |
/* |
| 2 |
|
|
================================================================== |
| 3 |
|
|
Photon map data structures and kd-tree handling |
| 4 |
|
|
|
| 5 |
|
|
Roland Schregle (roland.schregle@{hslu.ch, gmail.com}) |
| 6 |
|
|
(c) Fraunhofer Institute for Solar Energy Systems, |
| 7 |
rschregle |
2.2 |
(c) Lucerne University of Applied Sciences and Arts, |
| 8 |
|
|
supported by the Swiss National Science Foundation (SNSF, #147053) |
| 9 |
greg |
2.1 |
================================================================== |
| 10 |
|
|
|
| 11 |
greg |
2.4 |
$Id: pmapdata.h,v 2.3 2015/05/20 12:58:31 greg Exp $ |
| 12 |
greg |
2.1 |
*/ |
| 13 |
|
|
|
| 14 |
|
|
|
| 15 |
|
|
#ifndef PMAPDATA_H |
| 16 |
|
|
#define PMAPDATA_H |
| 17 |
|
|
|
| 18 |
|
|
#include "ray.h" |
| 19 |
|
|
#include "pmaptype.h" |
| 20 |
|
|
#include "lookup.h" |
| 21 |
|
|
|
| 22 |
|
|
|
| 23 |
|
|
/* Define PMAP_FLOAT_FLUX to store photon flux as floats instead of |
| 24 |
|
|
* compact RGBE, which was found to improve accuracy in analytical |
| 25 |
|
|
* validation. */ |
| 26 |
|
|
#ifdef PMAP_FLOAT_FLUX |
| 27 |
|
|
#define setPhotonFlux(p,f) copycolor((p) -> flux, f) |
| 28 |
|
|
#define getPhotonFlux(p,f) copycolor(f, (p) -> flux) |
| 29 |
|
|
#else |
| 30 |
|
|
#define setPhotonFlux(p,f) setcolr((p)->flux, (f)[0], (f)[1], (f)[2]) |
| 31 |
|
|
#define getPhotonFlux(p,f) colr_color(f, (p) -> flux) |
| 32 |
|
|
#endif |
| 33 |
|
|
|
| 34 |
|
|
|
| 35 |
|
|
/* Primary photon ray for light source contributions */ |
| 36 |
|
|
typedef struct { |
| 37 |
|
|
short srcIdx; /* Index of emitting light source */ |
| 38 |
greg |
2.3 |
float dir [3], pos [3]; /* Incident dir & hit point */ |
| 39 |
greg |
2.1 |
} PhotonPrimary; |
| 40 |
|
|
|
| 41 |
|
|
#define photonSrcIdx(pm, p) ((pm) -> primary [(p) -> primary].srcIdx) |
| 42 |
|
|
|
| 43 |
|
|
|
| 44 |
|
|
typedef struct { |
| 45 |
|
|
float pos [3]; /* Photon position */ |
| 46 |
|
|
signed char norm [3]; /* Surface normal at pos (incident |
| 47 |
|
|
direction for volume photons) */ |
| 48 |
|
|
char flags; /* Bit 0-1: kd-tree discriminator axis, |
| 49 |
|
|
Bit 2: caustic photon */ |
| 50 |
|
|
#ifdef PMAP_FLOAT_FLUX |
| 51 |
|
|
COLOR flux; |
| 52 |
|
|
#else |
| 53 |
|
|
COLR flux; /* Photon flux */ |
| 54 |
|
|
#endif |
| 55 |
|
|
|
| 56 |
greg |
2.4 |
uint32 primary; /* Index to primary ray */ |
| 57 |
greg |
2.1 |
} Photon; |
| 58 |
|
|
|
| 59 |
|
|
/* Photon flag bitmasks and manipulation macros */ |
| 60 |
|
|
#define PMAP_DISCR_BIT 3 |
| 61 |
|
|
#define PMAP_CAUST_BIT 4 |
| 62 |
|
|
#define photonDiscr(p) ((p).flags & PMAP_DISCR_BIT) |
| 63 |
|
|
#define setPhotonDiscr(p, d) ((p).flags = ((p).flags & ~PMAP_DISCR_BIT) | \ |
| 64 |
|
|
((d) & PMAP_DISCR_BIT)) |
| 65 |
|
|
|
| 66 |
|
|
/* Photon map type tests */ |
| 67 |
|
|
#define isGlobalPmap(p) ((p) -> type == PMAP_TYPE_GLOBAL) |
| 68 |
|
|
#define isCausticPmap(p) ((p) -> type == PMAP_TYPE_CAUSTIC) |
| 69 |
|
|
#define isContribPmap(p) ((p) -> type == PMAP_TYPE_CONTRIB) |
| 70 |
|
|
#define isVolumePmap(p) ((p) -> type == PMAP_TYPE_VOLUME) |
| 71 |
|
|
|
| 72 |
|
|
|
| 73 |
|
|
/* Queue node for photon lookups */ |
| 74 |
|
|
typedef struct { |
| 75 |
|
|
Photon *photon; |
| 76 |
|
|
float dist; |
| 77 |
|
|
} PhotonSQNode; |
| 78 |
|
|
|
| 79 |
|
|
/* Bias compensation history node */ |
| 80 |
|
|
typedef struct { |
| 81 |
|
|
COLOR irrad; |
| 82 |
|
|
float weight; |
| 83 |
|
|
} PhotonBCNode; |
| 84 |
|
|
|
| 85 |
|
|
|
| 86 |
|
|
struct PhotonMap; /* Forward declarations */ |
| 87 |
|
|
|
| 88 |
|
|
typedef struct PhotonMap { |
| 89 |
|
|
PhotonMapType type; /* See pmaptype.h */ |
| 90 |
|
|
char *fileName; /* Photon map file */ |
| 91 |
|
|
Photon *heap; /* Photon k-d tree as linear array */ |
| 92 |
|
|
PhotonSQNode *squeue; /* Search queue */ |
| 93 |
|
|
PhotonBCNode *biasCompHist; /* Bias compensation history */ |
| 94 |
|
|
char lookupFlags; /* Flags passed to findPhotons() */ |
| 95 |
|
|
|
| 96 |
|
|
unsigned long distribTarget, /* Num stored specified by user */ |
| 97 |
|
|
heapSize, |
| 98 |
|
|
heapSizeInc, |
| 99 |
|
|
heapEnd, /* Num actually stored in heap */ |
| 100 |
|
|
numDensity, /* Num density estimates */ |
| 101 |
|
|
totalGathered, /* Total photons gathered */ |
| 102 |
|
|
numLookups, /* Counters for short photon lookups */ |
| 103 |
|
|
numShortLookups; |
| 104 |
|
|
|
| 105 |
|
|
unsigned minGather, /* Specified min/max photons per */ |
| 106 |
|
|
maxGather, /* density estimate */ |
| 107 |
|
|
squeueSize, |
| 108 |
|
|
squeueEnd, |
| 109 |
|
|
minGathered, /* Min/max photons actually gathered */ |
| 110 |
|
|
maxGathered, /* per density estimate */ |
| 111 |
|
|
shortLookupPct; /* Percentage of short lookups (for |
| 112 |
|
|
statistics output */ |
| 113 |
|
|
|
| 114 |
|
|
/* NOTE: All distances are SQUARED */ |
| 115 |
|
|
float maxDist, /* Max search radius during NN search */ |
| 116 |
|
|
maxDist0, /* Initial value for above */ |
| 117 |
|
|
maxDistLimit, /* Hard limit for above */ |
| 118 |
|
|
CoGdist, /* Avg distance to centre of gravity */ |
| 119 |
|
|
maxPos [3], minPos [3], /* Max & min photon positions */ |
| 120 |
|
|
distribRatio, /* Probability of photon storage */ |
| 121 |
|
|
gatherTolerance, /* Fractional deviation from minGather/ |
| 122 |
|
|
maxGather for short lookup */ |
| 123 |
|
|
minError, maxError, /* Min/max/rms density estimate error */ |
| 124 |
|
|
rmsError; |
| 125 |
|
|
|
| 126 |
|
|
FVECT CoG; /* Centre of gravity (avg photon pos) */ |
| 127 |
|
|
COLOR photonFlux; /* Average photon flux */ |
| 128 |
|
|
unsigned short randState [3]; /* Local RNG state */ |
| 129 |
|
|
|
| 130 |
|
|
void (*lookup)(struct PhotonMap*, RAY*, COLOR); |
| 131 |
|
|
/* Callback for type-specific photon |
| 132 |
|
|
* lookup (usually density estimate) */ |
| 133 |
|
|
|
| 134 |
|
|
PhotonPrimary *primary; /* Primary photon rays & associated |
| 135 |
|
|
counters */ |
| 136 |
|
|
unsigned primarySize, primaryEnd; |
| 137 |
|
|
|
| 138 |
|
|
LUTAB *srcContrib; /* lookup table for source contribs */ |
| 139 |
|
|
} PhotonMap; |
| 140 |
|
|
|
| 141 |
|
|
|
| 142 |
|
|
|
| 143 |
|
|
/* Photon maps by type (see PhotonMapType) */ |
| 144 |
|
|
extern PhotonMap *photonMaps []; |
| 145 |
|
|
|
| 146 |
|
|
/* Macros for specific photon map types */ |
| 147 |
|
|
#define globalPmap (photonMaps [PMAP_TYPE_GLOBAL]) |
| 148 |
|
|
#define preCompPmap (photonMaps [PMAP_TYPE_PRECOMP]) |
| 149 |
|
|
#define causticPmap (photonMaps [PMAP_TYPE_CAUSTIC]) |
| 150 |
|
|
#define volumePmap (photonMaps [PMAP_TYPE_VOLUME]) |
| 151 |
|
|
#define directPmap (photonMaps [PMAP_TYPE_DIRECT]) |
| 152 |
|
|
#define contribPmap (photonMaps [PMAP_TYPE_CONTRIB]) |
| 153 |
|
|
|
| 154 |
|
|
|
| 155 |
|
|
|
| 156 |
|
|
void initPhotonMap (PhotonMap *pmap, PhotonMapType t); |
| 157 |
|
|
/* Initialise empty photon map of specified type */ |
| 158 |
|
|
|
| 159 |
|
|
const PhotonPrimary* addPhotonPrimary (PhotonMap *pmap, const RAY *ray); |
| 160 |
|
|
/* Add primary ray for emitted photon and save light source index, origin |
| 161 |
|
|
* on source, and emitted direction; used by contrib photons */ |
| 162 |
|
|
|
| 163 |
|
|
const Photon* addPhoton (PhotonMap *pmap, const RAY *ray); |
| 164 |
|
|
/* Create new photon with ray's direction, intersection point, and flux, |
| 165 |
|
|
and add to photon map subject to acceptance probability pmap -> |
| 166 |
|
|
distribRatio for global density control; if the photon is rejected, |
| 167 |
|
|
NULL is returned. The flux is scaled by ray -> rweight and |
| 168 |
|
|
1 / pmap -> distribRatio. */ |
| 169 |
|
|
|
| 170 |
|
|
void balancePhotons (PhotonMap *pmap, double *photonFlux); |
| 171 |
|
|
/* Build a balanced kd-tree as heap to guarantee logarithmic search |
| 172 |
|
|
* times. This must be called prior to performing photon search with |
| 173 |
|
|
* findPhotons(). |
| 174 |
|
|
* PhotonFlux is the flux scaling factor per photon averaged over RGB. In |
| 175 |
|
|
* the case of a contribution photon map, this is an array with a |
| 176 |
|
|
* separate factor specific to each light source due to non-uniform |
| 177 |
|
|
* photon emission; Otherwise it is referenced as a scalar value. Flux is |
| 178 |
|
|
* not scaled if photonFlux == NULL. */ |
| 179 |
|
|
|
| 180 |
|
|
void buildHeap (Photon *heap, unsigned long *heapIdx, |
| 181 |
|
|
unsigned long *heapXdi, const float min [3], |
| 182 |
|
|
const float max [3], unsigned long left, |
| 183 |
|
|
unsigned long right, unsigned long root); |
| 184 |
|
|
/* Recursive part of balancePhotons(..); builds heap from subarray |
| 185 |
|
|
* defined by indices left and right. */ |
| 186 |
|
|
|
| 187 |
|
|
void findPhotons (PhotonMap* pmap, const RAY *ray); |
| 188 |
|
|
/* Find pmap -> squeueSize closest photons to ray -> rop with similar |
| 189 |
|
|
normal. For volume photons ray -> rorg is used and the normal is |
| 190 |
|
|
ignored (being the incident direction in this case). Found photons |
| 191 |
|
|
are placed in pmap -> squeue, with pmap -> squeueEnd being the number |
| 192 |
|
|
actually found. */ |
| 193 |
|
|
|
| 194 |
|
|
Photon *find1Photon (PhotonMap *pmap, const RAY *ray); |
| 195 |
|
|
/* Finds single closest photon to ray -> rop with similar normal. |
| 196 |
|
|
Returns NULL if none found. */ |
| 197 |
|
|
|
| 198 |
|
|
void deletePhotons (PhotonMap*); |
| 199 |
|
|
/* Free dem mammaries... */ |
| 200 |
|
|
|
| 201 |
|
|
#endif |