ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/mkpmap.c
Revision: 2.11
Committed: Wed Apr 14 11:26:25 2021 UTC (3 years ago) by rschregle
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.10: +151 -89 lines
Log Message:
feat(mkpmap): Added -apI option for spherical ROI

File Contents

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