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

# User Rev Content
1 rschregle 1.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     }