ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/pmapdump.c
Revision: 2.15
Committed: Wed Aug 14 18:02:11 2019 UTC (4 years, 9 months ago) by rschregle
Content type: text/plain
Branch: MAIN
Changes since 2.14: +8 -3 lines
Log Message:
Photon flux is scaled by the fraction of dumped photons when using -f.

File Contents

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