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

# User Rev Content
1 greg 2.4 #ifndef lint
2 rschregle 2.16 static const char RCSid[] = "$Id: pmapdump.c,v 2.15 2019/08/14 18:02:11 rschregle Exp $";
3 greg 2.4 #endif
4 rschregle 2.7
5 greg 2.1 /*
6 rschregle 2.7 ======================================================================
7 rschregle 2.14 Dump photon maps as RADIANCE scene description or ASCII point list
8     to stdout
9 greg 2.1
10     Roland Schregle (roland.schregle@{hslu.ch, gmail.com})
11     (c) Fraunhofer Institute for Solar Energy Systems,
12 rschregle 2.16 supported by the German Research Foundation (DFG)
13     as part of the FARESYS project
14 rschregle 2.3 (c) Lucerne University of Applied Sciences and Arts,
15 rschregle 2.7 supported by the Swiss National Science Foundation (SNSF, #147053)
16 rschregle 2.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 rschregle 2.7 ======================================================================
21 greg 2.1
22 rschregle 2.16 $Id: pmapdump.c,v 2.15 2019/08/14 18:02:11 rschregle Exp $
23 greg 2.1 */
24    
25    
26    
27 rschregle 2.14 #include "pmap.h"
28 greg 2.1 #include "pmapio.h"
29     #include "rtio.h"
30     #include "resolu.h"
31     #include "random.h"
32 greg 2.2 #include "math.h"
33 greg 2.1
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 rschregle 2.14 /* 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 greg 2.1
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 rschregle 2.14 { "void glow mat.global\n0\n0\n4 %g %g %g 0\n",
53 greg 2.1 "mat.global sphere obj.global\n0\n0\n4 %g %g %g %g\n"
54     },
55 rschregle 2.14 { "void glow mat.pglobal\n0\n0\n4 %g %g %g 0\n",
56 rschregle 2.13 "mat.pglobal sphere obj.pglobal\n0\n0\n4 %g %g %g %g\n"
57 greg 2.1 },
58 rschregle 2.14 { "void glow mat.caustic\n0\n0\n4 %g %g %g 0\n",
59 greg 2.1 "mat.caustic sphere obj.caustic\n0\n0\n4 %g %g %g %g\n"
60     },
61 rschregle 2.14 { "void glow mat.volume\n0\n0\n4 %g %g %g 0\n",
62 greg 2.1 "mat.volume sphere obj.volume\n0\n0\n4 %g %g %g %g\n"
63     },
64 rschregle 2.14 { "void glow mat.direct\n0\n0\n4 %g %g %g 0\n",
65 greg 2.1 "mat.direct sphere obj.direct\n0\n0\n4 %g %g %g %g\n"
66     },
67 rschregle 2.14 { "void glow mat.contrib\n0\n0\n4 %g %g %g 0\n",
68 greg 2.1 "mat.contrib sphere obj.contrib\n0\n0\n4 %g %g %g %g\n"
69     }
70     };
71    
72 rschregle 2.14
73 rschregle 2.12 /* 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 rschregle 2.13 {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 rschregle 2.12 };
83 greg 2.1
84    
85 rschregle 2.14 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 greg 2.1 int main (int argc, char** argv)
106     {
107 greg 2.11 char format [MAXFMTLEN];
108 rschregle 2.9 RREAL rad, radScale = RADSCALE, extent, dumpRatio;
109 rschregle 2.14 unsigned arg, j, ptype, dim, fluxCol = 0, points = 0;
110 rschregle 2.7 long numSpheres = NSPHERES;
111 rschregle 2.14 COLOR col = {0, 0, 0};
112 rschregle 2.7 FILE *pmapFile;
113     PhotonMap pm;
114     PhotonPrimary pri;
115     Photon p;
116     #ifdef PMAP_OOC
117     char leafFname [1024];
118     #endif
119 rschregle 2.13
120 greg 2.1 if (argc < 2) {
121 rschregle 2.14 puts("Dump photon maps as RADIANCE scene description "
122     "or ASCII point list\n");
123 rschregle 2.12 printf("Usage: %s "
124 rschregle 2.14 "[-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 rschregle 2.12 "...\n", argv [0]);
129 greg 2.1 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 rschregle 2.14 case 'a':
137     if (!setBool(argv [arg], 2, &points))
138     error(USER, "invalid option syntax at -a");
139     break;
140 greg 2.1 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 rschregle 2.14 error(USER, "invalid number of points/spheres");
148 greg 2.1 break;
149    
150 rschregle 2.12 case 'c':
151 rschregle 2.13 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 rschregle 2.12 for (j = 0; j < 3; j++)
158 rschregle 2.14 col [j] = atof(argv [++arg]);
159 rschregle 2.13 break;
160    
161     case 'f':
162 rschregle 2.14 if (intens(col) > 0)
163 rschregle 2.13 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 rschregle 2.12 break;
168    
169 greg 2.1 default:
170     sprintf(errmsg, "unknown option %s", argv [arg]);
171     error(USER, errmsg);
172     return -1;
173     }
174    
175     continue;
176     }
177 rschregle 2.13
178 rschregle 2.14 /* Open next photon map file */
179 greg 2.1 if (!(pmapFile = fopen(argv [arg], "rb"))) {
180     sprintf(errmsg, "can't open %s", argv [arg]);
181     error(SYSTEM, errmsg);
182     }
183 rschregle 2.13
184 greg 2.1 /* 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 rschregle 2.13
192 greg 2.1 /* Identify photon map type from format string */
193     for (ptype = 0;
194 rschregle 2.6 ptype < NUM_PMAP_TYPES && strcmp(pmapFormat [ptype], format);
195 greg 2.1 ptype++);
196 rschregle 2.13
197 greg 2.1 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 rschregle 2.7 if (strcmp(getstr(format, pmapFile), PMAP_FILEVER))
205 greg 2.1 error(USER, "incompatible photon map file format");
206 rschregle 2.13
207 rschregle 2.14 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 rschregle 2.13 if (!fluxCol) {
217 rschregle 2.14 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 rschregle 2.13 }
224 greg 2.1
225 rschregle 2.7 /* Get number of photons */
226     pm.numPhotons = getint(sizeof(pm.numPhotons), pmapFile);
227 rschregle 2.13
228 greg 2.1 /* Skip avg photon flux */
229     for (j = 0; j < 3; j++)
230     getflt(pmapFile);
231 rschregle 2.13
232 greg 2.1 /* Get distribution extent (min & max photon positions) */
233     for (j = 0; j < 3; j++) {
234 rschregle 2.7 pm.minPos [j] = getflt(pmapFile);
235     pm.maxPos [j] = getflt(pmapFile);
236 greg 2.1 }
237    
238     /* Skip centre of gravity, and avg photon dist to it */
239     for (j = 0; j < 4; j++)
240     getflt(pmapFile);
241    
242 rschregle 2.9 /* 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 greg 2.1
257     /* Photon dump probability to satisfy target sphere count */
258 rschregle 2.14 dumpRatio = min(1, (float)numSpheres / pm.numPhotons);
259 greg 2.1
260 rschregle 2.7 /* Skip primary rays */
261     pm.numPrimary = getint(sizeof(pm.numPrimary), pmapFile);
262     while (pm.numPrimary-- > 0) {
263 rschregle 2.8 /* Skip source index & incident dir */
264 rschregle 2.10 getint(sizeof(pri.srcIdx), pmapFile);
265     #ifdef PMAP_PRIMARYDIR
266     /* Skip primary incident dir */
267     getint(sizeof(pri.dir), pmapFile);
268 rschregle 2.13 #endif
269     #ifdef PMAP_PRIMARYPOS
270 rschregle 2.8 /* Skip primary hitpoint */
271 rschregle 2.7 for (j = 0; j < 3; j++)
272     getflt(pmapFile);
273 rschregle 2.8 #endif
274 rschregle 2.7 }
275    
276     #ifdef PMAP_OOC
277     /* Open leaf file with filename derived from pmap, replace pmapFile
278     * (which is currently the node file) */
279 rschregle 2.16 strncpy(leafFname, argv [arg], sizeof(leafFname) - 1);
280     strncat(leafFname, PMAP_OOC_LEAFSUFFIX, sizeof(leafFname) - 1);
281 rschregle 2.7 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 rschregle 2.14 /* Read photons */
289 rschregle 2.7 while (pm.numPhotons-- > 0) {
290     #ifdef PMAP_OOC
291 rschregle 2.13 /* Get entire photon record from ooC octree leaf file
292 rschregle 2.7 !!! 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 rschregle 2.13 #else /* kd-tree */
298     /* Get photon position */
299 greg 2.1 for (j = 0; j < 3; j++)
300     p.pos [j] = getflt(pmapFile);
301 rschregle 2.13
302     /* Get photon normal (currently not used) */
303 greg 2.1 for (j = 0; j < 3; j++)
304 rschregle 2.13 p.norm [j] = getint(1, pmapFile);
305    
306     /* Get photon flux */
307     #ifdef PMAP_FLOAT_FLUX
308 rschregle 2.7 for (j = 0; j < 3; j++)
309 rschregle 2.13 p.flux [j] = getflt(pmapFile);
310     #else
311 rschregle 2.7 for (j = 0; j < 4; j++)
312 rschregle 2.13 p.flux [j] = getint(1, pmapFile);
313     #endif
314 rschregle 2.15
315    
316 greg 2.1
317     /* Skip primary ray index */
318     getint(sizeof(p.primary), pmapFile);
319    
320     /* Skip flags */
321     getint(sizeof(p.flags), pmapFile);
322 rschregle 2.7 #endif
323 rschregle 2.13
324     /* Dump photon probabilistically acc. to target sphere count */
325     if (frandom() <= dumpRatio) {
326 rschregle 2.15 if (fluxCol) {
327 rschregle 2.14 /* Get photon flux */
328     getPhotonFlux(&p, col);
329 rschregle 2.15 /* Scale by dumpRatio for energy conservation */
330     scalecolor(col, 1.0 / dumpRatio);
331     }
332 rschregle 2.14
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 rschregle 2.13 fputc('\n', stdout);
342     }
343 rschregle 2.14 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 rschregle 2.13 }
347 rschregle 2.14
348 rschregle 2.7 if (ferror(pmapFile) || feof(pmapFile)) {
349 greg 2.1 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 rschregle 2.14 col [0] = col [1] = col [2] = 0;
360     fluxCol = points = 0;
361 greg 2.1 }
362    
363     return 0;
364     }