| 1 |
greg |
2.9 |
/* RCSid $Id: pmapdata.h,v 2.8 2015/08/18 18:45:55 greg Exp $ */
|
| 2 |
greg |
2.1 |
/*
|
| 3 |
|
|
==================================================================
|
| 4 |
|
|
Photon map data structures and kd-tree handling
|
| 5 |
|
|
|
| 6 |
|
|
Roland Schregle (roland.schregle@{hslu.ch, gmail.com})
|
| 7 |
|
|
(c) Fraunhofer Institute for Solar Energy Systems,
|
| 8 |
rschregle |
2.2 |
(c) Lucerne University of Applied Sciences and Arts,
|
| 9 |
|
|
supported by the Swiss National Science Foundation (SNSF, #147053)
|
| 10 |
greg |
2.1 |
==================================================================
|
| 11 |
|
|
|
| 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 |
greg |
2.6 |
int32 srcIdx; /* Index of emitting light source */
|
| 38 |
greg |
2.5 |
int32 dir; /* Encoded ray direction */
|
| 39 |
|
|
float pos [3]; /* Hit point */
|
| 40 |
greg |
2.1 |
} 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 |
greg |
2.4 |
uint32 primary; /* Index to primary ray */
|
| 58 |
greg |
2.1 |
} 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
|