ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/mkpmap.c
Revision: 2.13
Committed: Wed Apr 23 02:13:34 2025 UTC (9 days, 15 hours ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.12: +6 -3 lines
Log Message:
fix(mkpmap): Added missing call to initialize functions

File Contents

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