ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/pmapooc.c
Revision: 1.3
Committed: Wed Jan 24 19:39:05 2018 UTC (6 years, 3 months ago) by rschregle
Content type: text/plain
Branch: MAIN
Changes since 1.2: +16 -12 lines
Log Message:
Hack to render contrib pmap as regular global pmap with rpict/rtrace/rvu

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.3 $Id: pmapooc.c,v 1.2 2017/08/14 21:12:10 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 rschregle 1.3 if (isContribPmap(pmap)) {
218     /* Lookup in contribution photon map; filter according to emitting
219     * light source if contrib list set, else accept all */
220    
221     if (pmap -> srcContrib) {
222     OBJREC *srcMod;
223     const int srcIdx = photonSrcIdx(pmap, photon);
224 rschregle 1.1
225 rschregle 1.3 if (srcIdx < 0 || srcIdx >= nsources)
226     error(INTERNAL, "invalid light source index in photon map");
227 rschregle 1.1
228 rschregle 1.3 srcMod = findmaterial(source [srcIdx].so);
229 rschregle 1.1
230 rschregle 1.3 /* Reject photon if contributions from light source which emitted
231     * it are not sought */
232     if (!lu_find(pmap -> srcContrib, srcMod -> oname) -> data)
233     return 0;
234     }
235 rschregle 1.1
236     /* Reject non-caustic photon if lookup for caustic contribs */
237     if (pmap -> lookupCaustic && !photon -> caustic)
238     return 0;
239     }
240    
241     /* Accept photon */
242     return 1;
243     }
244    
245    
246    
247     void OOC_FindPhotons (struct PhotonMap *pmap, const FVECT pos, const FVECT norm)
248     {
249     OOC_SearchFilter filt;
250     OOC_FilterData filtData;
251     float n [3];
252    
253     /* Lazily init OOC cache */
254     if (!pmap -> store.cache)
255     OOC_InitPhotonCache(pmap);
256    
257     /* Set up filter callback */
258     filtData.pmap = pmap;
259     VCOPY(n, norm);
260     filtData.norm = n;
261     filt.data = &filtData;
262     filt.func = OOC_FilterPhoton;
263    
264     pmap -> maxDist2 = OOC_FindNearest(&pmap -> store,
265     OOC_ROOT(&pmap -> store), 0,
266     pmap -> store.org, pmap -> store.size,
267     pos, &filt, &pmap -> squeue,
268     pmap -> maxDist2);
269    
270     if (pmap -> maxDist2 < 0)
271     error(INTERNAL, "failed k-NN photon lookup in OOC_FindPhotons");
272     }
273    
274    
275    
276     void OOC_Find1Photon (struct PhotonMap* pmap, const FVECT pos,
277     const FVECT norm, Photon *photon)
278     {
279     OOC_SearchFilter filt;
280     OOC_FilterData filtData;
281     float n [3];
282    
283     /* Lazily init OOC cache */
284     if (!pmap -> store.cache)
285     OOC_InitPhotonCache(pmap);
286    
287     /* Set up filter callback */
288     filtData.pmap = pmap;
289     VCOPY(n, norm);
290     filtData.norm = n;
291     filt.data = &filtData;
292     filt.func = OOC_FilterPhoton;
293    
294     pmap -> maxDist2 = OOC_Find1Nearest(&pmap -> store,
295     OOC_ROOT(&pmap -> store), 0,
296     pmap -> store.org, pmap -> store.size,
297     pos, &filt, photon, pmap -> maxDist2);
298    
299     if (pmap -> maxDist2 < 0)
300     error(INTERNAL, "failed 1-NN photon lookup in OOC_Find1Photon");
301     }
302    
303    
304    
305     int OOC_GetPhoton (struct PhotonMap *pmap, PhotonIdx idx,
306     Photon *photon)
307     {
308     return OOC_GetData(&pmap -> store, idx, photon);
309     }
310    
311    
312    
313     Photon *OOC_GetNearestPhoton (const PhotonSearchQueue *squeue, PhotonIdx idx)
314     {
315     return OOC_GetNearest(squeue, idx);
316     }
317    
318    
319    
320     PhotonIdx OOC_FirstPhoton (const struct PhotonMap* pmap)
321     {
322     return 0;
323     }