Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F70464620
pmapdump.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Jul 7, 00:04
Size
13 KB
Mime Type
text/x-c
Expires
Tue, Jul 9, 00:04 (2 d)
Engine
blob
Format
Raw Data
Handle
18848271
Attached To
R10977 RADIANCE Photon Map
pmapdump.c
View Options
#ifndef lint
static const char RCSid[] = "$Id: pmapdump.c,v 2.18 2021/02/18 17:08:50 rschregle Exp $";
#endif
/*
======================================================================
Dump photon maps as RADIANCE scene description or ASCII point list
to stdout
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",
SNSF #179067, "Light Fields for Spatio-Temporal Glare Assessment")
(c) Tokyo University of Science,
supported by the JSPS Grants-in-Aid for Scientific Research
(KAKENHI JP19KK0115, "Three-Dimensional Light Flow")
======================================================================
$Id: pmapdump.c,v 2.18 2021/02/18 17:08:50 rschregle Exp $
*/
#include "pmap.h"
#include "pmapio.h"
#include "rtio.h"
#include "resolu.h"
#include "random.h"
#include "math.h"
/* Defaults */
/* Sphere radius as fraction of avg. intersphere dist */
/* Relative scale for sphere radius (fudge factor) */
/* Number of spheres */
#define RADCOEFF 0.05
#define RADSCALE 1.0
#define NSPHERES 10000
/* Formats for ASCII output as XYZ RGB points plus optional normals
(incident directions for volume photons) and path IDs */
#define POINTFMT "%g\t%g\t%g\t%g\t%g\t%g"
#define NORMFMT "\t%f\t%f\t%f"
#define PATHFMT "\t%u:%lu"
#define SRCFMT "\t%u"
#define TIMEFMT "\t%g"
/* RADIANCE material and object defs for each photon type */
typedef struct {
char *mat, *obj;
} RadianceDef;
const RadianceDef radDefs [] = {
{ "void glow mat.global\n0\n0\n4 %g %g %g 0\n",
"mat.global sphere obj.global\n0\n0\n4 %g %g %g %g\n"
},
{ "void glow mat.pglobal\n0\n0\n4 %g %g %g 0\n",
"mat.pglobal sphere obj.pglobal\n0\n0\n4 %g %g %g %g\n"
},
{ "void glow mat.caustic\n0\n0\n4 %g %g %g 0\n",
"mat.caustic sphere obj.caustic\n0\n0\n4 %g %g %g %g\n"
},
{ "void glow mat.volume\n0\n0\n4 %g %g %g 0\n",
"mat.volume sphere obj.volume\n0\n0\n4 %g %g %g %g\n"
},
{ "void glow mat.direct\n0\n0\n4 %g %g %g 0\n",
"mat.direct sphere obj.direct\n0\n0\n4 %g %g %g %g\n"
},
{ "void glow mat.contrib\n0\n0\n4 %g %g %g 0\n",
"mat.contrib sphere obj.contrib\n0\n0\n4 %g %g %g %g\n"
},
{ "void glow mat.transient\n0\n0\n4 %g %g %g 0\n",
"mat.transient sphere obj.transient\n0\n0\n4 %g %g %g %g\n"
}
#ifdef PMAP_PHOTONFLOW
, { "void glow mat.lightflow\n0\n0\n4 %g %g %g 0\n",
"mat.lightflow sphere obj.lightflow\n0\n0\n4 %g %g %g %g\n"
},
{ "void glow mat.tlightflow\n0\n0\n4 %g %g %g 0\n",
"mat.tlightflow sphere obj.tlightflow\n0\n0\n4 %g %g %g %g\n"
}
#endif
};
/* Default colour codes are as follows: global = blue
precomp global = cyan
caustic = red
transient = white
volume/lightflow = green
direct = magenta
contrib = yellow */
const COLOR colDefs [] = {
{0.25, 0.25, 2}, {0.1, 1, 1}, {1, 0.1, 0.1},
{0.1, 1, 0.1}, {1, 0.1, 1}, {1, 1, 0.1}, {1, 1, 1}
#ifdef PMAP_PHOTONFLOW
, {0.1, 1, 0.1}, {1, 1, 1}
#endif
};
static int setBool(char *str, unsigned pos, unsigned *var)
{
switch ((str) [pos]) {
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:
return 0;
}
return 1;
}
int main (int argc, char** argv)
{
char format [MAXFMTLEN];
RREAL rad, radScale = RADSCALE, extent, dumpRatio;
unsigned arg, j, ptype, dim,
fluxCol = 0, points = 0, normals = 0, aux = 0;
long numSpheres = NSPHERES;
COLOR col = {0, 0, 0};
FILE *pmapFile;
PhotonMap pm;
Photon p;
#ifdef PMAP_OOC
char leafFname [1024];
#endif
if (argc < 2) {
puts("Dump photon maps as RADIANCE scene description "
"or ASCII point list\n"
);
printf("Usage:\n"
"%s [-a [-N][-A|-P]] [-r radscale1] [-n num1] [-f | -c r1 g1 b1] pmap1\n"
"\t[-a [-N][-A|-P]] [-r radscale2] [-n num2] [-f | -c r2 g2 b2] pmap2 "
" ...\n",
argv [0]
);
return 1;
}
for (arg = 1; arg < argc; arg++) {
/* Parse options */
if (argv [arg][0] == '-') {
switch (argv [arg][1]) {
case 'a':
if (!setBool(argv [arg], 2, &points))
error(USER, "invalid option syntax at -a");
break;
case 'A': /* Dump type-specific auxiliary data */
case 'P': /* Dump paths; kept for backward compatibility */
if (!setBool(argv [arg], 2, &aux))
error(USER, "invalid option syntax at -A / -P");
break;
case 'c':
if (fluxCol)
error(USER, "-f and -c are mutually exclusive");
if (badarg(argc - arg - 1, &argv [arg + 1], "fff"))
error(USER, "invalid RGB colour");
for (j = 0; j < 3; j++)
col [j] = atof(argv [++arg]);
break;
case 'f':
if (intens(col) > 0)
error(USER, "-f and -c are mutually exclusive");
if (!setBool(argv [arg], 2, &fluxCol))
error(USER, "invalid option syntax at -f");
break;
case 'n':
if ((numSpheres = parseMultiplier(argv [++arg])) <= 0)
error(USER, "invalid number of points/spheres");
break;
case 'N':
if (!setBool(argv [arg], 2, &normals))
error(USER, "invalid option syntax at -N");
break;
case 'r':
if ((radScale = atof(argv [++arg])) <= 0)
error(USER, "invalid radius scale");
break;
default:
sprintf(errmsg, "unknown option %s", argv [arg]);
error(USER, errmsg);
return -1;
}
continue;
}
/* Check for compatible options */
if ((normals || aux) && !points)
error(USER, "options -A, -N, -P only valid in conjuction with -a");
/* Open next photon map file */
if (!(pmapFile = fopen(argv [arg], "rb"))) {
sprintf(errmsg, "can't open %s", argv [arg]);
error(SYSTEM, errmsg);
}
/* Get format string */
strcpy(format, PMAP_FORMAT_GLOB);
if (checkheader(pmapFile, format, NULL) != 1) {
sprintf(errmsg, "photon map file %s has an unknown format",
argv [arg]
);
error(USER, errmsg);
}
/* Identify photon map type from format string */
for (ptype = 0;
ptype < NUM_PMAP_TYPES && strcmp(pmapFormat [ptype], format);
ptype++
);
if (!validPmapType(ptype)) {
sprintf(errmsg, "file %s contains an unknown photon map type",
argv [arg]
);
error(USER, errmsg);
}
/* Get file format version and check for compatibility */
if (strcmp(getstr(format, pmapFile), PMAP_FILEVER))
error(USER, "incompatible photon map file format");
if (!points) {
/* Dump command line as comment */
fputs("# ", stdout);
printargs(argc, argv, stdout);
fputc('\n', stdout);
}
/* Set point/sphere colour if independent of photon flux,
output RADIANCE material def if required */
if (!fluxCol) {
if (intens(col) <= 0)
copycolor(col, colDefs [ptype]);
if (!points) {
printf(radDefs [ptype].mat, col [0], col [1], col [2]);
fputc('\n', stdout);
}
}
/* Get number of photons as fixed size, which possibly results in
* padding of MSB with 0 on some platforms. Unlike sizeof() however,
* this ensures portability since this value may span 32 or 64 bits
* depending on platform. */
pm.numPhotons = getint(PMAP_LONGSIZE, pmapFile);
/* Skip avg photon flux */
for (j = 0; j < 3; j++)
getflt(pmapFile);
/* Get distribution extent (min & max photon positions) */
for (j = 0; j < 3; j++) {
pm.minPos [j] = getflt(pmapFile);
pm.maxPos [j] = getflt(pmapFile);
}
/* Skip centre of gravity, and avg photon dist to it */
for (j = 0; j < 4; j++)
getflt(pmapFile);
/* Get photon velocity, skip min/max/avg path length */
pm.velocity = getflt(pmapFile);
for (j = 0; j < 3; j++)
getflt(pmapFile);
/* Sphere radius based on avg intersphere dist depending on
whether the distribution occupies a 1D line (!), a 2D plane,
or 3D volume (= sphere distrib density ^-1/d, where d is the
dimensionality of the distribution) */
for (j = 0, extent = 1.0, dim = 0; j < 3; j++) {
rad = pm.maxPos [j] - pm.minPos [j];
if (rad > FTINY) {
dim++;
extent *= rad;
}
}
rad = radScale * RADCOEFF * pow(extent / numSpheres, 1./dim);
/* Photon dump probability to satisfy target sphere count */
dumpRatio = min(1, (float)numSpheres / pm.numPhotons);
#ifdef PMAP_OOC
/* Open leaf file with filename derived from pmap, replace pmapFile
* (which is currently the node file) */
strncpy(leafFname, argv [arg], sizeof(leafFname) - 1);
strncat(leafFname, PMAP_OOC_LEAFSUFFIX, sizeof(leafFname) - 1);
fclose(pmapFile);
if (!(pmapFile = fopen(leafFname, "rb"))) {
sprintf(errmsg, "cannot open leaf file %s", leafFname);
error(SYSTEM, errmsg);
}
#endif
/* Read photons */
while (pm.numPhotons-- > 0) {
#ifdef PMAP_OOC
/* Get entire photon record from ooC octree leaf file
!!! OOC PMAP FILES CURRENTLY DON'T USE PORTABLE I/O !!! */
if (!fread(&p, sizeof(p), 1, pmapFile)) {
sprintf(errmsg, "error reading OOC leaf file %s", leafFname);
error(SYSTEM, errmsg);
}
#else /* kd-tree */
/* Get photon position */
for (j = 0; j < 3; j++)
p.pos [j] = getflt(pmapFile);
/* Get photon normal (dumped with -N) */
for (j = 0; j < 3; j++)
p.norm [j] = getint(1, pmapFile);
/* Get photon flux */
#ifdef PMAP_FLOAT_FLUX
for (j = 0; j < 3; j++)
p.flux [j] = getflt(pmapFile);
#else
for (j = 0; j < 4; j++)
p.flux [j] = getint(1, pmapFile);
#endif
/* Get photon's auxiliary field (dumped with -A/-P) */
getbinary(&p.aux, 1, sizeof(p.aux), pmapFile);
/* Get photon's flags (includes subprocess prefix for path ID */
p.flags = getint(sizeof(p.flags), pmapFile);
#endif
/* Dump photon probabilistically acc. to target sphere count */
if (frandom() <= dumpRatio) {
if (fluxCol) {
/* Get photon flux */
getPhotonFlux(&p, col);
/* Scale by dumpRatio for energy conservation */
scalecolor(col, 1.0 / dumpRatio);
}
if (!points) {
if (fluxCol) {
/* Dump material def if variable (depends on flux) */
printf(radDefs [ptype].mat, col [0], col [1], col [2]);
fputc('\n', stdout);
}
printf(radDefs [ptype].obj,
p.pos [0], p.pos [1], p.pos [2], rad
);
fputc('\n', stdout);
}
else {
/* Dump as XYZ RGB point */
printf(POINTFMT, p.pos [0], p.pos [1], p.pos [2],
col [0], col [1] ,col [2]
);
if (normals)
printf(NORMFMT,
p.norm [0] / 127., p.norm [1] / 127., p.norm [2] / 127.
);
if (aux)
/* Interpret auxiliary data depending on photon type */
switch (ptype) {
case PMAP_TYPE_TRANSIENT:
#ifdef PMAP_PHOTONFLOW
case PMAP_TYPE_TRANSLIGHTFLOW:
#endif
/* Aux field contains path length; calculate
photon's time of flight */
printf(TIMEFMT, p.aux.pathLen / pm.velocity);
break;
case PMAP_TYPE_CONTRIB:
/* Aux field contains photon's emitting light
source index */
printf(SRCFMT, p.aux.contribSrc);
break;
default:
/* Aux field contains photon's path ID; prefix with
photon's process index for uniqueness */
printf(PATHFMT, p.proc, (unsigned long)p.aux.pathID);
}
fputc('\n', stdout);
}
}
if (ferror(pmapFile) || feof(pmapFile)) {
sprintf(errmsg, "error reading %s", argv [arg]);
error(USER, errmsg);
}
}
fclose(pmapFile);
/* Reset defaults for next dump */
radScale = RADSCALE;
numSpheres = NSPHERES;
col [0] = col [1] = col [2] = 0;
fluxCol = points = 0;
}
return 0;
}
Event Timeline
Log In to Comment