ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/pmapdump.c
Revision: 2.16
Committed: Tue Jul 21 16:10:42 2020 UTC (3 years, 9 months ago) by rschregle
Content type: text/plain
Branch: MAIN
Changes since 2.15: +10 -4 lines
Log Message:
fix(pmapdump): fixed potential string overflow after warnings related to
strncat().

File Contents

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