ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/mkpmap.c
Revision: 2.9
Committed: Tue Mar 20 19:55:33 2018 UTC (6 years, 2 months ago) by rschregle
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2
Changes since 2.8: +248 -196 lines
Log Message:
Added -ae/-ai ambient exclude options to mkpmap, cleaned up opt parsing.

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: mkpmap.c,v 2.8 2018/02/02 19:47:55 rschregle Exp $";
3 #endif
4
5
6 /*
7 ======================================================================
8 Photon map generator
9
10 Roland Schregle (roland.schregle@{hslu.ch, gmail.com})
11 (c) Fraunhofer Institute for Solar Energy Systems,
12 Lucerne University of Applied Sciences & Arts
13 (c) Lucerne University of Applied Sciences and Arts,
14 supported by the Swiss National Science Foundation (SNSF, #147053)
15 ======================================================================
16
17 $Id: mkpmap.c,v 2.8 2018/02/02 19:47:55 rschregle Exp $
18 */
19
20
21 #include "pmap.h"
22 #include "pmapmat.h"
23 #include "pmapsrc.h"
24 #include "pmapcontrib.h"
25 #include "pmaprand.h"
26 #include "paths.h"
27 #include "ambient.h"
28 #include "resolu.h"
29 #include "source.h"
30 #include <string.h>
31 #include <sys/stat.h>
32
33
34 /* Enable options for Ze Ekspertz only! */
35 #define PMAP_EKSPERTZ
36
37
38 extern char VersionID [];
39
40
41 char* progname; /* argv[0] */
42 int dimlist [MAXDIM]; /* sampling dimensions */
43 int ndims = 0; /* number of sampling dimenshunns */
44 char* octname = NULL; /* octree name */
45 CUBE thescene; /* scene top-level octree */
46 OBJECT nsceneobjs; /* number of objects in scene */
47 double srcsizerat = 0.01; /* source partition size ratio */
48 int backvis = 1; /* back face visibility */
49 int clobber = 0; /* overwrite output */
50 COLOR cextinction = BLKCOLOR; /* global extinction coefficient */
51 COLOR salbedo = BLKCOLOR; /* global scattering albedo */
52 double seccg = 0; /* global scattering eccentricity */
53 char *amblist [AMBLLEN + 1]; /* ambient include/exclude list */
54 int ambincl = -1; /* include == 1, exclude == 0 */
55 char *diagFile = NULL; /* diagnostics output file */
56 int rand_samp = 1; /* uncorrelated random sampling */
57 unsigned nproc = 1; /* number of parallel processes */
58 #ifdef EVALDRC_HACK
59 char *angsrcfile = NULL; /* angular source file for EvalDRC */
60 #endif
61
62
63 /* Dummies for linkage */
64
65 COLOR ambval = BLKCOLOR;
66 double shadthresh = .05, ambacc = 0.2, shadcert = .5, minweight = 5e-3,
67 ssampdist = 0, dstrsrc = 0.0, specthresh = 0.15, specjitter = 1.0,
68 avgrefl = 0.5;
69 int ambvwt = 0, ambssamp = 0, ambres = 32, ambounce = 0, directrelay = 1,
70 directvis = 1, samplendx, do_irrad = 0, ambdiv = 128, vspretest = 512,
71 maxdepth = 6, contrib = 0;
72 char *shm_boundary = NULL, *ambfile = NULL, *RCCONTEXT = NULL;
73 void (*trace)() = NULL, (*addobjnotify [])() = {ambnotify, NULL};
74
75
76 void printdefaults()
77 /* print default values to stdout */
78 {
79
80 #ifdef EVALDRC_HACK
81 /* EvalDRC support */
82 puts("-A\t\t\t\t# angular source file");
83 #endif
84 puts("-ae mod\t\t\t\t# exclude modifier");
85 puts("-aE file\t\t\t\t# exclude modifiers from file");
86 puts("-ai mod\t\t\t\t# include modifier");
87 puts("-aI file\t\t\t\t# include modifiers from file");
88 #ifdef PMAP_EKSPERTZ
89 puts("-api xmin ymin zmin xmax ymax zmax\t# region of interest");
90 #endif
91 puts("-apg file nPhotons\t\t\t# global photon map");
92 puts("-apc file nPhotons\t\t\t# caustic photon map");
93 puts("-apd file nPhotons\t\t\t# direct photon map");
94 puts("-app file nPhotons bwidth\t\t# precomputed global photon map");
95 puts("-apv file nPhotons\t\t\t# volume photon map");
96 puts("-apC file nPhotons\t\t\t# contribution photon map");
97 printf("-apD %f\t\t\t\t# predistribution factor\n", preDistrib);
98 printf("-apM %d\t\t\t\t\t# max predistrib passes\n", maxPreDistrib);
99 #if 1
100 /* Kept for backwards compat, will be gradually phased out by -lD, -lr */
101 printf("-apm %ld\t\t\t\t# limit photon bounces\n", photonMaxBounce);
102 #endif
103 puts("-apo mod\t\t\t\t# photon port modifier");
104 puts("-apO file\t\t\t\t# photon ports from file");
105 printf("-apP %f\t\t\t\t# precomputation factor\n", finalGather);
106 printf("-apr %d\t\t\t\t\t# random seed\n", randSeed);
107 puts("-aps mod\t\t\t\t# antimatter sensor modifier");
108 puts("-apS file\t\t\t\t# antimatter sensors from file");
109
110 printf(backvis ? "-bv+\t\t\t\t\t# back face visibility on\n"
111 : "-bv-\t\t\t\t\t# back face visibility off\n");
112 printf("-dp %.1f\t\t\t\t# PDF samples / sr\n", pdfSamples);
113 printf("-ds %f\t\t\t\t# source partition size ratio\n", srcsizerat);
114 printf("-e %s\t\t\t\t# diagnostics output file\n", diagFile);
115 printf(clobber ? "-fo+\t\t\t\t\t# force overwrite\n"
116 : "-fo-\t\t\t\t\t# do not overwrite\n");
117 #ifdef PMAP_EKSPERTZ
118 /* NU STUFF for Ze Exspertz! */
119 printf("-ld %.1f\t\t\t\t\t# limit photon distance\n", photonMaxDist);
120 printf("-lr %ld\t\t\t\t# limit photon bounces\n", photonMaxBounce);
121 #endif
122 printf("-ma %.2f %.2f %.2f\t\t\t# scattering albedo\n",
123 colval(salbedo,RED), colval(salbedo,GRN), colval(salbedo,BLU));
124 printf("-me %.2e %.2e %.2e\t\t# extinction coefficient\n",
125 colval(cextinction,RED), colval(cextinction,GRN),
126 colval(cextinction,BLU));
127 printf("-mg %.2f\t\t\t\t# scattering eccentricity\n", seccg);
128 #if NIX
129 /* Multiprocessing on NIX only */
130 printf("-n %d\t\t\t\t\t# number of parallel processes\n", nproc);
131 #endif
132 printf("-t %-9d\t\t\t\t# time between reports\n", photonRepTime);
133 printf(verbose ? "-v+\t\t\t\t\t# verbose console output\n"
134 : "-v-\t\t\t\t\t# terse console output\n");
135 }
136
137
138 int main (int argc, char* argv [])
139 {
140 #define check(ol, al) if (argv [i][ol] || \
141 badarg(argc - i - 1,argv + i + 1, al)) \
142 goto badopt
143
144 #define check_bool(olen, var) switch (argv [i][olen]) { \
145 case '\0': var = !var; break; \
146 case 'y': case 'Y': case 't': case 'T': \
147 case '+': case '1': var = 1; break; \
148 case 'n': case 'N': case 'f': case 'F': \
149 case '-': case '0': var = 0; break; \
150 default: goto badopt; \
151 }
152
153 int loadflags = IO_CHECK | IO_SCENE | IO_TREE | IO_BOUNDS, rval, i, j, n;
154 char **portLp = photonPortList, **sensLp = photonSensorList,
155 **amblp = NULL;
156 struct stat pmstat;
157
158 /* Global program name */
159 progname = fixargv0(argv [0]);
160 /* Initialize object types */
161 initotypes();
162
163 /* Parse options */
164 for (i = 1; i < argc; i++) {
165 /* Eggs-pand arguments */
166 while ((rval = expandarg(&argc, &argv, i)))
167 if (rval < 0) {
168 sprintf(errmsg, "cannot eggs-pand '%s'", argv [i]);
169 error(SYSTEM, errmsg);
170 }
171
172 if (argv[i] == NULL)
173 break;
174
175 if (!strcmp(argv [i], "-version")) {
176 puts(VersionID);
177 quit(0);
178 }
179
180 if (!strcmp(argv [i], "-defaults") || !strcmp(argv [i], "-help")) {
181 printdefaults();
182 quit(0);
183 }
184
185 /* Get octree */
186 if (i == argc - 1) {
187 octname = argv [i];
188 break;
189 }
190
191 switch (argv [i][1]) {
192 case 'a': /* Ambient */
193 switch (argv [i][2]) {
194 case 'i': /* Ambient include */
195 case 'I':
196 check(3, "s");
197 if (ambincl != 1) {
198 ambincl = 1;
199 amblp = amblist;
200 }
201 if (argv [i][2] == 'I') {
202 /* Add modifiers from file */
203 rval = wordfile(amblp, AMBLLEN - (amblp - amblist),
204 getpath(argv [++i],
205 getrlibpath(), R_OK));
206 if (rval < 0) {
207 sprintf(errmsg,
208 "cannot open ambient include file \"%s\"",
209 argv [i]);
210 error(SYSTEM, errmsg);
211 }
212 amblp += rval;
213 }
214 else {
215 /* Add modifier from next arg */
216 *amblp++ = savqstr(argv [++i]);
217 *amblp = NULL;
218 }
219 break;
220
221 case 'e': /* Ambient exclude */
222 case 'E':
223 check(3, "s");
224 if (ambincl != 0) {
225 ambincl = 0;
226 amblp = amblist;
227 }
228 if (argv [i][2] == 'E') {
229 /* Add modifiers from file */
230 rval = wordfile(amblp, AMBLLEN - (amblp - amblist),
231 getpath(argv [++i],
232 getrlibpath(), R_OK));
233 if (rval < 0) {
234 sprintf(errmsg,
235 "cannot open ambient exclude file \"%s\"",
236 argv [i]);
237 error(SYSTEM, errmsg);
238 }
239 amblp += rval;
240 }
241 else {
242 /* Add modifier from next arg */
243 *amblp++ = savqstr(argv [++i]);
244 *amblp = NULL;
245 }
246 break;
247
248 case 'p': /* Pmap-specific */
249 switch (argv [i][3]) {
250 case 'g': /* Global photon map */
251 check(4, "ss");
252 globalPmapParams.fileName = argv [++i];
253 globalPmapParams.distribTarget =
254 parseMultiplier(argv [++i]);
255 if (!globalPmapParams.distribTarget)
256 goto badopt;
257 globalPmapParams.minGather =
258 globalPmapParams.maxGather = 0;
259 break;
260
261 case 'p': /* Precomputed global photon map */
262 check(4, "ssi");
263 preCompPmapParams.fileName = argv [++i];
264 preCompPmapParams.distribTarget =
265 parseMultiplier(argv [++i]);
266 if (!preCompPmapParams.distribTarget)
267 goto badopt;
268 preCompPmapParams.minGather =
269 preCompPmapParams.maxGather = atoi(argv [++i]);
270 if (!preCompPmapParams.maxGather)
271 goto badopt;
272 break;
273
274 case 'c': /* Caustic photon map */
275 check(4, "ss");
276 causticPmapParams.fileName = argv [++i];
277 causticPmapParams.distribTarget =
278 parseMultiplier(argv [++i]);
279 if (!causticPmapParams.distribTarget)
280 goto badopt;
281 break;
282
283 case 'v': /* Volume photon map */
284 check(4, "ss");
285 volumePmapParams.fileName = argv [++i];
286 volumePmapParams.distribTarget =
287 parseMultiplier(argv [++i]);
288 if (!volumePmapParams.distribTarget)
289 goto badopt;
290 break;
291
292 case 'd': /* Direct photon map */
293 check(4, "ss");
294 directPmapParams.fileName = argv [++i];
295 directPmapParams.distribTarget =
296 parseMultiplier(argv [++i]);
297 if (!directPmapParams.distribTarget)
298 goto badopt;
299 break;
300
301 case 'C': /* Contribution photon map */
302 check(4, "ss");
303 contribPmapParams.fileName = argv [++i];
304 contribPmapParams.distribTarget =
305 parseMultiplier(argv [++i]);
306 if (!contribPmapParams.distribTarget)
307 goto badopt;
308 break;
309
310 case 'D': /* Predistribution factor */
311 check(4, "f");
312 preDistrib = atof(argv [++i]);
313 if (preDistrib <= 0)
314 error(USER, "predistrib factor must be > 0");
315 break;
316
317 case 'M': /* Max predistribution passes */
318 check(4, "i");
319 maxPreDistrib = atoi(argv [++i]);
320 if (maxPreDistrib <= 0)
321 error(USER, "max predistrib passes must be > 0");
322 break;
323
324 #if 1
325 /* Kept for backwards compat, to be phased out by -lr */
326 case 'm': /* Max photon bounces */
327 check(4, "i");
328 photonMaxBounce = atol(argv [++i]);
329 if (photonMaxBounce <= 0)
330 error(USER, "max photon bounces must be > 0");
331 break;
332 #endif
333
334 #ifdef PMAP_EKSPERTZ
335 case 'i': /* Add region of interest */
336 check(4, "ffffff");
337 n = pmapNumROI;
338 pmapROI = realloc(pmapROI,
339 ++pmapNumROI * sizeof(PhotonMapROI));
340 if (!pmapROI)
341 error(SYSTEM, "failed to allocate ROI");
342 pmapROI [n].min [0] = atof(argv [++i]);
343 pmapROI [n].min [1] = atof(argv [++i]);
344 pmapROI [n].min [2] = atof(argv [++i]);
345 pmapROI [n].max [0] = atof(argv [++i]);
346 pmapROI [n].max [1] = atof(argv [++i]);
347 pmapROI [n].max [2] = atof(argv [++i]);
348 for (j = 0; j < 3; j++)
349 if (pmapROI [n].min [j] >= pmapROI [n].max [j])
350 error(USER, "invalid region of interest "
351 "(swapped min/max?)");
352 break;
353 #endif
354
355 case 'P': /* Global photon precomp ratio */
356 check(4, "f");
357 finalGather = atof(argv [++i]);
358 if (finalGather <= 0 || finalGather > 1)
359 error(USER, "global photon precomputation ratio "
360 "must be in range ]0, 1]");
361 break;
362
363 case 'o': /* Photon port */
364 case 'O':
365 check(4, "s");
366 if (argv [i][3] == 'O') {
367 /* Add port modifiers from file */
368 rval = wordfile(portLp,
369 MAXSET - (portLp - photonPortList),
370 getpath(argv [++i],
371 getrlibpath(), R_OK));
372 if (rval < 0) {
373 sprintf(errmsg,
374 "cannot open photon port file %s",
375 argv [i]);
376 error(SYSTEM, errmsg);
377 }
378 portLp += rval;
379 }
380 else {
381 /* Add port modifier from next arg, mark end with
382 * NULL */
383 *portLp++ = savqstr(argv [++i]);
384 *portLp = NULL;
385 }
386 break;
387
388 case 'r': /* Random seed */
389 check(4, "i");
390 randSeed = atoi(argv [++i]);
391 break;
392
393 case 's': /* Antimatter sensor */
394 case 'S':
395 check(4, "s");
396 if (argv[i][3] == 'S') {
397 /* Add sensor modifiers from file */
398 rval = wordfile(sensLp,
399 MAXSET - (sensLp - photonSensorList),
400 getpath(argv [++i],
401 getrlibpath(), R_OK));
402 if (rval < 0) {
403 sprintf(errmsg,
404 "cannot open antimatter sensor file %s",
405 argv [i]);
406 error(SYSTEM, errmsg);
407 }
408 sensLp += rval;
409 }
410 else {
411 /* Append modifier to sensor list, mark end with
412 * NULL */
413 *sensLp++ = savqstr(argv [++i]);
414 *sensLp = NULL;
415 }
416 break;
417
418 default: goto badopt;
419 }
420 break;
421
422 default: goto badopt;
423 }
424 break;
425
426 case 'b': /* Back face visibility */
427 if (argv [i][2] == 'v') {
428 check_bool(3, backvis);
429 }
430 else goto badopt;
431 break;
432
433 case 'd': /* Direct */
434 switch (argv [i][2]) {
435 case 'p': /* PDF samples */
436 check(3, "f");
437 pdfSamples = atof(argv [++i]);
438 break;
439
440 case 's': /* Source partition size ratio */
441 check(3, "f");
442 srcsizerat = atof(argv [++i]);
443 break;
444
445 default: goto badopt;
446 }
447 break;
448
449 case 'e': /* Diagnostics file */
450 check(2, "s");
451 diagFile = argv [++i];
452 break;
453
454 case 'f': /* Force overwrite */
455 if (argv [i][2] == 'o') {
456 check_bool(3, clobber);
457 }
458 else goto badopt;
459 break;
460
461 #ifdef PMAP_EKSPERTZ
462 case 'l': /* Limits */
463 switch (argv [i][2]) {
464 case 'd': /* Limit photon path distance */
465 check(3, "f");
466 photonMaxDist = atof(argv [++i]);
467 if (photonMaxDist <= 0)
468 error(USER, "max photon distance must be > 0");
469 break;
470
471 case 'r': /* Limit photon bounces */
472 check(3, "i");
473 photonMaxBounce = atol(argv [++i]);
474 if (photonMaxBounce <= 0)
475 error(USER, "max photon bounces must be > 0");
476 break;
477
478 default: goto badopt;
479 }
480 break;
481 #endif
482
483 case 'm': /* Medium */
484 switch (argv[i][2]) {
485 case 'e': /* Eggs-tinction coefficient */
486 check(3, "fff");
487 setcolor(cextinction, atof(argv [i + 1]),
488 atof(argv [i + 2]), atof(argv [i + 3]));
489 i += 3;
490 break;
491
492 case 'a': /* Albedo */
493 check(3, "fff");
494 setcolor(salbedo, atof(argv [i + 1]),
495 atof(argv [i + 2]), atof(argv [i + 3]));
496 i += 3;
497 break;
498
499 case 'g': /* Scattering eccentricity */
500 check(3, "f");
501 seccg = atof(argv [++i]);
502 break;
503
504 default: goto badopt;
505 }
506 break;
507
508 #if NIX
509 case 'n': /* Num parallel processes (NIX only) */
510 check(2, "i");
511 nproc = atoi(argv [++i]);
512
513 if (nproc > PMAP_MAXPROC) {
514 nproc = PMAP_MAXPROC;
515 sprintf(errmsg, "too many parallel processes, clamping to "
516 "%d\n", nproc);
517 error(WARNING, errmsg);
518 }
519 break;
520 #endif
521
522 case 't': /* Timer */
523 check(2, "i");
524 photonRepTime = atoi(argv [++i]);
525 break;
526
527 case 'v': /* Verbosity */
528 check_bool(2, verbose);
529 break;
530
531 #ifdef EVALDRC_HACK
532 case 'A': /* Angular source file */
533 check(2,"s");
534 angsrcfile = argv[++i];
535 break;
536 #endif
537
538 default: goto badopt;
539 }
540 }
541
542 /* Open diagnostics file */
543 if (diagFile) {
544 if (!freopen(diagFile, "a", stderr)) quit(2);
545 fprintf(stderr, "**************\n*** PID %5d: ", getpid());
546 printargs(argc, argv, stderr);
547 putc('\n', stderr);
548 fflush(stderr);
549 }
550
551 #ifdef NICE
552 /* Lower priority */
553 nice(NICE);
554 #endif
555
556 if (octname == NULL)
557 error(USER, "missing octree argument");
558
559 /* Allocate photon maps and set parameters */
560 for (i = 0; i < NUM_PMAP_TYPES; i++) {
561 setPmapParam(photonMaps + i, pmapParams + i);
562
563 /* Don't overwrite existing photon map unless clobbering enabled */
564 if (photonMaps [i] && !stat(photonMaps [i] -> fileName, &pmstat) &&
565 !clobber) {
566 sprintf(errmsg, "photon map file %s exists, not overwritten",
567 photonMaps [i] -> fileName);
568 error(USER, errmsg);
569 }
570 }
571
572 for (i = 0; i < NUM_PMAP_TYPES && !photonMaps [i]; i++);
573 if (i >= NUM_PMAP_TYPES)
574 error(USER, "no photon maps specified");
575
576 readoct(octname, loadflags, &thescene, NULL);
577 #ifdef EVALDRC_HACK
578 if (angsrcfile)
579 readobj(angsrcfile); /* load angular sources */
580 #endif
581 nsceneobjs = nobjects;
582
583 /* Get sources */
584 marksources();
585
586 /* Do forward pass and build photon maps */
587 if (contribPmap)
588 /* Just build contrib pmap, ignore others */
589 distribPhotonContrib(contribPmap, nproc);
590 else
591 distribPhotons(photonMaps, nproc);
592
593 /* Save photon maps; no idea why GCC needs an explicit cast here... */
594 savePmaps((const PhotonMap**)photonMaps, argc, argv);
595 cleanUpPmaps(photonMaps);
596
597 quit(0);
598
599 badopt:
600 sprintf(errmsg, "command line error at '%s'", argv[i]);
601 error(USER, errmsg);
602
603 #undef check
604 #undef check_bool
605 return 0;
606 }