Page MenuHomec4science

mkpmap.c
No OneTemporary

File Metadata

Created
Sat, Apr 27, 09:30

mkpmap.c

#ifndef lint
static const char RCSid[] = "$Id: mkpmap.c,v 2.10 2020/08/07 01:21:13 rschregle Exp $";
#endif
/*
======================================================================
Photon map generator
Roland Schregle (roland.schregle@{hslu.ch, gmail.com})
(c) Fraunhofer Institute for Solar Energy Systems,
supported by the German Research Foundation
(DFG LU-204/10-2, "Fassadenintegrierte Regelsysteme" (FARESYS))
(c) Lucerne University of Applied Sciences and Arts,
supported by the Swiss National Science Foundation
(SNSF #147053, "Daylight Redirecting Components")
(c) Tokyo University of Science,
supported by the JSPS Grants-in-Aid for Scientific Research
(KAKENHI JP19KK0115, "Three-Dimensional Light Flow")
======================================================================
$Id: mkpmap.c,v 2.10 2020/08/07 01:21:13 rschregle Exp $
*/
#include "pmap.h"
#include "pmapmat.h"
#include "pmapsrc.h"
#include "pmapcontrib.h"
#include "pmaprand.h"
#include "paths.h"
#include "ambient.h"
#include "resolu.h"
#include "source.h"
#include <string.h>
#include <sys/stat.h>
/* Enable options for Ze Ekspertz only! */
#define PMAP_EKSPERTZ
extern char VersionID [];
char* progname; /* argv[0] */
int dimlist [MAXDIM]; /* sampling dimensions */
int ndims = 0; /* number of sampling dimenshunns */
char* octname = NULL; /* octree name */
CUBE thescene; /* scene top-level octree */
OBJECT nsceneobjs; /* number of objects in scene */
double srcsizerat = 0.01; /* source partition size ratio */
int backvis = 1; /* back face visibility */
int clobber = 0; /* overwrite output */
COLOR cextinction = BLKCOLOR; /* global extinction coefficient */
COLOR salbedo = BLKCOLOR; /* global scattering albedo */
double seccg = 0; /* global scattering eccentricity */
char *amblist [AMBLLEN + 1]; /* ambient include/exclude list */
int ambincl = -1; /* include == 1, exclude == 0 */
char *diagFile = NULL; /* diagnostics output file */
int rand_samp = 1; /* uncorrelated random sampling */
unsigned nproc = 1; /* number of parallel processes */
#ifdef EVALDRC_HACK
char *angsrcfile = NULL; /* angular source file for EvalDRC */
#endif
/* Dummies for linkage */
COLOR ambval = BLKCOLOR;
double shadthresh = .05, ambacc = 0.2, shadcert = .5, minweight = 5e-3,
ssampdist = 0, dstrsrc = 0.0, specthresh = 0.15, specjitter = 1.0,
avgrefl = 0.5;
int ambvwt = 0, ambssamp = 0, ambres = 32, ambounce = 0, directrelay = 1,
directvis = 1, samplendx, do_irrad = 0, ambdiv = 128, vspretest = 512,
maxdepth = 6, contrib = 0;
char *shm_boundary = NULL, *ambfile = NULL, *RCCONTEXT = NULL;
void (*trace)() = NULL, (*addobjnotify [])() = {ambnotify, NULL};
void printdefaults()
/* print default values to stdout */
{
#ifdef EVALDRC_HACK
/* EvalDRC support */
puts("-A\t\t\t\t# angular source file");
#endif
puts("-ae mod\t\t\t\t# exclude modifier");
puts("-aE file\t\t\t\t# exclude modifiers from file");
puts("-ai mod\t\t\t\t# include modifier");
puts("-aI file\t\t\t\t# include modifiers from file");
#ifdef PMAP_EKSPERTZ
puts("-api xmin ymin zmin xmax ymax zmax\t# region of interest");
#endif
puts("-apg file nPhotons\t\t\t# global photon map");
puts("-apc file nPhotons\t\t\t# caustic photon map");
puts("-apd file nPhotons\t\t\t# direct photon map");
puts("-app file nPhotons bwidth\t\t# precomputed global photon map");
puts("-apv file nPhotons\t\t\t# volume photon map");
puts("-apC file nPhotons\t\t\t# contribution photon map");
printf("-apD %f\t\t\t\t# predistribution factor\n", preDistrib);
printf("-apM %d\t\t\t\t\t# max predistrib passes\n", maxPreDistrib);
#if 1
/* Kept for backwards compat, will be gradually phased out by -ld, -lr */
printf("-apm %ld\t\t\t\t# limit photon bounces\n", photonMaxBounce);
#endif
puts("-apo+ mod\t\t\t\t# photon port modifier");
puts("-apO+ file\t\t\t\t# photon ports from file");
printf("-apP %f\t\t\t\t# precomputation factor\n", finalGather);
printf("-apr %d\t\t\t\t\t# random seed\n", randSeed);
puts("-aps mod\t\t\t\t# antimatter sensor modifier");
puts("-apS file\t\t\t\t# antimatter sensors from file");
printf(backvis ? "-bv+\t\t\t\t\t# back face visibility on\n"
: "-bv-\t\t\t\t\t# back face visibility off\n");
printf("-dp %.1f\t\t\t\t# PDF samples / sr\n", pdfSamples);
printf("-ds %f\t\t\t\t# source partition size ratio\n", srcsizerat);
printf("-e %s\t\t\t\t# diagnostics output file\n", diagFile);
printf(clobber ? "-fo+\t\t\t\t\t# force overwrite\n"
: "-fo-\t\t\t\t\t# do not overwrite\n");
#ifdef PMAP_EKSPERTZ
/* (Formerly) NU STUFF for Ze Exspertz! */
printf("-ld %.1f\t\t\t\t\t# limit photon distance\n", photonMaxDist);
printf("-lr %ld\t\t\t\t# limit photon bounces\n", photonMaxBounce);
#endif
printf("-ma %.2f %.2f %.2f\t\t\t# scattering albedo\n",
colval(salbedo,RED), colval(salbedo,GRN), colval(salbedo,BLU));
printf("-me %.2e %.2e %.2e\t\t# extinction coefficient\n",
colval(cextinction,RED), colval(cextinction,GRN),
colval(cextinction,BLU));
printf("-mg %.2f\t\t\t\t# scattering eccentricity\n", seccg);
#if NIX
/* Multiprocessing on NIX only; so tuff luck, Windoze Weenies! */
printf("-n %d\t\t\t\t\t# number of parallel processes\n", nproc);
#endif
printf("-t %-9d\t\t\t\t# time between reports\n", photonRepTime);
printf(verbose ? "-v+\t\t\t\t\t# verbose console output\n"
: "-v-\t\t\t\t\t# terse console output\n");
}
int main (int argc, char* argv [])
{
#define check(ol, al) if ( \
argv [i][ol] || badarg(argc - i - 1,argv + i + 1, al) \
) goto badopt
/* Evaluate boolean option, setting var accordingly */
#define check_bool(olen, var) switch (argv [i][olen]) { \
case '\0': \
var = !var; break; \
case 'y': case 'Y': case 't': case 'T': case '+': case '1': \
var = 1; break; \
case 'n': case 'N': case 'f': case 'F': case '-': case '0': \
var = 0; break; \
default: \
goto badopt; \
}
/* Evaluate trinary option, setting bits v1 and v2 in var accordingly */
#define check_tri(olen, v1, v2, var) switch (argv [i][olen]) { \
case '\0': case '+': \
var = v1; break; \
case '-': \
var = v2; break;\
case '0': \
var = v1 | v2; break; \
default: \
goto badopt; \
}
int loadflags = IO_CHECK | IO_SCENE | IO_TREE | IO_BOUNDS,
rval, i, j, n;
char **portLp = photonPortList, **sensLp = photonSensorList,
**amblp = NULL, sbuf [MAXSTR], portFlags [2] = "\0\0";
struct stat pmstat;
/* Global program name */
progname = fixargv0(argv [0]);
/* Initialize object types */
initotypes();
/* Parse options */
for (i = 1; i < argc; i++) {
/* Eggs-pand arguments */
while ((rval = expandarg(&argc, &argv, i)))
if (rval < 0) {
sprintf(errmsg, "cannot eggs-pand '%s'", argv [i]);
error(SYSTEM, errmsg);
}
if (argv[i] == NULL)
break;
if (!strcmp(argv [i], "-version")) {
puts(VersionID);
quit(0);
}
if (!strcmp(argv [i], "-defaults") || !strcmp(argv [i], "-help")) {
printdefaults();
quit(0);
}
/* Get octree */
if (i == argc - 1) {
octname = argv [i];
break;
}
switch (argv [i][1]) {
case 'a': /* Ambient */
switch (argv [i][2]) {
case 'i': /* Ambient include */
case 'I':
check(3, "s");
if (ambincl != 1) {
ambincl = 1;
amblp = amblist;
}
if (argv [i][2] == 'I') {
/* Add modifiers from file */
rval = wordfile(amblp, AMBLLEN - (amblp - amblist),
getpath(argv [++i],
getrlibpath(), R_OK));
if (rval < 0) {
sprintf(errmsg,
"cannot open ambient include file \"%s\"",
argv [i]);
error(SYSTEM, errmsg);
}
amblp += rval;
}
else {
/* Add modifier from next arg */
*amblp++ = savqstr(argv [++i]);
*amblp = NULL;
}
break;
case 'e': /* Ambient exclude */
case 'E':
check(3, "s");
if (ambincl != 0) {
ambincl = 0;
amblp = amblist;
}
if (argv [i][2] == 'E') {
/* Add modifiers from file */
rval = wordfile(amblp, AMBLLEN - (amblp - amblist),
getpath(argv [++i],
getrlibpath(), R_OK));
if (rval < 0) {
sprintf(errmsg,
"cannot open ambient exclude file \"%s\"",
argv [i]);
error(SYSTEM, errmsg);
}
amblp += rval;
}
else {
/* Add modifier from next arg */
*amblp++ = savqstr(argv [++i]);
*amblp = NULL;
}
break;
case 'p': /* Pmap-specific */
switch (argv [i][3]) {
case 'g': /* Global photon map */
check(4, "ss");
globalPmapParams.fileName = argv [++i];
globalPmapParams.distribTarget =
parseMultiplier(argv [++i]);
if (!globalPmapParams.distribTarget)
goto badopt;
globalPmapParams.minGather =
globalPmapParams.maxGather = 0;
break;
case 'p': /* Precomputed global photon map */
check(4, "ssi");
preCompPmapParams.fileName = argv [++i];
preCompPmapParams.distribTarget =
parseMultiplier(argv [++i]);
if (!preCompPmapParams.distribTarget)
goto badopt;
preCompPmapParams.minGather =
preCompPmapParams.maxGather = atoi(argv [++i]);
if (!preCompPmapParams.maxGather)
goto badopt;
break;
case 'c': /* Caustic photon map */
check(4, "ss");
causticPmapParams.fileName = argv [++i];
causticPmapParams.distribTarget =
parseMultiplier(argv [++i]);
if (!causticPmapParams.distribTarget)
goto badopt;
break;
case 'v': /* Volume photon map */
check(4, "ss");
volumePmapParams.fileName = argv [++i];
volumePmapParams.distribTarget =
parseMultiplier(argv [++i]);
if (!volumePmapParams.distribTarget)
goto badopt;
break;
case 'd': /* Direct photon map */
check(4, "ss");
directPmapParams.fileName = argv [++i];
directPmapParams.distribTarget =
parseMultiplier(argv [++i]);
if (!directPmapParams.distribTarget)
goto badopt;
break;
case 'C': /* Contribution photon map */
check(4, "ss");
contribPmapParams.fileName = argv [++i];
contribPmapParams.distribTarget =
parseMultiplier(argv [++i]);
if (!contribPmapParams.distribTarget)
goto badopt;
break;
case 'D': /* Predistribution factor */
check(4, "f");
preDistrib = atof(argv [++i]);
if (preDistrib <= 0)
error(USER, "predistrib factor must be > 0");
break;
case 'M': /* Max predistribution passes */
check(4, "i");
maxPreDistrib = atoi(argv [++i]);
if (maxPreDistrib <= 0)
error(USER, "max predistrib passes must be > 0");
break;
#if 1
/* Kept for backwards compat, to be phased out by -lr */
case 'm': /* Max photon bounces */
check(4, "i");
photonMaxBounce = atol(argv [++i]);
if (photonMaxBounce <= 0)
error(USER, "max photon bounces must be > 0");
break;
#endif
#ifdef PMAP_EKSPERTZ
case 'i': /* Add region of interest */
check(4, "ffffff");
n = pmapNumROI;
pmapROI = realloc(pmapROI,
++pmapNumROI * sizeof(PhotonMapROI));
if (!pmapROI)
error(SYSTEM, "failed to allocate ROI");
pmapROI [n].min [0] = atof(argv [++i]);
pmapROI [n].min [1] = atof(argv [++i]);
pmapROI [n].min [2] = atof(argv [++i]);
pmapROI [n].max [0] = atof(argv [++i]);
pmapROI [n].max [1] = atof(argv [++i]);
pmapROI [n].max [2] = atof(argv [++i]);
for (j = 0; j < 3; j++)
if (pmapROI [n].min [j] >= pmapROI [n].max [j])
error(USER, "invalid region of interest "
"(swapped min/max?)");
break;
#endif
case 'P': /* Global photon precomp ratio */
check(4, "f");
finalGather = atof(argv [++i]);
if (finalGather <= 0 || finalGather > 1)
error(USER, "global photon precomputation ratio "
"must be in range ]0, 1]");
break;
case 'o': /* Photon port */
case 'O':
/* Check for bad arg and length, taking into account
* default forward orientation if none specified, in
* order to maintain previous behaviour */
check(argv [i][4] ? 5 : 4, "s");
/* Get port orientation flags */
check_tri(
4, PMAP_PORTFWD, PMAP_PORTBWD, portFlags [0]
);
if (argv [i][3] == 'O') {
/* Add port modifiers from file */
rval = wordfile(
portLp, MAXSET - (portLp - photonPortList),
getpath(argv [++i], getrlibpath(), R_OK)
);
if (rval < 0) {
sprintf(
errmsg, "cannot open photon port file %s",
argv [i]
);
error(SYSTEM, errmsg);
}
/* HACK: append port orientation flags to every
* modifier; note this requires reallocation */
for (; rval--; portLp++) {
j = strlen(*portLp);
if (!(*portLp = realloc(*portLp, j + 2))) {
sprintf(
errmsg,
"cannot allocate photon port modifiers"
" from file %s", argv [i]
);
error(SYSTEM, errmsg);
}
strcat(*portLp, portFlags);
}
}
else {
/* Append port flags to port modifier, add to
* port list and mark of end list with NULL */
strcpy(sbuf, argv [++i]);
strcat(sbuf, portFlags);
*portLp++ = savqstr(sbuf);
*portLp = NULL;
}
break;
case 'r': /* Random seed */
check(4, "i");
randSeed = atoi(argv [++i]);
break;
case 's': /* Antimatter sensor */
case 'S':
check(4, "s");
if (argv[i][3] == 'S') {
/* Add sensor modifiers from file */
rval = wordfile(sensLp,
MAXSET - (sensLp - photonSensorList),
getpath(argv [++i],
getrlibpath(), R_OK));
if (rval < 0) {
sprintf(errmsg,
"cannot open antimatter sensor file %s",
argv [i]);
error(SYSTEM, errmsg);
}
sensLp += rval;
}
else {
/* Append modifier to sensor list, mark end with
* NULL */
*sensLp++ = savqstr(argv [++i]);
*sensLp = NULL;
}
break;
default: goto badopt;
}
break;
default: goto badopt;
}
break;
case 'b': /* Back face visibility */
if (argv [i][2] == 'v') {
check_bool(3, backvis);
}
else goto badopt;
break;
case 'd': /* Direct */
switch (argv [i][2]) {
case 'p': /* PDF samples */
check(3, "f");
pdfSamples = atof(argv [++i]);
break;
case 's': /* Source partition size ratio */
check(3, "f");
srcsizerat = atof(argv [++i]);
break;
default: goto badopt;
}
break;
case 'e': /* Diagnostics file */
check(2, "s");
diagFile = argv [++i];
break;
case 'f': /* Force overwrite */
if (argv [i][2] == 'o') {
check_bool(3, clobber);
}
else goto badopt;
break;
#ifdef PMAP_EKSPERTZ
case 'l': /* Limits */
switch (argv [i][2]) {
case 'd': /* Limit photon path distance */
check(3, "f");
photonMaxDist = atof(argv [++i]);
if (photonMaxDist <= 0)
error(USER, "max photon distance must be > 0");
break;
case 'r': /* Limit photon bounces */
check(3, "i");
photonMaxBounce = atol(argv [++i]);
if (photonMaxBounce <= 0)
error(USER, "max photon bounces must be > 0");
break;
default: goto badopt;
}
break;
#endif
case 'm': /* Medium */
switch (argv[i][2]) {
case 'e': /* Eggs-tinction coefficient */
check(3, "fff");
setcolor(cextinction, atof(argv [i + 1]),
atof(argv [i + 2]), atof(argv [i + 3]));
i += 3;
break;
case 'a': /* Albedo */
check(3, "fff");
setcolor(salbedo, atof(argv [i + 1]),
atof(argv [i + 2]), atof(argv [i + 3]));
i += 3;
break;
case 'g': /* Scattering eccentricity */
check(3, "f");
seccg = atof(argv [++i]);
break;
default: goto badopt;
}
break;
#if NIX
case 'n': /* Num parallel processes (NIX only) */
check(2, "i");
nproc = atoi(argv [++i]);
if (nproc > PMAP_MAXPROC) {
nproc = PMAP_MAXPROC;
sprintf(errmsg, "too many parallel processes, clamping to "
"%d\n", nproc);
error(WARNING, errmsg);
}
break;
#endif
case 't': /* Timer */
check(2, "i");
photonRepTime = atoi(argv [++i]);
break;
case 'v': /* Verbosity */
check_bool(2, verbose);
break;
#ifdef EVALDRC_HACK
case 'A': /* Angular source file */
check(2,"s");
angsrcfile = argv[++i];
break;
#endif
default: goto badopt;
}
}
/* Open diagnostics file */
if (diagFile) {
if (!freopen(diagFile, "a", stderr)) quit(2);
fprintf(stderr, "**************\n*** PID %5d: ", getpid());
printargs(argc, argv, stderr);
putc('\n', stderr);
fflush(stderr);
}
#ifdef NICE
/* Lower priority */
nice(NICE);
#endif
if (octname == NULL)
error(USER, "missing octree argument");
/* Allocate photon maps and set parameters */
for (i = 0; i < NUM_PMAP_TYPES; i++) {
setPmapParam(photonMaps + i, pmapParams + i);
/* Don't overwrite existing photon map unless clobbering enabled */
if (photonMaps [i] && !stat(photonMaps [i] -> fileName, &pmstat) &&
!clobber) {
sprintf(errmsg, "photon map file %s exists, not overwritten",
photonMaps [i] -> fileName);
error(USER, errmsg);
}
}
for (i = 0; i < NUM_PMAP_TYPES && !photonMaps [i]; i++);
if (i >= NUM_PMAP_TYPES)
error(USER, "no photon maps specified");
readoct(octname, loadflags, &thescene, NULL);
#ifdef EVALDRC_HACK
if (angsrcfile)
readobj(angsrcfile); /* load angular sources */
#endif
nsceneobjs = nobjects;
/* Get sources */
marksources();
/* Do forward pass and build photon maps */
if (contribPmap)
/* Just build contrib pmap, ignore others */
distribPhotonContrib(contribPmap, nproc);
else
distribPhotons(photonMaps, nproc);
/* Save photon maps; no idea why GCC needs an explicit cast here... */
savePmaps((const PhotonMap**)photonMaps, argc, argv);
cleanUpPmaps(photonMaps);
quit(0);
badopt:
sprintf(errmsg, "command line error at '%s'", argv[i]);
error(USER, errmsg);
#undef check
#undef check_bool
return 0;
}

Event Timeline