ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/pmapooc.c
Revision: 1.2
Committed: Mon Aug 14 21:12:10 2017 UTC (6 years, 9 months ago) by rschregle
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R1
Changes since 1.1: +5 -8 lines
Log Message:
Updated photon map code for Windows; no multproc or ooC for now

File Contents

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