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 (5 years, 4 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: pmapdump.c,v 2.12 2018/11/21 19:30:59 rschregle Exp $";
3 #endif
4
5 /*
6 ======================================================================
7 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 (c) Lucerne University of Applied Sciences and Arts,
12 supported by the Swiss National Science Foundation (SNSF, #147053)
13 ======================================================================
14
15 $Id: pmapdump.c,v 2.12 2018/11/21 19:30:59 rschregle Exp $
16 */
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 #include "math.h"
27
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 /* We use %e for the material def to preserve precision when outputting
45 photon flux */
46 const RadianceDef radDefs [] = {
47 { "void glow mat.global\n0\n0\n4 %e %e %e 0\n",
48 "mat.global sphere obj.global\n0\n0\n4 %g %g %g %g\n"
49 },
50 { "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 },
53 { "void glow mat.caustic\n0\n0\n4 %e %e %e 0\n",
54 "mat.caustic sphere obj.caustic\n0\n0\n4 %g %g %g %g\n"
55 },
56 { "void glow mat.volume\n0\n0\n4 %e %e %e 0\n",
57 "mat.volume sphere obj.volume\n0\n0\n4 %g %g %g %g\n"
58 },
59 { "void glow mat.direct\n0\n0\n4 %e %e %e 0\n",
60 "mat.direct sphere obj.direct\n0\n0\n4 %g %g %g %g\n"
61 },
62 { "void glow mat.contrib\n0\n0\n4 %e %e %e 0\n",
63 "mat.contrib sphere obj.contrib\n0\n0\n4 %g %g %g %g\n"
64 }
65 };
66
67 /* 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 {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 };
77
78
79 int main (int argc, char** argv)
80 {
81 char format [MAXFMTLEN];
82 RREAL rad, radScale = RADSCALE, extent, dumpRatio;
83 unsigned arg, j, ptype, dim, fluxCol = 0;
84 long numSpheres = NSPHERES;
85 COLOR customCol = {0, 0, 0};
86 FILE *pmapFile;
87 PhotonMap pm;
88 PhotonPrimary pri;
89 Photon p;
90 #ifdef PMAP_OOC
91 char leafFname [1024];
92 #endif
93
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 if (argc < 2) {
114 puts("Dump photon maps as RADIANCE scene description\n");
115 printf("Usage: %s "
116 "[-r radscale1] [-n nspheres1] [-f | -c rcol1 gcol1 bcol1] pmap1 "
117 "[-r radscale2] [-n nspheres2] [-f | -c rcol2 gcol2 bcol2] pmap2 "
118 "...\n", argv [0]);
119 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 case 'c':
137 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 for (j = 0; j < 3; j++)
144 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 break;
154
155 default:
156 sprintf(errmsg, "unknown option %s", argv [arg]);
157 error(USER, errmsg);
158 return -1;
159 }
160
161 continue;
162 }
163
164 /* 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
170 /* 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
178 /* Identify photon map type from format string */
179 for (ptype = 0;
180 ptype < NUM_PMAP_TYPES && strcmp(pmapFormat [ptype], format);
181 ptype++);
182
183 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 if (strcmp(getstr(format, pmapFile), PMAP_FILEVER))
191 error(USER, "incompatible photon map file format");
192
193 /* Dump command line as comment */
194 fputs("# ", stdout);
195 printargs(argc, argv, stdout);
196 fputc('\n', stdout);
197
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
210 /* Get number of photons */
211 pm.numPhotons = getint(sizeof(pm.numPhotons), pmapFile);
212
213 /* Skip avg photon flux */
214 for (j = 0; j < 3; j++)
215 getflt(pmapFile);
216
217 /* Get distribution extent (min & max photon positions) */
218 for (j = 0; j < 3; j++) {
219 pm.minPos [j] = getflt(pmapFile);
220 pm.maxPos [j] = getflt(pmapFile);
221 }
222
223 /* Skip centre of gravity, and avg photon dist to it */
224 for (j = 0; j < 4; j++)
225 getflt(pmapFile);
226
227 /* 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
242 /* Photon dump probability to satisfy target sphere count */
243 dumpRatio = numSpheres < pm.numPhotons
244 ? (float)numSpheres / pm.numPhotons : 1;
245
246 /* Skip primary rays */
247 pm.numPrimary = getint(sizeof(pm.numPrimary), pmapFile);
248 while (pm.numPrimary-- > 0) {
249 /* Skip source index & incident dir */
250 getint(sizeof(pri.srcIdx), pmapFile);
251 #ifdef PMAP_PRIMARYDIR
252 /* Skip primary incident dir */
253 getint(sizeof(pri.dir), pmapFile);
254 #endif
255 #ifdef PMAP_PRIMARYPOS
256 /* Skip primary hitpoint */
257 for (j = 0; j < 3; j++)
258 getflt(pmapFile);
259 #endif
260 }
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 /* Get entire photon record from ooC octree leaf file
278 !!! 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 #else /* kd-tree */
284 /* Get photon position */
285 for (j = 0; j < 3; j++)
286 p.pos [j] = getflt(pmapFile);
287
288 /* Get photon normal (currently not used) */
289 for (j = 0; j < 3; j++)
290 p.norm [j] = getint(1, pmapFile);
291
292 /* Get photon flux */
293 #ifdef PMAP_FLOAT_FLUX
294 for (j = 0; j < 3; j++)
295 p.flux [j] = getflt(pmapFile);
296 #else
297 for (j = 0; j < 4; j++)
298 p.flux [j] = getint(1, pmapFile);
299 #endif
300
301 /* Skip primary ray index */
302 getint(sizeof(p.primary), pmapFile);
303
304 /* Skip flags */
305 getint(sizeof(p.flags), pmapFile);
306 #endif
307
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 if (ferror(pmapFile) || feof(pmapFile)) {
323 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 customCol [0] = customCol [1] = customCol [2] = 0;
334 fluxCol = 0;
335 }
336
337 return 0;
338 }