ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/pmapooc.c
Revision: 1.1
Committed: Wed May 18 08:22:45 2016 UTC (8 years ago) by rschregle
Content type: text/plain
Branch: MAIN
Log Message:
Added missing sources of iC and ooC pmap

File Contents

# Content
1 /*
2 ==================================================================
3 Photon map interface to out-of-core octree
4
5 Roland Schregle (roland.schregle@{hslu.ch, gmail.com})
6 (c) Lucerne University of Applied Sciences and Arts,
7 supported by the Swiss National Science Foundation (SNSF, #147053)
8 ==================================================================
9
10 $Id: pmapooc.c,v 1.12 2016/04/25 17:50:30 taschreg Exp taschreg $
11 */
12
13
14 #ifndef PMAP_OOC
15 /* Checked in pmapdata.h */
16 #define PMAP_OOC
17 #endif
18 #include "pmapdata.h" /* Includes pmapooc.h */
19 #include "source.h"
20 #include "oocsort.h"
21 #include "oocbuild.h"
22
23
24
25 /* Returns photon position as sorting key for OOC_Octree & friends (notably
26 * for Morton code generation).
27 * !!! Uses type conversion from float via TEMPORARY storage;
28 * !!! THIS IS NOT THREAD SAFE!
29 * !!! RETURNED KEY PERSISTS ONLY IF COPIED BEFORE NEXT CALL! */
30 RREAL *OOC_PhotonKey (const void *p)
31 {
32 static FVECT photonPos; /* Temp storage for type conversion */
33
34 VCOPY(photonPos, ((Photon*)p) -> pos);
35 return photonPos;
36 }
37
38
39
40 #ifdef DEBUG_OOC
41 static int OOC_CheckKeys (FILE *file, const OOC_Octree *oct)
42 {
43 Photon p, lastp;
44 RREAL *key;
45 OOC_MortonIdx zIdx, lastzIdx = 0;
46
47 rewind(file);
48 memset(&lastp, 0, sizeof(lastp));
49
50 while (fread(&p, sizeof(p), 1, file) > 0) {
51 key = OOC_PhotonKey(&p);
52 zIdx = OOC_KEY2MORTON(key, oct);
53
54 if (zIdx < lastzIdx) {
55 error(INTERNAL, "photons not sorted");
56 return -1;
57 }
58
59 if (zIdx == lastzIdx) {
60 sprintf(errmsg, "identical key %021ld "
61 "for [%.9f, %.9f, %.9f]\tand [%.9f, %.9f, %.9f]",
62 zIdx, lastp.pos [0], lastp.pos [1], lastp.pos [2],
63 p.pos [0], p.pos [1], p.pos [2]);
64 error(WARNING, errmsg);
65 }
66
67 lastzIdx = zIdx;
68 memcpy(&lastp, &p, sizeof(p));
69 }
70
71 return 0;
72 }
73 #endif
74
75
76
77 void OOC_BuildPhotonMap (struct PhotonMap *pmap, unsigned numProc)
78 {
79 FILE *leafFile;
80 char leafFname [1024];
81 FVECT d, octOrg;
82 int i;
83 RREAL octSize = 0;
84
85 /* Determine octree size and origin from pmap extent and init octree */
86 VCOPY(octOrg, pmap -> minPos);
87 VSUB(d, pmap -> maxPos, pmap -> minPos);
88 for (i = 0; i < 3; i++)
89 if (octSize < d [i])
90 octSize = d [i];
91
92 if (octSize < FTINY)
93 error(INTERNAL, "zero octree size in OOC_BuildPhotonMap");
94
95 /* Derive leaf filename from photon map and open file */
96 strncpy(leafFname, pmap -> fileName, sizeof(leafFname));
97 strncat(leafFname, PMAP_OOC_LEAFSUFFIX,
98 sizeof(leafFname) - strlen(leafFname) - 1);
99 if (!(leafFile = fopen(leafFname, "w+b")))
100 error(SYSTEM, "failed to open leaf file in OOC_BuildPhotonMap");
101
102 #ifdef DEBUG_OOC
103 eputs("Sorting photons by Morton code...\n");
104 #endif
105
106 /* Sort photons in heapfile by Morton code and write to leaf file */
107 if (OOC_Sort(pmap -> heap, leafFile, PMAP_OOC_NUMBLK, PMAP_OOC_BLKSIZE,
108 numProc, sizeof(Photon), octOrg, octSize, OOC_PhotonKey))
109 error(INTERNAL, "failed out-of-core photon sort in OOC_BuildPhotonMap");
110
111 /* Init and build octree */
112 OOC_Init(&pmap -> store, sizeof(Photon), octOrg, octSize, OOC_PhotonKey,
113 leafFile);
114
115 #ifdef DEBUG_OOC
116 eputs("Checking leaf file consistency...\n");
117 OOC_CheckKeys(leafFile, &pmap -> store);
118
119 eputs("Building out-of-core octree...\n");
120 #endif
121
122 if (!OOC_Build(&pmap -> store, PMAP_OOC_LEAFMAX, PMAP_OOC_MAXDEPTH))
123 error(INTERNAL, "failed out-of-core octree build in OOC_BuildPhotonMap");
124
125 #ifdef DEBUG_OOC
126 eputs("Checking out-of-core octree consistency...\n");
127 if (OOC_Check(&pmap -> store, OOC_ROOT(&pmap -> store),
128 octOrg, octSize, 0))
129 error(INTERNAL, "inconsistent out-of-core octree; Time4Harakiri");
130 #endif
131 }
132
133
134
135 int OOC_SavePhotons (const struct PhotonMap *pmap, FILE *out)
136 {
137 return OOC_SaveOctree(&pmap -> store, out);
138 }
139
140
141
142 int OOC_LoadPhotons (struct PhotonMap *pmap, FILE *nodeFile)
143 {
144 FILE *leafFile;
145 char leafFname [1024];
146
147 /* Derive leaf filename from photon map and open file */
148 strncpy(leafFname, pmap -> fileName, sizeof(leafFname));
149 strncat(leafFname, PMAP_OOC_LEAFSUFFIX,
150 sizeof(leafFname) - strlen(leafFname) - 1);
151
152 if (!(leafFile = fopen(leafFname, "r")))
153 error(SYSTEM, "failed to open leaf file in OOC_LoadPhotons");
154
155 if (OOC_LoadOctree(&pmap -> store, nodeFile, OOC_PhotonKey, leafFile))
156 return -1;
157
158 return 0;
159 }
160
161
162
163 void OOC_InitFindPhotons (struct PhotonMap *pmap)
164 {
165 if (OOC_InitNearest(&pmap -> squeue, pmap -> maxGather + 1,
166 sizeof(Photon)))
167 error(SYSTEM, "can't allocate photon search queue");
168 }
169
170
171
172 static void OOC_InitPhotonCache (struct PhotonMap *pmap)
173 /* Initialise OOC photon cache */
174 {
175 static char warn = 1;
176
177 if (!pmap -> store.cache && !pmap -> numDensity) {
178 if (pmapCacheSize > 0) {
179 const unsigned pageSize = pmapCachePageSize * pmap -> maxGather,
180 numPages = pmapCacheSize / pageSize;
181 /* Allocate & init I/O cache in octree */
182 pmap -> store.cache = malloc(sizeof(OOC_Cache));
183
184 if (!pmap -> store.cache ||
185 OOC_CacheInit(pmap -> store.cache, numPages, pageSize,
186 sizeof(Photon))) {
187 error(SYSTEM, "failed OOC photon map cache init");
188 }
189 }
190 else if (warn) {
191 error(WARNING, "OOC photon map cache DISABLED");
192 warn = 0;
193 }
194 }
195 }
196
197
198
199 typedef struct {
200 const PhotonMap *pmap;
201 const float *norm;
202 } OOC_FilterData;
203
204
205
206 int OOC_FilterPhoton (void *p, void *fd)
207 /* Filter callback for photon kNN search, used by OOC_FindNearest() */
208 {
209 const Photon *photon = p;
210 const OOC_FilterData *filtData = fd;
211 const PhotonMap *pmap = filtData -> pmap;
212
213 /* Reject photon if normal faces away (ignored for volume photons) with
214 * tolerance to account for perturbation; note photon normal is coded
215 * in range [-127,127], hence we factor this in */
216 if (filtData -> norm &&
217 DOT(filtData->norm, photon->norm) <= PMAP_NORM_TOL * 127 * frandom())
218 return 0;
219
220 if (isContribPmap(pmap) && pmap -> srcContrib) {
221 /* Lookup in contribution photon map */
222 OBJREC *srcMod;
223 const int srcIdx = photonSrcIdx(pmap, photon);
224
225 if (srcIdx < 0 || srcIdx >= nsources)
226 error(INTERNAL, "invalid light source index in photon map");
227
228 srcMod = findmaterial(source [srcIdx].so);
229
230 /* Reject photon if contributions from light source which emitted it
231 * are not sought */
232 if (!lu_find(pmap -> srcContrib, srcMod -> oname) -> data)
233 return 0;
234
235 /* Reject non-caustic photon if lookup for caustic contribs */
236 if (pmap -> lookupCaustic && !photon -> caustic)
237 return 0;
238 }
239
240 /* Accept photon */
241 return 1;
242 }
243
244
245
246 void OOC_FindPhotons (struct PhotonMap *pmap, const FVECT pos, const FVECT norm)
247 {
248 OOC_SearchFilter filt;
249 OOC_FilterData filtData;
250 float n [3];
251
252 /* Lazily init OOC cache */
253 if (!pmap -> store.cache)
254 OOC_InitPhotonCache(pmap);
255
256 /* Set up filter callback */
257 filtData.pmap = pmap;
258 VCOPY(n, norm);
259 filtData.norm = n;
260 filt.data = &filtData;
261 filt.func = OOC_FilterPhoton;
262
263 pmap -> maxDist2 = OOC_FindNearest(&pmap -> store,
264 OOC_ROOT(&pmap -> store), 0,
265 pmap -> store.org, pmap -> store.size,
266 pos, &filt, &pmap -> squeue,
267 pmap -> maxDist2);
268
269 if (pmap -> maxDist2 < 0)
270 error(INTERNAL, "failed k-NN photon lookup in OOC_FindPhotons");
271 }
272
273
274
275 void OOC_Find1Photon (struct PhotonMap* pmap, const FVECT pos,
276 const FVECT norm, Photon *photon)
277 {
278 OOC_SearchFilter filt;
279 OOC_FilterData filtData;
280 float n [3];
281
282 /* Lazily init OOC cache */
283 if (!pmap -> store.cache)
284 OOC_InitPhotonCache(pmap);
285
286 /* Set up filter callback */
287 filtData.pmap = pmap;
288 VCOPY(n, norm);
289 filtData.norm = n;
290 filt.data = &filtData;
291 filt.func = OOC_FilterPhoton;
292
293 pmap -> maxDist2 = OOC_Find1Nearest(&pmap -> store,
294 OOC_ROOT(&pmap -> store), 0,
295 pmap -> store.org, pmap -> store.size,
296 pos, &filt, photon, pmap -> maxDist2);
297
298 if (pmap -> maxDist2 < 0)
299 error(INTERNAL, "failed 1-NN photon lookup in OOC_Find1Photon");
300 }
301
302
303
304 int OOC_GetPhoton (struct PhotonMap *pmap, PhotonIdx idx,
305 Photon *photon)
306 {
307 return OOC_GetData(&pmap -> store, idx, photon);
308 }
309
310
311
312 Photon *OOC_GetNearestPhoton (const PhotonSearchQueue *squeue, PhotonIdx idx)
313 {
314 return OOC_GetNearest(squeue, idx);
315 }
316
317
318
319 PhotonIdx OOC_FirstPhoton (const struct PhotonMap* pmap)
320 {
321 return 0;
322 }