ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/mkpmap.c
Revision: 2.10
Committed: Fri Aug 7 01:21:13 2020 UTC (3 years, 8 months ago) by rschregle
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R3
Changes since 2.9: +80 -37 lines
Log Message:
feat(mkpmap): Extended -apo option to reorient photon ports.

File Contents

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