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