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 |
rschregle |
2.2 |
$Id: pmapdata.h,v 2.1 2015/02/24 19:39:26 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 |
|
|
float dir [3], org [3]; /* Incident dir & origin on source */ |
39 |
|
|
} 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 |
|
|
unsigned primary; /* Index to primary ray */ |
57 |
|
|
} 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 |