ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/pmapdump.c
Revision: 2.13
Committed: Thu Jan 10 17:32:39 2019 UTC (6 years, 3 months ago) by rschregle
Content type: text/plain
Branch: MAIN
Changes since 2.12: +101 -56 lines
Log Message:
Added -f option to colour photons according to their RGB flux. Spheres now output with 'glow' modifier. Adjusted global photon default colour (blue) for improved visibility.

File Contents

# User Rev Content
1 greg 2.4 #ifndef lint
2 rschregle 2.13 static const char RCSid[] = "$Id: pmapdump.c,v 2.12 2018/11/21 19:30:59 rschregle Exp $";
3 greg 2.4 #endif
4 rschregle 2.7
5 greg 2.1 /*
6 rschregle 2.7 ======================================================================
7 greg 2.1 Dump photon maps as RADIANCE scene description to stdout
8    
9     Roland Schregle (roland.schregle@{hslu.ch, gmail.com})
10     (c) Fraunhofer Institute for Solar Energy Systems,
11 rschregle 2.3 (c) Lucerne University of Applied Sciences and Arts,
12 rschregle 2.7 supported by the Swiss National Science Foundation (SNSF, #147053)
13     ======================================================================
14 greg 2.1
15 rschregle 2.13 $Id: pmapdump.c,v 2.12 2018/11/21 19:30:59 rschregle Exp $
16 greg 2.1 */
17    
18    
19    
20     #include "pmapio.h"
21     #include "pmapparm.h"
22     #include "pmaptype.h"
23     #include "rtio.h"
24     #include "resolu.h"
25     #include "random.h"
26 greg 2.2 #include "math.h"
27 greg 2.1
28    
29     /* Defaults */
30     /* Sphere radius as fraction of avg. intersphere dist */
31     /* Relative scale for sphere radius (fudge factor) */
32     /* Number of spheres */
33     #define RADCOEFF 0.05
34     #define RADSCALE 1.0
35     #define NSPHERES 10000
36    
37    
38     /* RADIANCE material and object defs for each photon type */
39     typedef struct {
40     char *mat, *obj;
41     } RadianceDef;
42    
43    
44 rschregle 2.13 /* We use %e for the material def to preserve precision when outputting
45     photon flux */
46 greg 2.1 const RadianceDef radDefs [] = {
47 rschregle 2.13 { "void glow mat.global\n0\n0\n4 %e %e %e 0\n",
48 greg 2.1 "mat.global sphere obj.global\n0\n0\n4 %g %g %g %g\n"
49     },
50 rschregle 2.13 { "void glow mat.pglobal\n0\n0\n4 %e %e %e 0\n",
51     "mat.pglobal sphere obj.pglobal\n0\n0\n4 %g %g %g %g\n"
52 greg 2.1 },
53 rschregle 2.13 { "void glow mat.caustic\n0\n0\n4 %e %e %e 0\n",
54 greg 2.1 "mat.caustic sphere obj.caustic\n0\n0\n4 %g %g %g %g\n"
55     },
56 rschregle 2.13 { "void glow mat.volume\n0\n0\n4 %e %e %e 0\n",
57 greg 2.1 "mat.volume sphere obj.volume\n0\n0\n4 %g %g %g %g\n"
58     },
59 rschregle 2.13 { "void glow mat.direct\n0\n0\n4 %e %e %e 0\n",
60 greg 2.1 "mat.direct sphere obj.direct\n0\n0\n4 %g %g %g %g\n"
61     },
62 rschregle 2.13 { "void glow mat.contrib\n0\n0\n4 %e %e %e 0\n",
63 greg 2.1 "mat.contrib sphere obj.contrib\n0\n0\n4 %g %g %g %g\n"
64     }
65     };
66    
67 rschregle 2.12 /* Default colour codes are as follows: global = blue
68     precomp global = cyan
69     caustic = red
70     volume = green
71     direct = magenta
72     contrib = yellow */
73     const COLOR colDefs [] = {
74 rschregle 2.13 {0.25, 0.25, 2}, {0.1, 1, 1}, {1, 0.1, 0.1},
75     {0.1, 1, 0.1}, {1, 0.1, 1}, {1, 1, 0.1}
76 rschregle 2.12 };
77 greg 2.1
78    
79     int main (int argc, char** argv)
80     {
81 greg 2.11 char format [MAXFMTLEN];
82 rschregle 2.9 RREAL rad, radScale = RADSCALE, extent, dumpRatio;
83 rschregle 2.13 unsigned arg, j, ptype, dim, fluxCol = 0;
84 rschregle 2.7 long numSpheres = NSPHERES;
85 rschregle 2.12 COLOR customCol = {0, 0, 0};
86 rschregle 2.7 FILE *pmapFile;
87     PhotonMap pm;
88     PhotonPrimary pri;
89     Photon p;
90     #ifdef PMAP_OOC
91     char leafFname [1024];
92     #endif
93 rschregle 2.13
94     int setBool(char *str, int pos, int *var)
95     {
96     switch ((str) [pos]) {
97     case '\0':
98     *var = !*var;
99     break;
100     case 'y': case 'Y': case 't': case 'T': case '+': case '1':
101     *var = 1;
102     break;
103     case 'n': case 'N': case 'f': case 'F': case '-': case '0':
104     *var = 0;
105     break;
106     default:
107     return 0;
108     }
109    
110     return 1;
111     }
112    
113 greg 2.1 if (argc < 2) {
114     puts("Dump photon maps as RADIANCE scene description\n");
115 rschregle 2.12 printf("Usage: %s "
116 rschregle 2.13 "[-r radscale1] [-n nspheres1] [-f | -c rcol1 gcol1 bcol1] pmap1 "
117     "[-r radscale2] [-n nspheres2] [-f | -c rcol2 gcol2 bcol2] pmap2 "
118 rschregle 2.12 "...\n", argv [0]);
119 greg 2.1 return 1;
120     }
121    
122     for (arg = 1; arg < argc; arg++) {
123     /* Parse options */
124     if (argv [arg][0] == '-') {
125     switch (argv [arg][1]) {
126     case 'r':
127     if ((radScale = atof(argv [++arg])) <= 0)
128     error(USER, "invalid radius scale");
129     break;
130    
131     case 'n':
132     if ((numSpheres = parseMultiplier(argv [++arg])) <= 0)
133     error(USER, "invalid number of spheres");
134     break;
135    
136 rschregle 2.12 case 'c':
137 rschregle 2.13 if (fluxCol)
138     error(USER, "-f and -c are mutually exclusive");
139    
140     if (badarg(argc - arg - 1, &argv [arg + 1], "fff"))
141     error(USER, "invalid RGB colour");
142    
143 rschregle 2.12 for (j = 0; j < 3; j++)
144 rschregle 2.13 customCol [j] = atof(argv [++arg]);
145     break;
146    
147     case 'f':
148     if (intens(customCol) > 0)
149     error(USER, "-f and -c are mutually exclusive");
150    
151     if (!setBool(argv [arg], 2, &fluxCol))
152     error(USER, "invalid option syntax at -f");
153 rschregle 2.12 break;
154    
155 greg 2.1 default:
156     sprintf(errmsg, "unknown option %s", argv [arg]);
157     error(USER, errmsg);
158     return -1;
159     }
160    
161     continue;
162     }
163 rschregle 2.13
164 greg 2.1 /* Dump photon map */
165     if (!(pmapFile = fopen(argv [arg], "rb"))) {
166     sprintf(errmsg, "can't open %s", argv [arg]);
167     error(SYSTEM, errmsg);
168     }
169 rschregle 2.13
170 greg 2.1 /* Get format string */
171     strcpy(format, PMAP_FORMAT_GLOB);
172     if (checkheader(pmapFile, format, NULL) != 1) {
173     sprintf(errmsg, "photon map file %s has unknown format %s",
174     argv [arg], format);
175     error(USER, errmsg);
176     }
177 rschregle 2.13
178 greg 2.1 /* Identify photon map type from format string */
179     for (ptype = 0;
180 rschregle 2.6 ptype < NUM_PMAP_TYPES && strcmp(pmapFormat [ptype], format);
181 greg 2.1 ptype++);
182 rschregle 2.13
183 greg 2.1 if (!validPmapType(ptype)) {
184     sprintf(errmsg, "file %s contains an unknown photon map type",
185     argv [arg]);
186     error(USER, errmsg);
187     }
188    
189     /* Get file format version and check for compatibility */
190 rschregle 2.7 if (strcmp(getstr(format, pmapFile), PMAP_FILEVER))
191 greg 2.1 error(USER, "incompatible photon map file format");
192 rschregle 2.13
193 greg 2.1 /* Dump command line as comment */
194     fputs("# ", stdout);
195     printargs(argc, argv, stdout);
196     fputc('\n', stdout);
197 rschregle 2.13
198     /* Dump common material def if constant for all photons,
199     i.e. independent of individual flux */
200     if (!fluxCol) {
201     if (intens(customCol) > 0)
202     printf(radDefs [ptype].mat,
203     customCol [0], customCol [1], customCol [2]);
204     else
205     printf(radDefs [ptype].mat, colDefs [ptype][0],
206     colDefs [ptype][1], colDefs [ptype][2]);
207     fputc('\n', stdout);
208     }
209 greg 2.1
210 rschregle 2.7 /* Get number of photons */
211     pm.numPhotons = getint(sizeof(pm.numPhotons), pmapFile);
212 rschregle 2.13
213 greg 2.1 /* Skip avg photon flux */
214     for (j = 0; j < 3; j++)
215     getflt(pmapFile);
216 rschregle 2.13
217 greg 2.1 /* Get distribution extent (min & max photon positions) */
218     for (j = 0; j < 3; j++) {
219 rschregle 2.7 pm.minPos [j] = getflt(pmapFile);
220     pm.maxPos [j] = getflt(pmapFile);
221 greg 2.1 }
222    
223     /* Skip centre of gravity, and avg photon dist to it */
224     for (j = 0; j < 4; j++)
225     getflt(pmapFile);
226    
227 rschregle 2.9 /* Sphere radius based on avg intersphere dist depending on
228     whether the distribution occupies a 1D line (!), a 2D plane,
229     or 3D volume (= sphere distrib density ^-1/d, where d is the
230     dimensionality of the distribution) */
231     for (j = 0, extent = 1.0, dim = 0; j < 3; j++) {
232     rad = pm.maxPos [j] - pm.minPos [j];
233    
234     if (rad > FTINY) {
235     dim++;
236     extent *= rad;
237     }
238     }
239    
240     rad = radScale * RADCOEFF * pow(extent / numSpheres, 1./dim);
241 greg 2.1
242     /* Photon dump probability to satisfy target sphere count */
243 rschregle 2.7 dumpRatio = numSpheres < pm.numPhotons
244     ? (float)numSpheres / pm.numPhotons : 1;
245 greg 2.1
246 rschregle 2.7 /* Skip primary rays */
247     pm.numPrimary = getint(sizeof(pm.numPrimary), pmapFile);
248     while (pm.numPrimary-- > 0) {
249 rschregle 2.8 /* Skip source index & incident dir */
250 rschregle 2.10 getint(sizeof(pri.srcIdx), pmapFile);
251     #ifdef PMAP_PRIMARYDIR
252     /* Skip primary incident dir */
253     getint(sizeof(pri.dir), pmapFile);
254 rschregle 2.13 #endif
255     #ifdef PMAP_PRIMARYPOS
256 rschregle 2.8 /* Skip primary hitpoint */
257 rschregle 2.7 for (j = 0; j < 3; j++)
258     getflt(pmapFile);
259 rschregle 2.8 #endif
260 rschregle 2.7 }
261    
262     #ifdef PMAP_OOC
263     /* Open leaf file with filename derived from pmap, replace pmapFile
264     * (which is currently the node file) */
265     strncpy(leafFname, argv [arg], 1024);
266     strncat(leafFname, PMAP_OOC_LEAFSUFFIX, 1024);
267     fclose(pmapFile);
268     if (!(pmapFile = fopen(leafFname, "rb"))) {
269     sprintf(errmsg, "cannot open leaf file %s", leafFname);
270     error(SYSTEM, errmsg);
271     }
272     #endif
273    
274     /* Load photons */
275     while (pm.numPhotons-- > 0) {
276     #ifdef PMAP_OOC
277 rschregle 2.13 /* Get entire photon record from ooC octree leaf file
278 rschregle 2.7 !!! OOC PMAP FILES CURRENTLY DON'T USE PORTABLE I/O !!! */
279     if (!fread(&p, sizeof(p), 1, pmapFile)) {
280     sprintf(errmsg, "error reading OOC leaf file %s", leafFname);
281     error(SYSTEM, errmsg);
282     }
283 rschregle 2.13 #else /* kd-tree */
284     /* Get photon position */
285 greg 2.1 for (j = 0; j < 3; j++)
286     p.pos [j] = getflt(pmapFile);
287 rschregle 2.13
288     /* Get photon normal (currently not used) */
289 greg 2.1 for (j = 0; j < 3; j++)
290 rschregle 2.13 p.norm [j] = getint(1, pmapFile);
291    
292     /* Get photon flux */
293     #ifdef PMAP_FLOAT_FLUX
294 rschregle 2.7 for (j = 0; j < 3; j++)
295 rschregle 2.13 p.flux [j] = getflt(pmapFile);
296     #else
297 rschregle 2.7 for (j = 0; j < 4; j++)
298 rschregle 2.13 p.flux [j] = getint(1, pmapFile);
299     #endif
300 greg 2.1
301     /* Skip primary ray index */
302     getint(sizeof(p.primary), pmapFile);
303    
304     /* Skip flags */
305     getint(sizeof(p.flags), pmapFile);
306 rschregle 2.7 #endif
307 rschregle 2.13
308     /* Dump photon probabilistically acc. to target sphere count */
309     if (frandom() <= dumpRatio) {
310     if (fluxCol) {
311     /* Dump individual material def per photon acc. to flux */
312     getPhotonFlux(&p, customCol);
313     printf(radDefs [ptype].mat,
314     customCol [0], customCol [1], customCol [2]);
315     fputc('\n', stdout);
316     }
317    
318     printf(radDefs [ptype].obj, p.pos [0], p.pos [1], p.pos [2], rad);
319     fputc('\n', stdout);
320     }
321    
322 rschregle 2.7 if (ferror(pmapFile) || feof(pmapFile)) {
323 greg 2.1 sprintf(errmsg, "error reading %s", argv [arg]);
324     error(USER, errmsg);
325     }
326     }
327    
328     fclose(pmapFile);
329    
330     /* Reset defaults for next dump */
331     radScale = RADSCALE;
332     numSpheres = NSPHERES;
333 rschregle 2.12 customCol [0] = customCol [1] = customCol [2] = 0;
334 rschregle 2.13 fluxCol = 0;
335 greg 2.1 }
336    
337     return 0;
338     }